Files
ViewDesignEngine/tests/core/test_cam_optimization.cpp
T
茂之钳 2ecad1543f
CI / Build & Test (push) Failing after 1m31s
CI / Release Build (push) Failing after 31s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat(v8): ultimate performance + CAM full optimization + visualization/IGA/quality
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
2026-07-26 23:13:22 +08:00

285 lines
9.1 KiB
C++

#include <gtest/gtest.h>
#include "vde/core/cam_optimization.h"
#include "vde/core/cam_advanced.h"
#include "vde/core/cam_strategies.h"
#include "vde/core/cam_toolpath.h"
#include "vde/brep/brep.h"
#include "vde/brep/modeling.h"
#include <cmath>
using namespace vde::core;
using namespace vde::brep;
// ===========================================================================
// Helpers
// ===========================================================================
static BrepModel make_test_box(double w = 50.0, double h = 30.0, double d = 20.0) {
return make_box(w, h, d);
}
static Toolpath make_basic_toolpath() {
Toolpath tp;
tp.name = "TestBasic";
tp.safe_z = 15.0;
PathSegment s1{Point3D(0,0,15), Point3D(10,0,-1),
Point3D::Zero(), PathSegmentType::Linear, 500.0, -1.0};
PathSegment s2{Point3D(10,0,-1), Point3D(20,0,-1),
Point3D::Zero(), PathSegmentType::Linear, 500.0, -1.0};
PathSegment s3{Point3D(20,0,-1), Point3D(20,10,-1),
Point3D::Zero(), PathSegmentType::Linear, 500.0, -1.0};
tp.segments = {s1, s2, s3};
return tp;
}
// ===========================================================================
// chip_thinning_optimization 测试
// ===========================================================================
TEST(CamOptimizationTest, ChipThinning_AdjustsFeedForSmallAe) {
Toolpath tp = make_basic_toolpath();
Tool tool;
tool.diameter = 10.0; // R=5mm, 小径向切深 → 应触发补偿
tool.flutes = 2;
auto result = chip_thinning_optimization(tp, tool);
EXPECT_EQ(result.segments.size(), tp.segments.size());
EXPECT_GT(result.segments[0].feed_rate, 0);
// 名称应有变化
EXPECT_NE(result.name, tp.name);
}
TEST(CamOptimizationTest, ChipThinning_EmptyToolpath) {
Toolpath empty_tp;
Tool tool;
tool.diameter = 10.0;
auto result = chip_thinning_optimization(empty_tp, tool);
EXPECT_EQ(result.segments.size(), 0u);
}
TEST(CamOptimizationTest, ChipThinning_LargeToolNoChange) {
// 刀具直径很大,径向切深接近刀具半径 → 不补偿
Toolpath tp = make_basic_toolpath();
Tool tool;
tool.diameter = 100.0; // 非常大的刀具
auto result = chip_thinning_optimization(tp, tool);
// 大刀具时补偿因子应接近 1
for (size_t i = 0; i < result.segments.size(); ++i) {
if (result.segments[i].type == PathSegmentType::Linear) {
EXPECT_NEAR(result.segments[i].feed_rate, tp.segments[i].feed_rate, 300.0);
}
}
}
// ===========================================================================
// trochoidal_turn_milling 测试
// ===========================================================================
TEST(CamOptimizationTest, TrochoidalTurnMill_GeneratesSegments) {
auto box = make_test_box(30, 30, 15);
Tool tool;
tool.diameter = 8.0;
TurnMillParams params;
params.step_down = 5.0;
params.trochoid_radius = 2.0;
params.safe_z = 15.0;
auto tp = trochoidal_turn_milling(box, tool, params);
EXPECT_EQ(tp.name, "TrochoidalTurnMill");
EXPECT_GT(tp.segments.size(), 5u) << "Should generate turn-mill toolpath";
EXPECT_DOUBLE_EQ(tp.safe_z, 15.0);
}
TEST(CamOptimizationTest, TrochoidalTurnMill_IncludesRetract) {
auto box = make_test_box(20, 20, 10);
Tool tool;
tool.diameter = 6.0;
TurnMillParams params;
params.safe_z = 20.0;
params.step_down = 10.0; // 单层
auto tp = trochoidal_turn_milling(box, tool, params);
// 最后一段应为提刀
EXPECT_FALSE(tp.segments.empty());
EXPECT_EQ(tp.segments.back().type, PathSegmentType::Rapid);
}
// ===========================================================================
// high_speed_machining 测试
// ===========================================================================
TEST(CamOptimizationTest, HighSpeedMachining_IncreasesFeed) {
Toolpath tp = make_basic_toolpath();
HSMParams params;
params.feed_rate = 2000.0;
params.step_down = 0.5;
params.trochoidal_corners = false;
auto result = high_speed_machining(tp, params);
EXPECT_EQ(result.segments.size(), tp.segments.size());
// HSM 应提升进给率
for (size_t i = 0; i < result.segments.size(); ++i) {
if (result.segments[i].type == PathSegmentType::Linear) {
EXPECT_GE(result.segments[i].feed_rate, params.feed_rate * 0.5);
}
}
}
TEST(CamOptimizationTest, HighSpeedMachining_AddsCornerTransitions) {
// 创建有拐角的刀路
Toolpath tp;
tp.name = "CornerTest";
tp.safe_z = 15.0;
PathSegment s1{Point3D(0,0,5), Point3D(10,0,-1),
Point3D::Zero(), PathSegmentType::Linear, 500.0, -1.0};
PathSegment s2{Point3D(10,0,-1), Point3D(10,10,-1),
Point3D::Zero(), PathSegmentType::Linear, 500.0, -1.0}; // 90° 拐角
tp.segments = {s1, s2};
HSMParams params;
params.feed_rate = 2500.0;
params.trochoidal_corners = true;
params.corner_radius = 2.0;
auto result = high_speed_machining(tp, params);
// 拐角过渡应增加段数
EXPECT_GT(result.segments.size(), tp.segments.size());
}
TEST(CamOptimizationTest, HighSpeedMachining_EmptyToolpath) {
Toolpath empty_tp;
HSMParams params;
auto result = high_speed_machining(empty_tp, params);
EXPECT_EQ(result.segments.size(), 0u);
}
// ===========================================================================
// constant_engagement_milling 测试
// ===========================================================================
TEST(CamOptimizationTest, ConstantEngagement_GeneratesSpiral) {
auto box = make_test_box(40, 40, 10);
Tool tool;
tool.diameter = 8.0;
ConstantEngagementParams params;
params.target_engagement = 45.0;
params.step_down = 5.0;
params.safe_z = 15.0;
auto tp = constant_engagement_milling(box, tool, params);
EXPECT_EQ(tp.name, "ConstantEngagement");
EXPECT_GT(tp.segments.size(), 10u) << "Should generate multi-ring spiral";
EXPECT_DOUBLE_EQ(tp.safe_z, 15.0);
}
TEST(CamOptimizationTest, ConstantEngagement_DifferentEngagementAngles) {
auto box = make_test_box(30, 30, 10);
Tool tool;
tool.diameter = 8.0;
ConstantEngagementParams low_eng;
low_eng.target_engagement = 20.0;
low_eng.step_down = 10.0;
ConstantEngagementParams high_eng;
high_eng.target_engagement = 60.0;
high_eng.step_down = 10.0;
auto tp_low = constant_engagement_milling(box, tool, low_eng);
auto tp_high = constant_engagement_milling(box, tool, high_eng);
// 低啮合角 = 更密的螺旋圈 → 更多段
EXPECT_GT(tp_low.segments.size(), 0u);
EXPECT_GT(tp_high.segments.size(), 0u);
// 低啮合角应有更多段(步距更密)
EXPECT_GE(tp_low.segments.size(), tp_high.segments.size() * 0.5);
}
// ===========================================================================
// tool_life_management 测试
// ===========================================================================
TEST(CamOptimizationTest, ToolLifeManagement_ReturnsValidResult) {
Tool tool;
tool.diameter = 10.0;
tool.flutes = 4;
tool.type = ToolType::ENDMILL;
Material mat;
mat.name = "Aluminum";
mat.hardness_brinell = 95.0;
mat.specific_cutting_force = 800.0;
ToolLifeParams params;
params.max_cutting_time_min = 60.0;
params.max_cutting_length_m = 500.0;
auto result = tool_life_management(tool, mat, params);
// 铝合金 → 刀具寿命应较长
EXPECT_GT(result.estimated_life_min, 0);
EXPECT_GT(result.material_removed_mm3, 0);
EXPECT_FALSE(result.needs_replacement);
EXPECT_TRUE(result.warning_message.empty() || !result.needs_replacement);
}
TEST(CamOptimizationTest, ToolLifeManagement_HardMaterialShortLife) {
Tool tool;
tool.diameter = 6.0;
tool.flutes = 2;
tool.type = ToolType::BALLNOSE;
Material steel;
steel.name = "HardenedSteel";
steel.hardness_brinell = 400.0;
steel.specific_cutting_force = 4000.0;
Material aluminum;
aluminum.name = "Aluminum";
aluminum.hardness_brinell = 80.0;
aluminum.specific_cutting_force = 600.0;
ToolLifeParams params;
auto result_steel = tool_life_management(tool, steel, params);
auto result_alum = tool_life_management(tool, aluminum, params);
// 硬材料的寿命应远小于软材料
EXPECT_LT(result_steel.estimated_life_min,
result_alum.estimated_life_min);
}
TEST(CamOptimizationTest, ToolLifeManagement_WearNearLimit) {
Tool tool;
tool.diameter = 8.0;
tool.flutes = 3;
tool.type = ToolType::ENDMILL;
Material mat;
mat.name = "Steel";
mat.hardness_brinell = 250.0;
mat.specific_cutting_force = 2500.0;
// 使用较小的临界磨损值来触发报警
ToolLifeParams params;
params.critical_flank_wear = 0.05; // 非常小的临界值
params.max_cutting_time_min = 120.0;
params.wear_coefficient = 5.0e-5; // 高磨损系数
auto result = tool_life_management(tool, mat, params);
// 应该有磨损量记录
EXPECT_GT(result.accumulated_wear_mm, 0);
EXPECT_GT(result.current_flank_wear, 0);
}