152 lines
6.1 KiB
C++
152 lines
6.1 KiB
C++
|
|
#include <gtest/gtest.h>
|
|||
|
|
#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<std::vector<Point3D>> cp = {
|
|||
|
|
{Point3D(0,0,0), Point3D(2,0,0)},
|
|||
|
|
{Point3D(0,2,0), Point3D(2,2,0)}
|
|||
|
|
};
|
|||
|
|
std::vector<double> knots_u = {0, 0, 1, 1};
|
|||
|
|
std::vector<double> knots_v = {0, 0, 1, 1};
|
|||
|
|
std::vector<std::vector<double>> weights = {{1,1},{1,1}};
|
|||
|
|
return NurbsSurface(cp, knots_u, knots_v, weights, 1, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static NurbsSurface make_quadratic_surface() {
|
|||
|
|
std::vector<std::vector<Point3D>> 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<double> knots_u = {0, 0, 0, 1, 1, 1};
|
|||
|
|
std::vector<double> knots_v = {0, 0, 0, 1, 1, 1};
|
|||
|
|
std::vector<std::vector<double>> weights(3, std::vector<double>(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<int>(iga.knots_u.size()) - 1);
|
|||
|
|
int expected_spans_v = std::max(1, static_cast<int>(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<double> 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<int>(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<int>(C.size()), n);
|
|||
|
|
for (const auto& row : C)
|
|||
|
|
EXPECT_EQ(static_cast<int>(row.size()), n);
|
|||
|
|
}
|
|||
|
|
}
|