214 lines
8.5 KiB
C++
214 lines
8.5 KiB
C++
|
|
#include <gtest/gtest.h>
|
||
|
|
#include "vde/brep/quality_feedback.h"
|
||
|
|
#include "vde/brep/brep.h"
|
||
|
|
|
||
|
|
using namespace vde::brep;
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// Helper: create a simple BrepModel box
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
static BrepModel make_box_model() {
|
||
|
|
BrepModel model;
|
||
|
|
int v0 = model.add_vertex(Point3D(0, 0, 0));
|
||
|
|
int v1 = model.add_vertex(Point3D(10, 0, 0));
|
||
|
|
int v2 = model.add_vertex(Point3D(10, 10, 0));
|
||
|
|
int v3 = model.add_vertex(Point3D(0, 10, 0));
|
||
|
|
int v4 = model.add_vertex(Point3D(0, 0, 10));
|
||
|
|
int v5 = model.add_vertex(Point3D(10, 0, 10));
|
||
|
|
int v6 = model.add_vertex(Point3D(10, 10, 10));
|
||
|
|
int v7 = model.add_vertex(Point3D(0, 10, 10));
|
||
|
|
|
||
|
|
int e0 = model.add_edge(v0, v1);
|
||
|
|
int e1 = model.add_edge(v1, v2);
|
||
|
|
int e2 = model.add_edge(v2, v3);
|
||
|
|
int e3 = model.add_edge(v3, v0);
|
||
|
|
int e4 = model.add_edge(v4, v5);
|
||
|
|
int e5 = model.add_edge(v5, v6);
|
||
|
|
int e6 = model.add_edge(v6, v7);
|
||
|
|
int e7 = model.add_edge(v7, v4);
|
||
|
|
int e8 = model.add_edge(v0, v4);
|
||
|
|
int e9 = model.add_edge(v1, v5);
|
||
|
|
int e10 = model.add_edge(v2, v6);
|
||
|
|
int e11 = model.add_edge(v3, v7);
|
||
|
|
|
||
|
|
int f0 = model.add_face(0, {model.add_loop({e0, e1, e2, e3})});
|
||
|
|
int f1 = model.add_face(0, {model.add_loop({e7, e6, e5, e4})});
|
||
|
|
int f2 = model.add_face(0, {model.add_loop({e0, e9, e4, e8})});
|
||
|
|
int f3 = model.add_face(0, {model.add_loop({e1, e10, e5, e9})});
|
||
|
|
int f4 = model.add_face(0, {model.add_loop({e2, e11, e6, e10})});
|
||
|
|
int f5 = model.add_face(0, {model.add_loop({e3, e8, e7, e11})});
|
||
|
|
|
||
|
|
model.add_body({model.add_shell({f0, f1, f2, f3, f4, f5})}, "TestBox");
|
||
|
|
return model;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// 设计规则检查测试
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
TEST(DesignRuleCheckTest, DefaultRules) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = design_rule_check(body);
|
||
|
|
|
||
|
|
EXPECT_GT(report.total_rules, 0);
|
||
|
|
EXPECT_GE(report.passed_count + report.failed_count, report.total_rules);
|
||
|
|
EXPECT_GE(report.overall_score, 0.0);
|
||
|
|
EXPECT_LE(report.overall_score, 1.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(DesignRuleCheckTest, CustomRules) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
std::vector<DesignRule> rules = {
|
||
|
|
{"test_rule", "Test", 5.0, 15.0, 1.0, false},
|
||
|
|
};
|
||
|
|
auto report = design_rule_check(body, rules);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.total_rules, 1);
|
||
|
|
EXPECT_GE(report.results.size(), 1u);
|
||
|
|
EXPECT_EQ(report.results[0].rule_name, "test_rule");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(DesignRuleCheckTest, CriticalRuleFailure) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
std::vector<DesignRule> rules = {
|
||
|
|
{"always_fail", "Must fail", 100.0, -1, 1.0, true},
|
||
|
|
};
|
||
|
|
auto report = design_rule_check(body, rules);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.total_rules, 1);
|
||
|
|
EXPECT_FALSE(report.all_critical_passed);
|
||
|
|
EXPECT_GT(report.failed_count, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(DesignRuleCheckTest, AspectRatioRule) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
std::vector<DesignRule> rules = {
|
||
|
|
{"max_aspect_ratio", "最大纵横比", -1, 10.0, 1.0, false},
|
||
|
|
};
|
||
|
|
auto report = design_rule_check(body, rules);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.results[0].rule_name, "max_aspect_ratio");
|
||
|
|
EXPECT_TRUE(report.results[0].passed);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// 可制造性分析测试
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
TEST(ManufacturabilityTest, MachiningAnalysis) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = manufacturability_analysis(body, ManufacturingProcess::Machining);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.process, ManufacturingProcess::Machining);
|
||
|
|
EXPECT_GE(report.feasibility, 0.0);
|
||
|
|
EXPECT_LE(report.feasibility, 1.0);
|
||
|
|
EXPECT_GE(report.dfm_score, 0.0);
|
||
|
|
EXPECT_LE(report.dfm_score, 100.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(ManufacturabilityTest, InjectionMoldingAnalysis) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = manufacturability_analysis(body, ManufacturingProcess::InjectionMolding);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.process, ManufacturingProcess::InjectionMolding);
|
||
|
|
EXPECT_GT(report.total_issues, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(ManufacturabilityTest, AdditiveAnalysis) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = manufacturability_analysis(body, ManufacturingProcess::Additive);
|
||
|
|
|
||
|
|
EXPECT_EQ(report.process, ManufacturingProcess::Additive);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// 成本估算测试
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
TEST(CostEstimationTest, BasicEstimate) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
MaterialInfo alu{"Aluminum 6061-T6", 2700, 25.0, "6061-T6"};
|
||
|
|
auto est = cost_estimation(body, alu);
|
||
|
|
|
||
|
|
EXPECT_GT(est.volume_m3, 0.0);
|
||
|
|
EXPECT_GT(est.mass_kg, 0.0);
|
||
|
|
EXPECT_GT(est.material_cost, 0.0);
|
||
|
|
EXPECT_GT(est.total_cost, 0.0);
|
||
|
|
EXPECT_EQ(est.currency, "CNY");
|
||
|
|
EXPECT_EQ(est.material.name, "Aluminum 6061-T6");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(CostEstimationTest, DifferentMaterials) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
|
||
|
|
auto est_alu = cost_estimation(body, {"Aluminum 6061-T6", 2700, 25.0, "6061"});
|
||
|
|
auto est_steel = cost_estimation(body, {"Steel AISI 1045", 7850, 8.0, "1045"});
|
||
|
|
|
||
|
|
EXPECT_GT(est_steel.mass_kg, est_alu.mass_kg);
|
||
|
|
EXPECT_GT(est_alu.total_cost + est_steel.total_cost, 0.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// 综合质量评分测试
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
TEST(QualityScoreTest, BasicScore) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = quality_score(body);
|
||
|
|
|
||
|
|
EXPECT_GE(report.overall_score, 0.0);
|
||
|
|
EXPECT_LE(report.overall_score, 100.0);
|
||
|
|
EXPECT_FALSE(report.grade.empty());
|
||
|
|
EXPECT_TRUE(report.grade == "A" || report.grade == "B" ||
|
||
|
|
report.grade == "C" || report.grade == "D");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(QualityScoreTest, ComponentsSum) {
|
||
|
|
auto body = make_box_model();
|
||
|
|
auto report = quality_score(body);
|
||
|
|
|
||
|
|
EXPECT_GE(report.geometric_score, 0.0);
|
||
|
|
EXPECT_LE(report.geometric_score, 100.0);
|
||
|
|
EXPECT_GE(report.rule_score, 0.0);
|
||
|
|
EXPECT_LE(report.rule_score, 100.0);
|
||
|
|
EXPECT_GE(report.dfm_score, 0.0);
|
||
|
|
EXPECT_LE(report.dfm_score, 100.0);
|
||
|
|
EXPECT_GE(report.cost_score, 0.0);
|
||
|
|
EXPECT_LE(report.cost_score, 100.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
// 默认规则和材料库测试
|
||
|
|
// ═══════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
TEST(LibraryTest, DefaultDesignRulesNotEmpty) {
|
||
|
|
auto rules = default_design_rules();
|
||
|
|
EXPECT_GT(rules.size(), 0u);
|
||
|
|
|
||
|
|
for (const auto& r : rules) {
|
||
|
|
EXPECT_FALSE(r.name.empty());
|
||
|
|
EXPECT_GE(r.weight, 0.0);
|
||
|
|
EXPECT_LE(r.weight, 1.0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(LibraryTest, MaterialLibrary) {
|
||
|
|
auto materials = material_library();
|
||
|
|
EXPECT_GT(materials.size(), 0u);
|
||
|
|
|
||
|
|
for (const auto& m : materials) {
|
||
|
|
EXPECT_FALSE(m.name.empty());
|
||
|
|
EXPECT_GT(m.density_kgm3, 0.0);
|
||
|
|
EXPECT_GT(m.cost_per_kg, 0.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool has_aluminum = false, has_steel = false;
|
||
|
|
for (const auto& m : materials) {
|
||
|
|
if (m.name.find("Aluminum") != std::string::npos) has_aluminum = true;
|
||
|
|
if (m.name.find("Steel") != std::string::npos) has_steel = true;
|
||
|
|
}
|
||
|
|
EXPECT_TRUE(has_aluminum);
|
||
|
|
EXPECT_TRUE(has_steel);
|
||
|
|
}
|