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
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);
|
||
}
|
||
}
|