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
285 lines
9.1 KiB
C++
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);
|
|
}
|