mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-06-05 03:47:46 +08:00
Modeling Data - Fix IsClosed/IsPeriodic tolerance and add TKG2d GTests (#1109)
IsClosed() methods across curve and surface classes used gp::Resolution() (~1e-290) for point distance comparison, making the check practically unusable for floating-point evaluated points. Replaced with Precision::Computational() (~DBL_EPSILON) which correctly represents machine-precision arithmetic equality. TrimmedCurve (2D/3D) and RectangularTrimmedSurface IsClosed() and IsPeriodic() now detect when the trim spans an integer multiple of the basis geometry period using std::remainder(), instead of unconditionally returning false for trimmed parametric ranges. Added 17 new GTest files (271 tests) for TKG2d covering previously untested packages: Adaptor2d, Geom2dLProp, LProp, and fundamental Geom2d classes (Circle, Ellipse, Line, Hyperbola, Parabola, TrimmedCurve, Transformation, VectorWithMagnitude, Direction, CartesianPoint, AxisPlacement). IsClosed() tolerance fix applied to: - Geom2d_TrimmedCurve, Geom_TrimmedCurve - Geom2d_BSplineCurve, Geom_BSplineCurve - Geom2d_OffsetCurve, Geom_OffsetCurve IsPeriodic() / IsUPeriodic() / IsVPeriodic() fix applied to: - Geom2d_TrimmedCurve, Geom_TrimmedCurve - Geom_RectangularTrimmedSurface (also IsUClosed/IsVClosed)
This commit is contained in:
227
src/ModelingData/TKG2d/GTests/Adaptor2d_Line2d_Test.cxx
Normal file
227
src/ModelingData/TKG2d/GTests/Adaptor2d_Line2d_Test.cxx
Normal file
@@ -0,0 +1,227 @@
|
||||
// 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 <Adaptor2d_Line2d.hxx>
|
||||
#include <GeomAbs_CurveType.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class Adaptor2d_Line2dTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Line through origin along direction (1, 0) with bounds [0, 10]
|
||||
myLine = new Adaptor2d_Line2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), 0.0, 10.0);
|
||||
|
||||
// Line through (1, 2) along direction (3, 4)/5 with bounds [-5, 5]
|
||||
myDiagLine =
|
||||
new Adaptor2d_Line2d(gp_Pnt2d(1.0, 2.0), gp_Dir2d(3.0 / 5.0, 4.0 / 5.0), -5.0, 5.0);
|
||||
}
|
||||
|
||||
occ::handle<Adaptor2d_Line2d> myLine;
|
||||
occ::handle<Adaptor2d_Line2d> myDiagLine;
|
||||
};
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, DefaultConstructor)
|
||||
{
|
||||
Adaptor2d_Line2d aLine;
|
||||
EXPECT_EQ(aLine.GetType(), GeomAbs_Line);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, ParameterBounds)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(myLine->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(myLine->LastParameter(), 10.0);
|
||||
EXPECT_DOUBLE_EQ(myDiagLine->FirstParameter(), -5.0);
|
||||
EXPECT_DOUBLE_EQ(myDiagLine->LastParameter(), 5.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Continuity)
|
||||
{
|
||||
EXPECT_EQ(myLine->Continuity(), GeomAbs_CN);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, NbIntervals)
|
||||
{
|
||||
EXPECT_EQ(myLine->NbIntervals(GeomAbs_C0), 1);
|
||||
EXPECT_EQ(myLine->NbIntervals(GeomAbs_CN), 1);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Intervals)
|
||||
{
|
||||
NCollection_Array1<double> anIntervals(1, 2);
|
||||
myLine->Intervals(anIntervals, GeomAbs_CN);
|
||||
EXPECT_DOUBLE_EQ(anIntervals(1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(anIntervals(2), 10.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, IsNotClosed)
|
||||
{
|
||||
EXPECT_FALSE(myLine->IsClosed());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, IsNotPeriodic)
|
||||
{
|
||||
EXPECT_FALSE(myLine->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, GetType)
|
||||
{
|
||||
EXPECT_EQ(myLine->GetType(), GeomAbs_Line);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Value_AtOrigin)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myLine->Value(0.0);
|
||||
EXPECT_NEAR(aPnt.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Value_AtParameter)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myLine->Value(5.0);
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Value_DiagonalLine)
|
||||
{
|
||||
// At U=0, point should be origin (1, 2)
|
||||
const gp_Pnt2d aPnt0 = myDiagLine->Value(0.0);
|
||||
EXPECT_NEAR(aPnt0.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt0.Y(), 2.0, Precision::Confusion());
|
||||
|
||||
// At U=5, point should be (1 + 3, 2 + 4) = (4, 6)
|
||||
const gp_Pnt2d aPnt5 = myDiagLine->Value(5.0);
|
||||
EXPECT_NEAR(aPnt5.X(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt5.Y(), 6.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, D0)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
myLine->D0(3.0, aPnt);
|
||||
EXPECT_NEAR(aPnt.X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, D1_FirstDerivativeIsDirection)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aVec;
|
||||
myLine->D1(5.0, aPnt, aVec);
|
||||
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, D2_SecondDerivativeIsZero)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aV1, aV2;
|
||||
myLine->D2(5.0, aPnt, aV1, aV2);
|
||||
|
||||
EXPECT_NEAR(aV2.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, D3_ThirdDerivativeIsZero)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aV1, aV2, aV3;
|
||||
myLine->D3(5.0, aPnt, aV1, aV2, aV3);
|
||||
|
||||
EXPECT_NEAR(aV3.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, DN_FirstOrderMatchesD1)
|
||||
{
|
||||
const gp_Vec2d aDN1 = myLine->DN(5.0, 1);
|
||||
EXPECT_NEAR(aDN1.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDN1.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, DN_HigherOrderIsZero)
|
||||
{
|
||||
const gp_Vec2d aDN2 = myLine->DN(5.0, 2);
|
||||
EXPECT_NEAR(aDN2.Magnitude(), 0.0, Precision::Confusion());
|
||||
|
||||
const gp_Vec2d aDN3 = myLine->DN(5.0, 3);
|
||||
EXPECT_NEAR(aDN3.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Resolution)
|
||||
{
|
||||
// For a unit-speed line, resolution should equal the input tolerance
|
||||
const double aResolution = myLine->Resolution(0.001);
|
||||
EXPECT_NEAR(aResolution, 0.001, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, LineGeometry)
|
||||
{
|
||||
const gp_Lin2d aLin = myLine->Line();
|
||||
EXPECT_NEAR(aLin.Direction().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLin.Direction().Y(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLin.Location().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLin.Location().Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Load_WithLine)
|
||||
{
|
||||
Adaptor2d_Line2d aLine;
|
||||
gp_Lin2d aLin(gp_Pnt2d(1.0, 1.0), gp_Dir2d(0.0, 1.0));
|
||||
aLine.Load(aLin);
|
||||
|
||||
const gp_Pnt2d aPnt = aLine.Value(3.0);
|
||||
EXPECT_NEAR(aPnt.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Load_WithBounds)
|
||||
{
|
||||
Adaptor2d_Line2d aLine;
|
||||
gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
aLine.Load(aLin, 2.0, 8.0);
|
||||
|
||||
EXPECT_DOUBLE_EQ(aLine.FirstParameter(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(aLine.LastParameter(), 8.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, Trim)
|
||||
{
|
||||
occ::handle<Adaptor2d_Curve2d> aTrimmed = myLine->Trim(2.0, 7.0, Precision::Confusion());
|
||||
EXPECT_DOUBLE_EQ(aTrimmed->FirstParameter(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(aTrimmed->LastParameter(), 7.0);
|
||||
|
||||
const gp_Pnt2d aPnt = aTrimmed->Value(2.0);
|
||||
EXPECT_NEAR(aPnt.X(), 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_Line2dTest, ShallowCopy)
|
||||
{
|
||||
occ::handle<Adaptor2d_Curve2d> aCopy = myLine->ShallowCopy();
|
||||
EXPECT_DOUBLE_EQ(aCopy->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(aCopy->LastParameter(), 10.0);
|
||||
EXPECT_EQ(aCopy->GetType(), GeomAbs_Line);
|
||||
|
||||
const gp_Pnt2d aPnt = aCopy->Value(5.0);
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
}
|
||||
211
src/ModelingData/TKG2d/GTests/Adaptor2d_OffsetCurve_Test.cxx
Normal file
211
src/ModelingData/TKG2d/GTests/Adaptor2d_OffsetCurve_Test.cxx
Normal file
@@ -0,0 +1,211 @@
|
||||
// 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 <Adaptor2d_Line2d.hxx>
|
||||
#include <Adaptor2d_OffsetCurve.hxx>
|
||||
#include <GeomAbs_CurveType.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class Adaptor2d_OffsetCurveTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Horizontal line through origin, bounds [0, 10]
|
||||
myBaseLine = new Adaptor2d_Line2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0), 0.0, 10.0);
|
||||
}
|
||||
|
||||
occ::handle<Adaptor2d_Line2d> myBaseLine;
|
||||
};
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, DefaultConstructor)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset;
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 0.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, ConstructWithCurve_OffsetIsZero)
|
||||
{
|
||||
// Constructor with only curve sets offset to 0 and bounds to 0,0
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.LastParameter(), 0.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, ConstructWithOffset)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 3.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.LastParameter(), 10.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, ConstructWithOffsetAndBounds)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 2.0, 1.0, 8.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.FirstParameter(), 1.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.LastParameter(), 8.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Value_PositiveOffset)
|
||||
{
|
||||
// Offsetting a horizontal +X line by +3 shifts Y by -3
|
||||
// (OCCT 2D offset uses right-hand normal: Z cross tangent)
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
const gp_Pnt2d aPnt = anOffset.Value(5.0);
|
||||
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), -3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Value_NegativeOffset)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, -2.0);
|
||||
const gp_Pnt2d aPnt = anOffset.Value(5.0);
|
||||
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Value_ZeroOffset_MatchesBaseCurve)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 0.0);
|
||||
|
||||
for (double u = 0.0; u <= 10.0; u += 2.0)
|
||||
{
|
||||
const gp_Pnt2d aOffPnt = anOffset.Value(u);
|
||||
const gp_Pnt2d aBasePnt = myBaseLine->Value(u);
|
||||
EXPECT_TRUE(aOffPnt.IsEqual(aBasePnt, Precision::Confusion()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, D1_OffsetLine)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aVec;
|
||||
anOffset.D1(5.0, aPnt, aVec);
|
||||
|
||||
// First derivative of an offset line is same as the base line direction
|
||||
EXPECT_NEAR(aVec.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Continuity)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
// Offset of CN line is CN
|
||||
EXPECT_EQ(anOffset.Continuity(), GeomAbs_CN);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, NbIntervals)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
EXPECT_EQ(anOffset.NbIntervals(GeomAbs_CN), 1);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, GetType_Line)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
EXPECT_EQ(anOffset.GetType(), GeomAbs_Line);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, IsNotClosed)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
EXPECT_FALSE(anOffset.IsClosed());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, IsNotPeriodic)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
EXPECT_FALSE(anOffset.IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, LoadCurve_ResetsOffset)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 5.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 5.0);
|
||||
|
||||
// Load a new curve resets offset to 0
|
||||
occ::handle<Adaptor2d_Line2d> aNewLine =
|
||||
new Adaptor2d_Line2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(0.0, 1.0), 0.0, 5.0);
|
||||
anOffset.Load(aNewLine);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 0.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, LoadOffset)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 0.0);
|
||||
|
||||
anOffset.Load(7.5);
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 7.5);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, LoadOffsetWithBounds)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine);
|
||||
anOffset.Load(4.0, 2.0, 6.0);
|
||||
|
||||
EXPECT_DOUBLE_EQ(anOffset.Offset(), 4.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.FirstParameter(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(anOffset.LastParameter(), 6.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Curve_ReturnsBaseCurve)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
const occ::handle<Adaptor2d_Curve2d>& aCurve = anOffset.Curve();
|
||||
EXPECT_FALSE(aCurve.IsNull());
|
||||
EXPECT_EQ(aCurve->GetType(), GeomAbs_Line);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Trim)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
occ::handle<Adaptor2d_Curve2d> aTrimmed = anOffset.Trim(2.0, 7.0, Precision::Confusion());
|
||||
|
||||
EXPECT_DOUBLE_EQ(aTrimmed->FirstParameter(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(aTrimmed->LastParameter(), 7.0);
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, ShallowCopy)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0, 1.0, 9.0);
|
||||
occ::handle<Adaptor2d_Curve2d> aCopy = anOffset.ShallowCopy();
|
||||
|
||||
EXPECT_DOUBLE_EQ(aCopy->FirstParameter(), 1.0);
|
||||
EXPECT_DOUBLE_EQ(aCopy->LastParameter(), 9.0);
|
||||
|
||||
const gp_Pnt2d aPntOrig = anOffset.Value(5.0);
|
||||
const gp_Pnt2d aPntCopy = aCopy->Value(5.0);
|
||||
EXPECT_TRUE(aPntOrig.IsEqual(aPntCopy, Precision::Confusion()));
|
||||
}
|
||||
|
||||
TEST_F(Adaptor2d_OffsetCurveTest, Resolution)
|
||||
{
|
||||
Adaptor2d_OffsetCurve anOffset(myBaseLine, 3.0);
|
||||
const double aRes = anOffset.Resolution(0.001);
|
||||
EXPECT_GT(aRes, 0.0);
|
||||
}
|
||||
@@ -2,10 +2,23 @@
|
||||
set(OCCT_TKG2d_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKG2d_GTests_FILES
|
||||
Adaptor2d_Line2d_Test.cxx
|
||||
Adaptor2d_OffsetCurve_Test.cxx
|
||||
Geom2d_AxisPlacement_Test.cxx
|
||||
Geom2d_BSplineCurve_Test.cxx
|
||||
Geom2d_BezierCurve_Test.cxx
|
||||
Geom2d_CartesianPoint_Test.cxx
|
||||
Geom2d_Circle_Test.cxx
|
||||
Geom2d_CurveEval_Test.cxx
|
||||
Geom2d_Direction_Test.cxx
|
||||
Geom2d_Ellipse_Test.cxx
|
||||
Geom2d_Hyperbola_Test.cxx
|
||||
Geom2d_Line_Test.cxx
|
||||
Geom2d_OffsetCurve_Test.cxx
|
||||
Geom2d_Parabola_Test.cxx
|
||||
Geom2d_Transformation_Test.cxx
|
||||
Geom2d_TrimmedCurve_Test.cxx
|
||||
Geom2d_VectorWithMagnitude_Test.cxx
|
||||
Geom2dAdaptor_Curve_Test.cxx
|
||||
Geom2dAPI_InterCurveCurve_Test.cxx
|
||||
Geom2dEval_ArchimedeanSpiralCurve_Test.cxx
|
||||
@@ -22,4 +35,8 @@ set(OCCT_TKG2d_GTests_FILES
|
||||
Geom2dGridEval_Hyperbola_Test.cxx
|
||||
Geom2dGridEval_Parabola_Test.cxx
|
||||
Geom2dHash_CurveHasher_Test.cxx
|
||||
Geom2dLProp_CLProps2d_Test.cxx
|
||||
Geom2dLProp_CurAndInf2d_Test.cxx
|
||||
LProp_AnalyticCurInf_Test.cxx
|
||||
LProp_CurAndInf_Test.cxx
|
||||
)
|
||||
|
||||
231
src/ModelingData/TKG2d/GTests/Geom2dLProp_CLProps2d_Test.cxx
Normal file
231
src/ModelingData/TKG2d/GTests/Geom2dLProp_CLProps2d_Test.cxx
Normal file
@@ -0,0 +1,231 @@
|
||||
// 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 <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2dLProp_CLProps2d.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Elips2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <LProp_NotDefined.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2dLProp_CLProps2dTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Circle centered at origin, radius 5
|
||||
gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0);
|
||||
myCircle = new Geom2d_Circle(aCirc);
|
||||
|
||||
// Line through origin along X
|
||||
gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
myLine = new Geom2d_Line(aLin);
|
||||
|
||||
// Ellipse centered at origin, major radius 10, minor radius 5
|
||||
gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0);
|
||||
myEllipse = new Geom2d_Ellipse(anElips);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Circle> myCircle;
|
||||
occ::handle<Geom2d_Line> myLine;
|
||||
occ::handle<Geom2d_Ellipse> myEllipse;
|
||||
};
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_Value)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
|
||||
const gp_Pnt2d& aPnt = aProps.Value();
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_SetParameter)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 2, Precision::Confusion());
|
||||
|
||||
aProps.SetParameter(M_PI / 2.0);
|
||||
const gp_Pnt2d& aPnt = aProps.Value();
|
||||
EXPECT_NEAR(aPnt.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_TangentDefined)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
EXPECT_TRUE(aProps.IsTangentDefined());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_TangentAtZero)
|
||||
{
|
||||
// At U=0 on a circle, the tangent should point in +Y direction
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
|
||||
gp_Dir2d aTangent;
|
||||
aProps.Tangent(aTangent);
|
||||
EXPECT_NEAR(aTangent.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTangent.Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_Curvature)
|
||||
{
|
||||
// Curvature of a circle of radius R is 1/R
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
|
||||
const double aCurvature = aProps.Curvature();
|
||||
EXPECT_NEAR(aCurvature, 1.0 / 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_CurvatureConstant)
|
||||
{
|
||||
// Curvature on a circle should be the same at every point
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 2, Precision::Confusion());
|
||||
|
||||
for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0)
|
||||
{
|
||||
aProps.SetParameter(u);
|
||||
EXPECT_NEAR(aProps.Curvature(), 1.0 / 5.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_Normal)
|
||||
{
|
||||
// Normal at U=0 on a circle centered at origin should point inward (-X)
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
|
||||
gp_Dir2d aNormal;
|
||||
aProps.Normal(aNormal);
|
||||
// Normal should be perpendicular to tangent
|
||||
gp_Dir2d aTangent;
|
||||
aProps.Tangent(aTangent);
|
||||
EXPECT_NEAR(std::abs(aTangent.X() * aNormal.X() + aTangent.Y() * aNormal.Y()),
|
||||
0.0,
|
||||
Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_CentreOfCurvature)
|
||||
{
|
||||
// Centre of curvature of a circle is its center
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
|
||||
gp_Pnt2d aCenter;
|
||||
aProps.CentreOfCurvature(aCenter);
|
||||
EXPECT_NEAR(aCenter.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCenter.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Circle_CentreOfCurvature_AtPiHalf)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, M_PI / 2.0, 2, Precision::Confusion());
|
||||
|
||||
gp_Pnt2d aCenter;
|
||||
aProps.CentreOfCurvature(aCenter);
|
||||
EXPECT_NEAR(aCenter.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCenter.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Line_TangentDefined)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myLine, 0.0, 2, Precision::Confusion());
|
||||
EXPECT_TRUE(aProps.IsTangentDefined());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Line_Tangent)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myLine, 5.0, 2, Precision::Confusion());
|
||||
|
||||
gp_Dir2d aTangent;
|
||||
aProps.Tangent(aTangent);
|
||||
EXPECT_NEAR(aTangent.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTangent.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Line_CurvatureIsZero)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myLine, 5.0, 2, Precision::Confusion());
|
||||
const double aCurvature = aProps.Curvature();
|
||||
EXPECT_NEAR(aCurvature, 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Line_CentreOfCurvature_Throws)
|
||||
{
|
||||
// Centre of curvature is not defined for a line (zero curvature)
|
||||
Geom2dLProp_CLProps2d aProps(myLine, 5.0, 2, Precision::Confusion());
|
||||
gp_Pnt2d aCenter;
|
||||
EXPECT_THROW(aProps.CentreOfCurvature(aCenter), LProp_NotDefined);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Ellipse_CurvatureAtMajorVertex)
|
||||
{
|
||||
// At U=0, ellipse is at major vertex. Curvature = b^2/a^3 for a=10, b=5
|
||||
// but actually for parametric ellipse, curvature at end of major axis = b^2/(a^2) * (1/a)
|
||||
// = b^2/a^2 * 1/a ... let's compute it properly:
|
||||
// Curvature at parameter 0 for ellipse(a,b) = a/b^2
|
||||
// Actually: radius of curvature at major vertex = b^2/a, so curvature = a/b^2
|
||||
Geom2dLProp_CLProps2d aProps(myEllipse, 0.0, 2, Precision::Confusion());
|
||||
|
||||
const double aCurvature = aProps.Curvature();
|
||||
const double aExpected = 10.0 / (5.0 * 5.0); // a/b^2 = 10/25 = 0.4
|
||||
EXPECT_NEAR(aCurvature, aExpected, 1e-6);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, Ellipse_CurvatureAtMinorVertex)
|
||||
{
|
||||
// At U=PI/2, ellipse is at minor vertex. Curvature = b/a^2
|
||||
Geom2dLProp_CLProps2d aProps(myEllipse, M_PI / 2.0, 2, Precision::Confusion());
|
||||
|
||||
const double aCurvature = aProps.Curvature();
|
||||
const double aExpected = 5.0 / (10.0 * 10.0); // b/a^2 = 5/100 = 0.05
|
||||
EXPECT_NEAR(aCurvature, aExpected, 1e-6);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, SetCurve)
|
||||
{
|
||||
// Start with empty props, then set curve
|
||||
Geom2dLProp_CLProps2d aProps(2, Precision::Confusion());
|
||||
aProps.SetCurve(myCircle);
|
||||
aProps.SetParameter(0.0);
|
||||
|
||||
const gp_Pnt2d& aPnt = aProps.Value();
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, D1_Circle)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
const gp_Vec2d& aD1 = aProps.D1();
|
||||
|
||||
// First derivative at U=0 on circle(R=5) is (0, 5)
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CLProps2dTest, D2_Circle)
|
||||
{
|
||||
Geom2dLProp_CLProps2d aProps(myCircle, 0.0, 2, Precision::Confusion());
|
||||
const gp_Vec2d& aD2 = aProps.D2();
|
||||
|
||||
// Second derivative at U=0 on circle(R=5) is (-5, 0)
|
||||
EXPECT_NEAR(aD2.X(), -5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD2.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
158
src/ModelingData/TKG2d/GTests/Geom2dLProp_CurAndInf2d_Test.cxx
Normal file
158
src/ModelingData/TKG2d/GTests/Geom2dLProp_CurAndInf2d_Test.cxx
Normal file
@@ -0,0 +1,158 @@
|
||||
// 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 <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2dLProp_CurAndInf2d.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Elips2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <LProp_CIType.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class Geom2dLProp_CurAndInf2dTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Circle centered at origin, radius 5
|
||||
gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0);
|
||||
myCircle = new Geom2d_Circle(aCirc);
|
||||
|
||||
// Ellipse centered at origin, major radius 10, minor radius 3
|
||||
gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 3.0);
|
||||
myEllipse = new Geom2d_Ellipse(anElips);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Circle> myCircle;
|
||||
occ::handle<Geom2d_Ellipse> myEllipse;
|
||||
};
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Circle_Perform_NoInflections)
|
||||
{
|
||||
// A circle has constant curvature: no inflections or extrema
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.Perform(myCircle);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Circle_PerformInf_NoInflections)
|
||||
{
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformInf(myCircle);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Circle_PerformCurExt_NoExtrema)
|
||||
{
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformCurExt(myCircle);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_PerformCurExt_HasExtrema)
|
||||
{
|
||||
// An ellipse has 4 curvature extrema:
|
||||
// 2 maxima (at ends of minor axis) and 2 minima (at ends of major axis)
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformCurExt(myEllipse);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 4);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_PerformCurExt_Types)
|
||||
{
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformCurExt(myEllipse);
|
||||
|
||||
ASSERT_TRUE(aAnalyzer.IsDone());
|
||||
ASSERT_EQ(aAnalyzer.NbPoints(), 4);
|
||||
|
||||
// Count min and max curvature points
|
||||
int aNbMin = 0;
|
||||
int aNbMax = 0;
|
||||
for (int i = 1; i <= aAnalyzer.NbPoints(); ++i)
|
||||
{
|
||||
const LProp_CIType aType = aAnalyzer.Type(i);
|
||||
if (aType == LProp_MinCur)
|
||||
++aNbMin;
|
||||
else if (aType == LProp_MaxCur)
|
||||
++aNbMax;
|
||||
}
|
||||
EXPECT_EQ(aNbMin, 2);
|
||||
EXPECT_EQ(aNbMax, 2);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_PerformCurExt_Parameters)
|
||||
{
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformCurExt(myEllipse);
|
||||
|
||||
ASSERT_TRUE(aAnalyzer.IsDone());
|
||||
ASSERT_EQ(aAnalyzer.NbPoints(), 4);
|
||||
|
||||
// Parameters should be sorted in increasing order
|
||||
for (int i = 1; i < aAnalyzer.NbPoints(); ++i)
|
||||
{
|
||||
EXPECT_LT(aAnalyzer.Parameter(i), aAnalyzer.Parameter(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_PerformInf_NoInflections)
|
||||
{
|
||||
// An ellipse is a convex curve, so it has no inflection points
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformInf(myEllipse);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_Perform_CombinedResult)
|
||||
{
|
||||
// Perform computes both inflections and curvature extrema
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.Perform(myEllipse);
|
||||
|
||||
EXPECT_TRUE(aAnalyzer.IsDone());
|
||||
// Ellipse: 4 extrema, 0 inflections
|
||||
EXPECT_EQ(aAnalyzer.NbPoints(), 4);
|
||||
}
|
||||
|
||||
TEST_F(Geom2dLProp_CurAndInf2dTest, Ellipse_CurvatureExtremaAtExpectedParameters)
|
||||
{
|
||||
// For an ellipse with major axis along X:
|
||||
// Curvature extrema at U = 0, PI/2, PI, 3*PI/2
|
||||
Geom2dLProp_CurAndInf2d aAnalyzer;
|
||||
aAnalyzer.PerformCurExt(myEllipse);
|
||||
|
||||
ASSERT_TRUE(aAnalyzer.IsDone());
|
||||
ASSERT_EQ(aAnalyzer.NbPoints(), 4);
|
||||
|
||||
const double anExpectedParams[] = {0.0, M_PI / 2.0, M_PI, 3.0 * M_PI / 2.0};
|
||||
for (int i = 1; i <= 4; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aAnalyzer.Parameter(i), anExpectedParams[i - 1], 1e-6);
|
||||
}
|
||||
}
|
||||
185
src/ModelingData/TKG2d/GTests/Geom2d_AxisPlacement_Test.cxx
Normal file
185
src/ModelingData/TKG2d/GTests/Geom2d_AxisPlacement_Test.cxx
Normal file
@@ -0,0 +1,185 @@
|
||||
// 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 <Geom2d_AxisPlacement.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, ConstructFromAx2d)
|
||||
{
|
||||
gp_Ax2d anAxis(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_AxisPlacement> anAP = new Geom2d_AxisPlacement(anAxis);
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Location().Y(), 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, ConstructFromPointAndDir)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(3.0, 4.0), gp_Dir2d(0.0, 1.0));
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, SetLocation)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
anAP->SetLocation(gp_Pnt2d(5.0, 6.0));
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Location().Y(), 6.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, SetDirection)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
anAP->SetDirection(gp_Dir2d(0.0, 1.0));
|
||||
|
||||
EXPECT_NEAR(anAP->Direction().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, SetAxis)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
gp_Ax2d aNewAxis(gp_Pnt2d(10.0, 20.0), gp_Dir2d(0.0, 1.0));
|
||||
anAP->SetAxis(aNewAxis);
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Ax2d)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
const gp_Ax2d anAxis = anAP->Ax2d();
|
||||
EXPECT_NEAR(anAxis.Location().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAxis.Direction().X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Angle_Perpendicular)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP1 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_AxisPlacement> anAP2 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
|
||||
EXPECT_NEAR(anAP1->Angle(anAP2), M_PI / 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Angle_Parallel)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP1 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_AxisPlacement> anAP2 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(5.0, 5.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
EXPECT_NEAR(anAP1->Angle(anAP2), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Angle_Opposite)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP1 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_AxisPlacement> anAP2 =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(-1.0, 0.0));
|
||||
|
||||
EXPECT_NEAR(std::abs(anAP1->Angle(anAP2)), M_PI, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Reverse)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
anAP->Reverse();
|
||||
|
||||
EXPECT_NEAR(anAP->Direction().X(), -1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 0.0, Precision::Confusion());
|
||||
// Location unchanged
|
||||
EXPECT_NEAR(anAP->Location().X(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Reversed)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_AxisPlacement> aReversed = anAP->Reversed();
|
||||
|
||||
EXPECT_NEAR(aReversed->Direction().X(), -1.0, Precision::Confusion());
|
||||
// Original unchanged
|
||||
EXPECT_NEAR(anAP->Direction().X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Transform_Translation)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(10.0, 20.0));
|
||||
anAP->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 11.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Location().Y(), 22.0, Precision::Confusion());
|
||||
// Direction unchanged
|
||||
EXPECT_NEAR(anAP->Direction().X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Transform_Rotation)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(1.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
anAP->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(anAP->Location().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Location().Y(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAP->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_AxisPlacementTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_AxisPlacement> anAP =
|
||||
new Geom2d_AxisPlacement(gp_Pnt2d(1.0, 2.0), gp_Dir2d(0.0, 1.0));
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = anAP->Copy();
|
||||
occ::handle<Geom2d_AxisPlacement> aCopy = occ::down_cast<Geom2d_AxisPlacement>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->Location().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCopy->Direction().Y(), 1.0, Precision::Confusion());
|
||||
|
||||
// Verify independence
|
||||
aCopy->SetLocation(gp_Pnt2d(99.0, 99.0));
|
||||
EXPECT_NEAR(anAP->Location().X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
136
src/ModelingData/TKG2d/GTests/Geom2d_CartesianPoint_Test.cxx
Normal file
136
src/ModelingData/TKG2d/GTests/Geom2d_CartesianPoint_Test.cxx
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 <Geom2d_CartesianPoint.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, ConstructFromCoords)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
EXPECT_NEAR(aPnt->X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, ConstructFromPnt2d)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(gp_Pnt2d(5.0, 6.0));
|
||||
EXPECT_NEAR(aPnt->X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 6.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, SetCoord)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(0.0, 0.0);
|
||||
aPnt->SetCoord(7.0, 8.0);
|
||||
EXPECT_NEAR(aPnt->X(), 7.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, SetPnt2d)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(0.0, 0.0);
|
||||
aPnt->SetPnt2d(gp_Pnt2d(1.0, 2.0));
|
||||
EXPECT_NEAR(aPnt->X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, SetX_SetY)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(0.0, 0.0);
|
||||
aPnt->SetX(10.0);
|
||||
aPnt->SetY(20.0);
|
||||
EXPECT_NEAR(aPnt->X(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 20.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Coord)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
double aX = 0.0, aY = 0.0;
|
||||
aPnt->Coord(aX, aY);
|
||||
EXPECT_NEAR(aX, 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Pnt2d)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
const gp_Pnt2d aGpPnt = aPnt->Pnt2d();
|
||||
EXPECT_NEAR(aGpPnt.X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aGpPnt.Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Distance)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aP1 = new Geom2d_CartesianPoint(0.0, 0.0);
|
||||
occ::handle<Geom2d_CartesianPoint> aP2 = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
EXPECT_NEAR(aP1->Distance(aP2), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, SquareDistance)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aP1 = new Geom2d_CartesianPoint(0.0, 0.0);
|
||||
occ::handle<Geom2d_CartesianPoint> aP2 = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
EXPECT_NEAR(aP1->SquareDistance(aP2), 25.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Distance_SamePoint)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(5.0, 5.0);
|
||||
EXPECT_NEAR(aPnt->Distance(aPnt), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Transform_Translation)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(1.0, 2.0);
|
||||
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(3.0, 4.0));
|
||||
aPnt->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(aPnt->X(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 6.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Transform_Rotation)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(1.0, 0.0);
|
||||
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
aPnt->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(aPnt->X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt->Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_CartesianPointTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_CartesianPoint> aPnt = new Geom2d_CartesianPoint(3.0, 4.0);
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = aPnt->Copy();
|
||||
occ::handle<Geom2d_CartesianPoint> aCopy = occ::down_cast<Geom2d_CartesianPoint>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCopy->Y(), 4.0, Precision::Confusion());
|
||||
|
||||
aCopy->SetCoord(0.0, 0.0);
|
||||
EXPECT_NEAR(aPnt->X(), 3.0, Precision::Confusion());
|
||||
}
|
||||
177
src/ModelingData/TKG2d/GTests/Geom2d_Circle_Test.cxx
Normal file
177
src/ModelingData/TKG2d/GTests/Geom2d_Circle_Test.cxx
Normal file
@@ -0,0 +1,177 @@
|
||||
// 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 <Geom2d_Circle.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_CircleTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Circle centered at origin, radius 5
|
||||
gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0);
|
||||
myCircle = new Geom2d_Circle(aCirc);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Circle> myCircle;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_CircleTest, ConstructFromCirc2d)
|
||||
{
|
||||
EXPECT_NEAR(myCircle->Radius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, ConstructFromAxisAndRadius)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aCircle =
|
||||
new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0)), 3.0);
|
||||
|
||||
EXPECT_NEAR(aCircle->Radius(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCircle->Location().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCircle->Location().Y(), 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, ConstructFromAx22d)
|
||||
{
|
||||
gp_Ax22d anAxis(gp_Pnt2d(3.0, 4.0), gp_Dir2d(1.0, 0.0), gp_Dir2d(0.0, 1.0));
|
||||
occ::handle<Geom2d_Circle> aCircle = new Geom2d_Circle(anAxis, 7.0);
|
||||
|
||||
EXPECT_NEAR(aCircle->Radius(), 7.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCircle->Location().X(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, ParameterBounds)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(myCircle->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(myCircle->LastParameter(), 2.0 * M_PI);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, IsClosedAndPeriodic)
|
||||
{
|
||||
EXPECT_TRUE(myCircle->IsClosed());
|
||||
EXPECT_TRUE(myCircle->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, Eccentricity)
|
||||
{
|
||||
EXPECT_NEAR(myCircle->Eccentricity(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, SetRadius)
|
||||
{
|
||||
myCircle->SetRadius(10.0);
|
||||
EXPECT_NEAR(myCircle->Radius(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, Circ2d)
|
||||
{
|
||||
const gp_Circ2d aCirc = myCircle->Circ2d();
|
||||
EXPECT_NEAR(aCirc.Radius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalD0_AtZero)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myCircle->EvalD0(0.0);
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalD0_AtPiHalf)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myCircle->EvalD0(M_PI / 2.0);
|
||||
EXPECT_NEAR(aPnt.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalD0_AtPi)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myCircle->EvalD0(M_PI);
|
||||
EXPECT_NEAR(aPnt.X(), -5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalD1_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1] = myCircle->EvalD1(0.0);
|
||||
// Tangent at U=0 is (0, R) = (0, 5)
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalD2_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1, aD2] = myCircle->EvalD2(0.0);
|
||||
// Second derivative at U=0 is (-R, 0) = (-5, 0)
|
||||
EXPECT_NEAR(aD2.X(), -5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD2.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, EvalDN_Order1)
|
||||
{
|
||||
const gp_Vec2d aD1 = myCircle->EvalDN(0.0, 1);
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, ReversedParameter)
|
||||
{
|
||||
const double aU = M_PI / 3.0;
|
||||
const double aRev = myCircle->ReversedParameter(aU);
|
||||
EXPECT_NEAR(aRev, 2.0 * M_PI - aU, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myCircle->Copy();
|
||||
occ::handle<Geom2d_Circle> aCopy = occ::down_cast<Geom2d_Circle>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->Radius(), 5.0, Precision::Confusion());
|
||||
|
||||
// Verify independence
|
||||
aCopy->SetRadius(1.0);
|
||||
EXPECT_NEAR(myCircle->Radius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, Transform_Translation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(10.0, 20.0));
|
||||
myCircle->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(myCircle->Location().X(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myCircle->Location().Y(), 20.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myCircle->Radius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_CircleTest, PointOnCircle_DistanceFromCenter)
|
||||
{
|
||||
// All points on circle should be at distance R from center
|
||||
for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myCircle->EvalD0(u);
|
||||
const double aDist = aPnt.Distance(myCircle->Location());
|
||||
EXPECT_NEAR(aDist, 5.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
159
src/ModelingData/TKG2d/GTests/Geom2d_Direction_Test.cxx
Normal file
159
src/ModelingData/TKG2d/GTests/Geom2d_Direction_Test.cxx
Normal file
@@ -0,0 +1,159 @@
|
||||
// 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 <Geom2d_Direction.hxx>
|
||||
#include <Geom2d_VectorWithMagnitude.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_ConstructionError.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST(Geom2d_DirectionTest, ConstructFromCoords)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(3.0, 4.0);
|
||||
// Should be normalized
|
||||
EXPECT_NEAR(aDir->Magnitude(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->X(), 0.6, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Y(), 0.8, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, ConstructFromDir2d)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(gp_Dir2d(0.0, 1.0));
|
||||
EXPECT_NEAR(aDir->X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, ConstructFromZero_Throws)
|
||||
{
|
||||
#ifndef No_Exception
|
||||
EXPECT_THROW(new Geom2d_Direction(0.0, 0.0), Standard_ConstructionError);
|
||||
#else
|
||||
GTEST_SKIP() << "No_Exception is defined; exception behavior is disabled in this build.";
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, MagnitudeAlwaysOne)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(100.0, 200.0);
|
||||
EXPECT_NEAR(aDir->Magnitude(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->SquareMagnitude(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, SetCoord)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
aDir->SetCoord(0.0, 5.0);
|
||||
EXPECT_NEAR(aDir->X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, SetCoord_Zero_Throws)
|
||||
{
|
||||
#ifndef No_Exception
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
EXPECT_THROW(aDir->SetCoord(0.0, 0.0), Standard_ConstructionError);
|
||||
#else
|
||||
GTEST_SKIP() << "No_Exception is defined; exception behavior is disabled in this build.";
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Dir2d)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
const gp_Dir2d aGpDir = aDir->Dir2d();
|
||||
EXPECT_NEAR(aGpDir.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aGpDir.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Crossed)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDirX = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_Direction> aDirY = new Geom2d_Direction(0.0, 1.0);
|
||||
|
||||
// (1,0) x (0,1) = 1
|
||||
EXPECT_NEAR(aDirX->Crossed(aDirY), 1.0, Precision::Confusion());
|
||||
// (0,1) x (1,0) = -1
|
||||
EXPECT_NEAR(aDirY->Crossed(aDirX), -1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Angle)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDirX = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_Direction> aDirY = new Geom2d_Direction(0.0, 1.0);
|
||||
|
||||
EXPECT_NEAR(aDirX->Angle(aDirY), M_PI / 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Angle_OppositeDirections)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDirPos = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_Direction> aDirNeg = new Geom2d_Direction(-1.0, 0.0);
|
||||
|
||||
EXPECT_NEAR(std::abs(aDirPos->Angle(aDirNeg)), M_PI, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Dot)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDirX = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_Direction> aDirY = new Geom2d_Direction(0.0, 1.0);
|
||||
|
||||
EXPECT_NEAR(aDirX->Dot(aDirY), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDirX->Dot(aDirX), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Reverse)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
aDir->Reverse();
|
||||
EXPECT_NEAR(aDir->X(), -1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, CrossedWithVectorWithMagnitude)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec = new Geom2d_VectorWithMagnitude(0.0, 5.0);
|
||||
|
||||
EXPECT_NEAR(aDir->Crossed(aVec), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = aDir->Copy();
|
||||
occ::handle<Geom2d_Direction> aCopy = occ::down_cast<Geom2d_Direction>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->X(), 1.0, Precision::Confusion());
|
||||
|
||||
aCopy->SetCoord(0.0, 1.0);
|
||||
EXPECT_NEAR(aDir->X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_DirectionTest, Transform_Rotation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
|
||||
occ::handle<Geom2d_Direction> aDir = new Geom2d_Direction(1.0, 0.0);
|
||||
aDir->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(aDir->X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Y(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDir->Magnitude(), 1.0, Precision::Confusion());
|
||||
}
|
||||
173
src/ModelingData/TKG2d/GTests/Geom2d_Ellipse_Test.cxx
Normal file
173
src/ModelingData/TKG2d/GTests/Geom2d_Ellipse_Test.cxx
Normal file
@@ -0,0 +1,173 @@
|
||||
// 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 <Geom2d_Ellipse.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Elips2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_EllipseTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Ellipse centered at origin, major radius 10, minor radius 5
|
||||
gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0);
|
||||
myEllipse = new Geom2d_Ellipse(anElips);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Ellipse> myEllipse;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Radii)
|
||||
{
|
||||
EXPECT_NEAR(myEllipse->MajorRadius(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myEllipse->MinorRadius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, ParameterBounds)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(myEllipse->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(myEllipse->LastParameter(), 2.0 * M_PI);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, IsClosedAndPeriodic)
|
||||
{
|
||||
EXPECT_TRUE(myEllipse->IsClosed());
|
||||
EXPECT_TRUE(myEllipse->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Eccentricity)
|
||||
{
|
||||
// e = sqrt(1 - (b/a)^2) = sqrt(1 - 0.25) = sqrt(0.75)
|
||||
const double anExpected = std::sqrt(1.0 - (5.0 * 5.0) / (10.0 * 10.0));
|
||||
EXPECT_NEAR(myEllipse->Eccentricity(), anExpected, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Focal)
|
||||
{
|
||||
// Focal distance = sqrt(a^2 - b^2) * 2
|
||||
const double anExpected = 2.0 * std::sqrt(10.0 * 10.0 - 5.0 * 5.0);
|
||||
EXPECT_NEAR(myEllipse->Focal(), anExpected, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Foci)
|
||||
{
|
||||
const gp_Pnt2d aFocus1 = myEllipse->Focus1();
|
||||
const gp_Pnt2d aFocus2 = myEllipse->Focus2();
|
||||
const double c = std::sqrt(100.0 - 25.0); // sqrt(a^2 - b^2)
|
||||
|
||||
EXPECT_NEAR(aFocus1.X(), c, Precision::Confusion());
|
||||
EXPECT_NEAR(aFocus1.Y(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aFocus2.X(), -c, Precision::Confusion());
|
||||
EXPECT_NEAR(aFocus2.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Parameter)
|
||||
{
|
||||
// Semi-latus rectum = b^2/a = 25/10 = 2.5
|
||||
EXPECT_NEAR(myEllipse->Parameter(), 2.5, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, EvalD0_MajorVertex)
|
||||
{
|
||||
// At U=0: point on major axis = (a, 0) = (10, 0)
|
||||
const gp_Pnt2d aPnt = myEllipse->EvalD0(0.0);
|
||||
EXPECT_NEAR(aPnt.X(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, EvalD0_MinorVertex)
|
||||
{
|
||||
// At U=PI/2: point on minor axis = (0, b) = (0, 5)
|
||||
const gp_Pnt2d aPnt = myEllipse->EvalD0(M_PI / 2.0);
|
||||
EXPECT_NEAR(aPnt.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, EvalD1_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1] = myEllipse->EvalD1(0.0);
|
||||
// At U=0: tangent is (0, b) = (0, 5)
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, EvalD2_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1, aD2] = myEllipse->EvalD2(0.0);
|
||||
// At U=0: second derivative is (-a, 0) = (-10, 0)
|
||||
EXPECT_NEAR(aD2.X(), -10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD2.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, SetMajorRadius)
|
||||
{
|
||||
myEllipse->SetMajorRadius(20.0);
|
||||
EXPECT_NEAR(myEllipse->MajorRadius(), 20.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, SetMinorRadius)
|
||||
{
|
||||
myEllipse->SetMinorRadius(3.0);
|
||||
EXPECT_NEAR(myEllipse->MinorRadius(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, PointOnEllipse_FociDistanceSum)
|
||||
{
|
||||
// For any point on ellipse: d(P, F1) + d(P, F2) = 2a
|
||||
const gp_Pnt2d aF1 = myEllipse->Focus1();
|
||||
const gp_Pnt2d aF2 = myEllipse->Focus2();
|
||||
|
||||
for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myEllipse->EvalD0(u);
|
||||
const double aSum = aPnt.Distance(aF1) + aPnt.Distance(aF2);
|
||||
EXPECT_NEAR(aSum, 2.0 * 10.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myEllipse->Copy();
|
||||
occ::handle<Geom2d_Ellipse> aCopy = occ::down_cast<Geom2d_Ellipse>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->MajorRadius(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCopy->MinorRadius(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, Transform_Translation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(5.0, 10.0));
|
||||
myEllipse->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(myEllipse->Location().X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myEllipse->Location().Y(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myEllipse->MajorRadius(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_EllipseTest, ReversedParameter)
|
||||
{
|
||||
const double aU = M_PI / 4.0;
|
||||
EXPECT_NEAR(myEllipse->ReversedParameter(aU), 2.0 * M_PI - aU, Precision::Confusion());
|
||||
}
|
||||
152
src/ModelingData/TKG2d/GTests/Geom2d_Hyperbola_Test.cxx
Normal file
152
src/ModelingData/TKG2d/GTests/Geom2d_Hyperbola_Test.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 <Geom2d_Hyperbola.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Hypr2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_HyperbolaTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Hyperbola centered at origin, a=5, b=3
|
||||
gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0);
|
||||
myHyperbola = new Geom2d_Hyperbola(aHypr);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Hyperbola> myHyperbola;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Radii)
|
||||
{
|
||||
EXPECT_NEAR(myHyperbola->MajorRadius(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myHyperbola->MinorRadius(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, IsNotClosedNotPeriodic)
|
||||
{
|
||||
EXPECT_FALSE(myHyperbola->IsClosed());
|
||||
EXPECT_FALSE(myHyperbola->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Eccentricity)
|
||||
{
|
||||
// e = c/a where c = sqrt(a^2 + b^2) = sqrt(25+9) = sqrt(34)
|
||||
const double anExpected = std::sqrt(34.0) / 5.0;
|
||||
EXPECT_NEAR(myHyperbola->Eccentricity(), anExpected, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Focal)
|
||||
{
|
||||
// 2c = 2*sqrt(a^2 + b^2)
|
||||
const double anExpected = 2.0 * std::sqrt(25.0 + 9.0);
|
||||
EXPECT_NEAR(myHyperbola->Focal(), anExpected, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Foci)
|
||||
{
|
||||
const double c = std::sqrt(25.0 + 9.0);
|
||||
const gp_Pnt2d aF1 = myHyperbola->Focus1();
|
||||
const gp_Pnt2d aF2 = myHyperbola->Focus2();
|
||||
|
||||
EXPECT_NEAR(aF1.X(), c, Precision::Confusion());
|
||||
EXPECT_NEAR(aF2.X(), -c, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Parameter)
|
||||
{
|
||||
// Semi-latus rectum = b^2/a = 9/5 = 1.8
|
||||
EXPECT_NEAR(myHyperbola->Parameter(), 1.8, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, EvalD0_AtZero)
|
||||
{
|
||||
// At U=0: vertex = (a, 0) = (5, 0) since x = a*cosh(0) = a, y = b*sinh(0) = 0
|
||||
const gp_Pnt2d aPnt = myHyperbola->EvalD0(0.0);
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, EvalD1_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1] = myHyperbola->EvalD1(0.0);
|
||||
// At U=0: dx/du = a*sinh(0) = 0, dy/du = b*cosh(0) = b = 3
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, PointOnHyperbola_FociDistanceDifference)
|
||||
{
|
||||
// For any point on hyperbola: |d(P,F1) - d(P,F2)| = 2a
|
||||
const gp_Pnt2d aF1 = myHyperbola->Focus1();
|
||||
const gp_Pnt2d aF2 = myHyperbola->Focus2();
|
||||
|
||||
for (double u = -2.0; u <= 2.0; u += 0.5)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myHyperbola->EvalD0(u);
|
||||
const double aDiff = std::abs(aPnt.Distance(aF1) - aPnt.Distance(aF2));
|
||||
EXPECT_NEAR(aDiff, 2.0 * 5.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, SetMajorRadius)
|
||||
{
|
||||
myHyperbola->SetMajorRadius(8.0);
|
||||
EXPECT_NEAR(myHyperbola->MajorRadius(), 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, SetMinorRadius)
|
||||
{
|
||||
myHyperbola->SetMinorRadius(4.0);
|
||||
EXPECT_NEAR(myHyperbola->MinorRadius(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myHyperbola->Copy();
|
||||
occ::handle<Geom2d_Hyperbola> aCopy = occ::down_cast<Geom2d_Hyperbola>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->MajorRadius(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCopy->MinorRadius(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Transform_Translation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(10.0, 20.0));
|
||||
myHyperbola->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(myHyperbola->Location().X(), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myHyperbola->Location().Y(), 20.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_HyperbolaTest, Asymptotes)
|
||||
{
|
||||
const gp_Ax2d anAsym1 = myHyperbola->Asymptote1();
|
||||
const gp_Ax2d anAsym2 = myHyperbola->Asymptote2();
|
||||
|
||||
// Asymptotes pass through center
|
||||
EXPECT_NEAR(anAsym1.Location().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anAsym2.Location().X(), 0.0, Precision::Confusion());
|
||||
}
|
||||
188
src/ModelingData/TKG2d/GTests/Geom2d_Line_Test.cxx
Normal file
188
src/ModelingData/TKG2d/GTests/Geom2d_Line_Test.cxx
Normal file
@@ -0,0 +1,188 @@
|
||||
// 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 <Geom2d_Line.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_LineTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Horizontal line through origin
|
||||
myLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Line> myLine;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_LineTest, ConstructFromPointAndDir)
|
||||
{
|
||||
EXPECT_NEAR(myLine->Direction().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Direction().Y(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Location().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Location().Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, ConstructFromLin2d)
|
||||
{
|
||||
gp_Lin2d aLin(gp_Pnt2d(1.0, 2.0), gp_Dir2d(0.0, 1.0));
|
||||
occ::handle<Geom2d_Line> aLine = new Geom2d_Line(aLin);
|
||||
|
||||
EXPECT_NEAR(aLine->Direction().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLine->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, ConstructFromAxis)
|
||||
{
|
||||
gp_Ax2d anAxis(gp_Pnt2d(3.0, 4.0), gp_Dir2d(1.0, 0.0));
|
||||
occ::handle<Geom2d_Line> aLine = new Geom2d_Line(anAxis);
|
||||
|
||||
EXPECT_NEAR(aLine->Location().X(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, ParameterBounds)
|
||||
{
|
||||
// OCCT uses large finite bounds (not numeric_limits::max)
|
||||
EXPECT_LT(myLine->FirstParameter(), -1e+90);
|
||||
EXPECT_GT(myLine->LastParameter(), 1e+90);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, IsNotClosedNotPeriodic)
|
||||
{
|
||||
EXPECT_FALSE(myLine->IsClosed());
|
||||
EXPECT_FALSE(myLine->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Continuity)
|
||||
{
|
||||
EXPECT_EQ(myLine->Continuity(), GeomAbs_CN);
|
||||
EXPECT_TRUE(myLine->IsCN(100));
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, EvalD0)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myLine->EvalD0(5.0);
|
||||
EXPECT_NEAR(aPnt.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, EvalD1_DirectionIsConstant)
|
||||
{
|
||||
const auto [aPnt, aD1] = myLine->EvalD1(5.0);
|
||||
EXPECT_NEAR(aD1.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aD1.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, EvalD2_IsZero)
|
||||
{
|
||||
const auto [aPnt, aD1, aD2] = myLine->EvalD2(5.0);
|
||||
EXPECT_NEAR(aD2.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, EvalD3_IsZero)
|
||||
{
|
||||
const auto [aPnt, aD1, aD2, aD3] = myLine->EvalD3(5.0);
|
||||
EXPECT_NEAR(aD3.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, EvalDN_HigherOrder)
|
||||
{
|
||||
const gp_Vec2d aD4 = myLine->EvalDN(0.0, 4);
|
||||
EXPECT_NEAR(aD4.Magnitude(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Distance)
|
||||
{
|
||||
EXPECT_NEAR(myLine->Distance(gp_Pnt2d(5.0, 3.0)), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Distance(gp_Pnt2d(0.0, 0.0)), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, SetDirection)
|
||||
{
|
||||
myLine->SetDirection(gp_Dir2d(0.0, 1.0));
|
||||
EXPECT_NEAR(myLine->Direction().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Direction().Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, SetLocation)
|
||||
{
|
||||
myLine->SetLocation(gp_Pnt2d(3.0, 4.0));
|
||||
EXPECT_NEAR(myLine->Location().X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Location().Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Lin2d)
|
||||
{
|
||||
const gp_Lin2d aLin = myLine->Lin2d();
|
||||
EXPECT_NEAR(aLin.Direction().X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLin.Location().X(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myLine->Copy();
|
||||
occ::handle<Geom2d_Line> aCopy = occ::down_cast<Geom2d_Line>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->Direction().X(), 1.0, Precision::Confusion());
|
||||
|
||||
aCopy->SetDirection(gp_Dir2d(0.0, 1.0));
|
||||
EXPECT_NEAR(myLine->Direction().X(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Transform_Translation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(5.0, 10.0));
|
||||
myLine->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(myLine->Location().X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myLine->Location().Y(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, Transform_Rotation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
myLine->Transform(aTrsf);
|
||||
|
||||
// Horizontal line rotated 90 degrees becomes vertical
|
||||
EXPECT_NEAR(myLine->Direction().X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(std::abs(myLine->Direction().Y()), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, ReversedParameter)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(myLine->ReversedParameter(5.0), -5.0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_LineTest, DiagonalLine_Value)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aDiag = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0));
|
||||
|
||||
const gp_Pnt2d aPnt = aDiag->EvalD0(std::sqrt(2.0));
|
||||
EXPECT_NEAR(aPnt.X(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
141
src/ModelingData/TKG2d/GTests/Geom2d_Parabola_Test.cxx
Normal file
141
src/ModelingData/TKG2d/GTests/Geom2d_Parabola_Test.cxx
Normal file
@@ -0,0 +1,141 @@
|
||||
// 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 <Geom2d_Parabola.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Parab2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class Geom2d_ParabolaTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Parabola centered at origin with focal distance 4
|
||||
gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 4.0);
|
||||
myParabola = new Geom2d_Parabola(aParab);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Parabola> myParabola;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Focal)
|
||||
{
|
||||
EXPECT_NEAR(myParabola->Focal(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, IsNotClosedNotPeriodic)
|
||||
{
|
||||
EXPECT_FALSE(myParabola->IsClosed());
|
||||
EXPECT_FALSE(myParabola->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Eccentricity)
|
||||
{
|
||||
EXPECT_NEAR(myParabola->Eccentricity(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Focus)
|
||||
{
|
||||
const gp_Pnt2d aFocus = myParabola->Focus();
|
||||
EXPECT_NEAR(aFocus.X(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aFocus.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Parameter)
|
||||
{
|
||||
// p = 2*Focal = 8
|
||||
EXPECT_NEAR(myParabola->Parameter(), 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, EvalD0_AtZero)
|
||||
{
|
||||
// At U=0: vertex
|
||||
const gp_Pnt2d aPnt = myParabola->EvalD0(0.0);
|
||||
EXPECT_NEAR(aPnt.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, EvalD0_Symmetric)
|
||||
{
|
||||
// Parabola is symmetric: P(U) and P(-U) should have same X, opposite Y
|
||||
const double aU = 3.0;
|
||||
const gp_Pnt2d aPntPos = myParabola->EvalD0(aU);
|
||||
const gp_Pnt2d aPntNeg = myParabola->EvalD0(-aU);
|
||||
|
||||
EXPECT_NEAR(aPntPos.X(), aPntNeg.X(), Precision::Confusion());
|
||||
EXPECT_NEAR(aPntPos.Y(), -aPntNeg.Y(), Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, EvalD1_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1] = myParabola->EvalD1(0.0);
|
||||
// At vertex: tangent is along Y axis
|
||||
EXPECT_NEAR(aD1.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_GT(aD1.Magnitude(), Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, EvalD2_AtZero)
|
||||
{
|
||||
const auto [aPnt, aD1, aD2] = myParabola->EvalD2(0.0);
|
||||
// Second derivative at vertex should be along X (opening direction)
|
||||
EXPECT_GT(aD2.X(), 0.0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, PointOnParabola_FocusDirectrixProperty)
|
||||
{
|
||||
// For any point P on parabola: distance(P, Focus) = distance(P, Directrix)
|
||||
const gp_Pnt2d aFocus = myParabola->Focus();
|
||||
const gp_Ax2d aDirectrix = myParabola->Directrix();
|
||||
const gp_Lin2d aDirLine(aDirectrix);
|
||||
|
||||
for (double u = -5.0; u <= 5.0; u += 1.0)
|
||||
{
|
||||
const gp_Pnt2d aPnt = myParabola->EvalD0(u);
|
||||
const double aDistFocus = aPnt.Distance(aFocus);
|
||||
const double aDistDir = aDirLine.Distance(aPnt);
|
||||
EXPECT_NEAR(aDistFocus, aDistDir, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, SetFocal)
|
||||
{
|
||||
myParabola->SetFocal(10.0);
|
||||
EXPECT_NEAR(myParabola->Focal(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myParabola->Copy();
|
||||
occ::handle<Geom2d_Parabola> aCopy = occ::down_cast<Geom2d_Parabola>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->Focal(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_ParabolaTest, Transform_Translation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(5.0, 10.0));
|
||||
myParabola->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(myParabola->Location().X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myParabola->Location().Y(), 10.0, Precision::Confusion());
|
||||
}
|
||||
284
src/ModelingData/TKG2d/GTests/Geom2d_Transformation_Test.cxx
Normal file
284
src/ModelingData/TKG2d/GTests/Geom2d_Transformation_Test.cxx
Normal file
@@ -0,0 +1,284 @@
|
||||
// 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 <Geom2d_Transformation.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_TrsfForm.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST(Geom2d_TransformationTest, DefaultConstructor_Identity)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Identity);
|
||||
EXPECT_NEAR(aTrsf->ScaleFactor(), 1.0, Precision::Confusion());
|
||||
EXPECT_FALSE(aTrsf->IsNegative());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, ConstructFromTrsf2d)
|
||||
{
|
||||
gp_Trsf2d aGpTrsf;
|
||||
aGpTrsf.SetTranslation(gp_Vec2d(3.0, 4.0));
|
||||
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation(aGpTrsf);
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Translation);
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetTranslation_Vector)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetTranslation(gp_Vec2d(5.0, 10.0));
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Translation);
|
||||
|
||||
double aX = 1.0, aY = 2.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 6.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 12.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetTranslation_TwoPoints)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetTranslation(gp_Pnt2d(1.0, 1.0), gp_Pnt2d(4.0, 5.0));
|
||||
|
||||
double aX = 0.0, aY = 0.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetRotation)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Rotation);
|
||||
|
||||
double aX = 1.0, aY = 0.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetRotation_180Degrees)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetRotation(gp_Pnt2d(0.0, 0.0), M_PI);
|
||||
|
||||
double aX = 3.0, aY = 4.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, -3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetScale)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetScale(gp_Pnt2d(0.0, 0.0), 2.0);
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Scale);
|
||||
EXPECT_NEAR(aTrsf->ScaleFactor(), 2.0, Precision::Confusion());
|
||||
|
||||
double aX = 3.0, aY = 4.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 6.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetScale_Negative)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetScale(gp_Pnt2d(0.0, 0.0), -1.0);
|
||||
|
||||
// In 2D, IsNegative checks determinant sign; scale(-1) has det = (-1)*(-1) = 1 > 0
|
||||
EXPECT_FALSE(aTrsf->IsNegative());
|
||||
EXPECT_NEAR(aTrsf->ScaleFactor(), -1.0, Precision::Confusion());
|
||||
|
||||
double aX = 3.0, aY = 4.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, -3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetMirror_Point)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetMirror(gp_Pnt2d(0.0, 0.0));
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_PntMirror);
|
||||
// In 2D, point mirror has det = (-1)*(-1) = 1 > 0, so IsNegative is false
|
||||
EXPECT_FALSE(aTrsf->IsNegative());
|
||||
|
||||
double aX = 3.0, aY = 4.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, -3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetMirror_Axis)
|
||||
{
|
||||
// Mirror about X axis
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetMirror(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)));
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Ax1Mirror);
|
||||
|
||||
double aX = 3.0, aY = 4.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Inverted)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetTranslation(gp_Vec2d(5.0, 10.0));
|
||||
|
||||
occ::handle<Geom2d_Transformation> anInv = aTrsf->Inverted();
|
||||
|
||||
// Applying both should be identity
|
||||
double aX = 7.0, aY = 3.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
anInv->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 7.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Multiplied)
|
||||
{
|
||||
// Translation + Rotation
|
||||
occ::handle<Geom2d_Transformation> aTrans = new Geom2d_Transformation();
|
||||
aTrans->SetTranslation(gp_Vec2d(1.0, 0.0));
|
||||
|
||||
occ::handle<Geom2d_Transformation> aRot = new Geom2d_Transformation();
|
||||
aRot->SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
|
||||
// aRot * aTrans: first translate, then rotate
|
||||
occ::handle<Geom2d_Transformation> aComposed = aRot->Multiplied(aTrans);
|
||||
|
||||
double aX = 0.0, aY = 0.0;
|
||||
aComposed->Transforms(aX, aY);
|
||||
// (0,0) -> translate to (1,0) -> rotate 90deg to (0,1)
|
||||
EXPECT_NEAR(aX, 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Power_Zero_IsIdentity)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 4.0);
|
||||
aTrsf->Power(0);
|
||||
|
||||
EXPECT_EQ(aTrsf->Form(), gp_Identity);
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Power_Positive)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
aTrsf->Power(2); // Two 90-degree rotations = 180 degrees
|
||||
|
||||
double aX = 1.0, aY = 0.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, -1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 0.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Value_Matrix)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
// Identity matrix values
|
||||
EXPECT_NEAR(aTrsf->Value(1, 1), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrsf->Value(1, 2), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrsf->Value(2, 1), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrsf->Value(2, 2), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Trsf2d_RoundTrip)
|
||||
{
|
||||
gp_Trsf2d aGpTrsf;
|
||||
aGpTrsf.SetRotation(gp_Pnt2d(1.0, 2.0), M_PI / 3.0);
|
||||
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation(aGpTrsf);
|
||||
gp_Trsf2d aBack = aTrsf->Trsf2d();
|
||||
|
||||
// Verify the round-trip preserves the transformation
|
||||
double aX1 = 5.0, aY1 = 7.0;
|
||||
double aX2 = 5.0, aY2 = 7.0;
|
||||
aGpTrsf.Transforms(aX1, aY1);
|
||||
aBack.Transforms(aX2, aY2);
|
||||
EXPECT_NEAR(aX1, aX2, Precision::Confusion());
|
||||
EXPECT_NEAR(aY1, aY2, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetScale(gp_Pnt2d(0.0, 0.0), 3.0);
|
||||
|
||||
occ::handle<Geom2d_Transformation> aCopy = aTrsf->Copy();
|
||||
EXPECT_NEAR(aCopy->ScaleFactor(), 3.0, Precision::Confusion());
|
||||
|
||||
// Verify independence
|
||||
aCopy->SetScale(gp_Pnt2d(0.0, 0.0), 5.0);
|
||||
EXPECT_NEAR(aTrsf->ScaleFactor(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetScale_WithCenter)
|
||||
{
|
||||
// Scaling with center at (2, 3) by factor 2
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetScale(gp_Pnt2d(2.0, 3.0), 2.0);
|
||||
|
||||
// The center should remain fixed
|
||||
double aX = 2.0, aY = 3.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 3.0, Precision::Confusion());
|
||||
|
||||
// A different point should scale from the center
|
||||
aX = 4.0;
|
||||
aY = 3.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 6.0, Precision::Confusion()); // 2 + 2*(4-2) = 6
|
||||
EXPECT_NEAR(aY, 3.0, Precision::Confusion()); // 3 + 2*(3-3) = 3
|
||||
}
|
||||
|
||||
TEST(Geom2d_TransformationTest, SetRotation_WithCenter)
|
||||
{
|
||||
// 90-degree rotation about (1, 1)
|
||||
occ::handle<Geom2d_Transformation> aTrsf = new Geom2d_Transformation();
|
||||
aTrsf->SetRotation(gp_Pnt2d(1.0, 1.0), M_PI / 2.0);
|
||||
|
||||
// Center stays fixed
|
||||
double aX = 1.0, aY = 1.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 1.0, Precision::Confusion());
|
||||
|
||||
// (2, 1) relative to center is (1, 0), rotated 90 deg is (0, 1), so result is (1, 2)
|
||||
aX = 2.0;
|
||||
aY = 1.0;
|
||||
aTrsf->Transforms(aX, aY);
|
||||
EXPECT_NEAR(aX, 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aY, 2.0, Precision::Confusion());
|
||||
}
|
||||
197
src/ModelingData/TKG2d/GTests/Geom2d_TrimmedCurve_Test.cxx
Normal file
197
src/ModelingData/TKG2d/GTests/Geom2d_TrimmedCurve_Test.cxx
Normal file
@@ -0,0 +1,197 @@
|
||||
// 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 <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_ConstructionError.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_TrimmedCurveTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Line through origin along X
|
||||
myLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0));
|
||||
|
||||
// Circle centered at origin, radius 5
|
||||
gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0);
|
||||
myCircle = new Geom2d_Circle(aCirc);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_Line> myLine;
|
||||
occ::handle<Geom2d_Circle> myCircle;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, ConstructFromLine)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
|
||||
EXPECT_DOUBLE_EQ(aTrim->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(aTrim->LastParameter(), 10.0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, ConstructFromCircle)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
|
||||
EXPECT_DOUBLE_EQ(aTrim->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(aTrim->LastParameter(), M_PI);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, StartAndEndPoints)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 2.0, 8.0);
|
||||
|
||||
const gp_Pnt2d aStart = aTrim->StartPoint();
|
||||
const gp_Pnt2d anEnd = aTrim->EndPoint();
|
||||
|
||||
EXPECT_NEAR(aStart.X(), 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anEnd.X(), 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, BasisCurve)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
|
||||
occ::handle<Geom2d_Curve> aBasis = aTrim->BasisCurve();
|
||||
EXPECT_FALSE(aBasis.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, EvalD0_MatchesBasisCurve)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
|
||||
for (double u = 0.0; u <= M_PI; u += M_PI / 4.0)
|
||||
{
|
||||
const gp_Pnt2d aTrimPnt = aTrim->EvalD0(u);
|
||||
const gp_Pnt2d aBasePnt = myCircle->EvalD0(u);
|
||||
EXPECT_TRUE(aTrimPnt.IsEqual(aBasePnt, Precision::Confusion()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, EvalD1_MatchesBasisCurve)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
|
||||
const auto [aTrimPnt, aTrimD1] = aTrim->EvalD1(5.0);
|
||||
const auto [aBasePnt, aBaseD1] = myLine->EvalD1(5.0);
|
||||
|
||||
EXPECT_TRUE(aTrimPnt.IsEqual(aBasePnt, Precision::Confusion()));
|
||||
EXPECT_NEAR(aTrimD1.X(), aBaseD1.X(), Precision::Confusion());
|
||||
EXPECT_NEAR(aTrimD1.Y(), aBaseD1.Y(), Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, Continuity)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
EXPECT_EQ(aTrim->Continuity(), GeomAbs_CN);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsCN)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
EXPECT_TRUE(aTrim->IsCN(10));
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsClosed_OpenArc)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
EXPECT_FALSE(aTrim->IsClosed());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsClosed_FullCircle)
|
||||
{
|
||||
// Full-period trim on a periodic curve should be reported as closed
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, 2.0 * M_PI);
|
||||
|
||||
EXPECT_TRUE(aTrim->IsClosed());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsPeriodic_PartialArc)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
EXPECT_FALSE(aTrim->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsPeriodic_FullPeriod)
|
||||
{
|
||||
// Full-period trim on a periodic curve should be reported as periodic
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, 2.0 * M_PI);
|
||||
EXPECT_TRUE(aTrim->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, IsPeriodic_Line)
|
||||
{
|
||||
// Line is not periodic, so trimmed line should not be periodic
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
EXPECT_FALSE(aTrim->IsPeriodic());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, SetTrim)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
aTrim->SetTrim(3.0, 7.0);
|
||||
|
||||
EXPECT_DOUBLE_EQ(aTrim->FirstParameter(), 3.0);
|
||||
EXPECT_DOUBLE_EQ(aTrim->LastParameter(), 7.0);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI);
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = aTrim->Copy();
|
||||
occ::handle<Geom2d_TrimmedCurve> aCopy = occ::down_cast<Geom2d_TrimmedCurve>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_DOUBLE_EQ(aCopy->FirstParameter(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(aCopy->LastParameter(), M_PI);
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, Transform_Translation)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myLine, 0.0, 10.0);
|
||||
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec2d(5.0, 5.0));
|
||||
aTrim->Transform(aTrsf);
|
||||
|
||||
const gp_Pnt2d aStart = aTrim->StartPoint();
|
||||
EXPECT_NEAR(aStart.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aStart.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_TrimmedCurveTest, CircleArc_StartEndPoints)
|
||||
{
|
||||
// Quarter circle arc
|
||||
occ::handle<Geom2d_TrimmedCurve> aTrim = new Geom2d_TrimmedCurve(myCircle, 0.0, M_PI / 2.0);
|
||||
|
||||
const gp_Pnt2d aStart = aTrim->StartPoint();
|
||||
const gp_Pnt2d anEnd = aTrim->EndPoint();
|
||||
|
||||
EXPECT_NEAR(aStart.X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aStart.Y(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anEnd.X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(anEnd.Y(), 5.0, Precision::Confusion());
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
// 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 <Geom2d_Direction.hxx>
|
||||
#include <Geom2d_VectorWithMagnitude.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_ConstructionError.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class Geom2d_VectorWithMagnitudeTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
myVec1 = new Geom2d_VectorWithMagnitude(3.0, 4.0);
|
||||
myVec2 = new Geom2d_VectorWithMagnitude(1.0, 0.0);
|
||||
}
|
||||
|
||||
occ::handle<Geom2d_VectorWithMagnitude> myVec1;
|
||||
occ::handle<Geom2d_VectorWithMagnitude> myVec2;
|
||||
};
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, ConstructFromCoords)
|
||||
{
|
||||
EXPECT_NEAR(myVec1->X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, ConstructFromVec2d)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec =
|
||||
new Geom2d_VectorWithMagnitude(gp_Vec2d(5.0, 12.0));
|
||||
EXPECT_NEAR(aVec->Magnitude(), 13.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, ConstructFromTwoPoints)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec =
|
||||
new Geom2d_VectorWithMagnitude(gp_Pnt2d(1.0, 2.0), gp_Pnt2d(4.0, 6.0));
|
||||
EXPECT_NEAR(aVec->X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->Y(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->Magnitude(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Magnitude)
|
||||
{
|
||||
EXPECT_NEAR(myVec1->Magnitude(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec2->Magnitude(), 1.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, SquareMagnitude)
|
||||
{
|
||||
EXPECT_NEAR(myVec1->SquareMagnitude(), 25.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Added)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aSum = myVec1->Added(myVec2);
|
||||
EXPECT_NEAR(aSum->X(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aSum->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Subtracted)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aDiff = myVec1->Subtracted(myVec2);
|
||||
EXPECT_NEAR(aDiff->X(), 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aDiff->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Multiplied)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aScaled = myVec1->Multiplied(2.0);
|
||||
EXPECT_NEAR(aScaled->X(), 6.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aScaled->Y(), 8.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aScaled->Magnitude(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Divided)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aScaled = myVec1->Divided(5.0);
|
||||
EXPECT_NEAR(aScaled->X(), 0.6, Precision::Confusion());
|
||||
EXPECT_NEAR(aScaled->Y(), 0.8, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Normalize)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec = new Geom2d_VectorWithMagnitude(3.0, 4.0);
|
||||
aVec->Normalize();
|
||||
EXPECT_NEAR(aVec->Magnitude(), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->X(), 0.6, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->Y(), 0.8, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Normalized)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aNorm = myVec1->Normalized();
|
||||
EXPECT_NEAR(aNorm->Magnitude(), 1.0, Precision::Confusion());
|
||||
// Original unchanged
|
||||
EXPECT_NEAR(myVec1->Magnitude(), 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Crossed)
|
||||
{
|
||||
// Cross product in 2D is scalar: (3,4) x (1,0) = 3*0 - 4*1 = -4
|
||||
const double aCross = myVec1->Crossed(myVec2);
|
||||
EXPECT_NEAR(aCross, -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Dot)
|
||||
{
|
||||
// (3,4) . (1,0) = 3
|
||||
const double aDot = myVec1->Dot(myVec2);
|
||||
EXPECT_NEAR(aDot, 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Angle)
|
||||
{
|
||||
// Angle from (1,0) to (0,1) = PI/2
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVecY = new Geom2d_VectorWithMagnitude(0.0, 1.0);
|
||||
const double anAngle = myVec2->Angle(aVecY);
|
||||
EXPECT_NEAR(anAngle, M_PI / 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Angle_Negative)
|
||||
{
|
||||
// Angle from (0,1) to (1,0) = -PI/2
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVecY = new Geom2d_VectorWithMagnitude(0.0, 1.0);
|
||||
const double anAngle = aVecY->Angle(myVec2);
|
||||
EXPECT_NEAR(anAngle, -M_PI / 2.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Reverse)
|
||||
{
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec = new Geom2d_VectorWithMagnitude(3.0, 4.0);
|
||||
aVec->Reverse();
|
||||
EXPECT_NEAR(aVec->X(), -3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->Y(), -4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, SetCoord)
|
||||
{
|
||||
myVec1->SetCoord(7.0, 8.0);
|
||||
EXPECT_NEAR(myVec1->X(), 7.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 8.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Vec2d)
|
||||
{
|
||||
const gp_Vec2d aVec = myVec1->Vec2d();
|
||||
EXPECT_NEAR(aVec.X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec.Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Copy)
|
||||
{
|
||||
occ::handle<Geom2d_Geometry> aCopyGeom = myVec1->Copy();
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aCopy =
|
||||
occ::down_cast<Geom2d_VectorWithMagnitude>(aCopyGeom);
|
||||
|
||||
ASSERT_FALSE(aCopy.IsNull());
|
||||
EXPECT_NEAR(aCopy->X(), 3.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aCopy->Y(), 4.0, Precision::Confusion());
|
||||
|
||||
aCopy->SetCoord(0.0, 0.0);
|
||||
EXPECT_NEAR(myVec1->X(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Add_InPlace)
|
||||
{
|
||||
myVec1->Add(myVec2);
|
||||
EXPECT_NEAR(myVec1->X(), 4.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Subtract_InPlace)
|
||||
{
|
||||
myVec1->Subtract(myVec2);
|
||||
EXPECT_NEAR(myVec1->X(), 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 4.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Multiply_InPlace)
|
||||
{
|
||||
myVec1->Multiply(3.0);
|
||||
EXPECT_NEAR(myVec1->X(), 9.0, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 12.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Divide_InPlace)
|
||||
{
|
||||
myVec1->Divide(5.0);
|
||||
EXPECT_NEAR(myVec1->X(), 0.6, Precision::Confusion());
|
||||
EXPECT_NEAR(myVec1->Y(), 0.8, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST_F(Geom2d_VectorWithMagnitudeTest, Transform_Rotation)
|
||||
{
|
||||
gp_Trsf2d aTrsf;
|
||||
aTrsf.SetRotation(gp_Pnt2d(0.0, 0.0), M_PI / 2.0);
|
||||
|
||||
occ::handle<Geom2d_VectorWithMagnitude> aVec = new Geom2d_VectorWithMagnitude(1.0, 0.0);
|
||||
aVec->Transform(aTrsf);
|
||||
|
||||
EXPECT_NEAR(aVec->X(), 0.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aVec->Y(), 1.0, Precision::Confusion());
|
||||
}
|
||||
136
src/ModelingData/TKG2d/GTests/LProp_AnalyticCurInf_Test.cxx
Normal file
136
src/ModelingData/TKG2d/GTests/LProp_AnalyticCurInf_Test.cxx
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 <GeomAbs_CurveType.hxx>
|
||||
#include <LProp_AnalyticCurInf.hxx>
|
||||
#include <LProp_CIType.hxx>
|
||||
#include <LProp_CurAndInf.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Line_NoExtrema)
|
||||
{
|
||||
// A line has constant zero curvature - no extrema
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Line, 0.0, 10.0, aResult);
|
||||
EXPECT_EQ(aResult.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Circle_NoExtrema)
|
||||
{
|
||||
// A circle has constant curvature - no extrema
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Circle, 0.0, 2.0 * M_PI, aResult);
|
||||
EXPECT_EQ(aResult.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Ellipse_FourExtrema)
|
||||
{
|
||||
// An ellipse has 4 curvature extrema in a full period
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Ellipse, 0.0, 2.0 * M_PI, aResult);
|
||||
EXPECT_EQ(aResult.NbPoints(), 4);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Ellipse_ExtremaTypes)
|
||||
{
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Ellipse, 0.0, 2.0 * M_PI, aResult);
|
||||
ASSERT_EQ(aResult.NbPoints(), 4);
|
||||
|
||||
int aNbMin = 0;
|
||||
int aNbMax = 0;
|
||||
for (int i = 1; i <= aResult.NbPoints(); ++i)
|
||||
{
|
||||
if (aResult.Type(i) == LProp_MinCur)
|
||||
++aNbMin;
|
||||
else if (aResult.Type(i) == LProp_MaxCur)
|
||||
++aNbMax;
|
||||
}
|
||||
EXPECT_EQ(aNbMin, 2);
|
||||
EXPECT_EQ(aNbMax, 2);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Ellipse_ExtremaAtExpectedParameters)
|
||||
{
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Ellipse, 0.0, 2.0 * M_PI, aResult);
|
||||
ASSERT_EQ(aResult.NbPoints(), 4);
|
||||
|
||||
// Extrema at 0, PI/2, PI, 3*PI/2
|
||||
const double anExpected[] = {0.0, M_PI / 2.0, M_PI, 3.0 * M_PI / 2.0};
|
||||
for (int i = 1; i <= 4; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aResult.Parameter(i), anExpected[i - 1], 1e-10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Ellipse_PartialRange)
|
||||
{
|
||||
// Only first quadrant: should have 2 extrema (at 0 and PI/2)
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Ellipse, 0.0, M_PI / 2.0, aResult);
|
||||
EXPECT_EQ(aResult.NbPoints(), 2);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Parabola_MinRadiusAtVertex)
|
||||
{
|
||||
// Parabola has minimum radius of curvature (= maximum curvature) at vertex.
|
||||
// LProp_AnalyticCurInf reports this as LProp_MinCur (minimum radius of curvature).
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Parabola, -10.0, 10.0, aResult);
|
||||
ASSERT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_NEAR(aResult.Parameter(1), 0.0, 1e-10);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MinCur);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Hyperbola_MinRadiusAtVertex)
|
||||
{
|
||||
// Hyperbola has minimum radius of curvature at vertex (parameter 0).
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Hyperbola, -5.0, 5.0, aResult);
|
||||
ASSERT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_NEAR(aResult.Parameter(1), 0.0, 1e-10);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MinCur);
|
||||
}
|
||||
|
||||
TEST(LProp_AnalyticCurInfTest, Ellipse_ParametersSorted)
|
||||
{
|
||||
LProp_AnalyticCurInf anAnalyzer;
|
||||
LProp_CurAndInf aResult;
|
||||
|
||||
anAnalyzer.Perform(GeomAbs_Ellipse, 0.0, 2.0 * M_PI, aResult);
|
||||
|
||||
for (int i = 1; i < aResult.NbPoints(); ++i)
|
||||
{
|
||||
EXPECT_LE(aResult.Parameter(i), aResult.Parameter(i + 1));
|
||||
}
|
||||
}
|
||||
129
src/ModelingData/TKG2d/GTests/LProp_CurAndInf_Test.cxx
Normal file
129
src/ModelingData/TKG2d/GTests/LProp_CurAndInf_Test.cxx
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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 <LProp_CIType.hxx>
|
||||
#include <LProp_CurAndInf.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(LProp_CurAndInfTest, DefaultConstructor_IsEmpty)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
EXPECT_TRUE(aResult.IsEmpty());
|
||||
EXPECT_EQ(aResult.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, AddInflection)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddInflection(1.5);
|
||||
|
||||
EXPECT_FALSE(aResult.IsEmpty());
|
||||
EXPECT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_DOUBLE_EQ(aResult.Parameter(1), 1.5);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_Inflection);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, AddExtCur_Minimum)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddExtCur(2.0, true);
|
||||
|
||||
EXPECT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_DOUBLE_EQ(aResult.Parameter(1), 2.0);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MinCur);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, AddExtCur_Maximum)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddExtCur(3.0, false);
|
||||
|
||||
EXPECT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_DOUBLE_EQ(aResult.Parameter(1), 3.0);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MaxCur);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, MultiplePoints_SortedByParameter)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
// Add in non-sorted order
|
||||
aResult.AddInflection(5.0);
|
||||
aResult.AddExtCur(1.0, true);
|
||||
aResult.AddExtCur(3.0, false);
|
||||
aResult.AddInflection(7.0);
|
||||
|
||||
EXPECT_EQ(aResult.NbPoints(), 4);
|
||||
|
||||
// Verify sorted order
|
||||
for (int i = 1; i < aResult.NbPoints(); ++i)
|
||||
{
|
||||
EXPECT_LE(aResult.Parameter(i), aResult.Parameter(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, MultiplePoints_CorrectTypes)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddExtCur(1.0, true); // MinCur
|
||||
aResult.AddInflection(3.0); // Inflection
|
||||
aResult.AddExtCur(5.0, false); // MaxCur
|
||||
|
||||
EXPECT_EQ(aResult.NbPoints(), 3);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MinCur);
|
||||
EXPECT_EQ(aResult.Type(2), LProp_Inflection);
|
||||
EXPECT_EQ(aResult.Type(3), LProp_MaxCur);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, Clear)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddInflection(1.0);
|
||||
aResult.AddExtCur(2.0, true);
|
||||
|
||||
EXPECT_EQ(aResult.NbPoints(), 2);
|
||||
|
||||
aResult.Clear();
|
||||
EXPECT_TRUE(aResult.IsEmpty());
|
||||
EXPECT_EQ(aResult.NbPoints(), 0);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, Clear_ThenRefill)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddInflection(1.0);
|
||||
aResult.Clear();
|
||||
|
||||
aResult.AddExtCur(5.0, false);
|
||||
EXPECT_EQ(aResult.NbPoints(), 1);
|
||||
EXPECT_DOUBLE_EQ(aResult.Parameter(1), 5.0);
|
||||
EXPECT_EQ(aResult.Type(1), LProp_MaxCur);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, Parameter_OutOfRange_Throws)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddInflection(1.0);
|
||||
|
||||
EXPECT_THROW(aResult.Parameter(0), Standard_OutOfRange);
|
||||
EXPECT_THROW(aResult.Parameter(2), Standard_OutOfRange);
|
||||
}
|
||||
|
||||
TEST(LProp_CurAndInfTest, Type_OutOfRange_Throws)
|
||||
{
|
||||
LProp_CurAndInf aResult;
|
||||
aResult.AddInflection(1.0);
|
||||
|
||||
EXPECT_THROW(aResult.Type(0), Standard_OutOfRange);
|
||||
EXPECT_THROW(aResult.Type(2), Standard_OutOfRange);
|
||||
}
|
||||
@@ -134,7 +134,7 @@ bool Geom2d_BSplineCurve::IsG1(const double theTf, const double theTl, const dou
|
||||
|
||||
bool Geom2d_BSplineCurve::IsClosed() const
|
||||
{
|
||||
return (StartPoint().Distance(EndPoint())) <= gp::Resolution();
|
||||
return StartPoint().SquareDistance(EndPoint()) <= Precision::Computational();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -370,7 +370,7 @@ bool Geom2d_OffsetCurve::IsClosed() const
|
||||
gp_Pnt2d PF, PL;
|
||||
Geom2d_Curve::D0(FirstParameter(), PF);
|
||||
Geom2d_Curve::D0(LastParameter(), PL);
|
||||
return (PF.Distance(PL) <= gp::Resolution());
|
||||
return PF.SquareDistance(PL) <= Precision::Computational();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
@@ -181,15 +181,30 @@ double Geom2d_TrimmedCurve::FirstParameter() const
|
||||
|
||||
bool Geom2d_TrimmedCurve::IsClosed() const
|
||||
{
|
||||
double Dist = Value(FirstParameter()).Distance(Value(LastParameter()));
|
||||
return (Dist <= gp::Resolution());
|
||||
if (basisCurve->IsPeriodic())
|
||||
{
|
||||
const double aPeriod = basisCurve->Period();
|
||||
const double aLength = LastParameter() - FirstParameter();
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return Value(FirstParameter()).SquareDistance(Value(LastParameter()))
|
||||
<= Precision::Computational();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom2d_TrimmedCurve::IsPeriodic() const
|
||||
{
|
||||
// return basisCurve->IsPeriodic();
|
||||
if (basisCurve->IsPeriodic())
|
||||
{
|
||||
const double aPeriod = basisCurve->Period();
|
||||
const double aLength = LastParameter() - FirstParameter();
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,12 +151,13 @@ public:
|
||||
//! of the trimmed curve.
|
||||
Standard_EXPORT double FirstParameter() const final;
|
||||
|
||||
//! Returns True if the distance between the StartPoint and
|
||||
//! the EndPoint is lower or equal to Resolution from package
|
||||
//! gp.
|
||||
//! Returns TRUE if the basis curve is periodic and the trim spans
|
||||
//! exactly one full period, or if the distance between the StartPoint
|
||||
//! and the EndPoint is within computational precision.
|
||||
Standard_EXPORT bool IsClosed() const final;
|
||||
|
||||
//! Always returns FALSE (independently of the type of basis curve).
|
||||
//! Returns TRUE if the basis curve is periodic and the trim
|
||||
//! spans exactly one full period. Returns FALSE otherwise.
|
||||
Standard_EXPORT bool IsPeriodic() const final;
|
||||
|
||||
//! Returns the period of the basis curve of this trimmed curve.
|
||||
|
||||
@@ -132,9 +132,8 @@ bool Geom_BSplineCurve::IsG1(const double theTf, const double theTl, const doubl
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom_BSplineCurve::IsClosed() const
|
||||
//-- { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
|
||||
{
|
||||
return (StartPoint().SquareDistance(EndPoint())) <= 1e-16;
|
||||
return StartPoint().SquareDistance(EndPoint()) <= Precision::Computational();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -424,7 +424,7 @@ bool Geom_OffsetCurve::IsClosed() const
|
||||
gp_Pnt PF, PL;
|
||||
Geom_Curve::D0(FirstParameter(), PF);
|
||||
Geom_Curve::D0(LastParameter(), PL);
|
||||
return (PF.Distance(PL) <= gp::Resolution());
|
||||
return PF.SquareDistance(PL) <= Precision::Computational();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
@@ -476,15 +476,18 @@ void Geom_RectangularTrimmedSurface::Transform(const Trsf& T)
|
||||
basisSurf->TransformParameters(utrim2, vtrim2, T);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : IsUPeriodic
|
||||
// purpose :
|
||||
// 24/11/98: pmn : Compare la periode a la longeur de l'intervalle
|
||||
//=======================================================================
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom_RectangularTrimmedSurface::IsUPeriodic() const
|
||||
{
|
||||
return basisSurf->IsUPeriodic() && !isutrimmed;
|
||||
if (!basisSurf->IsUPeriodic())
|
||||
return false;
|
||||
if (!isutrimmed)
|
||||
return true;
|
||||
const double aPeriod = basisSurf->UPeriod();
|
||||
const double aLength = utrim2 - utrim1;
|
||||
return aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -498,7 +501,14 @@ double Geom_RectangularTrimmedSurface::UPeriod() const
|
||||
|
||||
bool Geom_RectangularTrimmedSurface::IsVPeriodic() const
|
||||
{
|
||||
return basisSurf->IsVPeriodic() && !isvtrimmed;
|
||||
if (!basisSurf->IsVPeriodic())
|
||||
return false;
|
||||
if (!isvtrimmed)
|
||||
return true;
|
||||
const double aPeriod = basisSurf->VPeriod();
|
||||
const double aLength = vtrim2 - vtrim1;
|
||||
return aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -512,22 +522,34 @@ double Geom_RectangularTrimmedSurface::VPeriod() const
|
||||
|
||||
bool Geom_RectangularTrimmedSurface::IsUClosed() const
|
||||
{
|
||||
|
||||
if (isutrimmed)
|
||||
return false;
|
||||
else
|
||||
if (!isutrimmed)
|
||||
return basisSurf->IsUClosed();
|
||||
if (basisSurf->IsUPeriodic())
|
||||
{
|
||||
const double aPeriod = basisSurf->UPeriod();
|
||||
const double aLength = utrim2 - utrim1;
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom_RectangularTrimmedSurface::IsVClosed() const
|
||||
{
|
||||
|
||||
if (isvtrimmed)
|
||||
return false;
|
||||
else
|
||||
if (!isvtrimmed)
|
||||
return basisSurf->IsVClosed();
|
||||
if (basisSurf->IsVPeriodic())
|
||||
{
|
||||
const double aPeriod = basisSurf->VPeriod();
|
||||
const double aLength = vtrim2 - vtrim1;
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -186,10 +186,14 @@ public:
|
||||
//! CN : the order of continuity is infinite.
|
||||
Standard_EXPORT GeomAbs_Shape Continuity() const final;
|
||||
|
||||
//! Returns true if this patch is closed in the given parametric direction.
|
||||
//! Returns true if this patch is closed in U: either not trimmed in U
|
||||
//! and the basis surface is U-closed, or trimmed with a length that is
|
||||
//! an integer multiple of the U period of a U-periodic basis surface.
|
||||
Standard_EXPORT bool IsUClosed() const final;
|
||||
|
||||
//! Returns true if this patch is closed in the given parametric direction.
|
||||
//! Returns true if this patch is closed in V: either not trimmed in V
|
||||
//! and the basis surface is V-closed, or trimmed with a length that is
|
||||
//! an integer multiple of the V period of a V-periodic basis surface.
|
||||
Standard_EXPORT bool IsVClosed() const final;
|
||||
|
||||
//! Returns true if the order of derivation in the U parametric
|
||||
@@ -202,8 +206,8 @@ public:
|
||||
//! Raised if N < 0.
|
||||
Standard_EXPORT bool IsCNv(const int N) const final;
|
||||
|
||||
//! Returns true if this patch is periodic and not trimmed in the given
|
||||
//! parametric direction.
|
||||
//! Returns true if the basis surface is U-periodic and either not trimmed
|
||||
//! in U, or the trim spans an integer multiple of the U period.
|
||||
Standard_EXPORT bool IsUPeriodic() const final;
|
||||
|
||||
//! Returns the period of this patch in the u
|
||||
@@ -211,8 +215,8 @@ public:
|
||||
//! raises if the surface is not uperiodic.
|
||||
Standard_EXPORT double UPeriod() const final;
|
||||
|
||||
//! Returns true if this patch is periodic and not trimmed in the given
|
||||
//! parametric direction.
|
||||
//! Returns true if the basis surface is V-periodic and either not trimmed
|
||||
//! in V, or the trim spans an integer multiple of the V period.
|
||||
Standard_EXPORT bool IsVPeriodic() const final;
|
||||
|
||||
//! Returns the period of this patch in the v
|
||||
|
||||
@@ -144,14 +144,29 @@ void Geom_TrimmedCurve::SetTrim(const double U1,
|
||||
|
||||
bool Geom_TrimmedCurve::IsClosed() const
|
||||
{
|
||||
return (StartPoint().Distance(EndPoint()) <= gp::Resolution());
|
||||
if (basisCurve->IsPeriodic())
|
||||
{
|
||||
const double aPeriod = basisCurve->Period();
|
||||
const double aLength = LastParameter() - FirstParameter();
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return StartPoint().SquareDistance(EndPoint()) <= Precision::Computational();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool Geom_TrimmedCurve::IsPeriodic() const
|
||||
{
|
||||
// return basisCurve->IsPeriodic();
|
||||
if (basisCurve->IsPeriodic())
|
||||
{
|
||||
const double aPeriod = basisCurve->Period();
|
||||
const double aLength = LastParameter() - FirstParameter();
|
||||
if (aLength > Precision::PConfusion()
|
||||
&& std::abs(std::remainder(aLength, aPeriod)) <= Precision::PConfusion())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,11 +156,13 @@ public:
|
||||
//! of the trimmed curve.
|
||||
Standard_EXPORT double FirstParameter() const final;
|
||||
|
||||
//! Returns True if the distance between the StartPoint and
|
||||
//! the EndPoint is lower or equal to Resolution from package gp.
|
||||
//! Returns TRUE if the basis curve is periodic and the trim spans
|
||||
//! exactly one full period, or if the distance between the StartPoint
|
||||
//! and the EndPoint is within computational precision.
|
||||
Standard_EXPORT bool IsClosed() const final;
|
||||
|
||||
//! Always returns FALSE (independently of the type of basis curve).
|
||||
//! Returns TRUE if the basis curve is periodic and the trim
|
||||
//! spans exactly one full period. Returns FALSE otherwise.
|
||||
Standard_EXPORT bool IsPeriodic() const final;
|
||||
|
||||
//! Returns the period of the basis curve of this trimmed curve.
|
||||
|
||||
Reference in New Issue
Block a user