From de64d3f411cd2d17f5fc0b5df8f334f3881934dc Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Mon, 23 Mar 2026 16:55:15 +0000 Subject: [PATCH] Modeling - Enhance GeomHash classes with configurable tolerances (#1169) - Added `CompTolerance` and `HashTolerance` fields + constructors to many specific hashers (3D + 2D). - Updated composite/poly hashers (`GeomHash_CurveHasher`, `GeomHash_SurfaceHasher`, `Geom2dHash_CurveHasher`) to carry tolerances and pass them through to nested hashers. - Replaced hardcoded tolerances (previously `1e-12`) with the new tolerance members throughout hashing and comparison logic. --- .../Geom2dHash/Geom2dHash_AxisPlacement.pxx | 19 ++- .../Geom2dHash_BSplineCurveHasher.pxx | 19 ++- .../Geom2dHash_BezierCurveHasher.pxx | 17 +- .../Geom2dHash/Geom2dHash_CircleHasher.pxx | 21 ++- .../Geom2dHash/Geom2dHash_CurveHasher.cxx | 115 +++++++++----- .../Geom2dHash/Geom2dHash_CurveHasher.hxx | 7 + .../Geom2dHash/Geom2dHash_DirectionHasher.pxx | 19 ++- .../Geom2dHash/Geom2dHash_EllipseHasher.pxx | 23 ++- .../Geom2dHash/Geom2dHash_HyperbolaHasher.pxx | 24 ++- .../Geom2dHash/Geom2dHash_LineHasher.pxx | 19 ++- .../Geom2dHash_OffsetCurveHasher.pxx | 22 ++- .../Geom2dHash/Geom2dHash_ParabolaHasher.pxx | 21 ++- .../Geom2dHash/Geom2dHash_PointHasher.pxx | 19 ++- .../Geom2dHash_TrimmedCurveHasher.pxx | 24 ++- .../TKG3d/GeomHash/GeomHash_AxisPlacement.pxx | 19 ++- .../GeomHash/GeomHash_BSplineCurveHasher.pxx | 19 ++- .../GeomHash_BSplineSurfaceHasher.pxx | 21 ++- .../GeomHash/GeomHash_BezierCurveHasher.pxx | 17 +- .../GeomHash/GeomHash_BezierSurfaceHasher.pxx | 17 +- .../TKG3d/GeomHash/GeomHash_CircleHasher.pxx | 21 ++- .../GeomHash_ConicalSurfaceHasher.pxx | 23 ++- .../TKG3d/GeomHash/GeomHash_CurveHasher.cxx | 113 ++++++++----- .../TKG3d/GeomHash/GeomHash_CurveHasher.hxx | 7 + .../GeomHash_CylindricalSurfaceHasher.pxx | 21 ++- .../GeomHash/GeomHash_DirectionHasher.pxx | 21 ++- .../TKG3d/GeomHash/GeomHash_EllipseHasher.pxx | 23 ++- .../GeomHash/GeomHash_HyperbolaHasher.pxx | 24 ++- .../TKG3d/GeomHash/GeomHash_LineHasher.pxx | 19 ++- .../GeomHash/GeomHash_OffsetCurveHasher.pxx | 26 +-- .../GeomHash/GeomHash_OffsetSurfaceHasher.pxx | 22 ++- .../GeomHash/GeomHash_ParabolaHasher.pxx | 21 ++- .../TKG3d/GeomHash/GeomHash_PlaneHasher.pxx | 15 +- .../TKG3d/GeomHash/GeomHash_PointHasher.pxx | 21 ++- ...omHash_RectangularTrimmedSurfaceHasher.pxx | 24 ++- .../GeomHash_SphericalSurfaceHasher.pxx | 21 ++- .../TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx | 150 ++++++++++-------- .../TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx | 7 + ...eomHash_SurfaceOfLinearExtrusionHasher.pxx | 19 ++- .../GeomHash_SurfaceOfRevolutionHasher.pxx | 23 ++- .../GeomHash_ToroidalSurfaceHasher.pxx | 23 ++- .../GeomHash/GeomHash_TrimmedCurveHasher.pxx | 24 ++- .../TKG3d/GeomHash/GeomHash_VectorHasher.pxx | 21 ++- 42 files changed, 800 insertions(+), 351 deletions(-) diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_AxisPlacement.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_AxisPlacement.pxx index d5592e3557..ccd344d49b 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_AxisPlacement.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_AxisPlacement.pxx @@ -18,16 +18,27 @@ #include #include #include +#include //! OCCT-style hasher for gp_Ax22d (2D coordinate system). //! Used for geometry deduplication. struct Geom2dHash_AxisPlacement { + double CompTolerance; + double HashTolerance; + + Geom2dHash_AxisPlacement(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes a 2D axis placement by its location, X direction, and Y direction. std::size_t operator()(const gp_Ax22d& theAxisPlacement) const noexcept { - const Geom2dHash_PointHasher aPointHasher; - const Geom2dHash_DirectionHasher aDirHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const Geom2dHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = {aPointHasher(theAxisPlacement.Location()), aDirHasher(theAxisPlacement.XDirection()), @@ -39,8 +50,8 @@ struct Geom2dHash_AxisPlacement bool operator()(const gp_Ax22d& theAxisPlacement1, const gp_Ax22d& theAxisPlacement2) const noexcept { - const Geom2dHash_PointHasher aPointHasher; - const Geom2dHash_DirectionHasher aDirHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const Geom2dHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); return aPointHasher(theAxisPlacement1.Location(), theAxisPlacement2.Location()) && aDirHasher(theAxisPlacement1.XDirection(), theAxisPlacement2.XDirection()) diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BSplineCurveHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BSplineCurveHasher.pxx index 8e6c6fc5b7..3427ea3896 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BSplineCurveHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BSplineCurveHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_BSplineCurve (2D B-spline curve). //! Used for geometry deduplication. //! Hashes only metadata (degree, pole count, knot count, rationality) for efficiency. struct Geom2dHash_BSplineCurveHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_BSplineCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the B-spline curve metadata only. std::size_t operator()(const occ::handle& theCurve) const noexcept { @@ -38,8 +49,6 @@ struct Geom2dHash_BSplineCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theCurve1->Degree() != theCurve2->Degree()) { @@ -55,7 +64,7 @@ struct Geom2dHash_BSplineCurveHasher // Compare knots and multiplicities for (int i = 1; i <= theCurve1->NbKnots(); ++i) { - if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > aTolerance + if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > CompTolerance || theCurve1->Multiplicity(i) != theCurve2->Multiplicity(i)) { return false; @@ -68,7 +77,7 @@ struct Geom2dHash_BSplineCurveHasher return false; } - const Geom2dHash_PointHasher aPointHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theCurve1->NbPoles(); ++i) @@ -84,7 +93,7 @@ struct Geom2dHash_BSplineCurveHasher { for (int i = 1; i <= theCurve1->NbPoles(); ++i) { - if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance) + if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BezierCurveHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BezierCurveHasher.pxx index 1cd8ebf631..418ad60b47 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BezierCurveHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_BezierCurveHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_BezierCurve (2D Bezier curve). //! Used for geometry deduplication. //! Hashes only metadata (degree, pole count, rationality) for efficiency. struct Geom2dHash_BezierCurveHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_BezierCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the Bezier curve metadata only. std::size_t operator()(const occ::handle& theCurve) const noexcept { @@ -37,8 +48,6 @@ struct Geom2dHash_BezierCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theCurve1->Degree() != theCurve2->Degree()) { @@ -51,7 +60,7 @@ struct Geom2dHash_BezierCurveHasher return false; } - const Geom2dHash_PointHasher aPointHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theCurve1->NbPoles(); ++i) @@ -67,7 +76,7 @@ struct Geom2dHash_BezierCurveHasher { for (int i = 1; i <= theCurve1->NbPoles(); ++i) { - if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance) + if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CircleHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CircleHasher.pxx index 063f95d064..c8504e2a9f 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CircleHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CircleHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_Circle (2D circle). //! Used for geometry deduplication. struct Geom2dHash_CircleHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_CircleHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the circle by its position and radius. std::size_t operator()(const occ::handle& theCircle) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theCircle->Position()), opencascade::hash(static_cast(std::round(theCircle->Radius() * aFactor)))}; @@ -40,11 +50,10 @@ struct Geom2dHash_CircleHasher bool operator()(const occ::handle& theCircle1, const occ::handle& theCircle2) const noexcept { - constexpr double aTolerance = 1e-12; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theCircle1->Position(), theCircle2->Position()) - && std::abs(theCircle1->Radius() - theCircle2->Radius()) <= aTolerance; + && std::abs(theCircle1->Radius() - theCircle2->Radius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx index e238b65958..ad78b49c6f 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx @@ -37,6 +37,14 @@ //================================================================================================= +Geom2dHash_CurveHasher::Geom2dHash_CurveHasher(double theCompTolerance, double theHashTolerance) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) +{ +} + +//================================================================================================= + std::size_t Geom2dHash_CurveHasher::operator()( const occ::handle& theCurve) const noexcept { @@ -45,46 +53,56 @@ std::size_t Geom2dHash_CurveHasher::operator()( return 0; } - // Dispatch based on actual curve type - if (occ::handle aLine = occ::down_cast(theCurve)) + // Dispatch based on actual curve type using DynamicType check first (cheaper than down_cast) + const Handle(Standard_Type)& aType = theCurve->DynamicType(); + if (aType == STANDARD_TYPE(Geom2d_Line)) { - return Geom2dHash_LineHasher{}(aLine); + return Geom2dHash_LineHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aCircle = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_Circle)) { - return Geom2dHash_CircleHasher{}(aCircle); + return Geom2dHash_CircleHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle anEllipse = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_Ellipse)) { - return Geom2dHash_EllipseHasher{}(anEllipse); + return Geom2dHash_EllipseHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aHyperbola = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_Hyperbola)) { - return Geom2dHash_HyperbolaHasher{}(aHyperbola); + return Geom2dHash_HyperbolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aParabola = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_Parabola)) { - return Geom2dHash_ParabolaHasher{}(aParabola); + return Geom2dHash_ParabolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aBezier = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_BezierCurve)) { - return Geom2dHash_BezierCurveHasher{}(aBezier); + return Geom2dHash_BezierCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve)); } - if (occ::handle aBSpline = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve)) { - return Geom2dHash_BSplineCurveHasher{}(aBSpline); + return Geom2dHash_BSplineCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve)); } - if (occ::handle aTrimmed = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_TrimmedCurve)) { - return Geom2dHash_TrimmedCurveHasher{}(aTrimmed); + return Geom2dHash_TrimmedCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve)); } - if (occ::handle anOffset = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom2d_OffsetCurve)) { - return Geom2dHash_OffsetCurveHasher{}(anOffset); + return Geom2dHash_OffsetCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve)); } // Unknown curve type - hash the type name - return Standard_CStringHasher{}(theCurve->DynamicType()->Name()); + return Standard_CStringHasher{}(aType->Name()); } //================================================================================================= @@ -108,42 +126,61 @@ bool Geom2dHash_CurveHasher::operator()(const occ::handle& theCurv return false; } - // Dispatch based on actual curve type - if (occ::handle aLine1 = occ::down_cast(theCurve1)) + // Dispatch based on actual curve type using DynamicType check (already confirmed types match) + const Handle(Standard_Type)& aType = theCurve1->DynamicType(); + if (aType == STANDARD_TYPE(Geom2d_Line)) { - return Geom2dHash_LineHasher{}(aLine1, occ::down_cast(theCurve2)); + return Geom2dHash_LineHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aCircle1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_Circle)) { - return Geom2dHash_CircleHasher{}(aCircle1, occ::down_cast(theCurve2)); + return Geom2dHash_CircleHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle anEllipse1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_Ellipse)) { - return Geom2dHash_EllipseHasher{}(anEllipse1, occ::down_cast(theCurve2)); + return Geom2dHash_EllipseHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aHyp1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_Hyperbola)) { - return Geom2dHash_HyperbolaHasher{}(aHyp1, occ::down_cast(theCurve2)); + return Geom2dHash_HyperbolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aPar1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_Parabola)) { - return Geom2dHash_ParabolaHasher{}(aPar1, occ::down_cast(theCurve2)); + return Geom2dHash_ParabolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aBez1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_BezierCurve)) { - return Geom2dHash_BezierCurveHasher{}(aBez1, occ::down_cast(theCurve2)); + return Geom2dHash_BezierCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aBSpl1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve)) { - return Geom2dHash_BSplineCurveHasher{}(aBSpl1, occ::down_cast(theCurve2)); + return Geom2dHash_BSplineCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aTrim1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_TrimmedCurve)) { - return Geom2dHash_TrimmedCurveHasher{}(aTrim1, occ::down_cast(theCurve2)); + return Geom2dHash_TrimmedCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aOff1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom2d_OffsetCurve)) { - return Geom2dHash_OffsetCurveHasher{}(aOff1, occ::down_cast(theCurve2)); + return Geom2dHash_OffsetCurveHasher{CompTolerance, HashTolerance}( + occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } // Unknown curve type - compare by pointer diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx index 9fbe3e46a2..a6cd5974cd 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx @@ -16,6 +16,7 @@ #include #include +#include class Geom2d_Curve; @@ -23,6 +24,12 @@ class Geom2d_Curve; //! Used for geometry deduplication. struct Geom2dHash_CurveHasher { + double CompTolerance; + double HashTolerance; + + Standard_EXPORT Geom2dHash_CurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()); + // Hashes any Geom2d_Curve by dispatching to the appropriate specific hasher. Standard_EXPORT std::size_t operator()(const occ::handle& theCurve) const noexcept; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_DirectionHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_DirectionHasher.pxx index 86e73a7700..2de2aa19db 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_DirectionHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_DirectionHasher.pxx @@ -17,16 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for gp_Dir2d (2D directions). //! Used for geometry deduplication. struct Geom2dHash_DirectionHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_DirectionHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the 2D direction by its XY components. std::size_t operator()(const gp_Dir2d& theDirection) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; // Round each component to tolerance precision before hashing const std::size_t aHashes[2] = { @@ -38,9 +48,8 @@ struct Geom2dHash_DirectionHasher // Compares two 2D directions with fixed tolerance. bool operator()(const gp_Dir2d& theDirection1, const gp_Dir2d& theDirection2) const noexcept { - constexpr double aTolerance = 1e-12; - return std::abs(theDirection1.X() - theDirection2.X()) <= aTolerance - && std::abs(theDirection1.Y() - theDirection2.Y()) <= aTolerance; + return std::abs(theDirection1.X() - theDirection2.X()) <= CompTolerance + && std::abs(theDirection1.Y() - theDirection2.Y()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_EllipseHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_EllipseHasher.pxx index 23867220f7..87cbed062e 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_EllipseHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_EllipseHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_Ellipse (2D ellipse). //! Used for geometry deduplication. struct Geom2dHash_EllipseHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_EllipseHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the ellipse by its position, major radius, and minor radius. std::size_t operator()(const occ::handle& theEllipse) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theEllipse->Position()), opencascade::hash(static_cast(std::round(theEllipse->MajorRadius() * aFactor))), @@ -41,12 +51,11 @@ struct Geom2dHash_EllipseHasher bool operator()(const occ::handle& theEllipse1, const occ::handle& theEllipse2) const noexcept { - constexpr double aTolerance = 1e-12; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theEllipse1->Position(), theEllipse2->Position()) - && std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= aTolerance - && std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= aTolerance; + && std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= CompTolerance + && std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_HyperbolaHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_HyperbolaHasher.pxx index 73999ecfb6..38f149c93d 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_HyperbolaHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_HyperbolaHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_Hyperbola (2D hyperbola). //! Used for geometry deduplication. struct Geom2dHash_HyperbolaHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_HyperbolaHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the hyperbola by its position, major radius, and minor radius. std::size_t operator()(const occ::handle& theHyperbola) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theHyperbola->Position()), opencascade::hash(static_cast(std::round(theHyperbola->MajorRadius() * aFactor))), @@ -41,12 +51,12 @@ struct Geom2dHash_HyperbolaHasher bool operator()(const occ::handle& theHyperbola1, const occ::handle& theHyperbola2) const noexcept { - constexpr double aTolerance = 1e-12; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theHyperbola1->Position(), theHyperbola2->Position()) - && std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= aTolerance - && std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) <= aTolerance; + && std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= CompTolerance + && std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) + <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx index 5321120886..d734c69804 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx @@ -18,16 +18,27 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_Line (2D line). //! Used for geometry deduplication. struct Geom2dHash_LineHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_LineHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the line by its location and direction. std::size_t operator()(const occ::handle& theLine) const noexcept { - const Geom2dHash_PointHasher aPointHasher; - const Geom2dHash_DirectionHasher aDirHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const Geom2dHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = {aPointHasher(theLine->Position().Location()), aDirHasher(theLine->Position().Direction())}; @@ -38,8 +49,8 @@ struct Geom2dHash_LineHasher bool operator()(const occ::handle& theLine1, const occ::handle& theLine2) const noexcept { - const Geom2dHash_PointHasher aPointHasher; - const Geom2dHash_DirectionHasher aDirHasher; + const Geom2dHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const Geom2dHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); return aPointHasher(theLine1->Position().Location(), theLine2->Position().Location()) && aDirHasher(theLine1->Position().Direction(), theLine2->Position().Direction()); diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_OffsetCurveHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_OffsetCurveHasher.pxx index ebb41a335d..9c77bc539e 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_OffsetCurveHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_OffsetCurveHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_OffsetCurve (2D offset curve). //! Used for geometry deduplication. struct Geom2dHash_OffsetCurveHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_OffsetCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the offset curve by its offset distance and basis curve. std::size_t operator()(const occ::handle& theCurve) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_CurveHasher aCurveHasher; + const Geom2dHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[2] = { aCurveHasher(theCurve->BasisCurve()), opencascade::hash(static_cast(std::round(theCurve->Offset() * aFactor)))}; @@ -40,12 +50,10 @@ struct Geom2dHash_OffsetCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - - const Geom2dHash_CurveHasher aCurveHasher; + const Geom2dHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve()) - && std::abs(theCurve1->Offset() - theCurve2->Offset()) <= aTolerance; + && std::abs(theCurve1->Offset() - theCurve2->Offset()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_ParabolaHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_ParabolaHasher.pxx index a564a3dbeb..f61d347534 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_ParabolaHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_ParabolaHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_Parabola (2D parabola). //! Used for geometry deduplication. struct Geom2dHash_ParabolaHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_ParabolaHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the parabola by its position and focal length. std::size_t operator()(const occ::handle& theParabola) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theParabola->Position()), opencascade::hash(static_cast(std::round(theParabola->Focal() * aFactor)))}; @@ -40,11 +50,10 @@ struct Geom2dHash_ParabolaHasher bool operator()(const occ::handle& theParabola1, const occ::handle& theParabola2) const noexcept { - constexpr double aTolerance = 1e-12; - const Geom2dHash_AxisPlacement anAxisHasher; + const Geom2dHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theParabola1->Position(), theParabola2->Position()) - && std::abs(theParabola1->Focal() - theParabola2->Focal()) <= aTolerance; + && std::abs(theParabola1->Focal() - theParabola2->Focal()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx index 12b31c1e56..12af184dac 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx @@ -17,16 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for gp_Pnt2d (2D points). //! Used for geometry deduplication. struct Geom2dHash_PointHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_PointHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the 2D point by its XY coordinates. std::size_t operator()(const gp_Pnt2d& thePoint) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; // Round each coordinate to tolerance precision before hashing const std::size_t aHashes[2] = { @@ -38,9 +48,8 @@ struct Geom2dHash_PointHasher // Compares two 2D points with fixed tolerance. bool operator()(const gp_Pnt2d& thePoint1, const gp_Pnt2d& thePoint2) const noexcept { - constexpr double aTolerance = 1e-12; - return std::abs(thePoint1.X() - thePoint2.X()) <= aTolerance - && std::abs(thePoint1.Y() - thePoint2.Y()) <= aTolerance; + return std::abs(thePoint1.X() - thePoint2.X()) <= CompTolerance + && std::abs(thePoint1.Y() - thePoint2.Y()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_TrimmedCurveHasher.pxx b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_TrimmedCurveHasher.pxx index 7104488c3b..e62e04fddd 100644 --- a/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_TrimmedCurveHasher.pxx +++ b/src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_TrimmedCurveHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom2d_TrimmedCurve (2D trimmed curve). //! Used for geometry deduplication. struct Geom2dHash_TrimmedCurveHasher { + double CompTolerance; + double HashTolerance; + + Geom2dHash_TrimmedCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the trimmed curve by its parameters and basis curve. std::size_t operator()(const occ::handle& theCurve) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const Geom2dHash_CurveHasher aCurveHasher; + const Geom2dHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[3] = { aCurveHasher(theCurve->BasisCurve()), opencascade::hash(static_cast(std::round(theCurve->FirstParameter() * aFactor))), @@ -41,13 +51,11 @@ struct Geom2dHash_TrimmedCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - - const Geom2dHash_CurveHasher aCurveHasher; + const Geom2dHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve()) - && std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= aTolerance - && std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= aTolerance; + && std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= CompTolerance + && std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx index c7174b0b1b..1b178725d4 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx @@ -18,17 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for gp_Ax2 (axis placement). //! Used for geometry deduplication. //! Compositional hasher using PointHasher and DirectionHasher. struct GeomHash_AxisPlacement { + double CompTolerance; + double HashTolerance; + + GeomHash_AxisPlacement(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the axis placement by location, axis direction, and X direction. std::size_t operator()(const gp_Ax2& theAxisPlacement) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirectionHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirectionHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = {aPointHasher(theAxisPlacement.Location()), aDirectionHasher(theAxisPlacement.Direction()), @@ -40,8 +51,8 @@ struct GeomHash_AxisPlacement // Compares two axis placements. bool operator()(const gp_Ax2& theAxisPlacement1, const gp_Ax2& theAxisPlacement2) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirectionHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirectionHasher(CompTolerance, HashTolerance); return aPointHasher(theAxisPlacement1.Location(), theAxisPlacement2.Location()) && aDirectionHasher(theAxisPlacement1.Direction(), theAxisPlacement2.Direction()) diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineCurveHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineCurveHasher.pxx index a1e27ae13c..e1a95914bd 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineCurveHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineCurveHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom_BSplineCurve (3D B-spline curve). //! Used for geometry deduplication. //! Hashes only metadata (degree, pole count, knot count, rationality) for efficiency. struct GeomHash_BSplineCurveHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_BSplineCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the B-spline curve metadata only. std::size_t operator()(const occ::handle& theCurve) const noexcept { @@ -38,8 +49,6 @@ struct GeomHash_BSplineCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theCurve1->Degree() != theCurve2->Degree()) { @@ -55,7 +64,7 @@ struct GeomHash_BSplineCurveHasher // Compare knots and multiplicities for (int i = 1; i <= theCurve1->NbKnots(); ++i) { - if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > aTolerance + if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > CompTolerance || theCurve1->Multiplicity(i) != theCurve2->Multiplicity(i)) { return false; @@ -68,7 +77,7 @@ struct GeomHash_BSplineCurveHasher return false; } - const GeomHash_PointHasher aPointHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theCurve1->NbPoles(); ++i) @@ -84,7 +93,7 @@ struct GeomHash_BSplineCurveHasher { for (int i = 1; i <= theCurve1->NbPoles(); ++i) { - if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance) + if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineSurfaceHasher.pxx index 1ee05c86ac..4c5c07910b 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_BSplineSurfaceHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom_BSplineSurface. //! Used for geometry deduplication. //! Hashes only metadata (degrees, pole counts, knot counts, rationality) for efficiency. struct GeomHash_BSplineSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_BSplineSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the B-spline surface metadata only. std::size_t operator()(const occ::handle& theSurface) const noexcept { @@ -43,8 +54,6 @@ struct GeomHash_BSplineSurfaceHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theSurface1->UDegree() != theSurface2->UDegree() || theSurface1->VDegree() != theSurface2->VDegree()) @@ -62,7 +71,7 @@ struct GeomHash_BSplineSurfaceHasher // Compare U knots and multiplicities for (int i = 1; i <= theSurface1->NbUKnots(); ++i) { - if (std::abs(theSurface1->UKnot(i) - theSurface2->UKnot(i)) > aTolerance + if (std::abs(theSurface1->UKnot(i) - theSurface2->UKnot(i)) > CompTolerance || theSurface1->UMultiplicity(i) != theSurface2->UMultiplicity(i)) { return false; @@ -72,7 +81,7 @@ struct GeomHash_BSplineSurfaceHasher // Compare V knots and multiplicities for (int i = 1; i <= theSurface1->NbVKnots(); ++i) { - if (std::abs(theSurface1->VKnot(i) - theSurface2->VKnot(i)) > aTolerance + if (std::abs(theSurface1->VKnot(i) - theSurface2->VKnot(i)) > CompTolerance || theSurface1->VMultiplicity(i) != theSurface2->VMultiplicity(i)) { return false; @@ -86,7 +95,7 @@ struct GeomHash_BSplineSurfaceHasher return false; } - const GeomHash_PointHasher aPointHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theSurface1->NbUPoles(); ++i) @@ -107,7 +116,7 @@ struct GeomHash_BSplineSurfaceHasher { for (int j = 1; j <= theSurface1->NbVPoles(); ++j) { - if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > aTolerance) + if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierCurveHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierCurveHasher.pxx index 065229f60d..1a3602919f 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierCurveHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierCurveHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom_BezierCurve (3D Bezier curve). //! Used for geometry deduplication. //! Hashes only metadata (degree, pole count, rationality) for efficiency. struct GeomHash_BezierCurveHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_BezierCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the Bezier curve metadata only. std::size_t operator()(const occ::handle& theCurve) const noexcept { @@ -37,8 +48,6 @@ struct GeomHash_BezierCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theCurve1->Degree() != theCurve2->Degree()) { @@ -51,7 +60,7 @@ struct GeomHash_BezierCurveHasher return false; } - const GeomHash_PointHasher aPointHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theCurve1->NbPoles(); ++i) @@ -67,7 +76,7 @@ struct GeomHash_BezierCurveHasher { for (int i = 1; i <= theCurve1->NbPoles(); ++i) { - if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance) + if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierSurfaceHasher.pxx index d57a6fd63d..c8d2f4d7f5 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_BezierSurfaceHasher.pxx @@ -18,12 +18,23 @@ #include #include #include +#include //! OCCT-style hasher for Geom_BezierSurface. //! Used for geometry deduplication. //! Hashes only metadata (degrees, pole counts, rationality) for efficiency. struct GeomHash_BezierSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_BezierSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the Bezier surface metadata only. std::size_t operator()(const occ::handle& theSurface) const noexcept { @@ -41,8 +52,6 @@ struct GeomHash_BezierSurfaceHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - constexpr double aTolerance = 1e-12; - // Compare degrees if (theSurface1->UDegree() != theSurface2->UDegree() || theSurface1->VDegree() != theSurface2->VDegree()) @@ -57,7 +66,7 @@ struct GeomHash_BezierSurfaceHasher return false; } - const GeomHash_PointHasher aPointHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); // Compare poles for (int i = 1; i <= theSurface1->NbUPoles(); ++i) @@ -78,7 +87,7 @@ struct GeomHash_BezierSurfaceHasher { for (int j = 1; j <= theSurface1->NbVPoles(); ++j) { - if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > aTolerance) + if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > CompTolerance) { return false; } diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx index 4ce9479c6c..b43d873518 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Circle (3D circle). //! Used for geometry deduplication. struct GeomHash_CircleHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_CircleHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the circle by its position and radius. std::size_t operator()(const occ::handle& theCircle) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theCircle->Position()), opencascade::hash(static_cast(std::round(theCircle->Radius() * aFactor)))}; @@ -40,11 +50,10 @@ struct GeomHash_CircleHasher bool operator()(const occ::handle& theCircle1, const occ::handle& theCircle2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theCircle1->Position(), theCircle2->Position()) - && std::abs(theCircle1->Radius() - theCircle2->Radius()) <= aTolerance; + && std::abs(theCircle1->Radius() - theCircle2->Radius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_ConicalSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_ConicalSurfaceHasher.pxx index 663340923c..f0022c70b0 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_ConicalSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_ConicalSurfaceHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_ConicalSurface. //! Used for geometry deduplication. struct GeomHash_ConicalSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_ConicalSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the cone by its position, apex radius, and semi-angle. std::size_t operator()(const occ::handle& theCone) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theCone->Position().Ax2()), opencascade::hash(static_cast(std::round(theCone->RefRadius() * aFactor))), @@ -41,11 +51,10 @@ struct GeomHash_ConicalSurfaceHasher bool operator()(const occ::handle& theCone1, const occ::handle& theCone2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theCone1->Position().Ax2(), theCone2->Position().Ax2()) - && std::abs(theCone1->RefRadius() - theCone2->RefRadius()) <= aTolerance - && std::abs(theCone1->SemiAngle() - theCone2->SemiAngle()) <= aTolerance; + && std::abs(theCone1->RefRadius() - theCone2->RefRadius()) <= CompTolerance + && std::abs(theCone1->SemiAngle() - theCone2->SemiAngle()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx index e91fa37601..c9327b08ec 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx @@ -37,6 +37,14 @@ //================================================================================================= +GeomHash_CurveHasher::GeomHash_CurveHasher(double theCompTolerance, double theHashTolerance) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) +{ +} + +//================================================================================================= + std::size_t GeomHash_CurveHasher::operator()(const occ::handle& theCurve) const noexcept { if (theCurve.IsNull()) @@ -44,46 +52,55 @@ std::size_t GeomHash_CurveHasher::operator()(const occ::handle& theC return 0; } - // Dispatch based on actual curve type - if (occ::handle aLine = occ::down_cast(theCurve)) + // Dispatch based on actual curve type using DynamicType check first (cheaper than down_cast) + const Handle(Standard_Type)& aType = theCurve->DynamicType(); + if (aType == STANDARD_TYPE(Geom_Line)) { - return GeomHash_LineHasher{}(aLine); + return GeomHash_LineHasher{CompTolerance, HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aCircle = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_Circle)) { - return GeomHash_CircleHasher{}(aCircle); + return GeomHash_CircleHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle anEllipse = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_Ellipse)) { - return GeomHash_EllipseHasher{}(anEllipse); + return GeomHash_EllipseHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aHyperbola = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_Hyperbola)) { - return GeomHash_HyperbolaHasher{}(aHyperbola); + return GeomHash_HyperbolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aParabola = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_Parabola)) { - return GeomHash_ParabolaHasher{}(aParabola); + return GeomHash_ParabolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aBezier = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_BezierCurve)) { - return GeomHash_BezierCurveHasher{}(aBezier); + return GeomHash_BezierCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aBSpline = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_BSplineCurve)) { - return GeomHash_BSplineCurveHasher{}(aBSpline); + return GeomHash_BSplineCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle aTrimmed = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_TrimmedCurve)) { - return GeomHash_TrimmedCurveHasher{}(aTrimmed); + return GeomHash_TrimmedCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } - if (occ::handle anOffset = occ::down_cast(theCurve)) + else if (aType == STANDARD_TYPE(Geom_OffsetCurve)) { - return GeomHash_OffsetCurveHasher{}(anOffset); + return GeomHash_OffsetCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve)); } // Unknown curve type - hash the type name - return Standard_CStringHasher{}(theCurve->DynamicType()->Name()); + return Standard_CStringHasher{}(aType->Name()); } //================================================================================================= @@ -107,42 +124,60 @@ bool GeomHash_CurveHasher::operator()(const occ::handle& theCurve1, return false; } - // Dispatch based on actual curve type - if (occ::handle aLine1 = occ::down_cast(theCurve1)) + // Dispatch based on actual curve type using DynamicType check (already confirmed types match) + const Handle(Standard_Type)& aType = theCurve1->DynamicType(); + if (aType == STANDARD_TYPE(Geom_Line)) { - return GeomHash_LineHasher{}(aLine1, occ::down_cast(theCurve2)); + return GeomHash_LineHasher{CompTolerance, HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aCircle1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_Circle)) { - return GeomHash_CircleHasher{}(aCircle1, occ::down_cast(theCurve2)); + return GeomHash_CircleHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle anEllipse1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_Ellipse)) { - return GeomHash_EllipseHasher{}(anEllipse1, occ::down_cast(theCurve2)); + return GeomHash_EllipseHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aHyp1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_Hyperbola)) { - return GeomHash_HyperbolaHasher{}(aHyp1, occ::down_cast(theCurve2)); + return GeomHash_HyperbolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aPar1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_Parabola)) { - return GeomHash_ParabolaHasher{}(aPar1, occ::down_cast(theCurve2)); + return GeomHash_ParabolaHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aBez1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_BezierCurve)) { - return GeomHash_BezierCurveHasher{}(aBez1, occ::down_cast(theCurve2)); + return GeomHash_BezierCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aBSpl1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_BSplineCurve)) { - return GeomHash_BSplineCurveHasher{}(aBSpl1, occ::down_cast(theCurve2)); + return GeomHash_BSplineCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aTrim1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_TrimmedCurve)) { - return GeomHash_TrimmedCurveHasher{}(aTrim1, occ::down_cast(theCurve2)); + return GeomHash_TrimmedCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } - if (occ::handle aOff1 = occ::down_cast(theCurve1)) + else if (aType == STANDARD_TYPE(Geom_OffsetCurve)) { - return GeomHash_OffsetCurveHasher{}(aOff1, occ::down_cast(theCurve2)); + return GeomHash_OffsetCurveHasher{CompTolerance, + HashTolerance}(occ::down_cast(theCurve1), + occ::down_cast(theCurve2)); } // Unknown curve type - compare by pointer diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx index 1e43da0c60..074cdd48ee 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx @@ -16,6 +16,7 @@ #include #include +#include class Geom_Curve; @@ -23,6 +24,12 @@ class Geom_Curve; //! Used for geometry deduplication. struct GeomHash_CurveHasher { + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_CurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()); + // Hashes any Geom_Curve by dispatching to the appropriate specific hasher. Standard_EXPORT std::size_t operator()(const occ::handle& theCurve) const noexcept; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_CylindricalSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_CylindricalSurfaceHasher.pxx index 983a5c8692..9a37920bcb 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_CylindricalSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_CylindricalSurfaceHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_CylindricalSurface. //! Used for geometry deduplication. struct GeomHash_CylindricalSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_CylindricalSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the cylinder by its position and radius. std::size_t operator()(const occ::handle& theCylinder) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theCylinder->Position().Ax2()), opencascade::hash(static_cast(std::round(theCylinder->Radius() * aFactor)))}; @@ -40,10 +50,9 @@ struct GeomHash_CylindricalSurfaceHasher bool operator()(const occ::handle& theCylinder1, const occ::handle& theCylinder2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theCylinder1->Position().Ax2(), theCylinder2->Position().Ax2()) - && std::abs(theCylinder1->Radius() - theCylinder2->Radius()) <= aTolerance; + && std::abs(theCylinder1->Radius() - theCylinder2->Radius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx index 561b0e639b..e33c97a77a 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx @@ -17,16 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for gp_Dir (3D directions). //! Used for geometry deduplication. struct GeomHash_DirectionHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_DirectionHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the 3D direction by its XYZ components. std::size_t operator()(const gp_Dir& theDirection) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; // Round each component to tolerance precision before hashing const std::size_t aHashes[3] = { @@ -39,10 +49,9 @@ struct GeomHash_DirectionHasher // Compares two 3D directions with fixed tolerance. bool operator()(const gp_Dir& theDirection1, const gp_Dir& theDirection2) const noexcept { - constexpr double aTolerance = 1e-12; - return std::abs(theDirection1.X() - theDirection2.X()) <= aTolerance - && std::abs(theDirection1.Y() - theDirection2.Y()) <= aTolerance - && std::abs(theDirection1.Z() - theDirection2.Z()) <= aTolerance; + return std::abs(theDirection1.X() - theDirection2.X()) <= CompTolerance + && std::abs(theDirection1.Y() - theDirection2.Y()) <= CompTolerance + && std::abs(theDirection1.Z() - theDirection2.Z()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx index 61507f36b1..14a19b73a0 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Ellipse (3D ellipse). //! Used for geometry deduplication. struct GeomHash_EllipseHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_EllipseHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the ellipse by its position, major radius, and minor radius. std::size_t operator()(const occ::handle& theEllipse) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theEllipse->Position()), opencascade::hash(static_cast(std::round(theEllipse->MajorRadius() * aFactor))), @@ -41,12 +51,11 @@ struct GeomHash_EllipseHasher bool operator()(const occ::handle& theEllipse1, const occ::handle& theEllipse2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theEllipse1->Position(), theEllipse2->Position()) - && std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= aTolerance - && std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= aTolerance; + && std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= CompTolerance + && std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx index f0749f55f9..27856e6d9c 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Hyperbola (3D hyperbola). //! Used for geometry deduplication. struct GeomHash_HyperbolaHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_HyperbolaHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the hyperbola by its position, major radius, and minor radius. std::size_t operator()(const occ::handle& theHyperbola) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theHyperbola->Position()), opencascade::hash(static_cast(std::round(theHyperbola->MajorRadius() * aFactor))), @@ -41,12 +51,12 @@ struct GeomHash_HyperbolaHasher bool operator()(const occ::handle& theHyperbola1, const occ::handle& theHyperbola2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theHyperbola1->Position(), theHyperbola2->Position()) - && std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= aTolerance - && std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) <= aTolerance; + && std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= CompTolerance + && std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) + <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx index 743e3403fe..0fcd0d412b 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx @@ -18,16 +18,27 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Line (3D line). //! Used for geometry deduplication. struct GeomHash_LineHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_LineHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the line by its location and direction. std::size_t operator()(const occ::handle& theLine) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = {aPointHasher(theLine->Position().Location()), aDirHasher(theLine->Position().Direction())}; @@ -38,8 +49,8 @@ struct GeomHash_LineHasher bool operator()(const occ::handle& theLine1, const occ::handle& theLine2) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); return aPointHasher(theLine1->Position().Location(), theLine2->Position().Location()) && aDirHasher(theLine1->Position().Direction(), theLine2->Position().Direction()); diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetCurveHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetCurveHasher.pxx index 719ccb0145..6959be2f3c 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetCurveHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetCurveHasher.pxx @@ -19,19 +19,29 @@ #include #include #include +#include //! OCCT-style hasher for Geom_OffsetCurve (3D offset curve). //! Used for geometry deduplication. struct GeomHash_OffsetCurveHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_OffsetCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the offset curve by its offset distance, direction, and basis curve. std::size_t operator()(const occ::handle& theCurve) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[3] = { aCurveHasher(theCurve->BasisCurve()), opencascade::hash(static_cast(std::round(theCurve->Offset() * aFactor))), @@ -43,13 +53,11 @@ struct GeomHash_OffsetCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve()) - && std::abs(theCurve1->Offset() - theCurve2->Offset()) <= aTolerance + && std::abs(theCurve1->Offset() - theCurve2->Offset()) <= CompTolerance && aDirHasher(theCurve1->Direction(), theCurve2->Direction()); } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetSurfaceHasher.pxx index 0d26cb0dd1..94ed029e14 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_OffsetSurfaceHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_OffsetSurface. //! Used for geometry deduplication. struct GeomHash_OffsetSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_OffsetSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the offset surface by its offset distance and basis surface. std::size_t operator()(const occ::handle& theSurface) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_SurfaceHasher aSurfaceHasher; + const GeomHash_SurfaceHasher aSurfaceHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[2] = { aSurfaceHasher(theSurface->BasisSurface()), opencascade::hash(static_cast(std::round(theSurface->Offset() * aFactor)))}; @@ -40,12 +50,10 @@ struct GeomHash_OffsetSurfaceHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - constexpr double aTolerance = 1e-12; - - const GeomHash_SurfaceHasher aSurfaceHasher; + const GeomHash_SurfaceHasher aSurfaceHasher{CompTolerance, HashTolerance}; return aSurfaceHasher(theSurface1->BasisSurface(), theSurface2->BasisSurface()) - && std::abs(theSurface1->Offset() - theSurface2->Offset()) <= aTolerance; + && std::abs(theSurface1->Offset() - theSurface2->Offset()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx index f8a1bf62a0..ca5036a7d6 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Parabola (3D parabola). //! Used for geometry deduplication. struct GeomHash_ParabolaHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_ParabolaHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the parabola by its position and focal length. std::size_t operator()(const occ::handle& theParabola) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theParabola->Position()), opencascade::hash(static_cast(std::round(theParabola->Focal() * aFactor)))}; @@ -40,11 +50,10 @@ struct GeomHash_ParabolaHasher bool operator()(const occ::handle& theParabola1, const occ::handle& theParabola2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theParabola1->Position(), theParabola2->Position()) - && std::abs(theParabola1->Focal() - theParabola2->Focal()) <= aTolerance; + && std::abs(theParabola1->Focal() - theParabola2->Focal()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx index 115b15c78e..6631909896 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx @@ -17,15 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for Geom_Plane surfaces. //! Used for geometry deduplication. struct GeomHash_PlaneHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_PlaneHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the plane by its position (location, normal, reference direction). std::size_t operator()(const occ::handle& thePlane) const noexcept { - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(thePlane->Position().Ax2()); } @@ -33,7 +44,7 @@ struct GeomHash_PlaneHasher bool operator()(const occ::handle& thePlane1, const occ::handle& thePlane2) const noexcept { - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(thePlane1->Position().Ax2(), thePlane2->Position().Ax2()); } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx index d7d9cf087e..edc8a24c0f 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx @@ -17,16 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for gp_Pnt (3D points). //! Used for geometry deduplication. struct GeomHash_PointHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_PointHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the 3D point by its XYZ coordinates. std::size_t operator()(const gp_Pnt& thePoint) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; // Round each coordinate to tolerance precision before hashing const std::size_t aHashes[3] = { @@ -39,10 +49,9 @@ struct GeomHash_PointHasher // Compares two 3D points with fixed tolerance. bool operator()(const gp_Pnt& thePoint1, const gp_Pnt& thePoint2) const noexcept { - constexpr double aTolerance = 1e-12; - return std::abs(thePoint1.X() - thePoint2.X()) <= aTolerance - && std::abs(thePoint1.Y() - thePoint2.Y()) <= aTolerance - && std::abs(thePoint1.Z() - thePoint2.Z()) <= aTolerance; + return std::abs(thePoint1.X() - thePoint2.X()) <= CompTolerance + && std::abs(thePoint1.Y() - thePoint2.Y()) <= CompTolerance + && std::abs(thePoint1.Z() - thePoint2.Z()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_RectangularTrimmedSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_RectangularTrimmedSurfaceHasher.pxx index 51b3775227..515f6abd2c 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_RectangularTrimmedSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_RectangularTrimmedSurfaceHasher.pxx @@ -18,19 +18,29 @@ #include #include #include +#include //! OCCT-style hasher for Geom_RectangularTrimmedSurface. //! Used for geometry deduplication. struct GeomHash_RectangularTrimmedSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_RectangularTrimmedSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the trimmed surface by its trim bounds and basis surface. std::size_t operator()( const occ::handle& theSurface) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_SurfaceHasher aSurfaceHasher; + const GeomHash_SurfaceHasher aSurfaceHasher{CompTolerance, HashTolerance}; double aU1, aU2, aV1, aV2; theSurface->Bounds(aU1, aU2, aV1, aV2); @@ -48,9 +58,7 @@ struct GeomHash_RectangularTrimmedSurfaceHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - constexpr double aTolerance = 1e-12; - - const GeomHash_SurfaceHasher aSurfaceHasher; + const GeomHash_SurfaceHasher aSurfaceHasher{CompTolerance, HashTolerance}; // Compare basis surfaces if (!aSurfaceHasher(theSurface1->BasisSurface(), theSurface2->BasisSurface())) @@ -64,8 +72,8 @@ struct GeomHash_RectangularTrimmedSurfaceHasher theSurface1->Bounds(aU1_1, aU2_1, aV1_1, aV2_1); theSurface2->Bounds(aU1_2, aU2_2, aV1_2, aV2_2); - return std::abs(aU1_1 - aU1_2) <= aTolerance && std::abs(aU2_1 - aU2_2) <= aTolerance - && std::abs(aV1_1 - aV1_2) <= aTolerance && std::abs(aV2_1 - aV2_2) <= aTolerance; + return std::abs(aU1_1 - aU1_2) <= CompTolerance && std::abs(aU2_1 - aU2_2) <= CompTolerance + && std::abs(aV1_1 - aV1_2) <= CompTolerance && std::abs(aV2_1 - aV2_2) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_SphericalSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_SphericalSurfaceHasher.pxx index dc57bc9333..fe0f0efd87 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_SphericalSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_SphericalSurfaceHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_SphericalSurface. //! Used for geometry deduplication. struct GeomHash_SphericalSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_SphericalSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the sphere by its position and radius. std::size_t operator()(const occ::handle& theSphere) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[2] = { anAxisHasher(theSphere->Position().Ax2()), opencascade::hash(static_cast(std::round(theSphere->Radius() * aFactor)))}; @@ -40,10 +50,9 @@ struct GeomHash_SphericalSurfaceHasher bool operator()(const occ::handle& theSphere1, const occ::handle& theSphere2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theSphere1->Position().Ax2(), theSphere2->Position().Ax2()) - && std::abs(theSphere1->Radius() - theSphere2->Radius()) <= aTolerance; + && std::abs(theSphere1->Radius() - theSphere2->Radius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx index 96ededf3e1..7c708bcbdb 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx @@ -41,6 +41,14 @@ //================================================================================================= +GeomHash_SurfaceHasher::GeomHash_SurfaceHasher(double theCompTolerance, double theHashTolerance) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) +{ +} + +//================================================================================================= + std::size_t GeomHash_SurfaceHasher::operator()( const occ::handle& theSurface) const noexcept { @@ -49,59 +57,66 @@ std::size_t GeomHash_SurfaceHasher::operator()( return 0; } - // Dispatch based on actual surface type - if (occ::handle aPlane = occ::down_cast(theSurface)) + // Dispatch based on actual surface type using DynamicType check first (cheaper than down_cast) + const Handle(Standard_Type)& aType = theSurface->DynamicType(); + if (aType == STANDARD_TYPE(Geom_Plane)) { - return GeomHash_PlaneHasher{}(aPlane); + return GeomHash_PlaneHasher{CompTolerance, + HashTolerance}(occ::down_cast(theSurface)); } - if (occ::handle aCylinder = - occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_CylindricalSurface)) { - return GeomHash_CylindricalSurfaceHasher{}(aCylinder); + return GeomHash_CylindricalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aCone = occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_ConicalSurface)) { - return GeomHash_ConicalSurfaceHasher{}(aCone); + return GeomHash_ConicalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aSphere = - occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_SphericalSurface)) { - return GeomHash_SphericalSurfaceHasher{}(aSphere); + return GeomHash_SphericalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aTorus = occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_ToroidalSurface)) { - return GeomHash_ToroidalSurfaceHasher{}(aTorus); + return GeomHash_ToroidalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aRevol = - occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution)) { - return GeomHash_SurfaceOfRevolutionHasher{}(aRevol); + return GeomHash_SurfaceOfRevolutionHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aExtr = - occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) { - return GeomHash_SurfaceOfLinearExtrusionHasher{}(aExtr); + return GeomHash_SurfaceOfLinearExtrusionHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aBezier = occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_BezierSurface)) { - return GeomHash_BezierSurfaceHasher{}(aBezier); + return GeomHash_BezierSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aBSpline = occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_BSplineSurface)) { - return GeomHash_BSplineSurfaceHasher{}(aBSpline); + return GeomHash_BSplineSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aTrimmed = - occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { - return GeomHash_RectangularTrimmedSurfaceHasher{}(aTrimmed); + return GeomHash_RectangularTrimmedSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } - if (occ::handle aOffset = occ::down_cast(theSurface)) + else if (aType == STANDARD_TYPE(Geom_OffsetSurface)) { - return GeomHash_OffsetSurfaceHasher{}(aOffset); + return GeomHash_OffsetSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface)); } // Unknown surface type - hash the type name - return Standard_CStringHasher{}(theSurface->DynamicType()->Name()); + return Standard_CStringHasher{}(aType->Name()); } //================================================================================================= @@ -125,66 +140,73 @@ bool GeomHash_SurfaceHasher::operator()(const occ::handle& theSurf return false; } - // Dispatch based on actual surface type - if (occ::handle aPlane1 = occ::down_cast(theSurface1)) + // Dispatch based on actual surface type using DynamicType check (already confirmed types match) + const Handle(Standard_Type)& aType = theSurface1->DynamicType(); + if (aType == STANDARD_TYPE(Geom_Plane)) { - return GeomHash_PlaneHasher{}(aPlane1, occ::down_cast(theSurface2)); + return GeomHash_PlaneHasher{CompTolerance, + HashTolerance}(occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aCyl1 = - occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_CylindricalSurface)) { - return GeomHash_CylindricalSurfaceHasher{}( - aCyl1, + return GeomHash_CylindricalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), occ::down_cast(theSurface2)); } - if (occ::handle aCone1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_ConicalSurface)) { - return GeomHash_ConicalSurfaceHasher{}(aCone1, - occ::down_cast(theSurface2)); + return GeomHash_ConicalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aSph1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_SphericalSurface)) { - return GeomHash_SphericalSurfaceHasher{}(aSph1, - occ::down_cast(theSurface2)); + return GeomHash_SphericalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aTor1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_ToroidalSurface)) { - return GeomHash_ToroidalSurfaceHasher{}(aTor1, - occ::down_cast(theSurface2)); + return GeomHash_ToroidalSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aRev1 = - occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution)) { - return GeomHash_SurfaceOfRevolutionHasher{}( - aRev1, + return GeomHash_SurfaceOfRevolutionHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), occ::down_cast(theSurface2)); } - if (occ::handle aExt1 = - occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) { - return GeomHash_SurfaceOfLinearExtrusionHasher{}( - aExt1, + return GeomHash_SurfaceOfLinearExtrusionHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), occ::down_cast(theSurface2)); } - if (occ::handle aBez1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_BezierSurface)) { - return GeomHash_BezierSurfaceHasher{}(aBez1, occ::down_cast(theSurface2)); + return GeomHash_BezierSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aBSpl1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_BSplineSurface)) { - return GeomHash_BSplineSurfaceHasher{}(aBSpl1, - occ::down_cast(theSurface2)); + return GeomHash_BSplineSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } - if (occ::handle aTrim1 = - occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { - return GeomHash_RectangularTrimmedSurfaceHasher{}( - aTrim1, + return GeomHash_RectangularTrimmedSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), occ::down_cast(theSurface2)); } - if (occ::handle aOff1 = occ::down_cast(theSurface1)) + else if (aType == STANDARD_TYPE(Geom_OffsetSurface)) { - return GeomHash_OffsetSurfaceHasher{}(aOff1, occ::down_cast(theSurface2)); + return GeomHash_OffsetSurfaceHasher{CompTolerance, HashTolerance}( + occ::down_cast(theSurface1), + occ::down_cast(theSurface2)); } // Unknown surface type - compare by pointer diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx index 8f5c978248..a5f4427f3c 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx @@ -16,6 +16,7 @@ #include #include +#include class Geom_Surface; @@ -23,6 +24,12 @@ class Geom_Surface; //! Used for geometry deduplication. struct GeomHash_SurfaceHasher { + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_SurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()); + // Hashes any Geom_Surface by dispatching to the appropriate specific hasher. Standard_EXPORT std::size_t operator()( const occ::handle& theSurface) const noexcept; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfLinearExtrusionHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfLinearExtrusionHasher.pxx index fcd39c0d4c..a4c49c4e6f 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfLinearExtrusionHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfLinearExtrusionHasher.pxx @@ -18,17 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_SurfaceOfLinearExtrusion. //! Used for geometry deduplication. struct GeomHash_SurfaceOfLinearExtrusionHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_SurfaceOfLinearExtrusionHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the extrusion surface by its direction and basis curve. std::size_t operator()( const occ::handle& theSurface) const noexcept { - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[2] = {aCurveHasher(theSurface->BasisCurve()), aDirHasher(theSurface->Direction())}; return opencascade::hashBytes(aHashes, sizeof(aHashes)); @@ -38,8 +49,8 @@ struct GeomHash_SurfaceOfLinearExtrusionHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; return aCurveHasher(theSurface1->BasisCurve(), theSurface2->BasisCurve()) && aDirHasher(theSurface1->Direction(), theSurface2->Direction()); diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfRevolutionHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfRevolutionHasher.pxx index 2a6c519156..f385923bca 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfRevolutionHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceOfRevolutionHasher.pxx @@ -19,17 +19,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_SurfaceOfRevolution. //! Used for geometry deduplication. struct GeomHash_SurfaceOfRevolutionHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_SurfaceOfRevolutionHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the revolution surface by its axis and basis curve. std::size_t operator()(const occ::handle& theSurface) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const gp_Ax1& anAxis = theSurface->Axis(); const std::size_t aHashes[3] = {aCurveHasher(theSurface->BasisCurve()), @@ -42,9 +53,9 @@ struct GeomHash_SurfaceOfRevolutionHasher bool operator()(const occ::handle& theSurface1, const occ::handle& theSurface2) const noexcept { - const GeomHash_PointHasher aPointHasher; - const GeomHash_DirectionHasher aDirHasher; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_PointHasher aPointHasher(CompTolerance, HashTolerance); + const GeomHash_DirectionHasher aDirHasher(CompTolerance, HashTolerance); + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const gp_Ax1& anAxis1 = theSurface1->Axis(); const gp_Ax1& anAxis2 = theSurface2->Axis(); diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_ToroidalSurfaceHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_ToroidalSurfaceHasher.pxx index 6474adc5e4..b50a7d724f 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_ToroidalSurfaceHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_ToroidalSurfaceHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_ToroidalSurface. //! Used for geometry deduplication. struct GeomHash_ToroidalSurfaceHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_ToroidalSurfaceHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the torus by its position, major radius, and minor radius. std::size_t operator()(const occ::handle& theTorus) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); const std::size_t aHashes[3] = { anAxisHasher(theTorus->Position().Ax2()), opencascade::hash(static_cast(std::round(theTorus->MajorRadius() * aFactor))), @@ -41,11 +51,10 @@ struct GeomHash_ToroidalSurfaceHasher bool operator()(const occ::handle& theTorus1, const occ::handle& theTorus2) const noexcept { - constexpr double aTolerance = 1e-12; - const GeomHash_AxisPlacement anAxisHasher; + const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance); return anAxisHasher(theTorus1->Position().Ax2(), theTorus2->Position().Ax2()) - && std::abs(theTorus1->MajorRadius() - theTorus2->MajorRadius()) <= aTolerance - && std::abs(theTorus1->MinorRadius() - theTorus2->MinorRadius()) <= aTolerance; + && std::abs(theTorus1->MajorRadius() - theTorus2->MajorRadius()) <= CompTolerance + && std::abs(theTorus1->MinorRadius() - theTorus2->MinorRadius()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_TrimmedCurveHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_TrimmedCurveHasher.pxx index 2ea46e7188..25d4d5e846 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_TrimmedCurveHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_TrimmedCurveHasher.pxx @@ -18,18 +18,28 @@ #include #include #include +#include //! OCCT-style hasher for Geom_TrimmedCurve (3D trimmed curve). //! Used for geometry deduplication. struct GeomHash_TrimmedCurveHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_TrimmedCurveHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the trimmed curve by its parameters and basis curve. std::size_t operator()(const occ::handle& theCurve) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; const std::size_t aHashes[3] = { aCurveHasher(theCurve->BasisCurve()), opencascade::hash(static_cast(std::round(theCurve->FirstParameter() * aFactor))), @@ -41,13 +51,11 @@ struct GeomHash_TrimmedCurveHasher bool operator()(const occ::handle& theCurve1, const occ::handle& theCurve2) const noexcept { - constexpr double aTolerance = 1e-12; - - const GeomHash_CurveHasher aCurveHasher; + const GeomHash_CurveHasher aCurveHasher{CompTolerance, HashTolerance}; return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve()) - && std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= aTolerance - && std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= aTolerance; + && std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= CompTolerance + && std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= CompTolerance; } }; diff --git a/src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx b/src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx index b81f0eb0d2..c6a9b28888 100644 --- a/src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx +++ b/src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx @@ -17,16 +17,26 @@ #include #include #include +#include //! OCCT-style hasher for gp_Vec (3D vectors). //! Used for geometry deduplication. struct GeomHash_VectorHasher { + double CompTolerance; + double HashTolerance; + + GeomHash_VectorHasher(double theCompTolerance = Precision::Angular(), + double theHashTolerance = Precision::Confusion()) + : CompTolerance(theCompTolerance), + HashTolerance(theHashTolerance) + { + } + // Hashes the 3D vector by its XYZ components. std::size_t operator()(const gp_Vec& theVector) const noexcept { - constexpr double aTolerance = 1e-12; - constexpr double aFactor = 1.0 / aTolerance; + const double aFactor = 1.0 / HashTolerance; // Round each component to tolerance precision before hashing const std::size_t aHashes[3] = { @@ -39,10 +49,9 @@ struct GeomHash_VectorHasher // Compares two 3D vectors with fixed tolerance. bool operator()(const gp_Vec& theVector1, const gp_Vec& theVector2) const noexcept { - constexpr double aTolerance = 1e-12; - return std::abs(theVector1.X() - theVector2.X()) <= aTolerance - && std::abs(theVector1.Y() - theVector2.Y()) <= aTolerance - && std::abs(theVector1.Z() - theVector2.Z()) <= aTolerance; + return std::abs(theVector1.X() - theVector2.X()) <= CompTolerance + && std::abs(theVector1.Y() - theVector2.Y()) <= CompTolerance + && std::abs(theVector1.Z() - theVector2.Z()) <= CompTolerance; } };