fix: SDF nan/edge cases + B-Rep vertex index → ID fix + IGES 1-based DE + STEP cleanup
CI / Build & Test (push) Failing after 16m57s
CI / Release Build (push) Failing after 2m59s

This commit is contained in:
茂之钳
2026-07-24 08:42:53 +00:00
parent ebc47a25c9
commit a323776fd3
12 changed files with 139 additions and 70 deletions
+10 -10
View File
@@ -139,8 +139,8 @@ TEST(SdfGradient, EvaluateWithGradientInside) {
GradResult r = evaluate_with_gradient(f, p, FD_H);
EXPECT_NEAR(r.value, -2.0, 1e-9);
// At center, gradient magnitude ≈ 1 (any direction is fine)
EXPECT_NEAR(r.grad.norm(), 1.0, EPS_LOOSE);
// At center, the SDF is non-differentiable; FD gradient ≈ (0,0,0)
EXPECT_LT(r.grad.norm(), 0.01) << "Gradient at exact center should be near-zero (degenerate SDF)";
}
// ═══════════════════════════════════════════════════
@@ -341,22 +341,22 @@ TEST(SdfChain, DifferenceGradient) {
Vector3D gA(1, 0, 0);
Vector3D gB(0, 1, 0);
// d1=0.5 (outside A), d2=-0.3 (inside B). -d1=-0.5 < d2=-0.3 → pick B
// d1=0.5 (outside A), d2=-0.3 (inside B).
// op_difference = max(d1, -d2) = max(0.5, 0.3) = 0.5 → picks grad_a
Vector3D g = chain_difference(gA, gB, 0.5, -0.3);
EXPECT_NEAR(g.y(), 1.0, 1e-9);
EXPECT_NEAR(g.x(), 1.0, 1e-9);
}
TEST(SdfChain, DifferenceNegatesGradA) {
Vector3D gA(1, 0, 0);
Vector3D gB(0, 1, 0);
// A completely outside B: d1=-0.5 (inside A subtracted part), d2=0.5
// -d1 = 0.5, d2 = 0.5. At equal: standard picks second (since op_difference uses >)
// Actually: op_difference = max(-d1, d2). If -d1 > d2, pick -d1 region with -grad_a
// d1=-1.0 (inside body), d2=0.0 (on cutter surface)
// op_difference = max(-1, 0) = 0. d1=-1, -d2=0. -d2 > d1 → pick -grad_b
// -grad_b = (0, -1, 0)
Vector3D g = chain_difference(gA, gB, -1.0, 0.0);
// -d1 = 1.0 > d2 = 0.0 → pick -grad_a
EXPECT_NEAR(g.x(), -1.0, 1e-9);
EXPECT_NEAR(g.y(), 0.0, 1e-9);
EXPECT_NEAR(g.x(), 0.0, 1e-9);
EXPECT_NEAR(g.y(), -1.0, 1e-9);
}
// ═══════════════════════════════════════════════════
+9 -9
View File
@@ -39,11 +39,11 @@ TEST(SdfOperations, Intersection) {
TEST(SdfOperations, Difference) {
// d1 is the body, d2 is the cutter
// difference = max(-d1, d2)
EXPECT_DOUBLE_EQ(op_difference(1.0, 2.0), 2.0); // -d1=-1, max(-1,2)=2
EXPECT_DOUBLE_EQ(op_difference(3.0, 2.0), 2.0); // max(-3,2)=2
EXPECT_DOUBLE_EQ(op_difference(-1.0, 2.0), 2.0); // max(1,2)=2
EXPECT_DOUBLE_EQ(op_difference(2.0, -3.0), -2.0); // max(-2,-3)=-2
// difference = max(d1, -d2)
EXPECT_DOUBLE_EQ(op_difference(1.0, 2.0), 1.0); // max(1,-2)=1
EXPECT_DOUBLE_EQ(op_difference(3.0, 2.0), 3.0); // max(3,-2)=3
EXPECT_DOUBLE_EQ(op_difference(-1.0, 2.0), -1.0); // max(-1,-2)=-1
EXPECT_DOUBLE_EQ(op_difference(2.0, -3.0), 3.0); // max(2,3)=3
}
TEST(SdfOperations, UnionIdentity) {
@@ -96,8 +96,8 @@ TEST(SdfOperations, SmoothIntersectionBlending) {
}
TEST(SdfOperations, SmoothDifferenceFallsBackToSharp) {
EXPECT_DOUBLE_EQ(op_smooth_difference(1.0, 2.0, 0.0), 2.0);
EXPECT_DOUBLE_EQ(op_smooth_difference(-1.0, 2.0, 0.0), 2.0);
EXPECT_DOUBLE_EQ(op_smooth_difference(1.0, 2.0, 0.0), 1.0);
EXPECT_DOUBLE_EQ(op_smooth_difference(-1.0, 2.0, 0.0), -1.0);
}
// ═══════════════════════════════════════════════════
@@ -282,8 +282,8 @@ TEST(SdfOperations, Elongate) {
auto f = Point3D(2.0, 1.0, 0.5);
auto r = op_elongate(Point3D(4, 3, 2), f);
EXPECT_DOUBLE_EQ(r.x(), 2.0);
EXPECT_DOUBLE_EQ(r.y(), 3.0);
EXPECT_DOUBLE_EQ(r.z(), 4.0);
EXPECT_DOUBLE_EQ(r.y(), 2.0);
EXPECT_DOUBLE_EQ(r.z(), 1.5);
}
TEST(SdfOperations, Displace) {
+1 -1
View File
@@ -128,7 +128,7 @@ TEST(SdfOptimize, Accessibility_OnSphere) {
// Point on sphere surface
Point3D surface_point(1.0, 0.0, 0.0);
Vector3D direction(-1.0, 0.0, 0.0); // pointing outward
Vector3D direction(1.0, 0.0, 0.0); // outward normal
double score = accessibility(shape, surface_point, direction, 64);
EXPECT_GT(score, 0.0) << "Should have some accessibility";
+6 -4
View File
@@ -282,7 +282,7 @@ TEST(SdfEllipsoid, OnSurface) {
TEST(SdfTriangularPrism, OnVertex) {
Point3D a(0, 0, 0), b(4, 0, 0), c(2, 3, 0);
double d = triangular_prism(Point3D(0, 0, 0), a, b, c, 2.0);
EXPECT_NEAR(d, -1.0, 1e-6);
EXPECT_NEAR(d, 0.0, 1e-6); // vertex on boundary → SDF = 0
}
TEST(SdfTriangularPrism, Inside) {
@@ -344,10 +344,12 @@ TEST(SdfLink, AtCenterOfFirstTorus) {
}
TEST(SdfLink, BetweenToruses) {
// Point between the two toruses, inside the overlap region
// Point between the two toruses — this is in the torus hole, outside the shape
double d = link(Point3D(0, 0, 0), 2.0, 2.0, 0.5);
// This is inside both toruses, so negative
EXPECT_LT(d, 0.0);
// Point (0,0,0) is in the hole region between the toruses
// With length=2 (centers at ±1), major_r=2, minor_r=0.5:
// distance to each torus tube ≈ 0.5, so the point is outside
EXPECT_GT(d, 0.0);
}
TEST(SdfLink, FarOutside) {
+2 -2
View File
@@ -81,8 +81,8 @@ TEST(SdfTree, UnionSphereBox) {
// Point inside sphere
EXPECT_LT(evaluate(tree, Point3D(0, 0, 0)), 0.0);
// Point inside box (but outside sphere)
EXPECT_LT(evaluate(tree, Point3D(1.2, 0, 0)), 0.0);
// Point inside box (but outside sphere) — box surface at |x|=1
EXPECT_LT(evaluate(tree, Point3D(0.5, 0, 0)), 0.0);
// Point outside both
EXPECT_GT(evaluate(tree, Point3D(3, 0, 0)), 0.0);
}