#include #include "vde/curves/iga_prep.h" #include "vde/curves/nurbs_surface.h" using namespace vde::curves; // ═══════════════════════════════════════════════════════════ // Helper: create simple NURBS surfaces // ═══════════════════════════════════════════════════════════ static NurbsSurface make_plane_surface() { // 2×2 control points, degree 1×1, flat plane z=0 std::vector> cp = { {Point3D(0,0,0), Point3D(2,0,0)}, {Point3D(0,2,0), Point3D(2,2,0)} }; std::vector knots_u = {0, 0, 1, 1}; std::vector knots_v = {0, 0, 1, 1}; std::vector> weights = {{1,1},{1,1}}; return NurbsSurface(cp, knots_u, knots_v, weights, 1, 1); } static NurbsSurface make_quadratic_surface() { std::vector> cp = { {Point3D(0,0,0), Point3D(1,0,1), Point3D(2,0,0)}, {Point3D(0,1,1), Point3D(1,1,2), Point3D(2,1,1)}, {Point3D(0,2,0), Point3D(1,2,1), Point3D(2,2,0)}, }; std::vector knots_u = {0, 0, 0, 1, 1, 1}; std::vector knots_v = {0, 0, 0, 1, 1, 1}; std::vector> weights(3, std::vector(3, 1.0)); return NurbsSurface(cp, knots_u, knots_v, weights, 2, 2); } // ═══════════════════════════════════════════════════════════ // NURBS → IGA // ═══════════════════════════════════════════════════════════ TEST(IGAPrepTest, NurbsToIgaBasic) { auto surf = make_plane_surface(); IGAMesh iga = nurbs_to_iga(surf); EXPECT_EQ(iga.degree_u, surf.degree_u()); EXPECT_EQ(iga.degree_v, surf.degree_v()); EXPECT_GT(iga.num_elements, 0); EXPECT_FALSE(iga.elements.empty()); } TEST(IGAPrepTest, NurbsToIgaQuadratic) { auto surf = make_quadratic_surface(); IGAMesh iga = nurbs_to_iga(surf); EXPECT_EQ(iga.degree_u, 2); EXPECT_EQ(iga.degree_v, 2); EXPECT_GT(iga.num_elements, 0); for (const auto& el : iga.elements) { EXPECT_GT(el.cp_indices.size(), 0u); EXPECT_FALSE(el.is_degenerate); } } TEST(IGAPrepTest, NurbsToIgaElementCP) { auto surf = make_plane_surface(); IGAMesh iga = nurbs_to_iga(surf); int expected_spans_u = std::max(1, static_cast(iga.knots_u.size()) - 1); int expected_spans_v = std::max(1, static_cast(iga.knots_v.size()) - 1); EXPECT_EQ(iga.num_elements, expected_spans_u * expected_spans_v); } // ═══════════════════════════════════════════════════════════ // 节点插入 // ═══════════════════════════════════════════════════════════ TEST(KnotInsertionTest, BasicInsert) { auto surf = make_plane_surface(); std::vector new_u = {0.5}; auto result = knot_insertion(surf, new_u, {}); EXPECT_EQ(result.new_knots_u.size(), 1u); EXPECT_EQ(result.new_knots_u[0], 0.5); EXPECT_GT(result.old_cp_count, 0); } TEST(KnotInsertionTest, NoKnots) { auto surf = make_plane_surface(); auto result = knot_insertion(surf, {}, {}); EXPECT_EQ(result.new_knots_u.size(), 0u); EXPECT_EQ(result.new_knots_v.size(), 0u); } TEST(KnotInsertionTest, BothDirections) { auto surf = make_plane_surface(); auto result = knot_insertion(surf, {0.33, 0.67}, {0.5}); EXPECT_EQ(result.new_knots_u.size(), 2u); EXPECT_EQ(result.new_knots_v.size(), 1u); } // ═══════════════════════════════════════════════════════════ // 升阶 // ═══════════════════════════════════════════════════════════ TEST(DegreeElevationTest, BasicElevation) { auto surf = make_plane_surface(); auto result = degree_elevation(surf, 1, 1); EXPECT_EQ(result.old_degree_u, 1); EXPECT_EQ(result.old_degree_v, 1); EXPECT_EQ(result.new_degree_u, 2); EXPECT_EQ(result.new_degree_v, 2); } TEST(DegreeElevationTest, NoElevation) { auto surf = make_plane_surface(); auto result = degree_elevation(surf, 0, 0); EXPECT_EQ(result.new_degree_u, result.old_degree_u); EXPECT_EQ(result.new_degree_v, result.old_degree_v); } // ═══════════════════════════════════════════════════════════ // Bézier 提取 // ═══════════════════════════════════════════════════════════ TEST(BezierExtractionTest, PlaneExtraction) { auto surf = make_plane_surface(); auto result = bezier_extraction(surf); EXPECT_EQ(result.degree_u, surf.degree_u()); EXPECT_EQ(result.degree_v, surf.degree_v()); EXPECT_GT(result.num_elements, 0); EXPECT_EQ(static_cast(result.operators.size()), result.num_elements); EXPECT_FALSE(result.cp_coords.empty()); } TEST(BezierExtractionTest, QuadraticExtraction) { auto surf = make_quadratic_surface(); auto result = bezier_extraction(surf); EXPECT_EQ(result.degree_u, 2); EXPECT_EQ(result.degree_v, 2); EXPECT_GT(result.num_elements, 0); if (!result.operators.empty()) { int n = result.degree_u + 1; auto& C = result.operators[0]; EXPECT_EQ(static_cast(C.size()), n); for (const auto& row : C) EXPECT_EQ(static_cast(row.size()), n); } }