#include #include "vde/curves/advanced_intersection.h" #include "vde/curves/nurbs_curve.h" #include "vde/curves/nurbs_surface.h" #include using namespace vde::curves; using namespace vde::core; // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- /// 平面 XY 平面 [0,1]×[0,1] static NurbsSurface plane_surface() { std::vector> 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> 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> 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> 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> 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(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); }