921c29cb22
v7.1 — B-Rep 深度攻坚 (对标 Parasolid 95%): - advanced_healing: auto_heal_pipeline, face_splitting/merging, topology_optimization - watertight_verification, tolerance_analysis, tolerance diagnostic report - sheet_metal: unfold_sheet_metal (K-Factor/BFS), bend_deduction_table, create_flange - direct_modeling enhanced: draft_face_advanced (hinge), scale_body (non-uniform), mirror_body - 32 tests (17 healing + 15 sheet metal), syntax-check passed v7.2 — Class-A 曲面攻坚 (对标 CGM 95%): - class_a_surfacing: g3_blend (4-row CP), curvature_matching (Levenberg-Marquardt) - highlight_lines, reflection_lines, iso_photes, surface_diagnosis, shape_modification - advanced_intersection: robust_ssi (3-stage: AABB+subdivision→Newton 1e-12→singularity) - curve_surface_intersection, self_intersection_detection (BVH) - 30 tests (18 class-A + 12 intersection), zero compile errors v7.3 — CAM 深化 + 性能优化: - cam_advanced: adaptive_clearing, trochoidal_milling, rest_machining, pencil_tracing - tool_holder_collision_check, toolpath_optimization, feed_rate_optimization - performance_tuning: parallel_task_graph (DAG+Kahn), work_stealing_scheduler - memory_pool_integration, cache_optimization_hints, profile_guided_layout - Fixed BrepModel API compatibility (body.bounds()/to_mesh() instead of .faces()) - 20 tests 12 files, ~5200 lines, 82 tests
226 lines
7.0 KiB
C++
226 lines
7.0 KiB
C++
#include <gtest/gtest.h>
|
||
#include "vde/curves/advanced_intersection.h"
|
||
#include "vde/curves/nurbs_curve.h"
|
||
#include "vde/curves/nurbs_surface.h"
|
||
#include <cmath>
|
||
|
||
using namespace vde::curves;
|
||
using namespace vde::core;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
/// 平面 XY 平面 [0,1]×[0,1]
|
||
static NurbsSurface plane_surface() {
|
||
std::vector<std::vector<Point3D>> grid = {
|
||
{Point3D(0,0,0), Point3D(0,1,0)},
|
||
{Point3D(1,0,0), Point3D(1,1,0)}
|
||
};
|
||
return NurbsSurface(grid, {0,0,1,1}, {0,0,1,1}, {{1,1},{1,1}}, 1, 1);
|
||
}
|
||
|
||
/// 倾斜平面(对角线方向)
|
||
static NurbsSurface tilted_plane() {
|
||
std::vector<std::vector<Point3D>> grid = {
|
||
{Point3D(0,0,0), Point3D(0,1,0.5)},
|
||
{Point3D(1,0,0.5), Point3D(1,1,1)}
|
||
};
|
||
return NurbsSurface(grid, {0,0,1,1}, {0,0,1,1}, {{1,1},{1,1}}, 1, 1);
|
||
}
|
||
|
||
/// 抛物面
|
||
static NurbsSurface quad_surface() {
|
||
std::vector<std::vector<Point3D>> grid = {
|
||
{Point3D(0,0,0), Point3D(0,1,0.5), Point3D(0,2,0)},
|
||
{Point3D(1,0,0.5), Point3D(1,1,1), Point3D(1,2,0.5)},
|
||
{Point3D(2,0,0), Point3D(2,1,0.5), Point3D(2,2,0)}
|
||
};
|
||
return NurbsSurface(grid,
|
||
{0,0,0,1,1,1}, {0,0,0,1,1,1},
|
||
{{1,1,1},{1,1,1},{1,1,1}}, 2, 2);
|
||
}
|
||
|
||
/// 构造简单 NURBS 曲线
|
||
static NurbsCurve line(double x0, double y0, double z0, double x1, double y1, double z1) {
|
||
return NurbsCurve(
|
||
{Point3D(x0, y0, z0), Point3D(x1, y1, z1)},
|
||
{0, 0, 1, 1}, {1, 1}, 1);
|
||
}
|
||
|
||
/// 三次 NURBS 曲线
|
||
static NurbsCurve cubic_curve() {
|
||
return NurbsCurve(
|
||
{Point3D(0,0,0), Point3D(1,2,0), Point3D(2,1,0), Point3D(3,0,0)},
|
||
{0,0,0,0,1,1,1,1}, {1,1,1,1}, 3);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Test: Robust SSI — 鲁棒曲面求交
|
||
// ---------------------------------------------------------------------------
|
||
|
||
TEST(AdvancedIntersectionTest, RobustSSI_NonIntersectingPlanes) {
|
||
auto a = plane_surface();
|
||
// 平面在 Z=5,与 XY 平面无交
|
||
std::vector<std::vector<Point3D>> grid2 = {
|
||
{Point3D(0,0,5), Point3D(0,1,5)},
|
||
{Point3D(1,0,5), Point3D(1,1,5)}
|
||
};
|
||
auto b = NurbsSurface(grid2, {0,0,1,1}, {0,0,1,1}, {{1,1},{1,1}}, 1, 1);
|
||
|
||
SSIOptions opts;
|
||
auto result = robust_ssi(a, b, opts);
|
||
|
||
EXPECT_TRUE(result.success);
|
||
EXPECT_EQ(0u, result.segments.size());
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, RobustSSI_CoincidentPlanes) {
|
||
auto a = plane_surface();
|
||
auto b = plane_surface(); // 完全相同
|
||
|
||
auto result = robust_ssi(a, b);
|
||
|
||
EXPECT_TRUE(result.success);
|
||
// 重合面应检测到交线(可能多个)
|
||
EXPECT_GT(result.phase1_subdivisions, 0);
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, RobustSSI_CrossingPlanes) {
|
||
// XY 平面
|
||
auto a = plane_surface();
|
||
// XZ 平面(法向量为 Y 方向)
|
||
std::vector<std::vector<Point3D>> grid2 = {
|
||
{Point3D(0,0.5,0), Point3D(0,0.5,1)},
|
||
{Point3D(1,0.5,0), Point3D(1,0.5,1)}
|
||
};
|
||
auto b = NurbsSurface(grid2, {0,0,1,1}, {0,0,1,1}, {{1,1},{1,1}}, 1, 1);
|
||
|
||
auto result = robust_ssi(a, b);
|
||
|
||
EXPECT_TRUE(result.success);
|
||
// 两相交平面应有交线
|
||
EXPECT_GT(result.segments.size(), 0u);
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, RobustSSI_PhaseStatistics) {
|
||
auto a = tilted_plane();
|
||
auto b = plane_surface();
|
||
|
||
auto result = robust_ssi(a, b);
|
||
|
||
// 阶段统计应合理
|
||
EXPECT_GE(result.phase1_subdivisions, 0);
|
||
EXPECT_GE(result.phase2_converged + result.phase2_diverged,
|
||
static_cast<int>(result.segments.size()));
|
||
EXPECT_GE(result.total_time_ms, 0.0);
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, RobustSSI_NewtonPrecision) {
|
||
auto a = tilted_plane();
|
||
auto b = plane_surface();
|
||
|
||
SSIOptions opts;
|
||
opts.newton_tolerance = 1e-10;
|
||
opts.max_newton_iter = 25;
|
||
|
||
auto result = robust_ssi(a, b, opts);
|
||
|
||
// 检查结果精度
|
||
for (const auto& seg : result.segments) {
|
||
for (size_t i = 0; i < seg.points.size(); ++i) {
|
||
auto pa = a.evaluate(seg.params_a[i].first, seg.params_a[i].second);
|
||
auto pb = b.evaluate(seg.params_b[i].first, seg.params_b[i].second);
|
||
EXPECT_LT((pa - pb).norm(), 1e-4);
|
||
}
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Test: Curve-Surface Intersection — 曲线-曲面求交
|
||
// ---------------------------------------------------------------------------
|
||
|
||
TEST(AdvancedIntersectionTest, CurveSurfaceIntersection_LineThroughPlane) {
|
||
auto surf = plane_surface();
|
||
auto curve = line(0.5, 0.5, -1, 0.5, 0.5, 2); // 垂直穿过的线
|
||
|
||
auto pts = curve_surface_intersection(curve, surf);
|
||
|
||
// 应检测到1个交点
|
||
EXPECT_GE(pts.size(), 1u);
|
||
if (!pts.empty()) {
|
||
EXPECT_NEAR(pts[0].position.z(), 0.0, 1e-4);
|
||
}
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, CurveSurfaceIntersection_LineParallelToPlane) {
|
||
auto surf = plane_surface();
|
||
// 平行于 XY 平面的线(在 z=5 处)
|
||
auto curve = line(0, 0, 5, 1, 1, 5);
|
||
|
||
auto pts = curve_surface_intersection(curve, surf);
|
||
|
||
// 平行线不应有交点(除非重合)
|
||
for (const auto& p : pts) {
|
||
EXPECT_NEAR(p.position.z(), 5.0, 1e-3);
|
||
}
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, CurveSurfaceIntersection_SortedByT) {
|
||
auto surf = quad_surface();
|
||
// 斜穿曲面的线(应在多处相交)
|
||
auto curve = line(0.5, 0.5, -1, 1.5, 1.5, 2);
|
||
|
||
auto pts = curve_surface_intersection(curve, surf);
|
||
|
||
// 交点应按 t 排序
|
||
for (size_t i = 1; i < pts.size(); ++i) {
|
||
EXPECT_GE(pts[i].t, pts[i-1].t);
|
||
}
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, CurveSurfaceIntersection_TangentContact) {
|
||
auto surf = plane_surface();
|
||
// 在平面内的线
|
||
auto curve = line(0, 0, 0, 1, 1, 0);
|
||
|
||
auto pts = curve_surface_intersection(curve, surf);
|
||
|
||
// 平面内的线可能有切线接触
|
||
// (实现可能返回多个交点或标记为切线)
|
||
for (const auto& p : pts) {
|
||
EXPECT_NEAR(p.distance, 0.0, 1e-8);
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Test: Self-Intersection Detection — 自交检测
|
||
// ---------------------------------------------------------------------------
|
||
|
||
TEST(AdvancedIntersectionTest, SelfIntersection_PlaneNoSelfIntersection) {
|
||
auto s = plane_surface();
|
||
auto result = self_intersection_detection(s);
|
||
|
||
// 平面不应自交
|
||
EXPECT_FALSE(result.has_self_intersection);
|
||
EXPECT_EQ(0u, result.regions.size());
|
||
EXPECT_GT(result.total_checks, 0);
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, SelfIntersection_QuadSurfaceNoSelfIntersection) {
|
||
auto s = quad_surface();
|
||
auto result = self_intersection_detection(s, 1e-6);
|
||
|
||
// 规则曲面不应自交
|
||
EXPECT_FALSE(result.has_self_intersection);
|
||
EXPECT_GT(result.total_checks, 0);
|
||
}
|
||
|
||
TEST(AdvancedIntersectionTest, SelfIntersection_DetectionTime) {
|
||
auto s = quad_surface();
|
||
auto result = self_intersection_detection(s, 1e-8);
|
||
|
||
EXPECT_GE(result.detection_time_ms, 0.0);
|
||
EXPECT_GT(result.total_checks, 0);
|
||
}
|