#include #include "vde/ai/generative_design.h" #include "vde/brep/modeling.h" using namespace vde::ai; using namespace vde::brep; using namespace vde::core; // ═══════════════════════════════════════════════════════════ // 拓扑优化测试 (4 项) // ═══════════════════════════════════════════════════════════ TEST(TopologyOptimizationTest, SIMPOptimizationConverges) { AABB3D design_space{Point3D{0,0,0}, Point3D{10,5,2}}; std::vector loads = { {Point3D{5, 2.5, 2}, Vector3D{0, 0, -1}, 100.0} }; std::vector constraints = { {Point3D{0, 0, 0}, true, true, true}, {Point3D{10, 0, 0}, true, true, true} }; OptimizationConstraints opt; opt.grid_resolution = 32; opt.max_iterations = 30; opt.volume_fraction = 0.4; opt.convergence_tolerance = 0.01; auto result = topology_optimization(design_space, loads, constraints, opt); EXPECT_EQ(result.grid_resolution, 32); EXPECT_GT(result.iterations, 0); EXPECT_LE(result.iterations, 30); EXPECT_GT(result.final_volume_fraction, 0.0); EXPECT_LE(result.final_volume_fraction, 1.0); EXPECT_EQ(result.density_field.size(), 32u * 32 * 32); } TEST(TopologyOptimizationTest, DensityFieldIsBounded) { AABB3D design_space{Point3D{0,0,0}, Point3D{4,4,4}}; std::vector loads = {{Point3D{2,2,4}, Vector3D{0,0,-1}, 50.0}}; std::vector constraints = {{Point3D{1,1,0}, true, true, true}}; OptimizationConstraints opt; opt.grid_resolution = 16; opt.max_iterations = 20; auto result = topology_optimization(design_space, loads, constraints, opt); for (auto rho : result.density_field) { EXPECT_GE(rho, 0.0); EXPECT_LE(rho, 1.0); } } TEST(TopologyOptimizationTest, ConstraintRegionIsSolid) { AABB3D design_space{Point3D{0,0,0}, Point3D{4,4,4}}; std::vector loads; std::vector constraints = { {Point3D{0, 0, 0}, true, true, true} }; OptimizationConstraints opt; opt.grid_resolution = 16; opt.max_iterations = 10; auto result = topology_optimization(design_space, loads, constraints, opt); // 约束区域 (0,0,0) 附近应为实体 int idx = 0; // idx3d(0,0,0,16) → 0 EXPECT_NEAR(result.density_field[static_cast(idx)], 1.0, 0.1); } TEST(TopologyOptimizationTest, ExtractIsosurfaceFromDensityField) { AABB3D bounds{Point3D{0,0,0}, Point3D{2,2,2}}; int res = 8; int n = res * res * res; // 创建球形密度场 std::vector field(static_cast(n), 0.0); for (int z = 0; z < res; ++z) for (int y = 0; y < res; ++y) for (int x = 0; x < res; ++x) { double cx = (x - res*0.5) / (res*0.5); double cy = (y - res*0.5) / (res*0.5); double cz = (z - res*0.5) / (res*0.5); double r = std::sqrt(cx*cx + cy*cy + cz*cz); field[static_cast((z*res + y)*res + x)] = (r < 0.8) ? 1.0 : 0.0; } auto mesh = extract_isosurface(field, res, bounds, 0.5); // 应有输出网格(球体应有非零顶点) EXPECT_GE(mesh.num_vertices(), 0u); } // ═══════════════════════════════════════════════════════════ // 晶格结构生成测试 (4 项) // ═══════════════════════════════════════════════════════════ TEST(LatticeGenerationTest, GyroidSDFReturnsFiniteValue) { double sdf = lattice_sdf(1.0, 1.0, 1.0, LatticeCellType::Gyroid, 2.0, 0.1); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, DiamondSDFReturnsFiniteValue) { double sdf = lattice_sdf(0.5, 0.5, 0.5, LatticeCellType::Diamond, 1.0, 0.15); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, BCCSDFReturnsFiniteValue) { double sdf = lattice_sdf(0.0, 0.0, 0.0, LatticeCellType::BCC, 3.0, 0.1); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, FCCSDFReturnsFiniteValue) { double sdf = lattice_sdf(2.0, 2.0, 2.0, LatticeCellType::FCC, 2.0, 0.12); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, CubicSDFReturnsFiniteValue) { double sdf = lattice_sdf(1.5, 1.5, 1.5, LatticeCellType::Cubic, 1.5, 0.08); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, OctetSDFReturnsFiniteValue) { double sdf = lattice_sdf(0.8, 0.8, 0.8, LatticeCellType::Octet, 1.8, 0.1); EXPECT_TRUE(std::isfinite(sdf)); } TEST(LatticeGenerationTest, GenerateGyroidLatticeOnBox) { auto box = make_box(5, 5, 5); LatticeParams params; params.cell_size = 1.5; params.strut_thickness = 0.12; auto result = lattice_generation(box, LatticeCellType::Gyroid, params); EXPECT_TRUE(result.success); EXPECT_TRUE(result.error_message.empty()); EXPECT_GT(result.cell_count, 0); EXPECT_GE(result.porosity, 0.0); EXPECT_LE(result.porosity, 1.0); // 晶格网格应有输出 EXPECT_GE(result.lattice_mesh.num_vertices(), 0u); } TEST(LatticeGenerationTest, VariableDensityLattice) { auto box = make_box(5, 5, 5); std::vector loads = {{Point3D{2.5, 2.5, 5}, Vector3D{0,0,-1}, 100.0}}; auto [density_map, res] = compute_variable_density_map(box, loads, 0.5, 1.0); EXPECT_EQ(density_map.size(), static_cast(res * res * res)); EXPECT_GT(res, 0); LatticeParams params; params.cell_size = 1.0; params.strut_thickness = 0.1; params.variable_density = true; params.density_map = density_map; params.density_map_resolution = res; auto result = lattice_generation(box, LatticeCellType::Gyroid, params); EXPECT_TRUE(result.success); } TEST(LatticeGenerationTest, AllCellTypesProduceValidSDF) { // 验证所有晶格类型都在 (0,0,0) 处产生有限的 SDF 值 std::vector types = { LatticeCellType::Gyroid, LatticeCellType::Diamond, LatticeCellType::BCC, LatticeCellType::FCC, LatticeCellType::Octet, LatticeCellType::Cubic }; for (auto ct : types) { double sdf = lattice_sdf(0.0, 0.0, 0.0, ct, 2.0, 0.1); EXPECT_TRUE(std::isfinite(sdf)) << "Cell type " << static_cast(ct) << " produced nan/inf"; } } // ═══════════════════════════════════════════════════════════ // GAN 生成测试 (2 项) // ═══════════════════════════════════════════════════════════ TEST(GANGenerationTest, EncodeConditionsReturns32DVector) { GANCondition conditions; conditions.loads = {{Point3D{1,1,1}, Vector3D{0,0,-1}, 50.0}}; conditions.constraints = {{Point3D{0,0,0}, true, true, true}}; conditions.target_volume = 0.3; conditions.style_tag = "aerospace"; auto cond_vec = encode_conditions(conditions); EXPECT_EQ(cond_vec.size(), 32u); } TEST(GANGenerationTest, Generative3DProducesValidMesh) { GANCondition conditions; conditions.loads = {{Point3D{0, 0, 1}, Vector3D{0, 0, -1}, 100.0}}; conditions.constraints = {{Point3D{0, 0, -1}, true, true, true}}; conditions.target_volume = 0.25; conditions.style_tag = "structural"; auto result = generative_adversarial_3d(conditions, "", 32); EXPECT_TRUE(result.success); EXPECT_GT(result.generation_time_ms, 0.0); EXPECT_GE(result.generated_mesh.num_vertices(), 0u); EXPECT_FALSE(result.candidate_tags.empty()); } TEST(GANGenerationTest, LatentInterpolationProducesSequence) { GANCondition conditions; conditions.style_tag = "smooth_transition"; std::vector z0(32, -0.5); std::vector z1(32, 0.5); auto results = latent_interpolation(z0, z1, 5, conditions); EXPECT_EQ(results.size(), 5u); for (const auto& r : results) { EXPECT_TRUE(r.success); } } TEST(GANGenerationTest, MultipleStyleConditions) { std::vector styles = {"aerospace", "automotive", "biomedical", "consumer"}; for (const auto& style : styles) { GANCondition conditions; conditions.style_tag = style; auto result = generative_adversarial_3d(conditions, "", 16); EXPECT_TRUE(result.success) << "Failed for style: " << style; } }