Files
ViewDesignEngine/tests/curves/test_surface_analysis.cpp
T
茂之钳 73df04d5cb
CI / Build & Test (push) Failing after 35s
CI / Release Build (push) Failing after 1m32s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat(v5-M2): G2/G3 continuity + surface analysis + extension + N-side fill + advanced blend
M2.1 — G2/G3 连续性分析 (Agent #0):
- surface_continuity.h/.cpp: G0/G1/G2/G3 curve/surface detection
- Weingarten equation for curvature, Frénet frame, zebra stripe
- surface_analysis.h/.cpp: curvature_map, deviation_analysis, curvature_comb
- 24 tests (12 continuity + 12 analysis)

M2.2 — 曲面延伸 + N边填充 (Agent #1):
- surface_extension.h/.cpp: extend_surface(G1/G2), n_sided_fill, blend_surfaces
- Coons patch generalization for N-sided holes
- 16/16 tests passed in Docker container

M2.3 — 高级过渡曲面 (Agent #2):
- advanced_blend.h/.cpp: real implementations replacing stubs
- variable_radius_blend, multi_face_blend, rolling_ball_blend, face_face_blend
- Ball-rolling envelope + corner sphere filling
- 15+ tests with validate() verification
2026-07-26 20:58:31 +08:00

182 lines
6.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <gtest/gtest.h>
#include "vde/curves/surface_analysis.h"
#include "vde/curves/nurbs_curve.h"
#include "vde/curves/nurbs_surface.h"
#include "vde/brep/modeling.h"
#include <cmath>
using namespace vde::curves;
using namespace vde::core;
using namespace vde::brep;
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/// Create a planar NURBS surface on XY plane over [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);
}
/// Create a simple NURBS curve (line)
static NurbsCurve line(const Point3D& a, const Point3D& b) {
return NurbsCurve({a, b}, {0, 0, 1, 1}, {1, 1}, 1);
}
/// Create a cubic NURBS curve (parabola-like)
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: CurvatureMap
// ---------------------------------------------------------------------------
TEST(SurfaceAnalysisTest, CurvatureMap_PlaneIsDevelopable) {
auto surf = plane_surface();
auto cm = curvature_map(surf, 20, 20);
EXPECT_EQ(21, static_cast<int>(cm.grid.size()));
EXPECT_EQ(21, static_cast<int>(cm.grid[0].size()));
// Plane: Gaussian curvature ≈ 0, Mean curvature ≈ 0
EXPECT_NEAR(cm.min_gaussian, 0.0, 1e-9);
EXPECT_NEAR(cm.max_gaussian, 0.0, 1e-9);
EXPECT_NEAR(cm.min_mean, 0.0, 1e-9);
EXPECT_NEAR(cm.max_mean, 0.0, 1e-9);
EXPECT_TRUE(cm.is_developable());
}
TEST(SurfaceAnalysisTest, CurvatureMap_GridDimensions) {
auto surf = plane_surface();
auto cm = curvature_map(surf, 5, 8);
EXPECT_EQ(6, static_cast<int>(cm.grid.size())); // res_u+1
EXPECT_EQ(9, static_cast<int>(cm.grid[0].size())); // res_v+1
EXPECT_EQ(5, cm.res_u);
EXPECT_EQ(8, cm.res_v);
}
// ---------------------------------------------------------------------------
// Test: Zebra Stripe
// ---------------------------------------------------------------------------
TEST(SurfaceAnalysisTest, ZebraStripe_OutputDimensions) {
auto surf = plane_surface();
auto zs = zebra_stripe(surf, Vector3D(1, 0, 0), 15, 10);
EXPECT_EQ(16, static_cast<int>(zs.intensity.size()));
EXPECT_EQ(11, static_cast<int>(zs.intensity[0].size()));
EXPECT_EQ(15, zs.res_u);
EXPECT_EQ(10, zs.res_v);
// Check light direction is normalized
EXPECT_NEAR(zs.light_direction.norm(), 1.0, 1e-12);
}
TEST(SurfaceAnalysisTest, ZebraStripe_IntensityRange) {
auto surf = plane_surface();
auto zs = zebra_stripe(surf, Vector3D(0, 0, 1), 10, 10);
for (size_t i = 0; i < zs.intensity.size(); ++i) {
for (size_t j = 0; j < zs.intensity[i].size(); ++j) {
double val = zs.intensity[i][j];
EXPECT_GE(val, 0.0);
EXPECT_LE(val, 1.0);
}
}
}
// ---------------------------------------------------------------------------
// Test: Curvature Comb
// ---------------------------------------------------------------------------
TEST(SurfaceAnalysisTest, CurvatureComb_StraightLine) {
auto c = line(Point3D(0, 0, 0), Point3D(10, 0, 0));
auto comb = curvature_comb(c, 20);
EXPECT_EQ(21, static_cast<int>(comb.points.size()));
// Straight line has zero curvature
EXPECT_NEAR(comb.min_curvature, 0.0, 1e-12);
EXPECT_NEAR(comb.max_curvature, 0.0, 1e-12);
}
TEST(SurfaceAnalysisTest, CurvatureComb_NonzeroCurvature) {
auto c = cubic_curve();
auto comb = curvature_comb(c, 100);
EXPECT_EQ(101, static_cast<int>(comb.points.size()));
// Cubic curve has non-zero curvature
EXPECT_GT(comb.max_curvature, 0.0);
// Scale should be auto-computed
EXPECT_GT(comb.scale, 0.0);
}
// ---------------------------------------------------------------------------
// Test: Deviation Analysis
// ---------------------------------------------------------------------------
TEST(SurfaceAnalysisTest, DeviationAnalysis_IdenticalPlanes) {
auto s1 = plane_surface();
auto s2 = plane_surface();
auto result = deviation_analysis(s1, s2, 10);
EXPECT_EQ(100u, result.sample_count);
// Identical planes: deviation ≈ 0
EXPECT_NEAR(result.rms, 0.0, 1e-6);
EXPECT_NEAR(result.mean_absolute, 0.0, 1e-6);
}
TEST(SurfaceAnalysisTest, DeviationAnalysis_OffsetPlanes) {
auto s1 = plane_surface();
// Same plane shifted up by 1 in Z
std::vector<std::vector<Point3D>> grid2 = {
{Point3D(0,0,1), Point3D(0,1,1)},
{Point3D(1,0,1), Point3D(1,1,1)}
};
auto s2 = NurbsSurface(grid2, {0,0,1,1}, {0,0,1,1},
{{1,1},{1,1}}, 1, 1);
auto result = deviation_analysis(s1, s2, 10);
EXPECT_NEAR(result.max_positive, 1.0, 0.05);
EXPECT_NEAR(result.rms, 1.0, 0.05);
}
// ---------------------------------------------------------------------------
// Test: Draft Face Angle
// ---------------------------------------------------------------------------
TEST(SurfaceAnalysisTest, DraftAngle_HorizontalPlaneVerticalPull) {
auto surf = plane_surface();
// Horizontal plane (normal = +Z), vertical pull (+Z) → angle = -π/2
// (face normal parallel to pull: face is perpendicular to opening)
double angle = draft_face_angle(surf, 0.5, 0.5, Vector3D(0, 0, 1));
EXPECT_NEAR(angle, -M_PI_2, 1e-6);
}
TEST(SurfaceAnalysisTest, DraftAngle_PullPerpendicularToNormal) {
auto surf = plane_surface();
// Horizontal plane (normal = +Z), pull in X → face parallel to pull → angle ≈ 0
double angle = draft_face_angle(surf, 0.5, 0.5, Vector3D(1, 0, 0));
EXPECT_NEAR(angle, 0.0, 1e-6);
}
TEST(SurfaceAnalysisTest, DraftAngle_BrepModel) {
auto box = make_box(10, 10, 10);
// Top face has normal ≈ +Z, pull +Z → angle ≈ -π/2
double angle = draft_face_angle(box, 0, Vector3D(0, 0, 1), 5);
EXPECT_NEAR(std::abs(angle), M_PI_2, 0.01);
}