From a7060abfc34873e035d95f4e8a0b5aac0548b618 Mon Sep 17 00:00:00 2001 From: Emmett Lalish Date: Tue, 22 Oct 2024 14:04:12 -0700 Subject: [PATCH] update tolerance defaults --- src/impl.cpp | 6 ++++-- src/impl.h | 4 ++-- src/manifold.cpp | 8 ++++++-- src/quickhull.cpp | 2 +- src/sort.cpp | 29 +++++++++++++++++------------ src/utils.h | 1 + test/test_main.cpp | 11 +++++------ 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/impl.cpp b/src/impl.cpp index a887e57a7..ff0687941 100644 --- a/src/impl.cpp +++ b/src/impl.cpp @@ -571,9 +571,11 @@ Manifold::Impl Manifold::Impl::Transform(const mat3x4& transform_) const { * Sets the precision based on the bounding box, and limits its minimum value * by the optional input. */ -void Manifold::Impl::SetEpsilon(double minEpsilon) { +void Manifold::Impl::SetEpsilon(double minEpsilon, bool useSingle) { epsilon_ = MaxEpsilon(minEpsilon, bBox_); - tolerance_ = std::max(tolerance_, epsilon_); + double minTol = epsilon_; + if (useSingle) minTol = std::max(minTol, kFloatTolerance * bBox_.Scale()); + tolerance_ = std::max(tolerance_, minTol); } /** diff --git a/src/impl.h b/src/impl.h index f8671cef4..8e9023082 100644 --- a/src/impl.h +++ b/src/impl.h @@ -202,7 +202,7 @@ struct Manifold::Impl { MarkFailure(Error::NonFiniteVertex); return; } - SetEpsilon(); + SetEpsilon(-1, std::is_same::value); SplitPinchedVerts(); @@ -277,7 +277,7 @@ struct Manifold::Impl { void CalculateBBox(); bool IsFinite() const; bool IsIndexInBounds(VecView triVerts) const; - void SetEpsilon(double minEpsilon = -1); + void SetEpsilon(double minEpsilon = -1, bool useSingle = false); bool IsManifold() const; bool Is2Manifold() const; bool MatchesTriNormals() const; diff --git a/src/manifold.cpp b/src/manifold.cpp index 565437436..de38ea807 100644 --- a/src/manifold.cpp +++ b/src/manifold.cpp @@ -71,8 +71,12 @@ MeshGLP GetMeshGLImpl(const manifold::Manifold::Impl& impl, MeshGLP out; out.numProp = 3 + numProp; - out.tolerance = std::max(std::numeric_limits::epsilon(), - static_cast(impl.tolerance_)); + out.tolerance = impl.tolerance_; + if (std::is_same::value) + out.tolerance = + std::max(out.tolerance, + static_cast(std::numeric_limits::epsilon() * + impl.bBox_.Scale())); out.triVerts.resize(3 * numTri); const int numHalfedge = impl.halfedgeTangent_.size(); diff --git a/src/quickhull.cpp b/src/quickhull.cpp index 8c4dc6a0d..6e20d8c97 100644 --- a/src/quickhull.cpp +++ b/src/quickhull.cpp @@ -847,7 +847,7 @@ void Manifold::Impl::Hull(VecView vertPos) { QuickHull qh(vertPos); std::tie(halfedge_, vertPos_) = qh.buildMesh(); CalculateBBox(); - SetEpsilon(bBox_.Scale() * kTolerance); + SetEpsilon(); CalculateNormals(); InitializeOriginal(); Finish(); diff --git a/src/sort.cpp b/src/sort.cpp index 1ef2f6c25..2f070bfa2 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -143,25 +143,30 @@ bool MergeMeshGLP(MeshGLP& mesh) { bBox.min[i] = minMax.first; bBox.max[i] = minMax.second; } - auto epsilon = MaxEpsilon(0, bBox); + + const double tolerance = std::max( + static_cast(mesh.tolerance), + (std::is_same::value ? kFloatTolerance : kTolerance) * + bBox.Scale()); + auto policy = autoPolicy(numOpenVert, 1e5); Vec vertBox(numOpenVert); Vec vertMorton(numOpenVert); - for_each_n( - policy, countAt(0), numOpenVert, - [&vertMorton, &vertBox, &openVerts, &bBox, &mesh, epsilon](const int i) { - int vert = openVerts[i]; + for_each_n(policy, countAt(0), numOpenVert, + [&vertMorton, &vertBox, &openVerts, &bBox, &mesh, + tolerance](const int i) { + int vert = openVerts[i]; - const vec3 center(mesh.vertProperties[mesh.numProp * vert], - mesh.vertProperties[mesh.numProp * vert + 1], - mesh.vertProperties[mesh.numProp * vert + 2]); + const vec3 center(mesh.vertProperties[mesh.numProp * vert], + mesh.vertProperties[mesh.numProp * vert + 1], + mesh.vertProperties[mesh.numProp * vert + 2]); - vertBox[i].min = center - epsilon / 2.0; - vertBox[i].max = center + epsilon / 2.0; + vertBox[i].min = center - tolerance / 2.0; + vertBox[i].max = center + tolerance / 2.0; - vertMorton[i] = MortonCode(center, bBox); - }); + vertMorton[i] = MortonCode(center, bBox); + }); Vec vertNew2Old(numOpenVert); sequence(vertNew2Old.begin(), vertNew2Old.end()); diff --git a/src/utils.h b/src/utils.h index f3e84a919..58f395d58 100644 --- a/src/utils.h +++ b/src/utils.h @@ -69,6 +69,7 @@ namespace manifold { } constexpr double kTolerance = 1e-12; +constexpr double kFloatTolerance = 1e-6; inline int Next3(int i) { constexpr ivec3 next3(1, 2, 0); diff --git a/test/test_main.cpp b/test/test_main.cpp index cda4be654..b313d0a34 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -300,10 +300,6 @@ void RelatedGL(const Manifold& out, const std::vector& originals, const ivec3 normalIdx = updateNormals ? ivec3(3, 4, 5) : ivec3(0); MeshGL output = out.GetMeshGL(normalIdx); - float epsilon = std::max(static_cast(out.GetEpsilon()), - std::numeric_limits::epsilon() * - static_cast(out.BoundingBox().Scale())); - for (size_t run = 0; run < output.runOriginalID.size(); ++run) { const float* m = output.runTransform.data() + 12 * run; const mat3x4 transform = @@ -318,6 +314,9 @@ void RelatedGL(const Manifold& out, const std::vector& originals, } ASSERT_LT(i, originals.size()); const MeshGL& inMesh = originals[i]; + const float tolerance = + std::max(static_cast(out.GetTolerance()), inMesh.tolerance); + for (uint32_t tri = output.runIndex[run] / 3; tri < output.runIndex[run + 1] / 3; ++tri) { if (!output.faceID.empty()) { @@ -355,7 +354,7 @@ void RelatedGL(const Manifold& out, const std::vector& originals, vec3 edges[3]; for (int k : {0, 1, 2}) edges[k] = inTriPos[k] - outTriPos[j]; const double volume = la::dot(edges[0], la::cross(edges[1], edges[2])); - ASSERT_LE(volume, area * epsilon); + ASSERT_LE(volume, area * tolerance); if (checkNormals) { vec3 normal; @@ -378,7 +377,7 @@ void RelatedGL(const Manifold& out, const std::vector& originals, const double volumeP = la::dot(edgesP[0], la::cross(edgesP[1], edgesP[2])); - ASSERT_LE(volumeP, area * epsilon); + ASSERT_LE(volumeP, area * tolerance); } } }