2ecad1543f
v8.1 — 极致性能 (SIMD + LockFree + Transaction + NUMA): - simd_vector.h: Vec4d/Vec4f SSE/AVX/NEON auto-detect, batch AABB, SoA transpose - concurrent_data: LockFreeQueue (MPMC CAS), LockFreeStack (Treiber), ConcurrentHashMap (64-segment sharded) - transaction: Command pattern, UndoManager (infinite undo/redo), crash-recovery journal - performance_tuning: NUMA-aware, cache_line aligned, prefetch, hot/cold separation - 20 tests (concurrent + transaction), ~2600 lines v8.2 — CAM 全面优化 + 装配模式: - cam_optimization: chip_thinning, HSM, constant_engagement, trochoidal_turn_milling - tool_life_management, probing_cycle, thread_milling - cam_advanced enhanced: Mazak/Okuma/Haas/DMG post-processors (8 total) - assembly_patterns: Circular/Rectangular/Mirror/PatternDriven/fill arrays - assembly_feature enhanced: assembly-level PMI propagation, batch interference check - 28 tests, compiled 0 errors (~2800 lines) v8.3 — 可视化+压缩+IGA+质量闭环: - visualization_quality: ambient_occlusion, edge_highlighting, wireframe, normals - topology_compression: Brep compression, Edgebreaker, vertex quantization - iga_prep: knot_insertion, degree_elevation, Bezier extraction for IGA analysis - quality_feedback: design_rule_check, manufacturability, cost_estimation, quality_score (0-100) - 28 tests, ~2349 lines 27 files, ~7750 lines, 76 tests
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);
|
|
}
|