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.
This commit is contained in:
Pasukhin Dmitry
2026-03-23 16:55:15 +00:00
committed by GitHub
parent 4cdb5a89e5
commit de64d3f411
42 changed files with 800 additions and 351 deletions
@@ -18,16 +18,27 @@
#include <gp_Ax22d.hxx>
#include <Geom2dHash_PointHasher.pxx>
#include <Geom2dHash_DirectionHasher.pxx>
#include <Precision.hxx>
//! 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())
@@ -18,12 +18,23 @@
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2dHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_BSplineCurve>& theCurve) const noexcept
{
@@ -38,8 +49,6 @@ struct Geom2dHash_BSplineCurveHasher
bool operator()(const occ::handle<Geom2d_BSplineCurve>& theCurve1,
const occ::handle<Geom2d_BSplineCurve>& 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;
}
@@ -18,12 +18,23 @@
#include <Geom2d_BezierCurve.hxx>
#include <Geom2dHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_BezierCurve>& theCurve) const noexcept
{
@@ -37,8 +48,6 @@ struct Geom2dHash_BezierCurveHasher
bool operator()(const occ::handle<Geom2d_BezierCurve>& theCurve1,
const occ::handle<Geom2d_BezierCurve>& 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;
}
@@ -18,18 +18,28 @@
#include <Geom2d_Circle.hxx>
#include <Geom2dHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_Circle>& 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<int64_t>(std::round(theCircle->Radius() * aFactor)))};
@@ -40,11 +50,10 @@ struct Geom2dHash_CircleHasher
bool operator()(const occ::handle<Geom2d_Circle>& theCircle1,
const occ::handle<Geom2d_Circle>& 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;
}
};
@@ -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<Geom2d_Curve>& theCurve) const noexcept
{
@@ -45,46 +53,56 @@ std::size_t Geom2dHash_CurveHasher::operator()(
return 0;
}
// Dispatch based on actual curve type
if (occ::handle<Geom2d_Line> aLine = occ::down_cast<Geom2d_Line>(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<Geom2d_Line>(theCurve));
}
if (occ::handle<Geom2d_Circle> aCircle = occ::down_cast<Geom2d_Circle>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_Circle))
{
return Geom2dHash_CircleHasher{}(aCircle);
return Geom2dHash_CircleHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Circle>(theCurve));
}
if (occ::handle<Geom2d_Ellipse> anEllipse = occ::down_cast<Geom2d_Ellipse>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_Ellipse))
{
return Geom2dHash_EllipseHasher{}(anEllipse);
return Geom2dHash_EllipseHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Ellipse>(theCurve));
}
if (occ::handle<Geom2d_Hyperbola> aHyperbola = occ::down_cast<Geom2d_Hyperbola>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_Hyperbola))
{
return Geom2dHash_HyperbolaHasher{}(aHyperbola);
return Geom2dHash_HyperbolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Hyperbola>(theCurve));
}
if (occ::handle<Geom2d_Parabola> aParabola = occ::down_cast<Geom2d_Parabola>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_Parabola))
{
return Geom2dHash_ParabolaHasher{}(aParabola);
return Geom2dHash_ParabolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Parabola>(theCurve));
}
if (occ::handle<Geom2d_BezierCurve> aBezier = occ::down_cast<Geom2d_BezierCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_BezierCurve))
{
return Geom2dHash_BezierCurveHasher{}(aBezier);
return Geom2dHash_BezierCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_BezierCurve>(theCurve));
}
if (occ::handle<Geom2d_BSplineCurve> aBSpline = occ::down_cast<Geom2d_BSplineCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve))
{
return Geom2dHash_BSplineCurveHasher{}(aBSpline);
return Geom2dHash_BSplineCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_BSplineCurve>(theCurve));
}
if (occ::handle<Geom2d_TrimmedCurve> aTrimmed = occ::down_cast<Geom2d_TrimmedCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_TrimmedCurve))
{
return Geom2dHash_TrimmedCurveHasher{}(aTrimmed);
return Geom2dHash_TrimmedCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_TrimmedCurve>(theCurve));
}
if (occ::handle<Geom2d_OffsetCurve> anOffset = occ::down_cast<Geom2d_OffsetCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom2d_OffsetCurve))
{
return Geom2dHash_OffsetCurveHasher{}(anOffset);
return Geom2dHash_OffsetCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_OffsetCurve>(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<Geom2d_Curve>& theCurv
return false;
}
// Dispatch based on actual curve type
if (occ::handle<Geom2d_Line> aLine1 = occ::down_cast<Geom2d_Line>(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<Geom2d_Line>(theCurve2));
return Geom2dHash_LineHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Line>(theCurve1),
occ::down_cast<Geom2d_Line>(theCurve2));
}
if (occ::handle<Geom2d_Circle> aCircle1 = occ::down_cast<Geom2d_Circle>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_Circle))
{
return Geom2dHash_CircleHasher{}(aCircle1, occ::down_cast<Geom2d_Circle>(theCurve2));
return Geom2dHash_CircleHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Circle>(theCurve1),
occ::down_cast<Geom2d_Circle>(theCurve2));
}
if (occ::handle<Geom2d_Ellipse> anEllipse1 = occ::down_cast<Geom2d_Ellipse>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_Ellipse))
{
return Geom2dHash_EllipseHasher{}(anEllipse1, occ::down_cast<Geom2d_Ellipse>(theCurve2));
return Geom2dHash_EllipseHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Ellipse>(theCurve1),
occ::down_cast<Geom2d_Ellipse>(theCurve2));
}
if (occ::handle<Geom2d_Hyperbola> aHyp1 = occ::down_cast<Geom2d_Hyperbola>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_Hyperbola))
{
return Geom2dHash_HyperbolaHasher{}(aHyp1, occ::down_cast<Geom2d_Hyperbola>(theCurve2));
return Geom2dHash_HyperbolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Hyperbola>(theCurve1),
occ::down_cast<Geom2d_Hyperbola>(theCurve2));
}
if (occ::handle<Geom2d_Parabola> aPar1 = occ::down_cast<Geom2d_Parabola>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_Parabola))
{
return Geom2dHash_ParabolaHasher{}(aPar1, occ::down_cast<Geom2d_Parabola>(theCurve2));
return Geom2dHash_ParabolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom2d_Parabola>(theCurve1),
occ::down_cast<Geom2d_Parabola>(theCurve2));
}
if (occ::handle<Geom2d_BezierCurve> aBez1 = occ::down_cast<Geom2d_BezierCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_BezierCurve))
{
return Geom2dHash_BezierCurveHasher{}(aBez1, occ::down_cast<Geom2d_BezierCurve>(theCurve2));
return Geom2dHash_BezierCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_BezierCurve>(theCurve1),
occ::down_cast<Geom2d_BezierCurve>(theCurve2));
}
if (occ::handle<Geom2d_BSplineCurve> aBSpl1 = occ::down_cast<Geom2d_BSplineCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve))
{
return Geom2dHash_BSplineCurveHasher{}(aBSpl1, occ::down_cast<Geom2d_BSplineCurve>(theCurve2));
return Geom2dHash_BSplineCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_BSplineCurve>(theCurve1),
occ::down_cast<Geom2d_BSplineCurve>(theCurve2));
}
if (occ::handle<Geom2d_TrimmedCurve> aTrim1 = occ::down_cast<Geom2d_TrimmedCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_TrimmedCurve))
{
return Geom2dHash_TrimmedCurveHasher{}(aTrim1, occ::down_cast<Geom2d_TrimmedCurve>(theCurve2));
return Geom2dHash_TrimmedCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_TrimmedCurve>(theCurve1),
occ::down_cast<Geom2d_TrimmedCurve>(theCurve2));
}
if (occ::handle<Geom2d_OffsetCurve> aOff1 = occ::down_cast<Geom2d_OffsetCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom2d_OffsetCurve))
{
return Geom2dHash_OffsetCurveHasher{}(aOff1, occ::down_cast<Geom2d_OffsetCurve>(theCurve2));
return Geom2dHash_OffsetCurveHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom2d_OffsetCurve>(theCurve1),
occ::down_cast<Geom2d_OffsetCurve>(theCurve2));
}
// Unknown curve type - compare by pointer
@@ -16,6 +16,7 @@
#include <Standard_Handle.hxx>
#include <cstddef>
#include <Precision.hxx>
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<Geom2d_Curve>& theCurve) const noexcept;
@@ -17,16 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <gp_Dir2d.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom2d_Ellipse.hxx>
#include <Geom2dHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_Ellipse>& 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<int64_t>(std::round(theEllipse->MajorRadius() * aFactor))),
@@ -41,12 +51,11 @@ struct Geom2dHash_EllipseHasher
bool operator()(const occ::handle<Geom2d_Ellipse>& theEllipse1,
const occ::handle<Geom2d_Ellipse>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom2d_Hyperbola.hxx>
#include <Geom2dHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_Hyperbola>& 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<int64_t>(std::round(theHyperbola->MajorRadius() * aFactor))),
@@ -41,12 +51,12 @@ struct Geom2dHash_HyperbolaHasher
bool operator()(const occ::handle<Geom2d_Hyperbola>& theHyperbola1,
const occ::handle<Geom2d_Hyperbola>& 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;
}
};
@@ -18,16 +18,27 @@
#include <Geom2d_Line.hxx>
#include <Geom2dHash_PointHasher.pxx>
#include <Geom2dHash_DirectionHasher.pxx>
#include <Precision.hxx>
//! 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<Geom2d_Line>& 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<Geom2d_Line>& theLine1,
const occ::handle<Geom2d_Line>& 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());
@@ -18,18 +18,28 @@
#include <Geom2d_OffsetCurve.hxx>
#include <Geom2dHash_CurveHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_OffsetCurve>& 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<int64_t>(std::round(theCurve->Offset() * aFactor)))};
@@ -40,12 +50,10 @@ struct Geom2dHash_OffsetCurveHasher
bool operator()(const occ::handle<Geom2d_OffsetCurve>& theCurve1,
const occ::handle<Geom2d_OffsetCurve>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom2d_Parabola.hxx>
#include <Geom2dHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_Parabola>& 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<int64_t>(std::round(theParabola->Focal() * aFactor)))};
@@ -40,11 +50,10 @@ struct Geom2dHash_ParabolaHasher
bool operator()(const occ::handle<Geom2d_Parabola>& theParabola1,
const occ::handle<Geom2d_Parabola>& 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;
}
};
@@ -17,16 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <gp_Pnt2d.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dHash_CurveHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom2d_TrimmedCurve>& 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<int64_t>(std::round(theCurve->FirstParameter() * aFactor))),
@@ -41,13 +51,11 @@ struct Geom2dHash_TrimmedCurveHasher
bool operator()(const occ::handle<Geom2d_TrimmedCurve>& theCurve1,
const occ::handle<Geom2d_TrimmedCurve>& 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;
}
};
@@ -18,17 +18,28 @@
#include <gp_Ax2.hxx>
#include <GeomHash_PointHasher.pxx>
#include <GeomHash_DirectionHasher.pxx>
#include <Precision.hxx>
//! 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())
@@ -18,12 +18,23 @@
#include <Geom_BSplineCurve.hxx>
#include <GeomHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_BSplineCurve>& theCurve) const noexcept
{
@@ -38,8 +49,6 @@ struct GeomHash_BSplineCurveHasher
bool operator()(const occ::handle<Geom_BSplineCurve>& theCurve1,
const occ::handle<Geom_BSplineCurve>& 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;
}
@@ -18,12 +18,23 @@
#include <Geom_BSplineSurface.hxx>
#include <GeomHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_BSplineSurface>& theSurface) const noexcept
{
@@ -43,8 +54,6 @@ struct GeomHash_BSplineSurfaceHasher
bool operator()(const occ::handle<Geom_BSplineSurface>& theSurface1,
const occ::handle<Geom_BSplineSurface>& 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;
}
@@ -18,12 +18,23 @@
#include <Geom_BezierCurve.hxx>
#include <GeomHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_BezierCurve>& theCurve) const noexcept
{
@@ -37,8 +48,6 @@ struct GeomHash_BezierCurveHasher
bool operator()(const occ::handle<Geom_BezierCurve>& theCurve1,
const occ::handle<Geom_BezierCurve>& 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;
}
@@ -18,12 +18,23 @@
#include <Geom_BezierSurface.hxx>
#include <GeomHash_PointHasher.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_BezierSurface>& theSurface) const noexcept
{
@@ -41,8 +52,6 @@ struct GeomHash_BezierSurfaceHasher
bool operator()(const occ::handle<Geom_BezierSurface>& theSurface1,
const occ::handle<Geom_BezierSurface>& 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;
}
@@ -18,18 +18,28 @@
#include <Geom_Circle.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_Circle>& 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<int64_t>(std::round(theCircle->Radius() * aFactor)))};
@@ -40,11 +50,10 @@ struct GeomHash_CircleHasher
bool operator()(const occ::handle<Geom_Circle>& theCircle1,
const occ::handle<Geom_Circle>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_ConicalSurface.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_ConicalSurface>& 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<int64_t>(std::round(theCone->RefRadius() * aFactor))),
@@ -41,11 +51,10 @@ struct GeomHash_ConicalSurfaceHasher
bool operator()(const occ::handle<Geom_ConicalSurface>& theCone1,
const occ::handle<Geom_ConicalSurface>& 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;
}
};
@@ -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<Geom_Curve>& theCurve) const noexcept
{
if (theCurve.IsNull())
@@ -44,46 +52,55 @@ std::size_t GeomHash_CurveHasher::operator()(const occ::handle<Geom_Curve>& theC
return 0;
}
// Dispatch based on actual curve type
if (occ::handle<Geom_Line> aLine = occ::down_cast<Geom_Line>(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<Geom_Line>(theCurve));
}
if (occ::handle<Geom_Circle> aCircle = occ::down_cast<Geom_Circle>(theCurve))
else if (aType == STANDARD_TYPE(Geom_Circle))
{
return GeomHash_CircleHasher{}(aCircle);
return GeomHash_CircleHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Circle>(theCurve));
}
if (occ::handle<Geom_Ellipse> anEllipse = occ::down_cast<Geom_Ellipse>(theCurve))
else if (aType == STANDARD_TYPE(Geom_Ellipse))
{
return GeomHash_EllipseHasher{}(anEllipse);
return GeomHash_EllipseHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Ellipse>(theCurve));
}
if (occ::handle<Geom_Hyperbola> aHyperbola = occ::down_cast<Geom_Hyperbola>(theCurve))
else if (aType == STANDARD_TYPE(Geom_Hyperbola))
{
return GeomHash_HyperbolaHasher{}(aHyperbola);
return GeomHash_HyperbolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Hyperbola>(theCurve));
}
if (occ::handle<Geom_Parabola> aParabola = occ::down_cast<Geom_Parabola>(theCurve))
else if (aType == STANDARD_TYPE(Geom_Parabola))
{
return GeomHash_ParabolaHasher{}(aParabola);
return GeomHash_ParabolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Parabola>(theCurve));
}
if (occ::handle<Geom_BezierCurve> aBezier = occ::down_cast<Geom_BezierCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom_BezierCurve))
{
return GeomHash_BezierCurveHasher{}(aBezier);
return GeomHash_BezierCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_BezierCurve>(theCurve));
}
if (occ::handle<Geom_BSplineCurve> aBSpline = occ::down_cast<Geom_BSplineCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom_BSplineCurve))
{
return GeomHash_BSplineCurveHasher{}(aBSpline);
return GeomHash_BSplineCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_BSplineCurve>(theCurve));
}
if (occ::handle<Geom_TrimmedCurve> aTrimmed = occ::down_cast<Geom_TrimmedCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom_TrimmedCurve))
{
return GeomHash_TrimmedCurveHasher{}(aTrimmed);
return GeomHash_TrimmedCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_TrimmedCurve>(theCurve));
}
if (occ::handle<Geom_OffsetCurve> anOffset = occ::down_cast<Geom_OffsetCurve>(theCurve))
else if (aType == STANDARD_TYPE(Geom_OffsetCurve))
{
return GeomHash_OffsetCurveHasher{}(anOffset);
return GeomHash_OffsetCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_OffsetCurve>(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<Geom_Curve>& theCurve1,
return false;
}
// Dispatch based on actual curve type
if (occ::handle<Geom_Line> aLine1 = occ::down_cast<Geom_Line>(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<Geom_Line>(theCurve2));
return GeomHash_LineHasher{CompTolerance, HashTolerance}(occ::down_cast<Geom_Line>(theCurve1),
occ::down_cast<Geom_Line>(theCurve2));
}
if (occ::handle<Geom_Circle> aCircle1 = occ::down_cast<Geom_Circle>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_Circle))
{
return GeomHash_CircleHasher{}(aCircle1, occ::down_cast<Geom_Circle>(theCurve2));
return GeomHash_CircleHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Circle>(theCurve1),
occ::down_cast<Geom_Circle>(theCurve2));
}
if (occ::handle<Geom_Ellipse> anEllipse1 = occ::down_cast<Geom_Ellipse>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_Ellipse))
{
return GeomHash_EllipseHasher{}(anEllipse1, occ::down_cast<Geom_Ellipse>(theCurve2));
return GeomHash_EllipseHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Ellipse>(theCurve1),
occ::down_cast<Geom_Ellipse>(theCurve2));
}
if (occ::handle<Geom_Hyperbola> aHyp1 = occ::down_cast<Geom_Hyperbola>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_Hyperbola))
{
return GeomHash_HyperbolaHasher{}(aHyp1, occ::down_cast<Geom_Hyperbola>(theCurve2));
return GeomHash_HyperbolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Hyperbola>(theCurve1),
occ::down_cast<Geom_Hyperbola>(theCurve2));
}
if (occ::handle<Geom_Parabola> aPar1 = occ::down_cast<Geom_Parabola>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_Parabola))
{
return GeomHash_ParabolaHasher{}(aPar1, occ::down_cast<Geom_Parabola>(theCurve2));
return GeomHash_ParabolaHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Parabola>(theCurve1),
occ::down_cast<Geom_Parabola>(theCurve2));
}
if (occ::handle<Geom_BezierCurve> aBez1 = occ::down_cast<Geom_BezierCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_BezierCurve))
{
return GeomHash_BezierCurveHasher{}(aBez1, occ::down_cast<Geom_BezierCurve>(theCurve2));
return GeomHash_BezierCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_BezierCurve>(theCurve1),
occ::down_cast<Geom_BezierCurve>(theCurve2));
}
if (occ::handle<Geom_BSplineCurve> aBSpl1 = occ::down_cast<Geom_BSplineCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_BSplineCurve))
{
return GeomHash_BSplineCurveHasher{}(aBSpl1, occ::down_cast<Geom_BSplineCurve>(theCurve2));
return GeomHash_BSplineCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_BSplineCurve>(theCurve1),
occ::down_cast<Geom_BSplineCurve>(theCurve2));
}
if (occ::handle<Geom_TrimmedCurve> aTrim1 = occ::down_cast<Geom_TrimmedCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_TrimmedCurve))
{
return GeomHash_TrimmedCurveHasher{}(aTrim1, occ::down_cast<Geom_TrimmedCurve>(theCurve2));
return GeomHash_TrimmedCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_TrimmedCurve>(theCurve1),
occ::down_cast<Geom_TrimmedCurve>(theCurve2));
}
if (occ::handle<Geom_OffsetCurve> aOff1 = occ::down_cast<Geom_OffsetCurve>(theCurve1))
else if (aType == STANDARD_TYPE(Geom_OffsetCurve))
{
return GeomHash_OffsetCurveHasher{}(aOff1, occ::down_cast<Geom_OffsetCurve>(theCurve2));
return GeomHash_OffsetCurveHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_OffsetCurve>(theCurve1),
occ::down_cast<Geom_OffsetCurve>(theCurve2));
}
// Unknown curve type - compare by pointer
@@ -16,6 +16,7 @@
#include <Standard_Handle.hxx>
#include <cstddef>
#include <Precision.hxx>
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<Geom_Curve>& theCurve) const noexcept;
@@ -18,18 +18,28 @@
#include <Geom_CylindricalSurface.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_CylindricalSurface>& 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<int64_t>(std::round(theCylinder->Radius() * aFactor)))};
@@ -40,10 +50,9 @@ struct GeomHash_CylindricalSurfaceHasher
bool operator()(const occ::handle<Geom_CylindricalSurface>& theCylinder1,
const occ::handle<Geom_CylindricalSurface>& 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;
}
};
@@ -17,16 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <gp_Dir.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_Ellipse.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_Ellipse>& 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<int64_t>(std::round(theEllipse->MajorRadius() * aFactor))),
@@ -41,12 +51,11 @@ struct GeomHash_EllipseHasher
bool operator()(const occ::handle<Geom_Ellipse>& theEllipse1,
const occ::handle<Geom_Ellipse>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_Hyperbola.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_Hyperbola>& 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<int64_t>(std::round(theHyperbola->MajorRadius() * aFactor))),
@@ -41,12 +51,12 @@ struct GeomHash_HyperbolaHasher
bool operator()(const occ::handle<Geom_Hyperbola>& theHyperbola1,
const occ::handle<Geom_Hyperbola>& 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;
}
};
@@ -18,16 +18,27 @@
#include <Geom_Line.hxx>
#include <GeomHash_PointHasher.pxx>
#include <GeomHash_DirectionHasher.pxx>
#include <Precision.hxx>
//! 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<Geom_Line>& 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<Geom_Line>& theLine1,
const occ::handle<Geom_Line>& 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());
@@ -19,19 +19,29 @@
#include <GeomHash_DirectionHasher.pxx>
#include <GeomHash_CurveHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_OffsetCurve>& 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<int64_t>(std::round(theCurve->Offset() * aFactor))),
@@ -43,13 +53,11 @@ struct GeomHash_OffsetCurveHasher
bool operator()(const occ::handle<Geom_OffsetCurve>& theCurve1,
const occ::handle<Geom_OffsetCurve>& 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());
}
};
@@ -18,18 +18,28 @@
#include <Geom_OffsetSurface.hxx>
#include <GeomHash_SurfaceHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_OffsetSurface>& 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<int64_t>(std::round(theSurface->Offset() * aFactor)))};
@@ -40,12 +50,10 @@ struct GeomHash_OffsetSurfaceHasher
bool operator()(const occ::handle<Geom_OffsetSurface>& theSurface1,
const occ::handle<Geom_OffsetSurface>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_Parabola.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_Parabola>& 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<int64_t>(std::round(theParabola->Focal() * aFactor)))};
@@ -40,11 +50,10 @@ struct GeomHash_ParabolaHasher
bool operator()(const occ::handle<Geom_Parabola>& theParabola1,
const occ::handle<Geom_Parabola>& 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;
}
};
@@ -17,15 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <Geom_Plane.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <Precision.hxx>
//! 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<Geom_Plane>& 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<Geom_Plane>& thePlane1,
const occ::handle<Geom_Plane>& thePlane2) const noexcept
{
const GeomHash_AxisPlacement anAxisHasher;
const GeomHash_AxisPlacement anAxisHasher(CompTolerance, HashTolerance);
return anAxisHasher(thePlane1->Position().Ax2(), thePlane2->Position().Ax2());
}
};
@@ -17,16 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <gp_Pnt.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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;
}
};
@@ -18,19 +18,29 @@
#include <Geom_RectangularTrimmedSurface.hxx>
#include <GeomHash_SurfaceHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_RectangularTrimmedSurface>& 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<Geom_RectangularTrimmedSurface>& theSurface1,
const occ::handle<Geom_RectangularTrimmedSurface>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_SphericalSurface.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_SphericalSurface>& 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<int64_t>(std::round(theSphere->Radius() * aFactor)))};
@@ -40,10 +50,9 @@ struct GeomHash_SphericalSurfaceHasher
bool operator()(const occ::handle<Geom_SphericalSurface>& theSphere1,
const occ::handle<Geom_SphericalSurface>& 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;
}
};
@@ -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<Geom_Surface>& theSurface) const noexcept
{
@@ -49,59 +57,66 @@ std::size_t GeomHash_SurfaceHasher::operator()(
return 0;
}
// Dispatch based on actual surface type
if (occ::handle<Geom_Plane> aPlane = occ::down_cast<Geom_Plane>(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<Geom_Plane>(theSurface));
}
if (occ::handle<Geom_CylindricalSurface> aCylinder =
occ::down_cast<Geom_CylindricalSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_CylindricalSurface))
{
return GeomHash_CylindricalSurfaceHasher{}(aCylinder);
return GeomHash_CylindricalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_CylindricalSurface>(theSurface));
}
if (occ::handle<Geom_ConicalSurface> aCone = occ::down_cast<Geom_ConicalSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_ConicalSurface))
{
return GeomHash_ConicalSurfaceHasher{}(aCone);
return GeomHash_ConicalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_ConicalSurface>(theSurface));
}
if (occ::handle<Geom_SphericalSurface> aSphere =
occ::down_cast<Geom_SphericalSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_SphericalSurface))
{
return GeomHash_SphericalSurfaceHasher{}(aSphere);
return GeomHash_SphericalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SphericalSurface>(theSurface));
}
if (occ::handle<Geom_ToroidalSurface> aTorus = occ::down_cast<Geom_ToroidalSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_ToroidalSurface))
{
return GeomHash_ToroidalSurfaceHasher{}(aTorus);
return GeomHash_ToroidalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_ToroidalSurface>(theSurface));
}
if (occ::handle<Geom_SurfaceOfRevolution> aRevol =
occ::down_cast<Geom_SurfaceOfRevolution>(theSurface))
else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
{
return GeomHash_SurfaceOfRevolutionHasher{}(aRevol);
return GeomHash_SurfaceOfRevolutionHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SurfaceOfRevolution>(theSurface));
}
if (occ::handle<Geom_SurfaceOfLinearExtrusion> aExtr =
occ::down_cast<Geom_SurfaceOfLinearExtrusion>(theSurface))
else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
return GeomHash_SurfaceOfLinearExtrusionHasher{}(aExtr);
return GeomHash_SurfaceOfLinearExtrusionHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SurfaceOfLinearExtrusion>(theSurface));
}
if (occ::handle<Geom_BezierSurface> aBezier = occ::down_cast<Geom_BezierSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_BezierSurface))
{
return GeomHash_BezierSurfaceHasher{}(aBezier);
return GeomHash_BezierSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_BezierSurface>(theSurface));
}
if (occ::handle<Geom_BSplineSurface> aBSpline = occ::down_cast<Geom_BSplineSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_BSplineSurface))
{
return GeomHash_BSplineSurfaceHasher{}(aBSpline);
return GeomHash_BSplineSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_BSplineSurface>(theSurface));
}
if (occ::handle<Geom_RectangularTrimmedSurface> aTrimmed =
occ::down_cast<Geom_RectangularTrimmedSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
return GeomHash_RectangularTrimmedSurfaceHasher{}(aTrimmed);
return GeomHash_RectangularTrimmedSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_RectangularTrimmedSurface>(theSurface));
}
if (occ::handle<Geom_OffsetSurface> aOffset = occ::down_cast<Geom_OffsetSurface>(theSurface))
else if (aType == STANDARD_TYPE(Geom_OffsetSurface))
{
return GeomHash_OffsetSurfaceHasher{}(aOffset);
return GeomHash_OffsetSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_OffsetSurface>(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<Geom_Surface>& theSurf
return false;
}
// Dispatch based on actual surface type
if (occ::handle<Geom_Plane> aPlane1 = occ::down_cast<Geom_Plane>(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<Geom_Plane>(theSurface2));
return GeomHash_PlaneHasher{CompTolerance,
HashTolerance}(occ::down_cast<Geom_Plane>(theSurface1),
occ::down_cast<Geom_Plane>(theSurface2));
}
if (occ::handle<Geom_CylindricalSurface> aCyl1 =
occ::down_cast<Geom_CylindricalSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_CylindricalSurface))
{
return GeomHash_CylindricalSurfaceHasher{}(
aCyl1,
return GeomHash_CylindricalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_CylindricalSurface>(theSurface1),
occ::down_cast<Geom_CylindricalSurface>(theSurface2));
}
if (occ::handle<Geom_ConicalSurface> aCone1 = occ::down_cast<Geom_ConicalSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_ConicalSurface))
{
return GeomHash_ConicalSurfaceHasher{}(aCone1,
occ::down_cast<Geom_ConicalSurface>(theSurface2));
return GeomHash_ConicalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_ConicalSurface>(theSurface1),
occ::down_cast<Geom_ConicalSurface>(theSurface2));
}
if (occ::handle<Geom_SphericalSurface> aSph1 = occ::down_cast<Geom_SphericalSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_SphericalSurface))
{
return GeomHash_SphericalSurfaceHasher{}(aSph1,
occ::down_cast<Geom_SphericalSurface>(theSurface2));
return GeomHash_SphericalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SphericalSurface>(theSurface1),
occ::down_cast<Geom_SphericalSurface>(theSurface2));
}
if (occ::handle<Geom_ToroidalSurface> aTor1 = occ::down_cast<Geom_ToroidalSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_ToroidalSurface))
{
return GeomHash_ToroidalSurfaceHasher{}(aTor1,
occ::down_cast<Geom_ToroidalSurface>(theSurface2));
return GeomHash_ToroidalSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_ToroidalSurface>(theSurface1),
occ::down_cast<Geom_ToroidalSurface>(theSurface2));
}
if (occ::handle<Geom_SurfaceOfRevolution> aRev1 =
occ::down_cast<Geom_SurfaceOfRevolution>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
{
return GeomHash_SurfaceOfRevolutionHasher{}(
aRev1,
return GeomHash_SurfaceOfRevolutionHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SurfaceOfRevolution>(theSurface1),
occ::down_cast<Geom_SurfaceOfRevolution>(theSurface2));
}
if (occ::handle<Geom_SurfaceOfLinearExtrusion> aExt1 =
occ::down_cast<Geom_SurfaceOfLinearExtrusion>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
return GeomHash_SurfaceOfLinearExtrusionHasher{}(
aExt1,
return GeomHash_SurfaceOfLinearExtrusionHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_SurfaceOfLinearExtrusion>(theSurface1),
occ::down_cast<Geom_SurfaceOfLinearExtrusion>(theSurface2));
}
if (occ::handle<Geom_BezierSurface> aBez1 = occ::down_cast<Geom_BezierSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_BezierSurface))
{
return GeomHash_BezierSurfaceHasher{}(aBez1, occ::down_cast<Geom_BezierSurface>(theSurface2));
return GeomHash_BezierSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_BezierSurface>(theSurface1),
occ::down_cast<Geom_BezierSurface>(theSurface2));
}
if (occ::handle<Geom_BSplineSurface> aBSpl1 = occ::down_cast<Geom_BSplineSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_BSplineSurface))
{
return GeomHash_BSplineSurfaceHasher{}(aBSpl1,
occ::down_cast<Geom_BSplineSurface>(theSurface2));
return GeomHash_BSplineSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_BSplineSurface>(theSurface1),
occ::down_cast<Geom_BSplineSurface>(theSurface2));
}
if (occ::handle<Geom_RectangularTrimmedSurface> aTrim1 =
occ::down_cast<Geom_RectangularTrimmedSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
return GeomHash_RectangularTrimmedSurfaceHasher{}(
aTrim1,
return GeomHash_RectangularTrimmedSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_RectangularTrimmedSurface>(theSurface1),
occ::down_cast<Geom_RectangularTrimmedSurface>(theSurface2));
}
if (occ::handle<Geom_OffsetSurface> aOff1 = occ::down_cast<Geom_OffsetSurface>(theSurface1))
else if (aType == STANDARD_TYPE(Geom_OffsetSurface))
{
return GeomHash_OffsetSurfaceHasher{}(aOff1, occ::down_cast<Geom_OffsetSurface>(theSurface2));
return GeomHash_OffsetSurfaceHasher{CompTolerance, HashTolerance}(
occ::down_cast<Geom_OffsetSurface>(theSurface1),
occ::down_cast<Geom_OffsetSurface>(theSurface2));
}
// Unknown surface type - compare by pointer
@@ -16,6 +16,7 @@
#include <Standard_Handle.hxx>
#include <cstddef>
#include <Precision.hxx>
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<Geom_Surface>& theSurface) const noexcept;
@@ -18,17 +18,28 @@
#include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <GeomHash_DirectionHasher.pxx>
#include <GeomHash_CurveHasher.hxx>
#include <Precision.hxx>
//! 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<Geom_SurfaceOfLinearExtrusion>& 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<Geom_SurfaceOfLinearExtrusion>& theSurface1,
const occ::handle<Geom_SurfaceOfLinearExtrusion>& 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());
@@ -19,17 +19,28 @@
#include <GeomHash_PointHasher.pxx>
#include <GeomHash_DirectionHasher.pxx>
#include <GeomHash_CurveHasher.hxx>
#include <Precision.hxx>
//! 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<Geom_SurfaceOfRevolution>& 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<Geom_SurfaceOfRevolution>& theSurface1,
const occ::handle<Geom_SurfaceOfRevolution>& 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();
@@ -18,18 +18,28 @@
#include <Geom_ToroidalSurface.hxx>
#include <GeomHash_AxisPlacement.pxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_ToroidalSurface>& 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<int64_t>(std::round(theTorus->MajorRadius() * aFactor))),
@@ -41,11 +51,10 @@ struct GeomHash_ToroidalSurfaceHasher
bool operator()(const occ::handle<Geom_ToroidalSurface>& theTorus1,
const occ::handle<Geom_ToroidalSurface>& 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;
}
};
@@ -18,18 +18,28 @@
#include <Geom_TrimmedCurve.hxx>
#include <GeomHash_CurveHasher.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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<Geom_TrimmedCurve>& 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<int64_t>(std::round(theCurve->FirstParameter() * aFactor))),
@@ -41,13 +51,11 @@ struct GeomHash_TrimmedCurveHasher
bool operator()(const occ::handle<Geom_TrimmedCurve>& theCurve1,
const occ::handle<Geom_TrimmedCurve>& 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;
}
};
@@ -17,16 +17,26 @@
#include <Standard_HashUtils.hxx>
#include <gp_Vec.hxx>
#include <cmath>
#include <Precision.hxx>
//! 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;
}
};