mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-10 09:30:48 +08:00
Modeling Data - Add GeomHash and Geom2dHash packages (#845)
- Implementation of hashers for analytic curves (Line, Circle, Ellipse, Hyperbola, Parabola) and freeform curves (Bezier, BSpline, Trimmed, Offset) in both 2D and 3D - Implementation of hashers for surfaces including elementary surfaces (Plane, Cylinder, Cone, Sphere, Torus) and derived surfaces (Revolution, LinearExtrusion, RectangularTrimmed, Offset) - Comprehensive test coverage for all hasher implementations
This commit is contained in:
@@ -8,4 +8,5 @@ set(OCCT_TKG2d_GTests_FILES
|
||||
Geom2dAPI_InterCurveCurve_Test.cxx
|
||||
Geom2dGcc_Circ2d2TanOn_Test.cxx
|
||||
Geom2dGcc_Circ2d2TanRad_Test.cxx
|
||||
Geom2dHash_CurveHasher_Test.cxx
|
||||
)
|
||||
|
||||
654
src/ModelingData/TKG2d/GTests/Geom2dHash_CurveHasher_Test.cxx
Normal file
654
src/ModelingData/TKG2d/GTests/Geom2dHash_CurveHasher_Test.cxx
Normal file
@@ -0,0 +1,654 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Geom2dHash_CurveHasher.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <TColgp_Array1OfPnt2d.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
|
||||
class Geom2dHash_CurveHasherTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
Geom2dHash_CurveHasher myHasher;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Line Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Line_CopiedLines_SameHash)
|
||||
{
|
||||
gp_Pnt2d aLoc(1.0, 2.0);
|
||||
gp_Dir2d aDir(1.0, 0.0);
|
||||
Handle(Geom2d_Line) aLine1 = new Geom2d_Line(aLoc, aDir);
|
||||
Handle(Geom2d_Line) aLine2 = Handle(Geom2d_Line)::DownCast(aLine1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_TRUE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Line_DifferentLines_DifferentHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine1 = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_Line) aLine2 = new Geom2d_Line(gp_Pnt2d(1.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Circle Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 5.0);
|
||||
Handle(Geom2d_Circle) aCircle2 = Handle(Geom2d_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_DifferentRadius_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 5.0);
|
||||
Handle(Geom2d_Circle) aCircle2 = new Geom2d_Circle(anAxis, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Ellipse Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Ellipse_CopiedEllipses_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAxis, 10.0, 5.0);
|
||||
Handle(Geom2d_Ellipse) anEllipse2 = Handle(Geom2d_Ellipse)::DownCast(anEllipse1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anEllipse1), myHasher(anEllipse2));
|
||||
EXPECT_TRUE(myHasher(anEllipse1, anEllipse2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Ellipse_DifferentRadii_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAxis, 10.0, 5.0);
|
||||
Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAxis, 10.0, 7.0);
|
||||
|
||||
EXPECT_NE(myHasher(anEllipse1), myHasher(anEllipse2));
|
||||
EXPECT_FALSE(myHasher(anEllipse1, anEllipse2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Hyperbola Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Hyperbola_CopiedHyperbolas_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Hyperbola) aHyp1 = new Geom2d_Hyperbola(anAxis, 5.0, 3.0);
|
||||
Handle(Geom2d_Hyperbola) aHyp2 = Handle(Geom2d_Hyperbola)::DownCast(aHyp1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aHyp1), myHasher(aHyp2));
|
||||
EXPECT_TRUE(myHasher(aHyp1, aHyp2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Hyperbola_DifferentRadii_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Hyperbola) aHyp1 = new Geom2d_Hyperbola(anAxis, 5.0, 3.0);
|
||||
Handle(Geom2d_Hyperbola) aHyp2 = new Geom2d_Hyperbola(anAxis, 5.0, 4.0);
|
||||
|
||||
EXPECT_NE(myHasher(aHyp1), myHasher(aHyp2));
|
||||
EXPECT_FALSE(myHasher(aHyp1, aHyp2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Parabola Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Parabola_CopiedParabolas_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Parabola) aPar1 = new Geom2d_Parabola(anAxis, 2.0);
|
||||
Handle(Geom2d_Parabola) aPar2 = Handle(Geom2d_Parabola)::DownCast(aPar1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aPar1), myHasher(aPar2));
|
||||
EXPECT_TRUE(myHasher(aPar1, aPar2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Parabola_DifferentFocal_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Parabola) aPar1 = new Geom2d_Parabola(anAxis, 2.0);
|
||||
Handle(Geom2d_Parabola) aPar2 = new Geom2d_Parabola(anAxis, 3.0);
|
||||
|
||||
EXPECT_NE(myHasher(aPar1), myHasher(aPar2));
|
||||
EXPECT_FALSE(myHasher(aPar1, aPar2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BezierCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BezierCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(3) = gp_Pnt2d(3.0, 2.0);
|
||||
aPoles(4) = gp_Pnt2d(4.0, 0.0);
|
||||
|
||||
Handle(Geom2d_BezierCurve) aCurve1 = new Geom2d_BezierCurve(aPoles);
|
||||
Handle(Geom2d_BezierCurve) aCurve2 = Handle(Geom2d_BezierCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BezierCurve_DifferentPoles_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles1(1, 3);
|
||||
aPoles1(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles1(2) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles1(3) = gp_Pnt2d(2.0, 0.0);
|
||||
|
||||
TColgp_Array1OfPnt2d aPoles2(1, 3);
|
||||
aPoles2(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles2(2) = gp_Pnt2d(1.0, 3.0); // Different
|
||||
aPoles2(3) = gp_Pnt2d(2.0, 0.0);
|
||||
|
||||
Handle(Geom2d_BezierCurve) aCurve1 = new Geom2d_BezierCurve(aPoles1);
|
||||
Handle(Geom2d_BezierCurve) aCurve2 = new Geom2d_BezierCurve(aPoles2);
|
||||
|
||||
// Hash may be same (metadata only), but comparison should differ
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSplineCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 1.0);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TrimmedCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, TrimmedCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_TrimmedCurve) aTrimmed1 = new Geom2d_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
Handle(Geom2d_TrimmedCurve) aTrimmed2 = Handle(Geom2d_TrimmedCurve)::DownCast(aTrimmed1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_TRUE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, TrimmedCurve_DifferentBounds_DifferentHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_TrimmedCurve) aTrimmed1 = new Geom2d_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
Handle(Geom2d_TrimmedCurve) aTrimmed2 = new Geom2d_TrimmedCurve(aLine, 0.0, 20.0);
|
||||
|
||||
EXPECT_NE(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_FALSE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// OffsetCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, OffsetCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_OffsetCurve) anOffset1 = new Geom2d_OffsetCurve(aLine, 5.0);
|
||||
Handle(Geom2d_OffsetCurve) anOffset2 = Handle(Geom2d_OffsetCurve)::DownCast(anOffset1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_TRUE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, OffsetCurve_DifferentOffset_DifferentHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_OffsetCurve) anOffset1 = new Geom2d_OffsetCurve(aLine, 5.0);
|
||||
Handle(Geom2d_OffsetCurve) anOffset2 = new Geom2d_OffsetCurve(aLine, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_FALSE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, DifferentTypes_DifferentComparison)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle = new Geom2d_Circle(anAxis, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aLine, aCircle));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, NullCurves_HandledCorrectly)
|
||||
{
|
||||
Handle(Geom2d_Curve) aNullCurve;
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
EXPECT_EQ(myHasher(aNullCurve), 0u);
|
||||
EXPECT_TRUE(myHasher(aNullCurve, aNullCurve));
|
||||
EXPECT_FALSE(myHasher(aLine, aNullCurve));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, SameObject_Equal)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
EXPECT_TRUE(myHasher(aLine, aLine));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_Weighted_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 1.0);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 4);
|
||||
aWeights(1) = 1.0;
|
||||
aWeights(2) = 2.0;
|
||||
aWeights(3) = 2.0;
|
||||
aWeights(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 =
|
||||
new Geom2d_BSplineCurve(aPoles, aWeights, aKnots, aMults, 3);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_DifferentWeights_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 1.0);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights1(1, 4);
|
||||
aWeights1(1) = 1.0;
|
||||
aWeights1(2) = 2.0;
|
||||
aWeights1(3) = 2.0;
|
||||
aWeights1(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aWeights2(1, 4);
|
||||
aWeights2(1) = 1.0;
|
||||
aWeights2(2) = 3.0; // Different
|
||||
aWeights2(3) = 2.0;
|
||||
aWeights2(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 =
|
||||
new Geom2d_BSplineCurve(aPoles, aWeights1, aKnots, aMults, 3);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 =
|
||||
new Geom2d_BSplineCurve(aPoles, aWeights2, aKnots, aMults, 3);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted Bezier Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BezierCurve_Weighted_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 3);
|
||||
aWeights(1) = 1.0;
|
||||
aWeights(2) = 2.0;
|
||||
aWeights(3) = 1.0;
|
||||
|
||||
Handle(Geom2d_BezierCurve) aCurve1 = new Geom2d_BezierCurve(aPoles, aWeights);
|
||||
Handle(Geom2d_BezierCurve) aCurve2 = Handle(Geom2d_BezierCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Axis Orientation Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_DifferentAxisOrientation_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis1(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
gp_Ax22d anAxis2(gp_Pnt2d(0.0, 0.0), gp_Dir2d(0.0, 1.0), gp_Dir2d(-1.0, 0.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis1, 5.0);
|
||||
Handle(Geom2d_Circle) aCircle2 = new Geom2d_Circle(anAxis2, 5.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Line_DifferentDirection_DifferentHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine1 = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_Line) aLine2 = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSpline with Different Knots Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_DifferentKnots_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 1.0);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots1(1, 2);
|
||||
aKnots1(1) = 0.0;
|
||||
aKnots1(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots2(1, 2);
|
||||
aKnots2(1) = 0.0;
|
||||
aKnots2(2) = 2.0; // Different
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 = new Geom2d_BSplineCurve(aPoles, aKnots1, aMults, 3);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = new Geom2d_BSplineCurve(aPoles, aKnots2, aMults, 3);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Periodic BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_QuadraticBezierEquivalent_CopiedCurves_SameHash)
|
||||
{
|
||||
// Simple quadratic B-spline (Bezier-like, single span)
|
||||
TColgp_Array1OfPnt2d aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 3;
|
||||
aMults(2) = 3;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Reversed Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Line_Reversed_DifferentComparison)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine1 = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_Line) aLine2 = Handle(Geom2d_Line)::DownCast(aLine1->Reversed());
|
||||
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BezierCurve_Reversed_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 0.0);
|
||||
|
||||
Handle(Geom2d_BezierCurve) aCurve1 = new Geom2d_BezierCurve(aPoles);
|
||||
Handle(Geom2d_BezierCurve) aCurve2 = Handle(Geom2d_BezierCurve)::DownCast(aCurve1->Reversed());
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Transformed Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_Translated_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 5.0);
|
||||
Handle(Geom2d_Circle) aCircle2 = Handle(Geom2d_Circle)::DownCast(aCircle1->Copy());
|
||||
aCircle2->Translate(gp_Vec2d(1.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_Scaled_DifferentHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 5.0);
|
||||
Handle(Geom2d_Circle) aCircle2 = Handle(Geom2d_Circle)::DownCast(aCircle1->Copy());
|
||||
aCircle2->Scale(gp_Pnt2d(0.0, 0.0), 2.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Higher Degree BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_HigherDegree_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt2d aPoles(1, 6);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 0.5);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 1.5);
|
||||
aPoles(5) = gp_Pnt2d(4.0, 0.0);
|
||||
aPoles(6) = gp_Pnt2d(5.0, 1.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 6;
|
||||
aMults(2) = 6;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 5);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Multiple Knot Spans Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, BSplineCurve_LinearMultipleSpans_CopiedCurves_SameHash)
|
||||
{
|
||||
// Linear B-spline with multiple knots (piecewise linear)
|
||||
TColgp_Array1OfPnt2d aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt2d(0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt2d(1.0, 1.0);
|
||||
aPoles(3) = gp_Pnt2d(2.0, 0.0);
|
||||
aPoles(4) = gp_Pnt2d(3.0, 1.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 4);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
aKnots(3) = 2.0;
|
||||
aKnots(4) = 3.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 4);
|
||||
aMults(1) = 2;
|
||||
aMults(2) = 1;
|
||||
aMults(3) = 1;
|
||||
aMults(4) = 2;
|
||||
|
||||
Handle(Geom2d_BSplineCurve) aCurve1 = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 1);
|
||||
Handle(Geom2d_BSplineCurve) aCurve2 = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Conic Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Ellipse_vs_Hyperbola_DifferentComparison)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Ellipse) anEllipse = new Geom2d_Ellipse(anAxis, 5.0, 3.0);
|
||||
Handle(Geom2d_Hyperbola) aHyperbola = new Geom2d_Hyperbola(anAxis, 5.0, 3.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(anEllipse, aHyperbola));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_vs_Ellipse_DifferentComparison)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle = new Geom2d_Circle(anAxis, 5.0);
|
||||
Handle(Geom2d_Ellipse) anEllipse = new Geom2d_Ellipse(anAxis, 5.0, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCircle, anEllipse));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Trimmed vs Base Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, TrimmedCurve_vs_BaseCurve_DifferentComparison)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_TrimmedCurve) aTrimmed = new Geom2d_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aLine, aTrimmed));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Edge Cases - Degenerate/Special Values
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_VerySmallRadius_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 1e-10);
|
||||
Handle(Geom2d_Circle) aCircle2 = Handle(Geom2d_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Circle_VeryLargeRadius_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(anAxis, 1e10);
|
||||
Handle(Geom2d_Circle) aCircle2 = Handle(Geom2d_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(Geom2dHash_CurveHasherTest, Line_AtOrigin_vs_FarFromOrigin_DifferentHash)
|
||||
{
|
||||
Handle(Geom2d_Line) aLine1 = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
Handle(Geom2d_Line) aLine2 = new Geom2d_Line(gp_Pnt2d(1e10, 1e10), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
22
src/ModelingData/TKG2d/Geom2dHash/FILES.cmake
Normal file
22
src/ModelingData/TKG2d/Geom2dHash/FILES.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
# Source files for Geom2dHash package
|
||||
set(OCCT_Geom2dHash_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_Geom2dHash_FILES
|
||||
# Foundational Hashers
|
||||
Geom2dHash_PointHasher.pxx
|
||||
Geom2dHash_DirectionHasher.pxx
|
||||
Geom2dHash_AxisPlacement.pxx
|
||||
|
||||
# Curve Hashers
|
||||
Geom2dHash_LineHasher.pxx
|
||||
Geom2dHash_CircleHasher.pxx
|
||||
Geom2dHash_EllipseHasher.pxx
|
||||
Geom2dHash_HyperbolaHasher.pxx
|
||||
Geom2dHash_ParabolaHasher.pxx
|
||||
Geom2dHash_BezierCurveHasher.pxx
|
||||
Geom2dHash_BSplineCurveHasher.pxx
|
||||
Geom2dHash_TrimmedCurveHasher.pxx
|
||||
Geom2dHash_OffsetCurveHasher.pxx
|
||||
Geom2dHash_CurveHasher.hxx
|
||||
Geom2dHash_CurveHasher.cxx
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_AxisPlacement_HeaderFile
|
||||
#define _Geom2dHash_AxisPlacement_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <Geom2dHash_PointHasher.pxx>
|
||||
#include <Geom2dHash_DirectionHasher.pxx>
|
||||
|
||||
//! OCCT-style hasher for gp_Ax22d (2D coordinate system).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_AxisPlacement
|
||||
{
|
||||
// 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 std::size_t aHashes[3] = {aPointHasher(theAxisPlacement.Location()),
|
||||
aDirHasher(theAxisPlacement.XDirection()),
|
||||
aDirHasher(theAxisPlacement.YDirection())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two 2D axis placements.
|
||||
bool operator()(const gp_Ax22d& theAxisPlacement1,
|
||||
const gp_Ax22d& theAxisPlacement2) const noexcept
|
||||
{
|
||||
const Geom2dHash_PointHasher aPointHasher;
|
||||
const Geom2dHash_DirectionHasher aDirHasher;
|
||||
|
||||
return aPointHasher(theAxisPlacement1.Location(), theAxisPlacement2.Location())
|
||||
&& aDirHasher(theAxisPlacement1.XDirection(), theAxisPlacement2.XDirection())
|
||||
&& aDirHasher(theAxisPlacement1.YDirection(), theAxisPlacement2.YDirection());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_AxisPlacement_HeaderFile
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_BSplineCurveHasher_HeaderFile
|
||||
#define _Geom2dHash_BSplineCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2dHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! 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
|
||||
{
|
||||
// Hashes the B-spline curve metadata only.
|
||||
std::size_t operator()(const Handle(Geom2d_BSplineCurve)& theCurve) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[4] = {opencascade::hash(theCurve->Degree()),
|
||||
opencascade::hash(theCurve->NbPoles()),
|
||||
opencascade::hash(theCurve->NbKnots()),
|
||||
opencascade::hash(static_cast<int>(theCurve->IsRational()))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two B-spline curves by full geometric data.
|
||||
bool operator()(const Handle(Geom2d_BSplineCurve)& theCurve1,
|
||||
const Handle(Geom2d_BSplineCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theCurve1->Degree() != theCurve2->Degree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare knot counts
|
||||
if (theCurve1->NbKnots() != theCurve2->NbKnots())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare knots and multiplicities
|
||||
for (int i = 1; i <= theCurve1->NbKnots(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > aTolerance
|
||||
|| theCurve1->Multiplicity(i) != theCurve2->Multiplicity(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theCurve1->IsRational() != theCurve2->IsRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const Geom2dHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (!aPointHasher(theCurve1->Pole(i), theCurve2->Pole(i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theCurve1->IsRational())
|
||||
{
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_BSplineCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_BezierCurveHasher_HeaderFile
|
||||
#define _Geom2dHash_BezierCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2dHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! 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
|
||||
{
|
||||
// Hashes the Bezier curve metadata only.
|
||||
std::size_t operator()(const Handle(Geom2d_BezierCurve)& theCurve) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[3] = {opencascade::hash(theCurve->Degree()),
|
||||
opencascade::hash(theCurve->NbPoles()),
|
||||
opencascade::hash(static_cast<int>(theCurve->IsRational()))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two Bezier curves by full geometric data.
|
||||
bool operator()(const Handle(Geom2d_BezierCurve)& theCurve1,
|
||||
const Handle(Geom2d_BezierCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theCurve1->Degree() != theCurve2->Degree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theCurve1->IsRational() != theCurve2->IsRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const Geom2dHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (!aPointHasher(theCurve1->Pole(i), theCurve2->Pole(i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theCurve1->IsRational())
|
||||
{
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_BezierCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_CircleHasher_HeaderFile
|
||||
#define _Geom2dHash_CircleHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2dHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_Circle (2D circle).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_CircleHasher
|
||||
{
|
||||
// Hashes the circle by its position and radius.
|
||||
std::size_t operator()(const Handle(Geom2d_Circle)& theCircle) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theCircle->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCircle->Radius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two circles by their positions and radii.
|
||||
bool operator()(const Handle(Geom2d_Circle)& theCircle1,
|
||||
const Handle(Geom2d_Circle)& theCircle2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theCircle1->Position(), theCircle2->Position())
|
||||
&& std::abs(theCircle1->Radius() - theCircle2->Radius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_CircleHasher_HeaderFile
|
||||
152
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx
Normal file
152
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.cxx
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Geom2dHash_CurveHasher.hxx>
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
|
||||
#include <Geom2dHash_LineHasher.pxx>
|
||||
#include <Geom2dHash_CircleHasher.pxx>
|
||||
#include <Geom2dHash_EllipseHasher.pxx>
|
||||
#include <Geom2dHash_HyperbolaHasher.pxx>
|
||||
#include <Geom2dHash_ParabolaHasher.pxx>
|
||||
#include <Geom2dHash_BezierCurveHasher.pxx>
|
||||
#include <Geom2dHash_BSplineCurveHasher.pxx>
|
||||
#include <Geom2dHash_TrimmedCurveHasher.pxx>
|
||||
#include <Geom2dHash_OffsetCurveHasher.pxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
std::size_t Geom2dHash_CurveHasher::operator()(const Handle(Geom2d_Curve)& theCurve) const noexcept
|
||||
{
|
||||
if (theCurve.IsNull())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dispatch based on actual curve type
|
||||
if (Handle(Geom2d_Line) aLine = Handle(Geom2d_Line)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_LineHasher{}(aLine);
|
||||
}
|
||||
if (Handle(Geom2d_Circle) aCircle = Handle(Geom2d_Circle)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_CircleHasher{}(aCircle);
|
||||
}
|
||||
if (Handle(Geom2d_Ellipse) anEllipse = Handle(Geom2d_Ellipse)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_EllipseHasher{}(anEllipse);
|
||||
}
|
||||
if (Handle(Geom2d_Hyperbola) aHyperbola = Handle(Geom2d_Hyperbola)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_HyperbolaHasher{}(aHyperbola);
|
||||
}
|
||||
if (Handle(Geom2d_Parabola) aParabola = Handle(Geom2d_Parabola)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_ParabolaHasher{}(aParabola);
|
||||
}
|
||||
if (Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_BezierCurveHasher{}(aBezier);
|
||||
}
|
||||
if (Handle(Geom2d_BSplineCurve) aBSpline = Handle(Geom2d_BSplineCurve)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_BSplineCurveHasher{}(aBSpline);
|
||||
}
|
||||
if (Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_TrimmedCurveHasher{}(aTrimmed);
|
||||
}
|
||||
if (Handle(Geom2d_OffsetCurve) anOffset = Handle(Geom2d_OffsetCurve)::DownCast(theCurve))
|
||||
{
|
||||
return Geom2dHash_OffsetCurveHasher{}(anOffset);
|
||||
}
|
||||
|
||||
// Unknown curve type - hash the type name
|
||||
return std::hash<std::string>{}(theCurve->DynamicType()->Name());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom2dHash_CurveHasher::operator()(const Handle(Geom2d_Curve)& theCurve1,
|
||||
const Handle(Geom2d_Curve)& theCurve2) const noexcept
|
||||
{
|
||||
if (theCurve1.IsNull() || theCurve2.IsNull())
|
||||
{
|
||||
return theCurve1.IsNull() && theCurve2.IsNull();
|
||||
}
|
||||
|
||||
if (theCurve1 == theCurve2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be same type
|
||||
if (theCurve1->DynamicType() != theCurve2->DynamicType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dispatch based on actual curve type
|
||||
if (Handle(Geom2d_Line) aLine1 = Handle(Geom2d_Line)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_LineHasher{}(aLine1, Handle(Geom2d_Line)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_Circle) aCircle1 = Handle(Geom2d_Circle)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_CircleHasher{}(aCircle1, Handle(Geom2d_Circle)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_Ellipse) anEllipse1 = Handle(Geom2d_Ellipse)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_EllipseHasher{}(anEllipse1, Handle(Geom2d_Ellipse)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_Hyperbola) aHyp1 = Handle(Geom2d_Hyperbola)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_HyperbolaHasher{}(aHyp1, Handle(Geom2d_Hyperbola)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_Parabola) aPar1 = Handle(Geom2d_Parabola)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_ParabolaHasher{}(aPar1, Handle(Geom2d_Parabola)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_BezierCurve) aBez1 = Handle(Geom2d_BezierCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_BezierCurveHasher{}(aBez1, Handle(Geom2d_BezierCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_BSplineCurve) aBSpl1 = Handle(Geom2d_BSplineCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_BSplineCurveHasher{}(aBSpl1,
|
||||
Handle(Geom2d_BSplineCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_TrimmedCurve) aTrim1 = Handle(Geom2d_TrimmedCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_TrimmedCurveHasher{}(aTrim1,
|
||||
Handle(Geom2d_TrimmedCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom2d_OffsetCurve) aOff1 = Handle(Geom2d_OffsetCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return Geom2dHash_OffsetCurveHasher{}(aOff1, Handle(Geom2d_OffsetCurve)::DownCast(theCurve2));
|
||||
}
|
||||
|
||||
// Unknown curve type - compare by pointer
|
||||
return theCurve1.get() == theCurve2.get();
|
||||
}
|
||||
34
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx
Normal file
34
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_CurveHasher.hxx
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_CurveHasher_HeaderFile
|
||||
#define _Geom2dHash_CurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <cstddef>
|
||||
|
||||
class Geom2d_Curve;
|
||||
|
||||
//! Polymorphic hasher for Geom2d_Curve using RTTI dispatch.
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_CurveHasher
|
||||
{
|
||||
// Hashes any Geom2d_Curve by dispatching to the appropriate specific hasher.
|
||||
Standard_EXPORT std::size_t operator()(const Handle(Geom2d_Curve)& theCurve) const noexcept;
|
||||
|
||||
// Compares two curves using polymorphic dispatch.
|
||||
Standard_EXPORT bool operator()(const Handle(Geom2d_Curve)& theCurve1,
|
||||
const Handle(Geom2d_Curve)& theCurve2) const noexcept;
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_CurveHasher_HeaderFile
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_DirectionHasher_HeaderFile
|
||||
#define _Geom2dHash_DirectionHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for gp_Dir2d (2D directions).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_DirectionHasher
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Round each component to tolerance precision before hashing
|
||||
const std::size_t aHashes[2] = {
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theDirection.X() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theDirection.Y() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_DirectionHasher_HeaderFile
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_EllipseHasher_HeaderFile
|
||||
#define _Geom2dHash_EllipseHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2dHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_Ellipse (2D ellipse).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_EllipseHasher
|
||||
{
|
||||
// Hashes the ellipse by its position, major radius, and minor radius.
|
||||
std::size_t operator()(const Handle(Geom2d_Ellipse)& theEllipse) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theEllipse->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theEllipse->MajorRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theEllipse->MinorRadius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two ellipses by their positions and radii.
|
||||
bool operator()(const Handle(Geom2d_Ellipse)& theEllipse1,
|
||||
const Handle(Geom2d_Ellipse)& theEllipse2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theEllipse1->Position(), theEllipse2->Position())
|
||||
&& std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= aTolerance
|
||||
&& std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_EllipseHasher_HeaderFile
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_HyperbolaHasher_HeaderFile
|
||||
#define _Geom2dHash_HyperbolaHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2dHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_Hyperbola (2D hyperbola).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_HyperbolaHasher
|
||||
{
|
||||
// Hashes the hyperbola by its position, major radius, and minor radius.
|
||||
std::size_t operator()(const Handle(Geom2d_Hyperbola)& theHyperbola) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theHyperbola->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theHyperbola->MajorRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theHyperbola->MinorRadius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two hyperbolas by their positions and radii.
|
||||
bool operator()(const Handle(Geom2d_Hyperbola)& theHyperbola1,
|
||||
const Handle(Geom2d_Hyperbola)& theHyperbola2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theHyperbola1->Position(), theHyperbola2->Position())
|
||||
&& std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= aTolerance
|
||||
&& std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_HyperbolaHasher_HeaderFile
|
||||
49
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx
Normal file
49
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_LineHasher.pxx
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_LineHasher_HeaderFile
|
||||
#define _Geom2dHash_LineHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2dHash_PointHasher.pxx>
|
||||
#include <Geom2dHash_DirectionHasher.pxx>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_Line (2D line).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_LineHasher
|
||||
{
|
||||
// Hashes the line by its location and direction.
|
||||
std::size_t operator()(const Handle(Geom2d_Line)& theLine) const noexcept
|
||||
{
|
||||
const Geom2dHash_PointHasher aPointHasher;
|
||||
const Geom2dHash_DirectionHasher aDirHasher;
|
||||
|
||||
const std::size_t aHashes[2] = {aPointHasher(theLine->Position().Location()),
|
||||
aDirHasher(theLine->Position().Direction())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two lines by their positions.
|
||||
bool operator()(const Handle(Geom2d_Line)& theLine1,
|
||||
const Handle(Geom2d_Line)& theLine2) const noexcept
|
||||
{
|
||||
const Geom2dHash_PointHasher aPointHasher;
|
||||
const Geom2dHash_DirectionHasher aDirHasher;
|
||||
|
||||
return aPointHasher(theLine1->Position().Location(), theLine2->Position().Location())
|
||||
&& aDirHasher(theLine1->Position().Direction(), theLine2->Position().Direction());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_LineHasher_HeaderFile
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_OffsetCurveHasher_HeaderFile
|
||||
#define _Geom2dHash_OffsetCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
#include <Geom2dHash_CurveHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_OffsetCurve (2D offset curve).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_OffsetCurveHasher
|
||||
{
|
||||
// Hashes the offset curve by its offset distance and basis curve.
|
||||
std::size_t operator()(const Handle(Geom2d_OffsetCurve)& theCurve) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_CurveHasher aCurveHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
aCurveHasher(theCurve->BasisCurve()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->Offset() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two offset curves.
|
||||
bool operator()(const Handle(Geom2d_OffsetCurve)& theCurve1,
|
||||
const Handle(Geom2d_OffsetCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const Geom2dHash_CurveHasher aCurveHasher;
|
||||
|
||||
return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve())
|
||||
&& std::abs(theCurve1->Offset() - theCurve2->Offset()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_OffsetCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_ParabolaHasher_HeaderFile
|
||||
#define _Geom2dHash_ParabolaHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2dHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_Parabola (2D parabola).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_ParabolaHasher
|
||||
{
|
||||
// Hashes the parabola by its position and focal length.
|
||||
std::size_t operator()(const Handle(Geom2d_Parabola)& theParabola) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theParabola->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theParabola->Focal() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two parabolas by their positions and focal lengths.
|
||||
bool operator()(const Handle(Geom2d_Parabola)& theParabola1,
|
||||
const Handle(Geom2d_Parabola)& theParabola2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const Geom2dHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theParabola1->Position(), theParabola2->Position())
|
||||
&& std::abs(theParabola1->Focal() - theParabola2->Focal()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_ParabolaHasher_HeaderFile
|
||||
47
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx
Normal file
47
src/ModelingData/TKG2d/Geom2dHash/Geom2dHash_PointHasher.pxx
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_PointHasher_HeaderFile
|
||||
#define _Geom2dHash_PointHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for gp_Pnt2d (2D points).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_PointHasher
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Round each coordinate to tolerance precision before hashing
|
||||
const std::size_t aHashes[2] = {
|
||||
opencascade::hash(static_cast<int64_t>(std::round(thePoint.X() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(thePoint.Y() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_PointHasher_HeaderFile
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Geom2dHash_TrimmedCurveHasher_HeaderFile
|
||||
#define _Geom2dHash_TrimmedCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2dHash_CurveHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom2d_TrimmedCurve (2D trimmed curve).
|
||||
//! Used for geometry deduplication.
|
||||
struct Geom2dHash_TrimmedCurveHasher
|
||||
{
|
||||
// Hashes the trimmed curve by its parameters and basis curve.
|
||||
std::size_t operator()(const Handle(Geom2d_TrimmedCurve)& theCurve) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const Geom2dHash_CurveHasher aCurveHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
aCurveHasher(theCurve->BasisCurve()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->FirstParameter() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->LastParameter() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two trimmed curves.
|
||||
bool operator()(const Handle(Geom2d_TrimmedCurve)& theCurve1,
|
||||
const Handle(Geom2d_TrimmedCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const Geom2dHash_CurveHasher aCurveHasher;
|
||||
|
||||
return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve())
|
||||
&& std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= aTolerance
|
||||
&& std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Geom2dHash_TrimmedCurveHasher_HeaderFile
|
||||
@@ -7,4 +7,5 @@ set(OCCT_TKG2d_LIST_OF_PACKAGES
|
||||
Geom2dLProp
|
||||
Geom2dAdaptor
|
||||
Geom2dEvaluator
|
||||
Geom2dHash
|
||||
)
|
||||
|
||||
@@ -10,4 +10,6 @@ set(OCCT_TKG3d_GTests_FILES
|
||||
Geom_OffsetSurface_Test.cxx
|
||||
GeomAPI_ExtremaCurveCurve_Test.cxx
|
||||
GeomAPI_Interpolate_Test.cxx
|
||||
GeomHash_CurveHasher_Test.cxx
|
||||
GeomHash_SurfaceHasher_Test.cxx
|
||||
)
|
||||
|
||||
690
src/ModelingData/TKG3d/GTests/GeomHash_CurveHasher_Test.cxx
Normal file
690
src/ModelingData/TKG3d/GTests/GeomHash_CurveHasher_Test.cxx
Normal file
@@ -0,0 +1,690 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
|
||||
class GeomHash_CurveHasherTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
GeomHash_CurveHasher myHasher;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Line Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Line_CopiedLines_SameHash)
|
||||
{
|
||||
gp_Pnt aLoc(1.0, 2.0, 3.0);
|
||||
gp_Dir aDir(1.0, 0.0, 0.0);
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(aLoc, aDir);
|
||||
Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast(aLine1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_TRUE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Line_DifferentLines_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_Line) aLine2 = new Geom_Line(gp_Pnt(1.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Circle Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 5.0);
|
||||
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_DifferentRadius_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 5.0);
|
||||
Handle(Geom_Circle) aCircle2 = new Geom_Circle(anAxis, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Ellipse Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Ellipse_CopiedEllipses_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Ellipse) anEllipse1 = new Geom_Ellipse(anAxis, 10.0, 5.0);
|
||||
Handle(Geom_Ellipse) anEllipse2 = Handle(Geom_Ellipse)::DownCast(anEllipse1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anEllipse1), myHasher(anEllipse2));
|
||||
EXPECT_TRUE(myHasher(anEllipse1, anEllipse2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Ellipse_DifferentRadii_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Ellipse) anEllipse1 = new Geom_Ellipse(anAxis, 10.0, 5.0);
|
||||
Handle(Geom_Ellipse) anEllipse2 = new Geom_Ellipse(anAxis, 10.0, 7.0);
|
||||
|
||||
EXPECT_NE(myHasher(anEllipse1), myHasher(anEllipse2));
|
||||
EXPECT_FALSE(myHasher(anEllipse1, anEllipse2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Hyperbola Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Hyperbola_CopiedHyperbolas_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Hyperbola) aHyp1 = new Geom_Hyperbola(anAxis, 5.0, 3.0);
|
||||
Handle(Geom_Hyperbola) aHyp2 = Handle(Geom_Hyperbola)::DownCast(aHyp1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aHyp1), myHasher(aHyp2));
|
||||
EXPECT_TRUE(myHasher(aHyp1, aHyp2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Hyperbola_DifferentRadii_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Hyperbola) aHyp1 = new Geom_Hyperbola(anAxis, 5.0, 3.0);
|
||||
Handle(Geom_Hyperbola) aHyp2 = new Geom_Hyperbola(anAxis, 5.0, 4.0);
|
||||
|
||||
EXPECT_NE(myHasher(aHyp1), myHasher(aHyp2));
|
||||
EXPECT_FALSE(myHasher(aHyp1, aHyp2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Parabola Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Parabola_CopiedParabolas_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Parabola) aPar1 = new Geom_Parabola(anAxis, 2.0);
|
||||
Handle(Geom_Parabola) aPar2 = Handle(Geom_Parabola)::DownCast(aPar1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aPar1), myHasher(aPar2));
|
||||
EXPECT_TRUE(myHasher(aPar1, aPar2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Parabola_DifferentFocal_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Parabola) aPar1 = new Geom_Parabola(anAxis, 2.0);
|
||||
Handle(Geom_Parabola) aPar2 = new Geom_Parabola(anAxis, 3.0);
|
||||
|
||||
EXPECT_NE(myHasher(aPar1), myHasher(aPar2));
|
||||
EXPECT_FALSE(myHasher(aPar1, aPar2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BezierCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BezierCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 2.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(3.0, 2.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(4.0, 0.0, 0.0);
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve1 = new Geom_BezierCurve(aPoles);
|
||||
Handle(Geom_BezierCurve) aCurve2 = Handle(Geom_BezierCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BezierCurve_DifferentPoles_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles1(1, 3);
|
||||
aPoles1(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles1(2) = gp_Pnt(1.0, 2.0, 0.0);
|
||||
aPoles1(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
|
||||
TColgp_Array1OfPnt aPoles2(1, 3);
|
||||
aPoles2(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles2(2) = gp_Pnt(1.0, 3.0, 0.0); // Different
|
||||
aPoles2(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve1 = new Geom_BezierCurve(aPoles1);
|
||||
Handle(Geom_BezierCurve) aCurve2 = new Geom_BezierCurve(aPoles2);
|
||||
|
||||
// Hash may be same (metadata only), but comparison should differ
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSplineCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = Handle(Geom_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TrimmedCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, TrimmedCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_TrimmedCurve) aTrimmed1 = new Geom_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
Handle(Geom_TrimmedCurve) aTrimmed2 = Handle(Geom_TrimmedCurve)::DownCast(aTrimmed1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_TRUE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, TrimmedCurve_DifferentBounds_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_TrimmedCurve) aTrimmed1 = new Geom_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
Handle(Geom_TrimmedCurve) aTrimmed2 = new Geom_TrimmedCurve(aLine, 0.0, 20.0);
|
||||
|
||||
EXPECT_NE(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_FALSE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// OffsetCurve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, OffsetCurve_CopiedCurves_SameHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
gp_Dir aRefDir(0.0, 0.0, 1.0);
|
||||
Handle(Geom_OffsetCurve) anOffset1 = new Geom_OffsetCurve(aLine, 5.0, aRefDir);
|
||||
Handle(Geom_OffsetCurve) anOffset2 = Handle(Geom_OffsetCurve)::DownCast(anOffset1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_TRUE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, OffsetCurve_DifferentOffset_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
gp_Dir aRefDir(0.0, 0.0, 1.0);
|
||||
Handle(Geom_OffsetCurve) anOffset1 = new Geom_OffsetCurve(aLine, 5.0, aRefDir);
|
||||
Handle(Geom_OffsetCurve) anOffset2 = new Geom_OffsetCurve(aLine, 10.0, aRefDir);
|
||||
|
||||
EXPECT_NE(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_FALSE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, DifferentTypes_DifferentComparison)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle = new Geom_Circle(anAxis, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aLine, aCircle));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, NullCurves_HandledCorrectly)
|
||||
{
|
||||
Handle(Geom_Curve) aNullCurve;
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
|
||||
EXPECT_EQ(myHasher(aNullCurve), 0u);
|
||||
EXPECT_TRUE(myHasher(aNullCurve, aNullCurve));
|
||||
EXPECT_FALSE(myHasher(aLine, aNullCurve));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, SameObject_Equal)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
EXPECT_TRUE(myHasher(aLine, aLine));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_Weighted_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 4);
|
||||
aWeights(1) = 1.0;
|
||||
aWeights(2) = 2.0;
|
||||
aWeights(3) = 2.0;
|
||||
aWeights(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aWeights, aKnots, aMults, 3);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = Handle(Geom_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_DifferentWeights_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights1(1, 4);
|
||||
aWeights1(1) = 1.0;
|
||||
aWeights1(2) = 2.0;
|
||||
aWeights1(3) = 2.0;
|
||||
aWeights1(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aWeights2(1, 4);
|
||||
aWeights2(1) = 1.0;
|
||||
aWeights2(2) = 3.0; // Different
|
||||
aWeights2(3) = 2.0;
|
||||
aWeights2(4) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aWeights1, aKnots, aMults, 3);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = new Geom_BSplineCurve(aPoles, aWeights2, aKnots, aMults, 3);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted Bezier Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BezierCurve_Weighted_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 2.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 3);
|
||||
aWeights(1) = 1.0;
|
||||
aWeights(2) = 2.0;
|
||||
aWeights(3) = 1.0;
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve1 = new Geom_BezierCurve(aPoles, aWeights);
|
||||
Handle(Geom_BezierCurve) aCurve2 = Handle(Geom_BezierCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Axis Orientation Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_DifferentAxisOrientation_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax2 anAxis2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis1, 5.0);
|
||||
Handle(Geom_Circle) aCircle2 = new Geom_Circle(anAxis2, 5.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Line_DifferentDirection_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_Line) aLine2 = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSpline with Different Knots Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_DifferentKnots_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots1(1, 2);
|
||||
aKnots1(1) = 0.0;
|
||||
aKnots1(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfReal aKnots2(1, 2);
|
||||
aKnots2(1) = 0.0;
|
||||
aKnots2(2) = 2.0; // Different
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 4;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots1, aMults, 3);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = new Geom_BSplineCurve(aPoles, aKnots2, aMults, 3);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Periodic BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_QuadraticBezierEquivalent_CopiedCurves_SameHash)
|
||||
{
|
||||
// Simple quadratic B-spline (Bezier-like, single span)
|
||||
TColgp_Array1OfPnt aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 2.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 3;
|
||||
aMults(2) = 3;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots, aMults, 2);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = Handle(Geom_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Reversed Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Line_Reversed_DifferentComparison)
|
||||
{
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast(aLine1->Reversed());
|
||||
|
||||
// Reversed line has opposite direction
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BezierCurve_Reversed_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 2.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve1 = new Geom_BezierCurve(aPoles);
|
||||
Handle(Geom_BezierCurve) aCurve2 = Handle(Geom_BezierCurve)::DownCast(aCurve1->Reversed());
|
||||
|
||||
// Reversed curve has poles in different order
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Transformed Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_Translated_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 5.0);
|
||||
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(aCircle1->Copy());
|
||||
aCircle2->Translate(gp_Vec(1.0, 0.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_Scaled_DifferentHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 5.0);
|
||||
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(aCircle1->Copy());
|
||||
aCircle2->Scale(gp_Pnt(0.0, 0.0, 0.0), 2.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_FALSE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Higher Degree BSpline Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_HigherDegree_CopiedCurves_SameHash)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 6);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 0.5, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 1.5, 0.0);
|
||||
aPoles(5) = gp_Pnt(4.0, 0.0, 0.0);
|
||||
aPoles(6) = gp_Pnt(5.0, 1.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 2);
|
||||
aMults(1) = 6;
|
||||
aMults(2) = 6;
|
||||
|
||||
// Degree 5 curve
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots, aMults, 5);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = Handle(Geom_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_DifferentDegree_DifferentComparison)
|
||||
{
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults1(1, 2);
|
||||
aMults1(1) = 4;
|
||||
aMults1(2) = 4;
|
||||
|
||||
TColStd_Array1OfInteger aMults2(1, 2);
|
||||
aMults2(1) = 3;
|
||||
aMults2(2) = 3;
|
||||
|
||||
// Different degrees: 3 vs 2
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots, aMults1, 3);
|
||||
|
||||
TColgp_Array1OfPnt aPoles2(1, 3);
|
||||
aPoles2(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles2(2) = gp_Pnt(1.5, 1.0, 0.0);
|
||||
aPoles2(3) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve2 = new Geom_BSplineCurve(aPoles2, aKnots, aMults2, 2);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Multiple Knot Spans Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, BSplineCurve_LinearMultipleSpans_CopiedCurves_SameHash)
|
||||
{
|
||||
// Linear B-spline with multiple knots (piecewise linear)
|
||||
TColgp_Array1OfPnt aPoles(1, 4);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(2.0, 0.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(3.0, 1.0, 0.0);
|
||||
|
||||
TColStd_Array1OfReal aKnots(1, 4);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
aKnots(3) = 2.0;
|
||||
aKnots(4) = 3.0;
|
||||
|
||||
TColStd_Array1OfInteger aMults(1, 4);
|
||||
aMults(1) = 2;
|
||||
aMults(2) = 1;
|
||||
aMults(3) = 1;
|
||||
aMults(4) = 2;
|
||||
|
||||
Handle(Geom_BSplineCurve) aCurve1 = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
|
||||
Handle(Geom_BSplineCurve) aCurve2 = Handle(Geom_BSplineCurve)::DownCast(aCurve1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCurve1), myHasher(aCurve2));
|
||||
EXPECT_TRUE(myHasher(aCurve1, aCurve2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Conic Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Ellipse_vs_Hyperbola_DifferentComparison)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Ellipse) anEllipse = new Geom_Ellipse(anAxis, 5.0, 3.0);
|
||||
Handle(Geom_Hyperbola) aHyperbola = new Geom_Hyperbola(anAxis, 5.0, 3.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(anEllipse, aHyperbola));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_vs_Ellipse_DifferentComparison)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle = new Geom_Circle(anAxis, 5.0);
|
||||
Handle(Geom_Ellipse) anEllipse = new Geom_Ellipse(anAxis, 5.0, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCircle, anEllipse));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Trimmed vs Base Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, TrimmedCurve_vs_BaseCurve_DifferentComparison)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_TrimmedCurve) aTrimmed = new Geom_TrimmedCurve(aLine, 0.0, 10.0);
|
||||
|
||||
// Trimmed curve is a different type from base curve
|
||||
EXPECT_FALSE(myHasher(aLine, aTrimmed));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Edge Cases - Degenerate/Special Values
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_VerySmallRadius_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 1e-10);
|
||||
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Circle_VeryLargeRadius_CopiedCircles_SameHash)
|
||||
{
|
||||
gp_Ax2 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Circle) aCircle1 = new Geom_Circle(anAxis, 1e10);
|
||||
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(aCircle1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCircle1), myHasher(aCircle2));
|
||||
EXPECT_TRUE(myHasher(aCircle1, aCircle2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_CurveHasherTest, Line_AtOrigin_vs_FarFromOrigin_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_Line) aLine2 = new Geom_Line(gp_Pnt(1e10, 1e10, 1e10), gp_Dir(1.0, 0.0, 0.0));
|
||||
|
||||
EXPECT_NE(myHasher(aLine1), myHasher(aLine2));
|
||||
EXPECT_FALSE(myHasher(aLine1, aLine2));
|
||||
}
|
||||
749
src/ModelingData/TKG3d/GTests/GeomHash_SurfaceHasher_Test.cxx
Normal file
749
src/ModelingData/TKG3d/GTests/GeomHash_SurfaceHasher_Test.cxx
Normal file
@@ -0,0 +1,749 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <GeomHash_SurfaceHasher.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <Geom_BezierSurface.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <Geom_SurfaceOfRevolution.hxx>
|
||||
#include <Geom_SurfaceOfLinearExtrusion.hxx>
|
||||
#include <Geom_RectangularTrimmedSurface.hxx>
|
||||
#include <Geom_OffsetSurface.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <TColgp_Array2OfPnt.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <TColStd_Array2OfReal.hxx>
|
||||
|
||||
class GeomHash_SurfaceHasherTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
GeomHash_SurfaceHasher myHasher;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Plane Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Plane_CopiedPlanes_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(anAxis);
|
||||
Handle(Geom_Plane) aPlane2 = Handle(Geom_Plane)::DownCast(aPlane1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aPlane1), myHasher(aPlane2));
|
||||
EXPECT_TRUE(myHasher(aPlane1, aPlane2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Plane_DifferentPlanes_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)));
|
||||
Handle(Geom_Plane) aPlane2 = new Geom_Plane(gp_Ax3(gp_Pnt(0.0, 0.0, 1.0), gp_Dir(0.0, 0.0, 1.0)));
|
||||
|
||||
EXPECT_NE(myHasher(aPlane1), myHasher(aPlane2));
|
||||
EXPECT_FALSE(myHasher(aPlane1, aPlane2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cylindrical Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, CylindricalSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(anAxis, 5.0);
|
||||
Handle(Geom_CylindricalSurface) aCyl2 = Handle(Geom_CylindricalSurface)::DownCast(aCyl1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCyl1), myHasher(aCyl2));
|
||||
EXPECT_TRUE(myHasher(aCyl1, aCyl2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, CylindricalSurface_DifferentRadius_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(anAxis, 5.0);
|
||||
Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(anAxis, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCyl1), myHasher(aCyl2));
|
||||
EXPECT_FALSE(myHasher(aCyl1, aCyl2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Conical Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, ConicalSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_ConicalSurface) aCone1 = new Geom_ConicalSurface(anAxis, M_PI / 6.0, 5.0);
|
||||
Handle(Geom_ConicalSurface) aCone2 = Handle(Geom_ConicalSurface)::DownCast(aCone1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aCone1), myHasher(aCone2));
|
||||
EXPECT_TRUE(myHasher(aCone1, aCone2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, ConicalSurface_DifferentAngle_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_ConicalSurface) aCone1 = new Geom_ConicalSurface(anAxis, M_PI / 6.0, 5.0);
|
||||
Handle(Geom_ConicalSurface) aCone2 = new Geom_ConicalSurface(anAxis, M_PI / 4.0, 5.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCone1), myHasher(aCone2));
|
||||
EXPECT_FALSE(myHasher(aCone1, aCone2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Spherical Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SphericalSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere1 = new Geom_SphericalSurface(anAxis, 5.0);
|
||||
Handle(Geom_SphericalSurface) aSphere2 =
|
||||
Handle(Geom_SphericalSurface)::DownCast(aSphere1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSphere1), myHasher(aSphere2));
|
||||
EXPECT_TRUE(myHasher(aSphere1, aSphere2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SphericalSurface_DifferentRadius_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere1 = new Geom_SphericalSurface(anAxis, 5.0);
|
||||
Handle(Geom_SphericalSurface) aSphere2 = new Geom_SphericalSurface(anAxis, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(aSphere1), myHasher(aSphere2));
|
||||
EXPECT_FALSE(myHasher(aSphere1, aSphere2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Toroidal Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, ToroidalSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_ToroidalSurface) aTorus1 = new Geom_ToroidalSurface(anAxis, 10.0, 3.0);
|
||||
Handle(Geom_ToroidalSurface) aTorus2 = Handle(Geom_ToroidalSurface)::DownCast(aTorus1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aTorus1), myHasher(aTorus2));
|
||||
EXPECT_TRUE(myHasher(aTorus1, aTorus2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, ToroidalSurface_DifferentRadii_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_ToroidalSurface) aTorus1 = new Geom_ToroidalSurface(anAxis, 10.0, 3.0);
|
||||
Handle(Geom_ToroidalSurface) aTorus2 = new Geom_ToroidalSurface(anAxis, 10.0, 5.0);
|
||||
|
||||
EXPECT_NE(myHasher(aTorus1), myHasher(aTorus2));
|
||||
EXPECT_FALSE(myHasher(aTorus1, aTorus2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BezierSurface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BezierSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
Handle(Geom_BezierSurface) aSurf1 = new Geom_BezierSurface(aPoles);
|
||||
Handle(Geom_BezierSurface) aSurf2 = Handle(Geom_BezierSurface)::DownCast(aSurf1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSurf1), myHasher(aSurf2));
|
||||
EXPECT_TRUE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BezierSurface_DifferentPoles_DifferentComparison)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles1(1, 2, 1, 2);
|
||||
aPoles1(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles1(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles1(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles1(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColgp_Array2OfPnt aPoles2(1, 2, 1, 2);
|
||||
aPoles2(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles2(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles2(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles2(2, 2) = gp_Pnt(1.0, 1.0, 2.0); // Different
|
||||
|
||||
Handle(Geom_BezierSurface) aSurf1 = new Geom_BezierSurface(aPoles1);
|
||||
Handle(Geom_BezierSurface) aSurf2 = new Geom_BezierSurface(aPoles2);
|
||||
|
||||
// Hash may be same (metadata only), but comparison should differ
|
||||
EXPECT_FALSE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSplineSurface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BSplineSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColStd_Array1OfReal aUKnots(1, 2), aVKnots(1, 2);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 1.0;
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2);
|
||||
aUMults(1) = 2;
|
||||
aUMults(2) = 2;
|
||||
aVMults(1) = 2;
|
||||
aVMults(2) = 2;
|
||||
|
||||
Handle(Geom_BSplineSurface) aSurf1 =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 1, 1);
|
||||
Handle(Geom_BSplineSurface) aSurf2 = Handle(Geom_BSplineSurface)::DownCast(aSurf1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSurf1), myHasher(aSurf2));
|
||||
EXPECT_TRUE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SurfaceOfRevolution Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SurfaceOfRevolution_CopiedSurfaces_SameHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(1.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax1 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SurfaceOfRevolution) aRev1 = new Geom_SurfaceOfRevolution(aLine, anAxis);
|
||||
Handle(Geom_SurfaceOfRevolution) aRev2 =
|
||||
Handle(Geom_SurfaceOfRevolution)::DownCast(aRev1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aRev1), myHasher(aRev2));
|
||||
EXPECT_TRUE(myHasher(aRev1, aRev2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SurfaceOfLinearExtrusion Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SurfaceOfLinearExtrusion_CopiedSurfaces_SameHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
gp_Dir aDir(0.0, 0.0, 1.0);
|
||||
Handle(Geom_SurfaceOfLinearExtrusion) anExt1 = new Geom_SurfaceOfLinearExtrusion(aLine, aDir);
|
||||
Handle(Geom_SurfaceOfLinearExtrusion) anExt2 =
|
||||
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(anExt1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anExt1), myHasher(anExt2));
|
||||
EXPECT_TRUE(myHasher(anExt1, anExt2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RectangularTrimmedSurface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, RectangularTrimmedSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_RectangularTrimmedSurface) aTrimmed1 =
|
||||
new Geom_RectangularTrimmedSurface(aPlane, 0.0, 10.0, 0.0, 10.0);
|
||||
Handle(Geom_RectangularTrimmedSurface) aTrimmed2 =
|
||||
Handle(Geom_RectangularTrimmedSurface)::DownCast(aTrimmed1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_TRUE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, RectangularTrimmedSurface_DifferentBounds_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_RectangularTrimmedSurface) aTrimmed1 =
|
||||
new Geom_RectangularTrimmedSurface(aPlane, 0.0, 10.0, 0.0, 10.0);
|
||||
Handle(Geom_RectangularTrimmedSurface) aTrimmed2 =
|
||||
new Geom_RectangularTrimmedSurface(aPlane, 0.0, 20.0, 0.0, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(aTrimmed1), myHasher(aTrimmed2));
|
||||
EXPECT_FALSE(myHasher(aTrimmed1, aTrimmed2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// OffsetSurface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, OffsetSurface_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_OffsetSurface) anOffset1 = new Geom_OffsetSurface(aPlane, 5.0);
|
||||
Handle(Geom_OffsetSurface) anOffset2 = Handle(Geom_OffsetSurface)::DownCast(anOffset1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_TRUE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, OffsetSurface_DifferentOffset_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_OffsetSurface) anOffset1 = new Geom_OffsetSurface(aPlane, 5.0);
|
||||
Handle(Geom_OffsetSurface) anOffset2 = new Geom_OffsetSurface(aPlane, 10.0);
|
||||
|
||||
EXPECT_NE(myHasher(anOffset1), myHasher(anOffset2));
|
||||
EXPECT_FALSE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, DifferentTypes_DifferentComparison)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAxis, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aPlane, aSphere));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, NullSurfaces_HandledCorrectly)
|
||||
{
|
||||
Handle(Geom_Surface) aNullSurface;
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
|
||||
EXPECT_EQ(myHasher(aNullSurface), 0u);
|
||||
EXPECT_TRUE(myHasher(aNullSurface, aNullSurface));
|
||||
EXPECT_FALSE(myHasher(aPlane, aNullSurface));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SameObject_Equal)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
EXPECT_TRUE(myHasher(aPlane, aPlane));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted BSpline Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BSplineSurface_Weighted_CopiedSurfaces_SameHash)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColStd_Array2OfReal aWeights(1, 2, 1, 2);
|
||||
aWeights(1, 1) = 1.0;
|
||||
aWeights(1, 2) = 1.0;
|
||||
aWeights(2, 1) = 1.0;
|
||||
aWeights(2, 2) = 2.0;
|
||||
|
||||
TColStd_Array1OfReal aUKnots(1, 2), aVKnots(1, 2);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 1.0;
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2);
|
||||
aUMults(1) = 2;
|
||||
aUMults(2) = 2;
|
||||
aVMults(1) = 2;
|
||||
aVMults(2) = 2;
|
||||
|
||||
Handle(Geom_BSplineSurface) aSurf1 =
|
||||
new Geom_BSplineSurface(aPoles, aWeights, aUKnots, aVKnots, aUMults, aVMults, 1, 1);
|
||||
Handle(Geom_BSplineSurface) aSurf2 = Handle(Geom_BSplineSurface)::DownCast(aSurf1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSurf1), myHasher(aSurf2));
|
||||
EXPECT_TRUE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BSplineSurface_DifferentWeights_DifferentComparison)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColStd_Array2OfReal aWeights1(1, 2, 1, 2);
|
||||
aWeights1(1, 1) = 1.0;
|
||||
aWeights1(1, 2) = 1.0;
|
||||
aWeights1(2, 1) = 1.0;
|
||||
aWeights1(2, 2) = 2.0;
|
||||
|
||||
TColStd_Array2OfReal aWeights2(1, 2, 1, 2);
|
||||
aWeights2(1, 1) = 1.0;
|
||||
aWeights2(1, 2) = 1.0;
|
||||
aWeights2(2, 1) = 1.0;
|
||||
aWeights2(2, 2) = 3.0; // Different
|
||||
|
||||
TColStd_Array1OfReal aUKnots(1, 2), aVKnots(1, 2);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 1.0;
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2);
|
||||
aUMults(1) = 2;
|
||||
aUMults(2) = 2;
|
||||
aVMults(1) = 2;
|
||||
aVMults(2) = 2;
|
||||
|
||||
Handle(Geom_BSplineSurface) aSurf1 =
|
||||
new Geom_BSplineSurface(aPoles, aWeights1, aUKnots, aVKnots, aUMults, aVMults, 1, 1);
|
||||
Handle(Geom_BSplineSurface) aSurf2 =
|
||||
new Geom_BSplineSurface(aPoles, aWeights2, aUKnots, aVKnots, aUMults, aVMults, 1, 1);
|
||||
|
||||
EXPECT_FALSE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Weighted Bezier Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BezierSurface_Weighted_CopiedSurfaces_SameHash)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColStd_Array2OfReal aWeights(1, 2, 1, 2);
|
||||
aWeights(1, 1) = 1.0;
|
||||
aWeights(1, 2) = 1.0;
|
||||
aWeights(2, 1) = 1.0;
|
||||
aWeights(2, 2) = 2.0;
|
||||
|
||||
Handle(Geom_BezierSurface) aSurf1 = new Geom_BezierSurface(aPoles, aWeights);
|
||||
Handle(Geom_BezierSurface) aSurf2 = Handle(Geom_BezierSurface)::DownCast(aSurf1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSurf1), myHasher(aSurf2));
|
||||
EXPECT_TRUE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Axis Orientation Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Plane_DifferentNormal_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax3 anAxis2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0));
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(anAxis1);
|
||||
Handle(Geom_Plane) aPlane2 = new Geom_Plane(anAxis2);
|
||||
|
||||
EXPECT_NE(myHasher(aPlane1), myHasher(aPlane2));
|
||||
EXPECT_FALSE(myHasher(aPlane1, aPlane2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, CylindricalSurface_DifferentAxis_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax3 anAxis2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(anAxis1, 5.0);
|
||||
Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(anAxis2, 5.0);
|
||||
|
||||
EXPECT_NE(myHasher(aCyl1), myHasher(aCyl2));
|
||||
EXPECT_FALSE(myHasher(aCyl1, aCyl2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Revolution with Different Basis Curve Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SurfaceOfRevolution_DifferentBasisCurve_DifferentComparison)
|
||||
{
|
||||
Handle(Geom_Line) aLine1 = new Geom_Line(gp_Pnt(1.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Line) aLine2 = new Geom_Line(gp_Pnt(2.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax1 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SurfaceOfRevolution) aRev1 = new Geom_SurfaceOfRevolution(aLine1, anAxis);
|
||||
Handle(Geom_SurfaceOfRevolution) aRev2 = new Geom_SurfaceOfRevolution(aLine2, anAxis);
|
||||
|
||||
EXPECT_FALSE(myHasher(aRev1, aRev2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Extrusion with Different Direction Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SurfaceOfLinearExtrusion_DifferentDirection_DifferentHash)
|
||||
{
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
gp_Dir aDir1(0.0, 0.0, 1.0);
|
||||
gp_Dir aDir2(0.0, 1.0, 0.0);
|
||||
Handle(Geom_SurfaceOfLinearExtrusion) anExt1 = new Geom_SurfaceOfLinearExtrusion(aLine, aDir1);
|
||||
Handle(Geom_SurfaceOfLinearExtrusion) anExt2 = new Geom_SurfaceOfLinearExtrusion(aLine, aDir2);
|
||||
|
||||
EXPECT_NE(myHasher(anExt1), myHasher(anExt2));
|
||||
EXPECT_FALSE(myHasher(anExt1, anExt2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSpline Surface with Different Knots Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BSplineSurface_DifferentKnots_DifferentComparison)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
TColStd_Array1OfReal aUKnots1(1, 2), aUKnots2(1, 2), aVKnots(1, 2);
|
||||
aUKnots1(1) = 0.0;
|
||||
aUKnots1(2) = 1.0;
|
||||
aUKnots2(1) = 0.0;
|
||||
aUKnots2(2) = 2.0; // Different
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2);
|
||||
aUMults(1) = 2;
|
||||
aUMults(2) = 2;
|
||||
aVMults(1) = 2;
|
||||
aVMults(2) = 2;
|
||||
|
||||
Handle(Geom_BSplineSurface) aSurf1 =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots1, aVKnots, aUMults, aVMults, 1, 1);
|
||||
Handle(Geom_BSplineSurface) aSurf2 =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots2, aVKnots, aUMults, aVMults, 1, 1);
|
||||
|
||||
EXPECT_FALSE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Transformed Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Plane_Translated_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(anAxis);
|
||||
Handle(Geom_Plane) aPlane2 = Handle(Geom_Plane)::DownCast(aPlane1->Copy());
|
||||
aPlane2->Translate(gp_Vec(0.0, 0.0, 1.0));
|
||||
|
||||
EXPECT_NE(myHasher(aPlane1), myHasher(aPlane2));
|
||||
EXPECT_FALSE(myHasher(aPlane1, aPlane2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Sphere_Scaled_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere1 = new Geom_SphericalSurface(anAxis, 5.0);
|
||||
Handle(Geom_SphericalSurface) aSphere2 =
|
||||
Handle(Geom_SphericalSurface)::DownCast(aSphere1->Copy());
|
||||
aSphere2->Scale(gp_Pnt(0.0, 0.0, 0.0), 2.0);
|
||||
|
||||
EXPECT_NE(myHasher(aSphere1), myHasher(aSphere2));
|
||||
EXPECT_FALSE(myHasher(aSphere1, aSphere2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// UReversed/VReversed Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BezierSurface_UReversed_DifferentComparison)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
Handle(Geom_BezierSurface) aSurf1 = new Geom_BezierSurface(aPoles);
|
||||
Handle(Geom_BezierSurface) aSurf2 = Handle(Geom_BezierSurface)::DownCast(aSurf1->UReversed());
|
||||
|
||||
EXPECT_FALSE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BezierSurface_VReversed_DifferentComparison)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 2, 1, 2);
|
||||
aPoles(1, 1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1, 2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
aPoles(2, 1) = gp_Pnt(0.0, 1.0, 0.0);
|
||||
aPoles(2, 2) = gp_Pnt(1.0, 1.0, 1.0);
|
||||
|
||||
Handle(Geom_BezierSurface) aSurf1 = new Geom_BezierSurface(aPoles);
|
||||
Handle(Geom_BezierSurface) aSurf2 = Handle(Geom_BezierSurface)::DownCast(aSurf1->VReversed());
|
||||
|
||||
EXPECT_FALSE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Higher Degree BSpline Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, BSplineSurface_HigherDegree_CopiedSurfaces_SameHash)
|
||||
{
|
||||
TColgp_Array2OfPnt aPoles(1, 4, 1, 4);
|
||||
for (Standard_Integer i = 1; i <= 4; ++i)
|
||||
{
|
||||
for (Standard_Integer j = 1; j <= 4; ++j)
|
||||
{
|
||||
aPoles(i, j) = gp_Pnt((i - 1) * 1.0, (j - 1) * 1.0, (i + j) * 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
TColStd_Array1OfReal aUKnots(1, 2), aVKnots(1, 2);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 1.0;
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 1.0;
|
||||
|
||||
TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2);
|
||||
aUMults(1) = 4;
|
||||
aUMults(2) = 4;
|
||||
aVMults(1) = 4;
|
||||
aVMults(2) = 4;
|
||||
|
||||
Handle(Geom_BSplineSurface) aSurf1 =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3);
|
||||
Handle(Geom_BSplineSurface) aSurf2 = Handle(Geom_BSplineSurface)::DownCast(aSurf1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSurf1), myHasher(aSurf2));
|
||||
EXPECT_TRUE(myHasher(aSurf1, aSurf2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-type Elementary Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Cylinder_vs_Cone_DifferentComparison)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_CylindricalSurface) aCylinder = new Geom_CylindricalSurface(anAxis, 5.0);
|
||||
Handle(Geom_ConicalSurface) aCone = new Geom_ConicalSurface(anAxis, M_PI / 6.0, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aCylinder, aCone));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Sphere_vs_Torus_DifferentComparison)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAxis, 5.0);
|
||||
Handle(Geom_ToroidalSurface) aTorus = new Geom_ToroidalSurface(anAxis, 5.0, 1.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aSphere, aTorus));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Trimmed vs Base Surface Tests
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, RectangularTrimmedSurface_vs_BaseSurface_DifferentComparison)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis);
|
||||
Handle(Geom_RectangularTrimmedSurface) aTrimmed =
|
||||
new Geom_RectangularTrimmedSurface(aPlane, 0.0, 10.0, 0.0, 10.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(aPlane, aTrimmed));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Edge Cases - Degenerate/Special Values
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Sphere_VerySmallRadius_CopiedSpheres_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere1 = new Geom_SphericalSurface(anAxis, 1e-10);
|
||||
Handle(Geom_SphericalSurface) aSphere2 =
|
||||
Handle(Geom_SphericalSurface)::DownCast(aSphere1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSphere1), myHasher(aSphere2));
|
||||
EXPECT_TRUE(myHasher(aSphere1, aSphere2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Sphere_VeryLargeRadius_CopiedSpheres_SameHash)
|
||||
{
|
||||
gp_Ax3 anAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SphericalSurface) aSphere1 = new Geom_SphericalSurface(anAxis, 1e10);
|
||||
Handle(Geom_SphericalSurface) aSphere2 =
|
||||
Handle(Geom_SphericalSurface)::DownCast(aSphere1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aSphere1), myHasher(aSphere2));
|
||||
EXPECT_TRUE(myHasher(aSphere1, aSphere2));
|
||||
}
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, Plane_AtOrigin_vs_FarFromOrigin_DifferentHash)
|
||||
{
|
||||
gp_Ax3 anAxis1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax3 anAxis2(gp_Pnt(1e10, 1e10, 1e10), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(anAxis1);
|
||||
Handle(Geom_Plane) aPlane2 = new Geom_Plane(anAxis2);
|
||||
|
||||
EXPECT_NE(myHasher(aPlane1), myHasher(aPlane2));
|
||||
EXPECT_FALSE(myHasher(aPlane1, aPlane2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Revolution with Circle Basis (forms Torus-like)
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, SurfaceOfRevolution_CircleBasis_CopiedSurfaces_SameHash)
|
||||
{
|
||||
gp_Ax2 aCircleAxis(gp_Pnt(5.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0));
|
||||
Handle(Geom_Circle) aCircle = new Geom_Circle(aCircleAxis, 1.0);
|
||||
gp_Ax1 aRevAxis(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_SurfaceOfRevolution) aRev1 = new Geom_SurfaceOfRevolution(aCircle, aRevAxis);
|
||||
Handle(Geom_SurfaceOfRevolution) aRev2 =
|
||||
Handle(Geom_SurfaceOfRevolution)::DownCast(aRev1->Copy());
|
||||
|
||||
EXPECT_EQ(myHasher(aRev1), myHasher(aRev2));
|
||||
EXPECT_TRUE(myHasher(aRev1, aRev2));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Offset Surface with Different Base
|
||||
// ============================================================================
|
||||
|
||||
TEST_F(GeomHash_SurfaceHasherTest, OffsetSurface_DifferentBaseSurface_DifferentComparison)
|
||||
{
|
||||
gp_Ax3 anAxis1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
gp_Ax3 anAxis2(gp_Pnt(1.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
|
||||
Handle(Geom_Plane) aPlane1 = new Geom_Plane(anAxis1);
|
||||
Handle(Geom_Plane) aPlane2 = new Geom_Plane(anAxis2);
|
||||
Handle(Geom_OffsetSurface) anOffset1 = new Geom_OffsetSurface(aPlane1, 5.0);
|
||||
Handle(Geom_OffsetSurface) anOffset2 = new Geom_OffsetSurface(aPlane2, 5.0);
|
||||
|
||||
EXPECT_FALSE(myHasher(anOffset1, anOffset2));
|
||||
}
|
||||
38
src/ModelingData/TKG3d/GeomHash/FILES.cmake
Normal file
38
src/ModelingData/TKG3d/GeomHash/FILES.cmake
Normal file
@@ -0,0 +1,38 @@
|
||||
# Source files for GeomHash package
|
||||
set(OCCT_GeomHash_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_GeomHash_FILES
|
||||
# Foundational Hashers
|
||||
GeomHash_PointHasher.pxx
|
||||
GeomHash_DirectionHasher.pxx
|
||||
GeomHash_VectorHasher.pxx
|
||||
GeomHash_AxisPlacement.pxx
|
||||
|
||||
# Surface Hashers
|
||||
GeomHash_PlaneHasher.pxx
|
||||
GeomHash_CylindricalSurfaceHasher.pxx
|
||||
GeomHash_ConicalSurfaceHasher.pxx
|
||||
GeomHash_SphericalSurfaceHasher.pxx
|
||||
GeomHash_ToroidalSurfaceHasher.pxx
|
||||
GeomHash_SurfaceOfRevolutionHasher.pxx
|
||||
GeomHash_SurfaceOfLinearExtrusionHasher.pxx
|
||||
GeomHash_BezierSurfaceHasher.pxx
|
||||
GeomHash_BSplineSurfaceHasher.pxx
|
||||
GeomHash_RectangularTrimmedSurfaceHasher.pxx
|
||||
GeomHash_OffsetSurfaceHasher.pxx
|
||||
GeomHash_SurfaceHasher.hxx
|
||||
GeomHash_SurfaceHasher.cxx
|
||||
|
||||
# Curve Hashers
|
||||
GeomHash_LineHasher.pxx
|
||||
GeomHash_CircleHasher.pxx
|
||||
GeomHash_EllipseHasher.pxx
|
||||
GeomHash_HyperbolaHasher.pxx
|
||||
GeomHash_ParabolaHasher.pxx
|
||||
GeomHash_BezierCurveHasher.pxx
|
||||
GeomHash_BSplineCurveHasher.pxx
|
||||
GeomHash_TrimmedCurveHasher.pxx
|
||||
GeomHash_OffsetCurveHasher.pxx
|
||||
GeomHash_CurveHasher.hxx
|
||||
GeomHash_CurveHasher.cxx
|
||||
)
|
||||
52
src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx
Normal file
52
src/ModelingData/TKG3d/GeomHash/GeomHash_AxisPlacement.pxx
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_AxisPlacement_HeaderFile
|
||||
#define _GeomHash_AxisPlacement_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <GeomHash_DirectionHasher.pxx>
|
||||
|
||||
//! OCCT-style hasher for gp_Ax2 (axis placement).
|
||||
//! Used for geometry deduplication.
|
||||
//! Compositional hasher using PointHasher and DirectionHasher.
|
||||
struct GeomHash_AxisPlacement
|
||||
{
|
||||
// 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 std::size_t aHashes[3] = {aPointHasher(theAxisPlacement.Location()),
|
||||
aDirectionHasher(theAxisPlacement.Direction()),
|
||||
aDirectionHasher(theAxisPlacement.XDirection())};
|
||||
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two axis placements.
|
||||
bool operator()(const gp_Ax2& theAxisPlacement1, const gp_Ax2& theAxisPlacement2) const noexcept
|
||||
{
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
const GeomHash_DirectionHasher aDirectionHasher;
|
||||
|
||||
return aPointHasher(theAxisPlacement1.Location(), theAxisPlacement2.Location())
|
||||
&& aDirectionHasher(theAxisPlacement1.Direction(), theAxisPlacement2.Direction())
|
||||
&& aDirectionHasher(theAxisPlacement1.XDirection(), theAxisPlacement2.XDirection());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_AxisPlacement_HeaderFile
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_BSplineCurveHasher_HeaderFile
|
||||
#define _GeomHash_BSplineCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! 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
|
||||
{
|
||||
// Hashes the B-spline curve metadata only.
|
||||
std::size_t operator()(const Handle(Geom_BSplineCurve)& theCurve) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[4] = {opencascade::hash(theCurve->Degree()),
|
||||
opencascade::hash(theCurve->NbPoles()),
|
||||
opencascade::hash(theCurve->NbKnots()),
|
||||
opencascade::hash(static_cast<int>(theCurve->IsRational()))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two B-spline curves by full geometric data.
|
||||
bool operator()(const Handle(Geom_BSplineCurve)& theCurve1,
|
||||
const Handle(Geom_BSplineCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theCurve1->Degree() != theCurve2->Degree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare knot counts
|
||||
if (theCurve1->NbKnots() != theCurve2->NbKnots())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare knots and multiplicities
|
||||
for (int i = 1; i <= theCurve1->NbKnots(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Knot(i) - theCurve2->Knot(i)) > aTolerance
|
||||
|| theCurve1->Multiplicity(i) != theCurve2->Multiplicity(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theCurve1->IsRational() != theCurve2->IsRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (!aPointHasher(theCurve1->Pole(i), theCurve2->Pole(i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theCurve1->IsRational())
|
||||
{
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_BSplineCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_BSplineSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_BSplineSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_BSplineSurface.
|
||||
//! Used for geometry deduplication.
|
||||
//! Hashes only metadata (degrees, pole counts, knot counts, rationality) for efficiency.
|
||||
struct GeomHash_BSplineSurfaceHasher
|
||||
{
|
||||
// Hashes the B-spline surface metadata only.
|
||||
std::size_t operator()(const Handle(Geom_BSplineSurface)& theSurface) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[7] = {
|
||||
opencascade::hash(theSurface->UDegree()),
|
||||
opencascade::hash(theSurface->VDegree()),
|
||||
opencascade::hash(theSurface->NbUPoles()),
|
||||
opencascade::hash(theSurface->NbVPoles()),
|
||||
opencascade::hash(theSurface->NbUKnots()),
|
||||
opencascade::hash(theSurface->NbVKnots()),
|
||||
opencascade::hash(static_cast<int>(theSurface->IsURational())
|
||||
| (static_cast<int>(theSurface->IsVRational()) << 1))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two B-spline surfaces by full geometric data.
|
||||
bool operator()(const Handle(Geom_BSplineSurface)& theSurface1,
|
||||
const Handle(Geom_BSplineSurface)& theSurface2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theSurface1->UDegree() != theSurface2->UDegree()
|
||||
|| theSurface1->VDegree() != theSurface2->VDegree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare knot counts
|
||||
if (theSurface1->NbUKnots() != theSurface2->NbUKnots()
|
||||
|| theSurface1->NbVKnots() != theSurface2->NbVKnots())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare U knots and multiplicities
|
||||
for (int i = 1; i <= theSurface1->NbUKnots(); ++i)
|
||||
{
|
||||
if (std::abs(theSurface1->UKnot(i) - theSurface2->UKnot(i)) > aTolerance
|
||||
|| theSurface1->UMultiplicity(i) != theSurface2->UMultiplicity(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare V knots and multiplicities
|
||||
for (int i = 1; i <= theSurface1->NbVKnots(); ++i)
|
||||
{
|
||||
if (std::abs(theSurface1->VKnot(i) - theSurface2->VKnot(i)) > aTolerance
|
||||
|| theSurface1->VMultiplicity(i) != theSurface2->VMultiplicity(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theSurface1->IsURational() != theSurface2->IsURational()
|
||||
|| theSurface1->IsVRational() != theSurface2->IsVRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theSurface1->NbUPoles(); ++i)
|
||||
{
|
||||
for (int j = 1; j <= theSurface1->NbVPoles(); ++j)
|
||||
{
|
||||
if (!aPointHasher(theSurface1->Pole(i, j), theSurface2->Pole(i, j)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theSurface1->IsURational() || theSurface1->IsVRational())
|
||||
{
|
||||
for (int i = 1; i <= theSurface1->NbUPoles(); ++i)
|
||||
{
|
||||
for (int j = 1; j <= theSurface1->NbVPoles(); ++j)
|
||||
{
|
||||
if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_BSplineSurfaceHasher_HeaderFile
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_BezierCurveHasher_HeaderFile
|
||||
#define _GeomHash_BezierCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! 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
|
||||
{
|
||||
// Hashes the Bezier curve metadata only.
|
||||
std::size_t operator()(const Handle(Geom_BezierCurve)& theCurve) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[3] = {opencascade::hash(theCurve->Degree()),
|
||||
opencascade::hash(theCurve->NbPoles()),
|
||||
opencascade::hash(static_cast<int>(theCurve->IsRational()))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two Bezier curves by full geometric data.
|
||||
bool operator()(const Handle(Geom_BezierCurve)& theCurve1,
|
||||
const Handle(Geom_BezierCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theCurve1->Degree() != theCurve2->Degree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theCurve1->IsRational() != theCurve2->IsRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (!aPointHasher(theCurve1->Pole(i), theCurve2->Pole(i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theCurve1->IsRational())
|
||||
{
|
||||
for (int i = 1; i <= theCurve1->NbPoles(); ++i)
|
||||
{
|
||||
if (std::abs(theCurve1->Weight(i) - theCurve2->Weight(i)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_BezierCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_BezierSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_BezierSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_BezierSurface.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_BezierSurface.
|
||||
//! Used for geometry deduplication.
|
||||
//! Hashes only metadata (degrees, pole counts, rationality) for efficiency.
|
||||
struct GeomHash_BezierSurfaceHasher
|
||||
{
|
||||
// Hashes the Bezier surface metadata only.
|
||||
std::size_t operator()(const Handle(Geom_BezierSurface)& theSurface) const noexcept
|
||||
{
|
||||
const std::size_t aHashes[5] = {
|
||||
opencascade::hash(theSurface->UDegree()),
|
||||
opencascade::hash(theSurface->VDegree()),
|
||||
opencascade::hash(theSurface->NbUPoles()),
|
||||
opencascade::hash(theSurface->NbVPoles()),
|
||||
opencascade::hash(static_cast<int>(theSurface->IsURational())
|
||||
| (static_cast<int>(theSurface->IsVRational()) << 1))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two Bezier surfaces by full geometric data.
|
||||
bool operator()(const Handle(Geom_BezierSurface)& theSurface1,
|
||||
const Handle(Geom_BezierSurface)& theSurface2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
// Compare degrees
|
||||
if (theSurface1->UDegree() != theSurface2->UDegree()
|
||||
|| theSurface1->VDegree() != theSurface2->VDegree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare rationality
|
||||
if (theSurface1->IsURational() != theSurface2->IsURational()
|
||||
|| theSurface1->IsVRational() != theSurface2->IsVRational())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
|
||||
// Compare poles
|
||||
for (int i = 1; i <= theSurface1->NbUPoles(); ++i)
|
||||
{
|
||||
for (int j = 1; j <= theSurface1->NbVPoles(); ++j)
|
||||
{
|
||||
if (!aPointHasher(theSurface1->Pole(i, j), theSurface2->Pole(i, j)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compare weights if rational
|
||||
if (theSurface1->IsURational() || theSurface1->IsVRational())
|
||||
{
|
||||
for (int i = 1; i <= theSurface1->NbUPoles(); ++i)
|
||||
{
|
||||
for (int j = 1; j <= theSurface1->NbVPoles(); ++j)
|
||||
{
|
||||
if (std::abs(theSurface1->Weight(i, j) - theSurface2->Weight(i, j)) > aTolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_BezierSurfaceHasher_HeaderFile
|
||||
51
src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx
Normal file
51
src/ModelingData/TKG3d/GeomHash/GeomHash_CircleHasher.pxx
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_CircleHasher_HeaderFile
|
||||
#define _GeomHash_CircleHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_Circle (3D circle).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_CircleHasher
|
||||
{
|
||||
// Hashes the circle by its position and radius.
|
||||
std::size_t operator()(const Handle(Geom_Circle)& theCircle) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theCircle->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCircle->Radius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two circles by their positions and radii.
|
||||
bool operator()(const Handle(Geom_Circle)& theCircle1,
|
||||
const Handle(Geom_Circle)& theCircle2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theCircle1->Position(), theCircle2->Position())
|
||||
&& std::abs(theCircle1->Radius() - theCircle2->Radius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_CircleHasher_HeaderFile
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_ConicalSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_ConicalSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_ConicalSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_ConicalSurfaceHasher
|
||||
{
|
||||
// Hashes the cone by its position, apex radius, and semi-angle.
|
||||
std::size_t operator()(const Handle(Geom_ConicalSurface)& theCone) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theCone->Position().Ax2()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCone->RefRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCone->SemiAngle() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two cones by their positions, radii, and semi-angles.
|
||||
bool operator()(const Handle(Geom_ConicalSurface)& theCone1,
|
||||
const Handle(Geom_ConicalSurface)& theCone2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(theCone1->Position().Ax2(), theCone2->Position().Ax2())
|
||||
&& std::abs(theCone1->RefRadius() - theCone2->RefRadius()) <= aTolerance
|
||||
&& std::abs(theCone1->SemiAngle() - theCone2->SemiAngle()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_ConicalSurfaceHasher_HeaderFile
|
||||
150
src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx
Normal file
150
src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.cxx
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
|
||||
#include <GeomHash_LineHasher.pxx>
|
||||
#include <GeomHash_CircleHasher.pxx>
|
||||
#include <GeomHash_EllipseHasher.pxx>
|
||||
#include <GeomHash_HyperbolaHasher.pxx>
|
||||
#include <GeomHash_ParabolaHasher.pxx>
|
||||
#include <GeomHash_BezierCurveHasher.pxx>
|
||||
#include <GeomHash_BSplineCurveHasher.pxx>
|
||||
#include <GeomHash_TrimmedCurveHasher.pxx>
|
||||
#include <GeomHash_OffsetCurveHasher.pxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
std::size_t GeomHash_CurveHasher::operator()(const Handle(Geom_Curve)& theCurve) const noexcept
|
||||
{
|
||||
if (theCurve.IsNull())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dispatch based on actual curve type
|
||||
if (Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_LineHasher{}(aLine);
|
||||
}
|
||||
if (Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_CircleHasher{}(aCircle);
|
||||
}
|
||||
if (Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_EllipseHasher{}(anEllipse);
|
||||
}
|
||||
if (Handle(Geom_Hyperbola) aHyperbola = Handle(Geom_Hyperbola)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_HyperbolaHasher{}(aHyperbola);
|
||||
}
|
||||
if (Handle(Geom_Parabola) aParabola = Handle(Geom_Parabola)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_ParabolaHasher{}(aParabola);
|
||||
}
|
||||
if (Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_BezierCurveHasher{}(aBezier);
|
||||
}
|
||||
if (Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_BSplineCurveHasher{}(aBSpline);
|
||||
}
|
||||
if (Handle(Geom_TrimmedCurve) aTrimmed = Handle(Geom_TrimmedCurve)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_TrimmedCurveHasher{}(aTrimmed);
|
||||
}
|
||||
if (Handle(Geom_OffsetCurve) anOffset = Handle(Geom_OffsetCurve)::DownCast(theCurve))
|
||||
{
|
||||
return GeomHash_OffsetCurveHasher{}(anOffset);
|
||||
}
|
||||
|
||||
// Unknown curve type - hash the type name
|
||||
return std::hash<std::string>{}(theCurve->DynamicType()->Name());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool GeomHash_CurveHasher::operator()(const Handle(Geom_Curve)& theCurve1,
|
||||
const Handle(Geom_Curve)& theCurve2) const noexcept
|
||||
{
|
||||
if (theCurve1.IsNull() || theCurve2.IsNull())
|
||||
{
|
||||
return theCurve1.IsNull() && theCurve2.IsNull();
|
||||
}
|
||||
|
||||
if (theCurve1 == theCurve2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be same type
|
||||
if (theCurve1->DynamicType() != theCurve2->DynamicType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dispatch based on actual curve type
|
||||
if (Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_LineHasher{}(aLine1, Handle(Geom_Line)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_Circle) aCircle1 = Handle(Geom_Circle)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_CircleHasher{}(aCircle1, Handle(Geom_Circle)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_Ellipse) anEllipse1 = Handle(Geom_Ellipse)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_EllipseHasher{}(anEllipse1, Handle(Geom_Ellipse)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_Hyperbola) aHyp1 = Handle(Geom_Hyperbola)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_HyperbolaHasher{}(aHyp1, Handle(Geom_Hyperbola)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_Parabola) aPar1 = Handle(Geom_Parabola)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_ParabolaHasher{}(aPar1, Handle(Geom_Parabola)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_BezierCurve) aBez1 = Handle(Geom_BezierCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_BezierCurveHasher{}(aBez1, Handle(Geom_BezierCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_BSplineCurve) aBSpl1 = Handle(Geom_BSplineCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_BSplineCurveHasher{}(aBSpl1, Handle(Geom_BSplineCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_TrimmedCurve) aTrim1 = Handle(Geom_TrimmedCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_TrimmedCurveHasher{}(aTrim1, Handle(Geom_TrimmedCurve)::DownCast(theCurve2));
|
||||
}
|
||||
if (Handle(Geom_OffsetCurve) aOff1 = Handle(Geom_OffsetCurve)::DownCast(theCurve1))
|
||||
{
|
||||
return GeomHash_OffsetCurveHasher{}(aOff1, Handle(Geom_OffsetCurve)::DownCast(theCurve2));
|
||||
}
|
||||
|
||||
// Unknown curve type - compare by pointer
|
||||
return theCurve1.get() == theCurve2.get();
|
||||
}
|
||||
34
src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx
Normal file
34
src/ModelingData/TKG3d/GeomHash/GeomHash_CurveHasher.hxx
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_CurveHasher_HeaderFile
|
||||
#define _GeomHash_CurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <cstddef>
|
||||
|
||||
class Geom_Curve;
|
||||
|
||||
//! Polymorphic hasher for Geom_Curve using RTTI dispatch.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_CurveHasher
|
||||
{
|
||||
// Hashes any Geom_Curve by dispatching to the appropriate specific hasher.
|
||||
Standard_EXPORT std::size_t operator()(const Handle(Geom_Curve)& theCurve) const noexcept;
|
||||
|
||||
// Compares two curves using polymorphic dispatch.
|
||||
Standard_EXPORT bool operator()(const Handle(Geom_Curve)& theCurve1,
|
||||
const Handle(Geom_Curve)& theCurve2) const noexcept;
|
||||
};
|
||||
|
||||
#endif // _GeomHash_CurveHasher_HeaderFile
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_CylindricalSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_CylindricalSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_CylindricalSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_CylindricalSurfaceHasher
|
||||
{
|
||||
// Hashes the cylinder by its position and radius.
|
||||
std::size_t operator()(const Handle(Geom_CylindricalSurface)& theCylinder) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theCylinder->Position().Ax2()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCylinder->Radius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two cylinders by their positions and radii.
|
||||
bool operator()(const Handle(Geom_CylindricalSurface)& theCylinder1,
|
||||
const Handle(Geom_CylindricalSurface)& theCylinder2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(theCylinder1->Position().Ax2(), theCylinder2->Position().Ax2())
|
||||
&& std::abs(theCylinder1->Radius() - theCylinder2->Radius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_CylindricalSurfaceHasher_HeaderFile
|
||||
49
src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx
Normal file
49
src/ModelingData/TKG3d/GeomHash/GeomHash_DirectionHasher.pxx
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_DirectionHasher_HeaderFile
|
||||
#define _GeomHash_DirectionHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for gp_Dir (3D directions).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_DirectionHasher
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Round each component to tolerance precision before hashing
|
||||
const std::size_t aHashes[3] = {
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theDirection.X() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theDirection.Y() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theDirection.Z() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_DirectionHasher_HeaderFile
|
||||
53
src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx
Normal file
53
src/ModelingData/TKG3d/GeomHash/GeomHash_EllipseHasher.pxx
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_EllipseHasher_HeaderFile
|
||||
#define _GeomHash_EllipseHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_Ellipse (3D ellipse).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_EllipseHasher
|
||||
{
|
||||
// Hashes the ellipse by its position, major radius, and minor radius.
|
||||
std::size_t operator()(const Handle(Geom_Ellipse)& theEllipse) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theEllipse->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theEllipse->MajorRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theEllipse->MinorRadius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two ellipses by their positions and radii.
|
||||
bool operator()(const Handle(Geom_Ellipse)& theEllipse1,
|
||||
const Handle(Geom_Ellipse)& theEllipse2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theEllipse1->Position(), theEllipse2->Position())
|
||||
&& std::abs(theEllipse1->MajorRadius() - theEllipse2->MajorRadius()) <= aTolerance
|
||||
&& std::abs(theEllipse1->MinorRadius() - theEllipse2->MinorRadius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_EllipseHasher_HeaderFile
|
||||
53
src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx
Normal file
53
src/ModelingData/TKG3d/GeomHash/GeomHash_HyperbolaHasher.pxx
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_HyperbolaHasher_HeaderFile
|
||||
#define _GeomHash_HyperbolaHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_Hyperbola (3D hyperbola).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_HyperbolaHasher
|
||||
{
|
||||
// Hashes the hyperbola by its position, major radius, and minor radius.
|
||||
std::size_t operator()(const Handle(Geom_Hyperbola)& theHyperbola) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theHyperbola->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theHyperbola->MajorRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theHyperbola->MinorRadius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two hyperbolas by their positions and radii.
|
||||
bool operator()(const Handle(Geom_Hyperbola)& theHyperbola1,
|
||||
const Handle(Geom_Hyperbola)& theHyperbola2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theHyperbola1->Position(), theHyperbola2->Position())
|
||||
&& std::abs(theHyperbola1->MajorRadius() - theHyperbola2->MajorRadius()) <= aTolerance
|
||||
&& std::abs(theHyperbola1->MinorRadius() - theHyperbola2->MinorRadius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_HyperbolaHasher_HeaderFile
|
||||
49
src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx
Normal file
49
src/ModelingData/TKG3d/GeomHash/GeomHash_LineHasher.pxx
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_LineHasher_HeaderFile
|
||||
#define _GeomHash_LineHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <GeomHash_DirectionHasher.pxx>
|
||||
|
||||
//! OCCT-style hasher for Geom_Line (3D line).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_LineHasher
|
||||
{
|
||||
// Hashes the line by its location and direction.
|
||||
std::size_t operator()(const Handle(Geom_Line)& theLine) const noexcept
|
||||
{
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
|
||||
const std::size_t aHashes[2] = {aPointHasher(theLine->Position().Location()),
|
||||
aDirHasher(theLine->Position().Direction())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two lines by their positions.
|
||||
bool operator()(const Handle(Geom_Line)& theLine1,
|
||||
const Handle(Geom_Line)& theLine2) const noexcept
|
||||
{
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
|
||||
return aPointHasher(theLine1->Position().Location(), theLine2->Position().Location())
|
||||
&& aDirHasher(theLine1->Position().Direction(), theLine2->Position().Direction());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_LineHasher_HeaderFile
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_OffsetCurveHasher_HeaderFile
|
||||
#define _GeomHash_OffsetCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
#include <GeomHash_DirectionHasher.pxx>
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_OffsetCurve (3D offset curve).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_OffsetCurveHasher
|
||||
{
|
||||
// Hashes the offset curve by its offset distance, direction, and basis curve.
|
||||
std::size_t operator()(const Handle(Geom_OffsetCurve)& theCurve) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
aCurveHasher(theCurve->BasisCurve()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->Offset() * aFactor))),
|
||||
aDirHasher(theCurve->Direction())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two offset curves.
|
||||
bool operator()(const Handle(Geom_OffsetCurve)& theCurve1,
|
||||
const Handle(Geom_OffsetCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
|
||||
return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve())
|
||||
&& std::abs(theCurve1->Offset() - theCurve2->Offset()) <= aTolerance
|
||||
&& aDirHasher(theCurve1->Direction(), theCurve2->Direction());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_OffsetCurveHasher_HeaderFile
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_OffsetSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_OffsetSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_OffsetSurface.hxx>
|
||||
#include <GeomHash_SurfaceHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_OffsetSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_OffsetSurfaceHasher
|
||||
{
|
||||
// Hashes the offset surface by its offset distance and basis surface.
|
||||
std::size_t operator()(const Handle(Geom_OffsetSurface)& theSurface) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_SurfaceHasher aSurfaceHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
aSurfaceHasher(theSurface->BasisSurface()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theSurface->Offset() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two offset surfaces by their offset distances and basis surfaces.
|
||||
bool operator()(const Handle(Geom_OffsetSurface)& theSurface1,
|
||||
const Handle(Geom_OffsetSurface)& theSurface2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const GeomHash_SurfaceHasher aSurfaceHasher;
|
||||
|
||||
return aSurfaceHasher(theSurface1->BasisSurface(), theSurface2->BasisSurface())
|
||||
&& std::abs(theSurface1->Offset() - theSurface2->Offset()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_OffsetSurfaceHasher_HeaderFile
|
||||
51
src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx
Normal file
51
src/ModelingData/TKG3d/GeomHash/GeomHash_ParabolaHasher.pxx
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_ParabolaHasher_HeaderFile
|
||||
#define _GeomHash_ParabolaHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_Parabola (3D parabola).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_ParabolaHasher
|
||||
{
|
||||
// Hashes the parabola by its position and focal length.
|
||||
std::size_t operator()(const Handle(Geom_Parabola)& theParabola) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theParabola->Position()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theParabola->Focal() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two parabolas by their positions and focal lengths.
|
||||
bool operator()(const Handle(Geom_Parabola)& theParabola1,
|
||||
const Handle(Geom_Parabola)& theParabola2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
|
||||
return anAxisHasher(theParabola1->Position(), theParabola2->Position())
|
||||
&& std::abs(theParabola1->Focal() - theParabola2->Focal()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_ParabolaHasher_HeaderFile
|
||||
41
src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx
Normal file
41
src/ModelingData/TKG3d/GeomHash/GeomHash_PlaneHasher.pxx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_PlaneHasher_HeaderFile
|
||||
#define _GeomHash_PlaneHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
|
||||
//! OCCT-style hasher for Geom_Plane surfaces.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_PlaneHasher
|
||||
{
|
||||
// Hashes the plane by its position (location, normal, reference direction).
|
||||
std::size_t operator()(const Handle(Geom_Plane)& thePlane) const noexcept
|
||||
{
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(thePlane->Position().Ax2());
|
||||
}
|
||||
|
||||
// Compares two planes by their positions.
|
||||
bool operator()(const Handle(Geom_Plane)& thePlane1,
|
||||
const Handle(Geom_Plane)& thePlane2) const noexcept
|
||||
{
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(thePlane1->Position().Ax2(), thePlane2->Position().Ax2());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_PlaneHasher_HeaderFile
|
||||
49
src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx
Normal file
49
src/ModelingData/TKG3d/GeomHash/GeomHash_PointHasher.pxx
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_PointHasher_HeaderFile
|
||||
#define _GeomHash_PointHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for gp_Pnt (3D points).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_PointHasher
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Round each coordinate to tolerance precision before hashing
|
||||
const std::size_t aHashes[3] = {
|
||||
opencascade::hash(static_cast<int64_t>(std::round(thePoint.X() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(thePoint.Y() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(thePoint.Z() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_PointHasher_HeaderFile
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_RectangularTrimmedSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_RectangularTrimmedSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_RectangularTrimmedSurface.hxx>
|
||||
#include <GeomHash_SurfaceHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_RectangularTrimmedSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_RectangularTrimmedSurfaceHasher
|
||||
{
|
||||
// Hashes the trimmed surface by its trim bounds and basis surface.
|
||||
std::size_t operator()(const Handle(Geom_RectangularTrimmedSurface)& theSurface) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_SurfaceHasher aSurfaceHasher;
|
||||
|
||||
double aU1, aU2, aV1, aV2;
|
||||
theSurface->Bounds(aU1, aU2, aV1, aV2);
|
||||
|
||||
const std::size_t aHashes[5] = {
|
||||
aSurfaceHasher(theSurface->BasisSurface()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(aU1 * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(aU2 * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(aV1 * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(aV2 * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two trimmed surfaces by their trim bounds and basis surfaces.
|
||||
bool operator()(const Handle(Geom_RectangularTrimmedSurface)& theSurface1,
|
||||
const Handle(Geom_RectangularTrimmedSurface)& theSurface2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const GeomHash_SurfaceHasher aSurfaceHasher;
|
||||
|
||||
// Compare basis surfaces
|
||||
if (!aSurfaceHasher(theSurface1->BasisSurface(), theSurface2->BasisSurface()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare trim bounds
|
||||
double aU1_1, aU2_1, aV1_1, aV2_1;
|
||||
double aU1_2, aU2_2, aV1_2, aV2_2;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_RectangularTrimmedSurfaceHasher_HeaderFile
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_SphericalSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_SphericalSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_SphericalSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_SphericalSurfaceHasher
|
||||
{
|
||||
// Hashes the sphere by its position and radius.
|
||||
std::size_t operator()(const Handle(Geom_SphericalSurface)& theSphere) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[2] = {
|
||||
anAxisHasher(theSphere->Position().Ax2()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theSphere->Radius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two spheres by their positions and radii.
|
||||
bool operator()(const Handle(Geom_SphericalSurface)& theSphere1,
|
||||
const Handle(Geom_SphericalSurface)& theSphere2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(theSphere1->Position().Ax2(), theSphere2->Position().Ax2())
|
||||
&& std::abs(theSphere1->Radius() - theSphere2->Radius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_SphericalSurfaceHasher_HeaderFile
|
||||
191
src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx
Normal file
191
src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.cxx
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <GeomHash_SurfaceHasher.hxx>
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <Geom_SurfaceOfRevolution.hxx>
|
||||
#include <Geom_SurfaceOfLinearExtrusion.hxx>
|
||||
#include <Geom_BezierSurface.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <Geom_RectangularTrimmedSurface.hxx>
|
||||
#include <Geom_OffsetSurface.hxx>
|
||||
|
||||
#include <GeomHash_PlaneHasher.pxx>
|
||||
#include <GeomHash_CylindricalSurfaceHasher.pxx>
|
||||
#include <GeomHash_ConicalSurfaceHasher.pxx>
|
||||
#include <GeomHash_SphericalSurfaceHasher.pxx>
|
||||
#include <GeomHash_ToroidalSurfaceHasher.pxx>
|
||||
#include <GeomHash_SurfaceOfRevolutionHasher.pxx>
|
||||
#include <GeomHash_SurfaceOfLinearExtrusionHasher.pxx>
|
||||
#include <GeomHash_BezierSurfaceHasher.pxx>
|
||||
#include <GeomHash_BSplineSurfaceHasher.pxx>
|
||||
#include <GeomHash_RectangularTrimmedSurfaceHasher.pxx>
|
||||
#include <GeomHash_OffsetSurfaceHasher.pxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
std::size_t GeomHash_SurfaceHasher::operator()(
|
||||
const Handle(Geom_Surface)& theSurface) const noexcept
|
||||
{
|
||||
if (theSurface.IsNull())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dispatch based on actual surface type
|
||||
if (Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_PlaneHasher{}(aPlane);
|
||||
}
|
||||
if (Handle(Geom_CylindricalSurface) aCylinder =
|
||||
Handle(Geom_CylindricalSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_CylindricalSurfaceHasher{}(aCylinder);
|
||||
}
|
||||
if (Handle(Geom_ConicalSurface) aCone = Handle(Geom_ConicalSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_ConicalSurfaceHasher{}(aCone);
|
||||
}
|
||||
if (Handle(Geom_SphericalSurface) aSphere = Handle(Geom_SphericalSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_SphericalSurfaceHasher{}(aSphere);
|
||||
}
|
||||
if (Handle(Geom_ToroidalSurface) aTorus = Handle(Geom_ToroidalSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_ToroidalSurfaceHasher{}(aTorus);
|
||||
}
|
||||
if (Handle(Geom_SurfaceOfRevolution) aRevol =
|
||||
Handle(Geom_SurfaceOfRevolution)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_SurfaceOfRevolutionHasher{}(aRevol);
|
||||
}
|
||||
if (Handle(Geom_SurfaceOfLinearExtrusion) aExtr =
|
||||
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_SurfaceOfLinearExtrusionHasher{}(aExtr);
|
||||
}
|
||||
if (Handle(Geom_BezierSurface) aBezier = Handle(Geom_BezierSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_BezierSurfaceHasher{}(aBezier);
|
||||
}
|
||||
if (Handle(Geom_BSplineSurface) aBSpline = Handle(Geom_BSplineSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_BSplineSurfaceHasher{}(aBSpline);
|
||||
}
|
||||
if (Handle(Geom_RectangularTrimmedSurface) aTrimmed =
|
||||
Handle(Geom_RectangularTrimmedSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_RectangularTrimmedSurfaceHasher{}(aTrimmed);
|
||||
}
|
||||
if (Handle(Geom_OffsetSurface) aOffset = Handle(Geom_OffsetSurface)::DownCast(theSurface))
|
||||
{
|
||||
return GeomHash_OffsetSurfaceHasher{}(aOffset);
|
||||
}
|
||||
|
||||
// Unknown surface type - hash the type name
|
||||
return std::hash<std::string>{}(theSurface->DynamicType()->Name());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool GeomHash_SurfaceHasher::operator()(const Handle(Geom_Surface)& theSurface1,
|
||||
const Handle(Geom_Surface)& theSurface2) const noexcept
|
||||
{
|
||||
if (theSurface1.IsNull() || theSurface2.IsNull())
|
||||
{
|
||||
return theSurface1.IsNull() && theSurface2.IsNull();
|
||||
}
|
||||
|
||||
if (theSurface1 == theSurface2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be same type
|
||||
if (theSurface1->DynamicType() != theSurface2->DynamicType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dispatch based on actual surface type
|
||||
if (Handle(Geom_Plane) aPlane1 = Handle(Geom_Plane)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_PlaneHasher{}(aPlane1, Handle(Geom_Plane)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_CylindricalSurface) aCyl1 =
|
||||
Handle(Geom_CylindricalSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_CylindricalSurfaceHasher{}(
|
||||
aCyl1,
|
||||
Handle(Geom_CylindricalSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_ConicalSurface) aCone1 = Handle(Geom_ConicalSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_ConicalSurfaceHasher{}(aCone1,
|
||||
Handle(Geom_ConicalSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_SphericalSurface) aSph1 = Handle(Geom_SphericalSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_SphericalSurfaceHasher{}(aSph1,
|
||||
Handle(Geom_SphericalSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_ToroidalSurface) aTor1 = Handle(Geom_ToroidalSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_ToroidalSurfaceHasher{}(aTor1,
|
||||
Handle(Geom_ToroidalSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_SurfaceOfRevolution) aRev1 =
|
||||
Handle(Geom_SurfaceOfRevolution)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_SurfaceOfRevolutionHasher{}(
|
||||
aRev1,
|
||||
Handle(Geom_SurfaceOfRevolution)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_SurfaceOfLinearExtrusion) aExt1 =
|
||||
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_SurfaceOfLinearExtrusionHasher{}(
|
||||
aExt1,
|
||||
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_BezierSurface) aBez1 = Handle(Geom_BezierSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_BezierSurfaceHasher{}(aBez1, Handle(Geom_BezierSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_BSplineSurface) aBSpl1 = Handle(Geom_BSplineSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_BSplineSurfaceHasher{}(aBSpl1,
|
||||
Handle(Geom_BSplineSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_RectangularTrimmedSurface) aTrim1 =
|
||||
Handle(Geom_RectangularTrimmedSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_RectangularTrimmedSurfaceHasher{}(
|
||||
aTrim1,
|
||||
Handle(Geom_RectangularTrimmedSurface)::DownCast(theSurface2));
|
||||
}
|
||||
if (Handle(Geom_OffsetSurface) aOff1 = Handle(Geom_OffsetSurface)::DownCast(theSurface1))
|
||||
{
|
||||
return GeomHash_OffsetSurfaceHasher{}(aOff1, Handle(Geom_OffsetSurface)::DownCast(theSurface2));
|
||||
}
|
||||
|
||||
// Unknown surface type - compare by pointer
|
||||
return theSurface1.get() == theSurface2.get();
|
||||
}
|
||||
34
src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx
Normal file
34
src/ModelingData/TKG3d/GeomHash/GeomHash_SurfaceHasher.hxx
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_SurfaceHasher_HeaderFile
|
||||
#define _GeomHash_SurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <cstddef>
|
||||
|
||||
class Geom_Surface;
|
||||
|
||||
//! Polymorphic hasher for Geom_Surface using RTTI dispatch.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_SurfaceHasher
|
||||
{
|
||||
// Hashes any Geom_Surface by dispatching to the appropriate specific hasher.
|
||||
Standard_EXPORT std::size_t operator()(const Handle(Geom_Surface)& theSurface) const noexcept;
|
||||
|
||||
// Compares two surfaces using polymorphic dispatch.
|
||||
Standard_EXPORT bool operator()(const Handle(Geom_Surface)& theSurface1,
|
||||
const Handle(Geom_Surface)& theSurface2) const noexcept;
|
||||
};
|
||||
|
||||
#endif // _GeomHash_SurfaceHasher_HeaderFile
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_SurfaceOfLinearExtrusionHasher_HeaderFile
|
||||
#define _GeomHash_SurfaceOfLinearExtrusionHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_SurfaceOfLinearExtrusion.hxx>
|
||||
#include <GeomHash_DirectionHasher.pxx>
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
|
||||
//! OCCT-style hasher for Geom_SurfaceOfLinearExtrusion.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_SurfaceOfLinearExtrusionHasher
|
||||
{
|
||||
// Hashes the extrusion surface by its direction and basis curve.
|
||||
std::size_t operator()(const Handle(Geom_SurfaceOfLinearExtrusion)& theSurface) const noexcept
|
||||
{
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
const std::size_t aHashes[2] = {aCurveHasher(theSurface->BasisCurve()),
|
||||
aDirHasher(theSurface->Direction())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two extrusion surfaces.
|
||||
bool operator()(const Handle(Geom_SurfaceOfLinearExtrusion)& theSurface1,
|
||||
const Handle(Geom_SurfaceOfLinearExtrusion)& theSurface2) const noexcept
|
||||
{
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
|
||||
return aCurveHasher(theSurface1->BasisCurve(), theSurface2->BasisCurve())
|
||||
&& aDirHasher(theSurface1->Direction(), theSurface2->Direction());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_SurfaceOfLinearExtrusionHasher_HeaderFile
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_SurfaceOfRevolutionHasher_HeaderFile
|
||||
#define _GeomHash_SurfaceOfRevolutionHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_SurfaceOfRevolution.hxx>
|
||||
#include <GeomHash_PointHasher.pxx>
|
||||
#include <GeomHash_DirectionHasher.pxx>
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
|
||||
//! OCCT-style hasher for Geom_SurfaceOfRevolution.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_SurfaceOfRevolutionHasher
|
||||
{
|
||||
// Hashes the revolution surface by its axis and basis curve.
|
||||
std::size_t operator()(const Handle(Geom_SurfaceOfRevolution)& theSurface) const noexcept
|
||||
{
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
|
||||
const gp_Ax1& anAxis = theSurface->Axis();
|
||||
const std::size_t aHashes[3] = {aCurveHasher(theSurface->BasisCurve()),
|
||||
aPointHasher(anAxis.Location()),
|
||||
aDirHasher(anAxis.Direction())};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two revolution surfaces.
|
||||
bool operator()(const Handle(Geom_SurfaceOfRevolution)& theSurface1,
|
||||
const Handle(Geom_SurfaceOfRevolution)& theSurface2) const noexcept
|
||||
{
|
||||
const GeomHash_PointHasher aPointHasher;
|
||||
const GeomHash_DirectionHasher aDirHasher;
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
|
||||
const gp_Ax1& anAxis1 = theSurface1->Axis();
|
||||
const gp_Ax1& anAxis2 = theSurface2->Axis();
|
||||
|
||||
return aCurveHasher(theSurface1->BasisCurve(), theSurface2->BasisCurve())
|
||||
&& aPointHasher(anAxis1.Location(), anAxis2.Location())
|
||||
&& aDirHasher(anAxis1.Direction(), anAxis2.Direction());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_SurfaceOfRevolutionHasher_HeaderFile
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_ToroidalSurfaceHasher_HeaderFile
|
||||
#define _GeomHash_ToroidalSurfaceHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <GeomHash_AxisPlacement.pxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_ToroidalSurface.
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_ToroidalSurfaceHasher
|
||||
{
|
||||
// Hashes the torus by its position, major radius, and minor radius.
|
||||
std::size_t operator()(const Handle(Geom_ToroidalSurface)& theTorus) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
anAxisHasher(theTorus->Position().Ax2()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theTorus->MajorRadius() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theTorus->MinorRadius() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two tori by their positions, major radii, and minor radii.
|
||||
bool operator()(const Handle(Geom_ToroidalSurface)& theTorus1,
|
||||
const Handle(Geom_ToroidalSurface)& theTorus2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
const GeomHash_AxisPlacement anAxisHasher;
|
||||
return anAxisHasher(theTorus1->Position().Ax2(), theTorus2->Position().Ax2())
|
||||
&& std::abs(theTorus1->MajorRadius() - theTorus2->MajorRadius()) <= aTolerance
|
||||
&& std::abs(theTorus1->MinorRadius() - theTorus2->MinorRadius()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_ToroidalSurfaceHasher_HeaderFile
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_TrimmedCurveHasher_HeaderFile
|
||||
#define _GeomHash_TrimmedCurveHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <GeomHash_CurveHasher.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for Geom_TrimmedCurve (3D trimmed curve).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_TrimmedCurveHasher
|
||||
{
|
||||
// Hashes the trimmed curve by its parameters and basis curve.
|
||||
std::size_t operator()(const Handle(Geom_TrimmedCurve)& theCurve) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
constexpr double aFactor = 1.0 / aTolerance;
|
||||
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
const std::size_t aHashes[3] = {
|
||||
aCurveHasher(theCurve->BasisCurve()),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->FirstParameter() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theCurve->LastParameter() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// Compares two trimmed curves.
|
||||
bool operator()(const Handle(Geom_TrimmedCurve)& theCurve1,
|
||||
const Handle(Geom_TrimmedCurve)& theCurve2) const noexcept
|
||||
{
|
||||
constexpr double aTolerance = 1e-12;
|
||||
|
||||
const GeomHash_CurveHasher aCurveHasher;
|
||||
|
||||
return aCurveHasher(theCurve1->BasisCurve(), theCurve2->BasisCurve())
|
||||
&& std::abs(theCurve1->FirstParameter() - theCurve2->FirstParameter()) <= aTolerance
|
||||
&& std::abs(theCurve1->LastParameter() - theCurve2->LastParameter()) <= aTolerance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_TrimmedCurveHasher_HeaderFile
|
||||
49
src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx
Normal file
49
src/ModelingData/TKG3d/GeomHash/GeomHash_VectorHasher.pxx
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _GeomHash_VectorHasher_HeaderFile
|
||||
#define _GeomHash_VectorHasher_HeaderFile
|
||||
|
||||
#include <Standard_HashUtils.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <cmath>
|
||||
|
||||
//! OCCT-style hasher for gp_Vec (3D vectors).
|
||||
//! Used for geometry deduplication.
|
||||
struct GeomHash_VectorHasher
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Round each component to tolerance precision before hashing
|
||||
const std::size_t aHashes[3] = {
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theVector.X() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theVector.Y() * aFactor))),
|
||||
opencascade::hash(static_cast<int64_t>(std::round(theVector.Z() * aFactor)))};
|
||||
return opencascade::hashBytes(aHashes, sizeof(aHashes));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GeomHash_VectorHasher_HeaderFile
|
||||
@@ -10,4 +10,5 @@ set(OCCT_TKG3d_LIST_OF_PACKAGES
|
||||
TopAbs
|
||||
GeomEvaluator
|
||||
GProp
|
||||
GeomHash
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user