fix: SDF nan/edge cases + B-Rep vertex index → ID fix + IGES 1-based DE + STEP cleanup
This commit is contained in:
@@ -142,8 +142,11 @@ struct GradResult {
|
||||
{
|
||||
double rho = std::sqrt(p.x() * p.x() + p.z() * p.z());
|
||||
if (rho < 1e-30) {
|
||||
// On the Y axis: gradient points radially outward in XZ plane
|
||||
return Vector3D(0.0, (p.y() >= 0.0 ? 1.0 : -1.0), 0.0);
|
||||
// On the Y axis: x and z gradients are 0 by symmetry;
|
||||
// y gradient = py / sqrt(major² + py²)
|
||||
double inner = std::sqrt(major_r * major_r + p.y() * p.y());
|
||||
if (inner < 1e-30) return Vector3D::Zero();
|
||||
return Vector3D(0.0, p.y() / inner, 0.0);
|
||||
}
|
||||
double inner = std::sqrt((rho - major_r) * (rho - major_r) + p.y() * p.y());
|
||||
if (inner < 1e-30) return Vector3D::Zero();
|
||||
@@ -209,11 +212,11 @@ struct GradResult {
|
||||
return (d1 > d2) ? grad_a : grad_b;
|
||||
}
|
||||
|
||||
/// Gradient after difference: max(-d1, d2)
|
||||
/// Gradient after difference: max(d1, -d2)
|
||||
[[nodiscard]] inline Vector3D chain_difference(const Vector3D& grad_a, const Vector3D& grad_b,
|
||||
double d1, double d2)
|
||||
{
|
||||
return (-d1 > d2) ? Vector3D(-grad_a.x(), -grad_a.y(), -grad_a.z()) : grad_b;
|
||||
return (d1 > -d2) ? grad_a : Vector3D(-grad_b.x(), -grad_b.y(), -grad_b.z());
|
||||
}
|
||||
|
||||
/// Gradient after smooth union with full chain rule
|
||||
@@ -222,7 +225,7 @@ struct GradResult {
|
||||
double d1, double d2, double k)
|
||||
{
|
||||
if (k <= 0.0) return chain_union(grad_a, grad_b, d1, d2);
|
||||
double h = std::clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
||||
double h = std::clamp(0.5 + 0.5 * (d1 - d2) / k, 0.0, 1.0);
|
||||
if (h <= 0.0) return grad_a;
|
||||
if (h >= 1.0) return grad_b;
|
||||
|
||||
|
||||
@@ -19,25 +19,25 @@ using core::Vector3D;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline double op_difference(double d1, double d2) {
|
||||
return std::max(-d1, d2);
|
||||
return std::max(d1, -d2);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline double op_smooth_union(double d1, double d2, double k) {
|
||||
if (k <= 0.0) return std::min(d1, d2);
|
||||
double h = std::clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
||||
double h = std::clamp(0.5 + 0.5 * (d1 - d2) / k, 0.0, 1.0);
|
||||
return d1 * (1.0 - h) + d2 * h - k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline double op_smooth_intersection(double d1, double d2, double k) {
|
||||
if (k <= 0.0) return std::max(d1, d2);
|
||||
double h = std::clamp(0.5 - 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
||||
double h = std::clamp(0.5 - 0.5 * (d1 - d2) / k, 0.0, 1.0);
|
||||
return d1 * (1.0 - h) + d2 * h + k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline double op_smooth_difference(double d1, double d2, double k) {
|
||||
if (k <= 0.0) return std::max(-d1, d2);
|
||||
if (k <= 0.0) return std::max(d1, -d2);
|
||||
double h = std::clamp(0.5 - 0.5 * (d2 + d1) / k, 0.0, 1.0);
|
||||
return (-d1) * (1.0 - h) + d2 * h + k * h * (1.0 - h);
|
||||
return d1 * (1.0 - h) + (-d2) * h + k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
// ── Modifiers (operate on a distance value) ──
|
||||
@@ -47,7 +47,7 @@ using core::Vector3D;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline double op_onion(double d, double thickness) {
|
||||
return std::abs(d) - thickness;
|
||||
return std::abs(d) - thickness * 0.5;
|
||||
}
|
||||
|
||||
// ── Domain deformation operators (transform point space) ──
|
||||
|
||||
@@ -46,7 +46,12 @@ using core::Vector3D;
|
||||
[[nodiscard]] inline double capsule(const Point3D& p, const Point3D& a, const Point3D& b, double radius) {
|
||||
Point3D pa = p - a;
|
||||
Point3D ba = b - a;
|
||||
double h = std::clamp(pa.dot(ba) / ba.squaredNorm(), 0.0, 1.0);
|
||||
double ba_sq = ba.squaredNorm();
|
||||
if (ba_sq < 1e-30) {
|
||||
// Degenerate to sphere
|
||||
return pa.norm() - radius;
|
||||
}
|
||||
double h = std::clamp(pa.dot(ba) / ba_sq, 0.0, 1.0);
|
||||
return (pa - ba * h).norm() - radius;
|
||||
}
|
||||
|
||||
@@ -75,6 +80,10 @@ using core::Vector3D;
|
||||
double k1 = Point3D(p.x() / (radii.x() * radii.x()),
|
||||
p.y() / (radii.y() * radii.y()),
|
||||
p.z() / (radii.z() * radii.z())).norm();
|
||||
if (k1 < 1e-30) {
|
||||
// Degenerate: point at origin → distance = -min(radii)
|
||||
return -std::min({radii.x(), radii.y(), radii.z()});
|
||||
}
|
||||
return k0 * (k0 - 1.0) / k1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user