diff --git a/src/ModelingData/TKG2d/GTests/FILES.cmake b/src/ModelingData/TKG2d/GTests/FILES.cmake index 4dba436cee..7b063e35ee 100644 --- a/src/ModelingData/TKG2d/GTests/FILES.cmake +++ b/src/ModelingData/TKG2d/GTests/FILES.cmake @@ -2,4 +2,7 @@ set(OCCT_TKG2d_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") set(OCCT_TKG2d_GTests_FILES + Geom2d_BSplineCurve_Test.cxx + Geom2d_BezierCurve_Test.cxx + Geom2d_OffsetCurve_Test.cxx ) diff --git a/src/ModelingData/TKG2d/GTests/Geom2d_BSplineCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2d_BSplineCurve_Test.cxx new file mode 100644 index 0000000000..0f294ee566 --- /dev/null +++ b/src/ModelingData/TKG2d/GTests/Geom2d_BSplineCurve_Test.cxx @@ -0,0 +1,139 @@ +// 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 +#include +#include +#include +#include + +#include + +class Geom2d_BSplineCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple BSpline curve for testing + TColgp_Array1OfPnt2d aPoles(1, 4); + aPoles(1) = gp_Pnt2d(0, 0); + aPoles(2) = gp_Pnt2d(1, 1); + aPoles(3) = gp_Pnt2d(2, 1); + aPoles(4) = gp_Pnt2d(3, 0); + + TColStd_Array1OfReal aKnots(1, 2); + aKnots(1) = 0.0; + aKnots(2) = 1.0; + + TColStd_Array1OfInteger aMults(1, 2); + aMults(1) = 4; + aMults(2) = 4; + + myOriginalCurve = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); + } + + Handle(Geom2d_BSplineCurve) myOriginalCurve; +}; + +TEST_F(Geom2d_BSplineCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom2d_BSplineCurve) aCopiedCurve = new Geom2d_BSplineCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + EXPECT_EQ(myOriginalCurve->NbKnots(), aCopiedCurve->NbKnots()); + EXPECT_EQ(myOriginalCurve->IsPeriodic(), aCopiedCurve->IsPeriodic()); + EXPECT_EQ(myOriginalCurve->IsRational(), aCopiedCurve->IsRational()); +} + +TEST_F(Geom2d_BSplineCurve_Test, CopyConstructorPoles) +{ + Handle(Geom2d_BSplineCurve) aCopiedCurve = new Geom2d_BSplineCurve(*myOriginalCurve); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbPoles(); ++i) + { + gp_Pnt2d anOrigPole = myOriginalCurve->Pole(i); + gp_Pnt2d aCopyPole = aCopiedCurve->Pole(i); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } +} + +TEST_F(Geom2d_BSplineCurve_Test, CopyConstructorKnots) +{ + Handle(Geom2d_BSplineCurve) aCopiedCurve = new Geom2d_BSplineCurve(*myOriginalCurve); + + // Verify all knots are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbKnots(); ++i) + { + EXPECT_DOUBLE_EQ(myOriginalCurve->Knot(i), aCopiedCurve->Knot(i)); + EXPECT_EQ(myOriginalCurve->Multiplicity(i), aCopiedCurve->Multiplicity(i)); + } +} + +TEST_F(Geom2d_BSplineCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom2d_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom2d_BSplineCurve) aCopiedCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.25) + { + gp_Pnt2d anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt2d aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom2d_BSplineCurve_Test, RationalCurveCopyConstructor) +{ + // Create a rational BSpline curve + TColgp_Array1OfPnt2d aPoles(1, 3); + aPoles(1) = gp_Pnt2d(0, 0); + aPoles(2) = gp_Pnt2d(1, 1); + aPoles(3) = gp_Pnt2d(2, 0); + + TColStd_Array1OfReal aWeights(1, 3); + aWeights(1) = 1.0; + aWeights(2) = 2.0; + aWeights(3) = 1.0; + + TColStd_Array1OfReal aKnots(1, 2); + aKnots(1) = 0.0; + aKnots(2) = 1.0; + + TColStd_Array1OfInteger aMults(1, 2); + aMults(1) = 3; + aMults(2) = 3; + + Handle(Geom2d_BSplineCurve) aRationalCurve = + new Geom2d_BSplineCurve(aPoles, aWeights, aKnots, aMults, 2); + Handle(Geom2d_BSplineCurve) aCopiedRational = new Geom2d_BSplineCurve(*aRationalCurve); + + EXPECT_TRUE(aCopiedRational->IsRational()); + + // Verify weights are copied correctly + for (Standard_Integer i = 1; i <= aRationalCurve->NbPoles(); ++i) + { + EXPECT_DOUBLE_EQ(aRationalCurve->Weight(i), aCopiedRational->Weight(i)); + } +} \ No newline at end of file diff --git a/src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx new file mode 100644 index 0000000000..17a790592d --- /dev/null +++ b/src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx @@ -0,0 +1,121 @@ +// 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 + +#include +#include +#include +#include + +class Geom2d_BezierCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple Bezier curve for testing + TColgp_Array1OfPnt2d aPoles(1, 4); + aPoles(1) = gp_Pnt2d(0, 0); + aPoles(2) = gp_Pnt2d(1, 1); + aPoles(3) = gp_Pnt2d(2, 1); + aPoles(4) = gp_Pnt2d(3, 0); + + myOriginalCurve = new Geom2d_BezierCurve(aPoles); + } + + Handle(Geom2d_BezierCurve) myOriginalCurve; +}; + +TEST_F(Geom2d_BezierCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom2d_BezierCurve) aCopiedCurve = new Geom2d_BezierCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + EXPECT_EQ(myOriginalCurve->IsRational(), aCopiedCurve->IsRational()); + EXPECT_EQ(myOriginalCurve->IsClosed(), aCopiedCurve->IsClosed()); +} + +TEST_F(Geom2d_BezierCurve_Test, CopyConstructorPoles) +{ + Handle(Geom2d_BezierCurve) aCopiedCurve = new Geom2d_BezierCurve(*myOriginalCurve); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbPoles(); ++i) + { + gp_Pnt2d anOrigPole = myOriginalCurve->Pole(i); + gp_Pnt2d aCopyPole = aCopiedCurve->Pole(i); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } +} + +TEST_F(Geom2d_BezierCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom2d_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom2d_BezierCurve) aCopiedCurve = Handle(Geom2d_BezierCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.25) + { + gp_Pnt2d anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt2d aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom2d_BezierCurve_Test, RationalCurveCopyConstructor) +{ + // Create a rational Bezier curve + TColgp_Array1OfPnt2d aPoles(1, 3); + aPoles(1) = gp_Pnt2d(0, 0); + aPoles(2) = gp_Pnt2d(1, 1); + aPoles(3) = gp_Pnt2d(2, 0); + + TColStd_Array1OfReal aWeights(1, 3); + aWeights(1) = 1.0; + aWeights(2) = 2.0; + aWeights(3) = 1.0; + + Handle(Geom2d_BezierCurve) aRationalCurve = new Geom2d_BezierCurve(aPoles, aWeights); + Handle(Geom2d_BezierCurve) aCopiedRational = new Geom2d_BezierCurve(*aRationalCurve); + + EXPECT_TRUE(aCopiedRational->IsRational()); + + // Verify weights are copied correctly + for (Standard_Integer i = 1; i <= aRationalCurve->NbPoles(); ++i) + { + EXPECT_DOUBLE_EQ(aRationalCurve->Weight(i), aCopiedRational->Weight(i)); + } +} + +TEST_F(Geom2d_BezierCurve_Test, CopyIndependence) +{ + Handle(Geom2d_BezierCurve) aCopiedCurve = new Geom2d_BezierCurve(*myOriginalCurve); + + // Modify the original curve + gp_Pnt2d aNewPole(10, 10); + myOriginalCurve->SetPole(2, aNewPole); + + // Verify the copied curve is not affected + gp_Pnt2d anOrigPole = aCopiedCurve->Pole(2); + EXPECT_FALSE(anOrigPole.IsEqual(aNewPole, 1e-10)); +} \ No newline at end of file diff --git a/src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx new file mode 100644 index 0000000000..362122c37c --- /dev/null +++ b/src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx @@ -0,0 +1,105 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +class Geom2d_OffsetCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a circle as basis curve + gp_Circ2d aCircle(gp_Ax2d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 5.0); + Handle(Geom2d_Circle) aBasisCurve = new Geom2d_Circle(aCircle); + + // Create offset curve + Standard_Real anOffsetValue = 2.0; + + myOriginalCurve = new Geom2d_OffsetCurve(aBasisCurve, anOffsetValue); + } + + Handle(Geom2d_OffsetCurve) myOriginalCurve; +}; + +TEST_F(Geom2d_OffsetCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom2d_OffsetCurve) aCopiedCurve = new Geom2d_OffsetCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_DOUBLE_EQ(myOriginalCurve->Offset(), aCopiedCurve->Offset()); + EXPECT_EQ(myOriginalCurve->IsPeriodic(), aCopiedCurve->IsPeriodic()); + EXPECT_EQ(myOriginalCurve->IsClosed(), aCopiedCurve->IsClosed()); +} + +TEST_F(Geom2d_OffsetCurve_Test, CopyConstructorBasisCurve) +{ + Handle(Geom2d_OffsetCurve) aCopiedCurve = new Geom2d_OffsetCurve(*myOriginalCurve); + + // Verify basis curves are equivalent but independent + Handle(Geom2d_Curve) anOrigBasis = myOriginalCurve->BasisCurve(); + Handle(Geom2d_Curve) aCopyBasis = aCopiedCurve->BasisCurve(); + + // They should be different objects + EXPECT_NE(anOrigBasis.get(), aCopyBasis.get()); + + // But functionally equivalent + EXPECT_DOUBLE_EQ(anOrigBasis->FirstParameter(), aCopyBasis->FirstParameter()); + EXPECT_DOUBLE_EQ(anOrigBasis->LastParameter(), aCopyBasis->LastParameter()); +} + +TEST_F(Geom2d_OffsetCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom2d_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom2d_OffsetCurve) aCopiedCurve = Handle(Geom2d_OffsetCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_DOUBLE_EQ(myOriginalCurve->Offset(), aCopiedCurve->Offset()); + + // Test evaluation at several points + Standard_Real anUFirst = myOriginalCurve->FirstParameter(); + Standard_Real anULast = myOriginalCurve->LastParameter(); + Standard_Real aStep = (anULast - anUFirst) / 4.0; + + for (Standard_Real u = anUFirst; u <= anULast; u += aStep) + { + gp_Pnt2d anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt2d aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom2d_OffsetCurve_Test, CopyIndependence) +{ + Handle(Geom2d_OffsetCurve) aCopiedCurve = new Geom2d_OffsetCurve(*myOriginalCurve); + + // Store original offset value + Standard_Real anOrigOffset = aCopiedCurve->Offset(); + + // Modify the original curve + myOriginalCurve->SetOffsetValue(10.0); + + // Verify the copied curve is not affected + EXPECT_DOUBLE_EQ(aCopiedCurve->Offset(), anOrigOffset); + EXPECT_NE(aCopiedCurve->Offset(), myOriginalCurve->Offset()); +} \ No newline at end of file diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.cxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.cxx index 8953a6b4b3..11c50d5480 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.cxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.cxx @@ -92,17 +92,41 @@ static Standard_Boolean Rational(const TColStd_Array1OfReal& theWeights) Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const { - Handle(Geom2d_BSplineCurve) C; - if (IsRational()) - C = new Geom2d_BSplineCurve(poles->Array1(), - weights->Array1(), - knots->Array1(), - mults->Array1(), - deg, - periodic); - else - C = new Geom2d_BSplineCurve(poles->Array1(), knots->Array1(), mults->Array1(), deg, periodic); - return C; + return new Geom2d_BSplineCurve(*this); +} + +//================================================================================================= + +Geom2d_BSplineCurve::Geom2d_BSplineCurve(const Geom2d_BSplineCurve& theOther) + : rational(theOther.rational), + periodic(theOther.periodic), + knotSet(theOther.knotSet), + smooth(theOther.smooth), + deg(theOther.deg), + maxderivinv(theOther.maxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray1OfPnt2d(theOther.poles->Lower(), theOther.poles->Upper()); + poles->ChangeArray1() = theOther.poles->Array1(); + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray1OfReal(theOther.weights->Lower(), theOther.weights->Upper()); + weights->ChangeArray1() = theOther.weights->Array1(); + } + + knots = new TColStd_HArray1OfReal(theOther.knots->Lower(), theOther.knots->Upper()); + knots->ChangeArray1() = theOther.knots->Array1(); + + mults = new TColStd_HArray1OfInteger(theOther.mults->Lower(), theOther.mults->Upper()); + mults->ChangeArray1() = theOther.mults->Array1(); + + if (!theOther.flatknots.IsNull()) + { + flatknots = new TColStd_HArray1OfReal(theOther.flatknots->Lower(), theOther.flatknots->Upper()); + flatknots->ChangeArray1() = theOther.flatknots->Array1(); + } } //================================================================================================= diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.hxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.hxx index 944304ff38..d9bb51d308 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.hxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.hxx @@ -196,6 +196,9 @@ public: const Standard_Integer Degree, const Standard_Boolean Periodic = Standard_False); + //! Copy constructor for optimized copying without validation. + Standard_EXPORT Geom2d_BSplineCurve(const Geom2d_BSplineCurve& theOther); + //! Increases the degree of this BSpline curve to //! Degree. As a result, the poles, weights and //! multiplicities tables are modified; the knots table is diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.cxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.cxx index 7f9ab22120..e3963aba05 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.cxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.cxx @@ -119,6 +119,25 @@ Geom2d_BezierCurve::Geom2d_BezierCurve(const TColgp_Array1OfPnt2d& Poles, //================================================================================================= +Geom2d_BezierCurve::Geom2d_BezierCurve(const Geom2d_BezierCurve& theOther) + : rational(theOther.rational), + closed(theOther.closed), + maxderivinv(theOther.maxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray1OfPnt2d(theOther.poles->Lower(), theOther.poles->Upper()); + poles->ChangeArray1() = theOther.poles->Array1(); + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray1OfReal(theOther.weights->Lower(), theOther.weights->Upper()); + weights->ChangeArray1() = theOther.weights->Array1(); + } +} + +//================================================================================================= + void Geom2d_BezierCurve::Increase(const Standard_Integer Deg) { if (Deg == Degree()) @@ -665,13 +684,7 @@ void Geom2d_BezierCurve::Resolution(const Standard_Real ToleranceUV, Standard_Re Handle(Geom2d_Geometry) Geom2d_BezierCurve::Copy() const { - - Handle(Geom2d_BezierCurve) C; - if (IsRational()) - C = new Geom2d_BezierCurve(poles->Array1(), weights->Array1()); - else - C = new Geom2d_BezierCurve(poles->Array1()); - return C; + return new Geom2d_BezierCurve(*this); } //================================================================================================= diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.hxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.hxx index f119160cb8..a157871e33 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.hxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.hxx @@ -108,6 +108,9 @@ public: Standard_EXPORT Geom2d_BezierCurve(const TColgp_Array1OfPnt2d& CurvePoles, const TColStd_Array1OfReal& PoleWeights); + //! Copy constructor for optimized copying without validation. + Standard_EXPORT Geom2d_BezierCurve(const Geom2d_BezierCurve& theOther); + //! Increases the degree of a bezier curve. Degree is the new //! degree of . //! raises ConstructionError if Degree is greater than MaxDegree or lower than 2 diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.cxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.cxx index de15644a6a..18d4db28fa 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.cxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.cxx @@ -42,9 +42,7 @@ static const Standard_Real MyAngularToleranceForG1 = Precision::Angular(); Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy() const { - Handle(Geom2d_OffsetCurve) C; - C = new Geom2d_OffsetCurve(basisCurve, offsetValue); - return C; + return new Geom2d_OffsetCurve(*this); } //======================================================================= @@ -63,6 +61,17 @@ Geom2d_OffsetCurve::Geom2d_OffsetCurve(const Handle(Geom2d_Curve)& theCurve, //================================================================================================= +Geom2d_OffsetCurve::Geom2d_OffsetCurve(const Geom2d_OffsetCurve& theOther) + : offsetValue(theOther.offsetValue), + myBasisCurveContinuity(theOther.myBasisCurveContinuity) +{ + // Deep copy basis curve and evaluator without validation + basisCurve = Handle(Geom2d_Curve)::DownCast(theOther.basisCurve->Copy()); + myEvaluator = new Geom2dEvaluator_OffsetCurve(basisCurve, offsetValue); +} + +//================================================================================================= + void Geom2d_OffsetCurve::Reverse() { basisCurve->Reverse(); diff --git a/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.hxx b/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.hxx index 12615d52fc..98d2060f64 100644 --- a/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.hxx +++ b/src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.hxx @@ -98,6 +98,9 @@ public: const Standard_Real Offset, const Standard_Boolean isNotCheckC0 = Standard_False); + //! Copy constructor for optimized copying without validation. + Standard_EXPORT Geom2d_OffsetCurve(const Geom2d_OffsetCurve& theOther); + //! Changes the direction of parametrization of . //! As a result: //! - the basis curve is reversed, diff --git a/src/ModelingData/TKG3d/GTests/FILES.cmake b/src/ModelingData/TKG3d/GTests/FILES.cmake index 28f2c9555d..cee3c93ea7 100644 --- a/src/ModelingData/TKG3d/GTests/FILES.cmake +++ b/src/ModelingData/TKG3d/GTests/FILES.cmake @@ -2,4 +2,10 @@ set(OCCT_TKG3d_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") set(OCCT_TKG3d_GTests_FILES + Geom_BSplineCurve_Test.cxx + Geom_BezierCurve_Test.cxx + Geom_BezierSurface_Test.cxx + Geom_BSplineSurface_Test.cxx + Geom_OffsetCurve_Test.cxx + Geom_OffsetSurface_Test.cxx ) diff --git a/src/ModelingData/TKG3d/GTests/Geom_BSplineCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BSplineCurve_Test.cxx new file mode 100644 index 0000000000..04d0aeda4a --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_BSplineCurve_Test.cxx @@ -0,0 +1,139 @@ +// 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 +#include +#include +#include +#include + +#include + +class Geom_BSplineCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple BSpline curve for testing + TColgp_Array1OfPnt aPoles(1, 4); + aPoles(1) = gp_Pnt(0, 0, 0); + aPoles(2) = gp_Pnt(1, 1, 0); + aPoles(3) = gp_Pnt(2, 1, 0); + aPoles(4) = gp_Pnt(3, 0, 0); + + TColStd_Array1OfReal aKnots(1, 2); + aKnots(1) = 0.0; + aKnots(2) = 1.0; + + TColStd_Array1OfInteger aMults(1, 2); + aMults(1) = 4; + aMults(2) = 4; + + myOriginalCurve = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3); + } + + Handle(Geom_BSplineCurve) myOriginalCurve; +}; + +TEST_F(Geom_BSplineCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_BSplineCurve) aCopiedCurve = new Geom_BSplineCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + EXPECT_EQ(myOriginalCurve->NbKnots(), aCopiedCurve->NbKnots()); + EXPECT_EQ(myOriginalCurve->IsPeriodic(), aCopiedCurve->IsPeriodic()); + EXPECT_EQ(myOriginalCurve->IsRational(), aCopiedCurve->IsRational()); +} + +TEST_F(Geom_BSplineCurve_Test, CopyConstructorPoles) +{ + Handle(Geom_BSplineCurve) aCopiedCurve = new Geom_BSplineCurve(*myOriginalCurve); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbPoles(); ++i) + { + gp_Pnt anOrigPole = myOriginalCurve->Pole(i); + gp_Pnt aCopyPole = aCopiedCurve->Pole(i); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } +} + +TEST_F(Geom_BSplineCurve_Test, CopyConstructorKnots) +{ + Handle(Geom_BSplineCurve) aCopiedCurve = new Geom_BSplineCurve(*myOriginalCurve); + + // Verify all knots are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbKnots(); ++i) + { + EXPECT_DOUBLE_EQ(myOriginalCurve->Knot(i), aCopiedCurve->Knot(i)); + EXPECT_EQ(myOriginalCurve->Multiplicity(i), aCopiedCurve->Multiplicity(i)); + } +} + +TEST_F(Geom_BSplineCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom_BSplineCurve) aCopiedCurve = Handle(Geom_BSplineCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.25) + { + gp_Pnt anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom_BSplineCurve_Test, RationalCurveCopyConstructor) +{ + // Create a rational BSpline curve + TColgp_Array1OfPnt aPoles(1, 3); + aPoles(1) = gp_Pnt(0, 0, 0); + aPoles(2) = gp_Pnt(1, 1, 0); + aPoles(3) = gp_Pnt(2, 0, 0); + + TColStd_Array1OfReal aWeights(1, 3); + aWeights(1) = 1.0; + aWeights(2) = 2.0; + aWeights(3) = 1.0; + + TColStd_Array1OfReal aKnots(1, 2); + aKnots(1) = 0.0; + aKnots(2) = 1.0; + + TColStd_Array1OfInteger aMults(1, 2); + aMults(1) = 3; + aMults(2) = 3; + + Handle(Geom_BSplineCurve) aRationalCurve = + new Geom_BSplineCurve(aPoles, aWeights, aKnots, aMults, 2); + Handle(Geom_BSplineCurve) aCopiedRational = new Geom_BSplineCurve(*aRationalCurve); + + EXPECT_TRUE(aCopiedRational->IsRational()); + + // Verify weights are copied correctly + for (Standard_Integer i = 1; i <= aRationalCurve->NbPoles(); ++i) + { + EXPECT_DOUBLE_EQ(aRationalCurve->Weight(i), aCopiedRational->Weight(i)); + } +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx new file mode 100644 index 0000000000..fb6bd81a90 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx @@ -0,0 +1,145 @@ +// 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 + +#include +#include +#include +#include +#include + +class Geom_BSplineSurface_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple BSpline surface for testing + TColgp_Array2OfPnt aPoles(1, 3, 1, 3); + for (Standard_Integer i = 1; i <= 3; ++i) + { + for (Standard_Integer j = 1; j <= 3; ++j) + { + aPoles(i, j) = gp_Pnt(i, j, (i + j) * 0.1); + } + } + + TColStd_Array1OfReal anUKnots(1, 2); + anUKnots(1) = 0.0; + anUKnots(2) = 1.0; + + TColStd_Array1OfReal aVKnots(1, 2); + aVKnots(1) = 0.0; + aVKnots(2) = 1.0; + + TColStd_Array1OfInteger anUMults(1, 2); + anUMults(1) = 3; + anUMults(2) = 3; + + TColStd_Array1OfInteger aVMults(1, 2); + aVMults(1) = 3; + aVMults(2) = 3; + + myOriginalSurface = new Geom_BSplineSurface(aPoles, anUKnots, aVKnots, anUMults, aVMults, 2, 2); + } + + Handle(Geom_BSplineSurface) myOriginalSurface; +}; + +TEST_F(Geom_BSplineSurface_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_BSplineSurface) aCopiedSurface = new Geom_BSplineSurface(*myOriginalSurface); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalSurface->UDegree(), aCopiedSurface->UDegree()); + EXPECT_EQ(myOriginalSurface->VDegree(), aCopiedSurface->VDegree()); + EXPECT_EQ(myOriginalSurface->NbUPoles(), aCopiedSurface->NbUPoles()); + EXPECT_EQ(myOriginalSurface->NbVPoles(), aCopiedSurface->NbVPoles()); + EXPECT_EQ(myOriginalSurface->NbUKnots(), aCopiedSurface->NbUKnots()); + EXPECT_EQ(myOriginalSurface->NbVKnots(), aCopiedSurface->NbVKnots()); + EXPECT_EQ(myOriginalSurface->IsUPeriodic(), aCopiedSurface->IsUPeriodic()); + EXPECT_EQ(myOriginalSurface->IsVPeriodic(), aCopiedSurface->IsVPeriodic()); +} + +TEST_F(Geom_BSplineSurface_Test, CopyConstructorPoles) +{ + Handle(Geom_BSplineSurface) aCopiedSurface = new Geom_BSplineSurface(*myOriginalSurface); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalSurface->NbUPoles(); ++i) + { + for (Standard_Integer j = 1; j <= myOriginalSurface->NbVPoles(); ++j) + { + gp_Pnt anOrigPole = myOriginalSurface->Pole(i, j); + gp_Pnt aCopyPole = aCopiedSurface->Pole(i, j); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } + } +} + +TEST_F(Geom_BSplineSurface_Test, CopyConstructorKnots) +{ + Handle(Geom_BSplineSurface) aCopiedSurface = new Geom_BSplineSurface(*myOriginalSurface); + + // Verify U knots are identical + for (Standard_Integer i = 1; i <= myOriginalSurface->NbUKnots(); ++i) + { + EXPECT_DOUBLE_EQ(myOriginalSurface->UKnot(i), aCopiedSurface->UKnot(i)); + EXPECT_EQ(myOriginalSurface->UMultiplicity(i), aCopiedSurface->UMultiplicity(i)); + } + + // Verify V knots are identical + for (Standard_Integer i = 1; i <= myOriginalSurface->NbVKnots(); ++i) + { + EXPECT_DOUBLE_EQ(myOriginalSurface->VKnot(i), aCopiedSurface->VKnot(i)); + EXPECT_EQ(myOriginalSurface->VMultiplicity(i), aCopiedSurface->VMultiplicity(i)); + } +} + +TEST_F(Geom_BSplineSurface_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalSurface->Copy(); + Handle(Geom_BSplineSurface) aCopiedSurface = Handle(Geom_BSplineSurface)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedSurface.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalSurface->UDegree(), aCopiedSurface->UDegree()); + EXPECT_EQ(myOriginalSurface->VDegree(), aCopiedSurface->VDegree()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.5) + { + for (Standard_Real v = 0.0; v <= 1.0; v += 0.5) + { + gp_Pnt anOrigPnt = myOriginalSurface->Value(u, v); + gp_Pnt aCopyPnt = aCopiedSurface->Value(u, v); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } + } +} + +TEST_F(Geom_BSplineSurface_Test, CopyIndependence) +{ + Handle(Geom_BSplineSurface) aCopiedSurface = new Geom_BSplineSurface(*myOriginalSurface); + + // Modify the original surface + gp_Pnt aNewPole(10, 10, 10); + myOriginalSurface->SetPole(2, 2, aNewPole); + + // Verify the copied surface is not affected + gp_Pnt anOrigPole = aCopiedSurface->Pole(2, 2); + EXPECT_FALSE(anOrigPole.IsEqual(aNewPole, 1e-10)); +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx new file mode 100644 index 0000000000..1ac1e842b2 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx @@ -0,0 +1,121 @@ +// 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 + +#include +#include +#include +#include + +class Geom_BezierCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple Bezier curve for testing + TColgp_Array1OfPnt aPoles(1, 4); + aPoles(1) = gp_Pnt(0, 0, 0); + aPoles(2) = gp_Pnt(1, 1, 0); + aPoles(3) = gp_Pnt(2, 1, 0); + aPoles(4) = gp_Pnt(3, 0, 0); + + myOriginalCurve = new Geom_BezierCurve(aPoles); + } + + Handle(Geom_BezierCurve) myOriginalCurve; +}; + +TEST_F(Geom_BezierCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_BezierCurve) aCopiedCurve = new Geom_BezierCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + EXPECT_EQ(myOriginalCurve->IsRational(), aCopiedCurve->IsRational()); + EXPECT_EQ(myOriginalCurve->IsClosed(), aCopiedCurve->IsClosed()); +} + +TEST_F(Geom_BezierCurve_Test, CopyConstructorPoles) +{ + Handle(Geom_BezierCurve) aCopiedCurve = new Geom_BezierCurve(*myOriginalCurve); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalCurve->NbPoles(); ++i) + { + gp_Pnt anOrigPole = myOriginalCurve->Pole(i); + gp_Pnt aCopyPole = aCopiedCurve->Pole(i); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } +} + +TEST_F(Geom_BezierCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom_BezierCurve) aCopiedCurve = Handle(Geom_BezierCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalCurve->Degree(), aCopiedCurve->Degree()); + EXPECT_EQ(myOriginalCurve->NbPoles(), aCopiedCurve->NbPoles()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.25) + { + gp_Pnt anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom_BezierCurve_Test, RationalCurveCopyConstructor) +{ + // Create a rational Bezier curve + TColgp_Array1OfPnt aPoles(1, 3); + aPoles(1) = gp_Pnt(0, 0, 0); + aPoles(2) = gp_Pnt(1, 1, 0); + aPoles(3) = gp_Pnt(2, 0, 0); + + TColStd_Array1OfReal aWeights(1, 3); + aWeights(1) = 1.0; + aWeights(2) = 2.0; + aWeights(3) = 1.0; + + Handle(Geom_BezierCurve) aRationalCurve = new Geom_BezierCurve(aPoles, aWeights); + Handle(Geom_BezierCurve) aCopiedRational = new Geom_BezierCurve(*aRationalCurve); + + EXPECT_TRUE(aCopiedRational->IsRational()); + + // Verify weights are copied correctly + for (Standard_Integer i = 1; i <= aRationalCurve->NbPoles(); ++i) + { + EXPECT_DOUBLE_EQ(aRationalCurve->Weight(i), aCopiedRational->Weight(i)); + } +} + +TEST_F(Geom_BezierCurve_Test, CopyIndependence) +{ + Handle(Geom_BezierCurve) aCopiedCurve = new Geom_BezierCurve(*myOriginalCurve); + + // Modify the original curve + gp_Pnt aNewPole(10, 10, 10); + myOriginalCurve->SetPole(2, aNewPole); + + // Verify the copied curve is not affected + gp_Pnt anOrigPole = aCopiedCurve->Pole(2); + EXPECT_FALSE(anOrigPole.IsEqual(aNewPole, 1e-10)); +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx new file mode 100644 index 0000000000..8531104899 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx @@ -0,0 +1,137 @@ +// 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 +#include +#include +#include + +#include + +class Geom_BezierSurface_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a simple Bezier surface for testing + TColgp_Array2OfPnt aPoles(1, 3, 1, 3); + for (Standard_Integer i = 1; i <= 3; ++i) + { + for (Standard_Integer j = 1; j <= 3; ++j) + { + aPoles(i, j) = gp_Pnt(i, j, (i + j) * 0.1); + } + } + + myOriginalSurface = new Geom_BezierSurface(aPoles); + } + + Handle(Geom_BezierSurface) myOriginalSurface; +}; + +TEST_F(Geom_BezierSurface_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_BezierSurface) aCopiedSurface = new Geom_BezierSurface(*myOriginalSurface); + + // Verify basic properties are identical + EXPECT_EQ(myOriginalSurface->UDegree(), aCopiedSurface->UDegree()); + EXPECT_EQ(myOriginalSurface->VDegree(), aCopiedSurface->VDegree()); + EXPECT_EQ(myOriginalSurface->NbUPoles(), aCopiedSurface->NbUPoles()); + EXPECT_EQ(myOriginalSurface->NbVPoles(), aCopiedSurface->NbVPoles()); + EXPECT_EQ(myOriginalSurface->IsURational(), aCopiedSurface->IsURational()); + EXPECT_EQ(myOriginalSurface->IsVRational(), aCopiedSurface->IsVRational()); +} + +TEST_F(Geom_BezierSurface_Test, CopyConstructorPoles) +{ + Handle(Geom_BezierSurface) aCopiedSurface = new Geom_BezierSurface(*myOriginalSurface); + + // Verify all poles are identical + for (Standard_Integer i = 1; i <= myOriginalSurface->NbUPoles(); ++i) + { + for (Standard_Integer j = 1; j <= myOriginalSurface->NbVPoles(); ++j) + { + gp_Pnt anOrigPole = myOriginalSurface->Pole(i, j); + gp_Pnt aCopyPole = aCopiedSurface->Pole(i, j); + EXPECT_TRUE(anOrigPole.IsEqual(aCopyPole, 1e-10)); + } + } +} + +TEST_F(Geom_BezierSurface_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalSurface->Copy(); + Handle(Geom_BezierSurface) aCopiedSurface = Handle(Geom_BezierSurface)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedSurface.IsNull()); + + // Verify the copy is functionally identical + EXPECT_EQ(myOriginalSurface->UDegree(), aCopiedSurface->UDegree()); + EXPECT_EQ(myOriginalSurface->VDegree(), aCopiedSurface->VDegree()); + + // Test evaluation at several points + for (Standard_Real u = 0.0; u <= 1.0; u += 0.5) + { + for (Standard_Real v = 0.0; v <= 1.0; v += 0.5) + { + gp_Pnt anOrigPnt = myOriginalSurface->Value(u, v); + gp_Pnt aCopyPnt = aCopiedSurface->Value(u, v); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } + } +} + +TEST_F(Geom_BezierSurface_Test, RationalSurfaceCopyConstructor) +{ + // Create a rational Bezier surface + TColgp_Array2OfPnt aPoles(1, 2, 1, 2); + aPoles(1, 1) = gp_Pnt(0, 0, 0); + aPoles(1, 2) = gp_Pnt(1, 0, 0); + aPoles(2, 1) = gp_Pnt(0, 1, 0); + aPoles(2, 2) = gp_Pnt(1, 1, 0); + + TColStd_Array2OfReal aWeights(1, 2, 1, 2); + aWeights(1, 1) = 1.0; + aWeights(1, 2) = 2.0; + aWeights(2, 1) = 2.0; + aWeights(2, 2) = 1.0; + + Handle(Geom_BezierSurface) aRationalSurface = new Geom_BezierSurface(aPoles, aWeights); + Handle(Geom_BezierSurface) aCopiedRational = new Geom_BezierSurface(*aRationalSurface); + + EXPECT_TRUE(aCopiedRational->IsURational() || aCopiedRational->IsVRational()); + + // Verify weights are copied correctly + for (Standard_Integer i = 1; i <= aRationalSurface->NbUPoles(); ++i) + { + for (Standard_Integer j = 1; j <= aRationalSurface->NbVPoles(); ++j) + { + EXPECT_DOUBLE_EQ(aRationalSurface->Weight(i, j), aCopiedRational->Weight(i, j)); + } + } +} + +TEST_F(Geom_BezierSurface_Test, CopyIndependence) +{ + Handle(Geom_BezierSurface) aCopiedSurface = new Geom_BezierSurface(*myOriginalSurface); + + // Modify the original surface + gp_Pnt aNewPole(10, 10, 10); + myOriginalSurface->SetPole(2, 2, aNewPole); + + // Verify the copied surface is not affected + gp_Pnt anOrigPole = aCopiedSurface->Pole(2, 2); + EXPECT_FALSE(anOrigPole.IsEqual(aNewPole, 1e-10)); +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx new file mode 100644 index 0000000000..0de247ebe3 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx @@ -0,0 +1,107 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +class Geom_OffsetCurve_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a circle as basis curve + gp_Circ aCircle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + Handle(Geom_Circle) aBasisCurve = new Geom_Circle(aCircle); + + // Create offset curve + gp_Dir anOffsetDir(0, 0, 1); + Standard_Real anOffsetValue = 2.0; + + myOriginalCurve = new Geom_OffsetCurve(aBasisCurve, anOffsetValue, anOffsetDir); + } + + Handle(Geom_OffsetCurve) myOriginalCurve; +}; + +TEST_F(Geom_OffsetCurve_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_OffsetCurve) aCopiedCurve = new Geom_OffsetCurve(*myOriginalCurve); + + // Verify basic properties are identical + EXPECT_DOUBLE_EQ(myOriginalCurve->Offset(), aCopiedCurve->Offset()); + EXPECT_TRUE(myOriginalCurve->Direction().IsEqual(aCopiedCurve->Direction(), 1e-10)); + EXPECT_EQ(myOriginalCurve->IsPeriodic(), aCopiedCurve->IsPeriodic()); + EXPECT_EQ(myOriginalCurve->IsClosed(), aCopiedCurve->IsClosed()); +} + +TEST_F(Geom_OffsetCurve_Test, CopyConstructorBasisCurve) +{ + Handle(Geom_OffsetCurve) aCopiedCurve = new Geom_OffsetCurve(*myOriginalCurve); + + // Verify basis curves are equivalent but independent + Handle(Geom_Curve) anOrigBasis = myOriginalCurve->BasisCurve(); + Handle(Geom_Curve) aCopyBasis = aCopiedCurve->BasisCurve(); + + // They should be different objects + EXPECT_NE(anOrigBasis.get(), aCopyBasis.get()); + + // But functionally equivalent + EXPECT_DOUBLE_EQ(anOrigBasis->FirstParameter(), aCopyBasis->FirstParameter()); + EXPECT_DOUBLE_EQ(anOrigBasis->LastParameter(), aCopyBasis->LastParameter()); +} + +TEST_F(Geom_OffsetCurve_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalCurve->Copy(); + Handle(Geom_OffsetCurve) aCopiedCurve = Handle(Geom_OffsetCurve)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedCurve.IsNull()); + + // Verify the copy is functionally identical + EXPECT_DOUBLE_EQ(myOriginalCurve->Offset(), aCopiedCurve->Offset()); + + // Test evaluation at several points + Standard_Real anUFirst = myOriginalCurve->FirstParameter(); + Standard_Real anULast = myOriginalCurve->LastParameter(); + Standard_Real aStep = (anULast - anUFirst) / 4.0; + + for (Standard_Real u = anUFirst; u <= anULast; u += aStep) + { + gp_Pnt anOrigPnt = myOriginalCurve->Value(u); + gp_Pnt aCopyPnt = aCopiedCurve->Value(u); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } +} + +TEST_F(Geom_OffsetCurve_Test, CopyIndependence) +{ + Handle(Geom_OffsetCurve) aCopiedCurve = new Geom_OffsetCurve(*myOriginalCurve); + + // Store original offset value + Standard_Real anOrigOffset = aCopiedCurve->Offset(); + + // Modify the original curve + myOriginalCurve->SetOffsetValue(10.0); + + // Verify the copied curve is not affected + EXPECT_DOUBLE_EQ(aCopiedCurve->Offset(), anOrigOffset); + EXPECT_NE(aCopiedCurve->Offset(), myOriginalCurve->Offset()); +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx new file mode 100644 index 0000000000..f812902963 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx @@ -0,0 +1,114 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +class Geom_OffsetSurface_Test : public ::testing::Test +{ +protected: + void SetUp() override + { + // Create a plane as basis surface + gp_Pln aPlane(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1))); + Handle(Geom_Plane) aBasisSurface = new Geom_Plane(aPlane); + + // Create offset surface + Standard_Real anOffsetValue = 3.0; + + myOriginalSurface = new Geom_OffsetSurface(aBasisSurface, anOffsetValue); + } + + Handle(Geom_OffsetSurface) myOriginalSurface; +}; + +TEST_F(Geom_OffsetSurface_Test, CopyConstructorBasicProperties) +{ + // Test copy constructor + Handle(Geom_OffsetSurface) aCopiedSurface = new Geom_OffsetSurface(*myOriginalSurface); + + // Verify basic properties are identical + EXPECT_DOUBLE_EQ(myOriginalSurface->Offset(), aCopiedSurface->Offset()); + EXPECT_EQ(myOriginalSurface->IsUPeriodic(), aCopiedSurface->IsUPeriodic()); + EXPECT_EQ(myOriginalSurface->IsVPeriodic(), aCopiedSurface->IsVPeriodic()); + EXPECT_EQ(myOriginalSurface->IsUClosed(), aCopiedSurface->IsUClosed()); + EXPECT_EQ(myOriginalSurface->IsVClosed(), aCopiedSurface->IsVClosed()); +} + +TEST_F(Geom_OffsetSurface_Test, CopyConstructorBasisSurface) +{ + Handle(Geom_OffsetSurface) aCopiedSurface = new Geom_OffsetSurface(*myOriginalSurface); + + // Verify basis surfaces are equivalent but independent + Handle(Geom_Surface) anOrigBasis = myOriginalSurface->BasisSurface(); + Handle(Geom_Surface) aCopyBasis = aCopiedSurface->BasisSurface(); + + // They should be different objects + EXPECT_NE(anOrigBasis.get(), aCopyBasis.get()); + + // But functionally equivalent + Standard_Real anUFirst, anULast, aVFirst, aVLast; + anOrigBasis->Bounds(anUFirst, anULast, aVFirst, aVLast); + + Standard_Real anUFirstCopy, anULastCopy, aVFirstCopy, aVLastCopy; + aCopyBasis->Bounds(anUFirstCopy, anULastCopy, aVFirstCopy, aVLastCopy); + + EXPECT_DOUBLE_EQ(anUFirst, anUFirstCopy); + EXPECT_DOUBLE_EQ(anULast, anULastCopy); + EXPECT_DOUBLE_EQ(aVFirst, aVFirstCopy); + EXPECT_DOUBLE_EQ(aVLast, aVLastCopy); +} + +TEST_F(Geom_OffsetSurface_Test, CopyMethodUsesOptimizedConstructor) +{ + // Test that Copy() method uses the optimized copy constructor + Handle(Geom_Geometry) aCopiedGeom = myOriginalSurface->Copy(); + Handle(Geom_OffsetSurface) aCopiedSurface = Handle(Geom_OffsetSurface)::DownCast(aCopiedGeom); + + EXPECT_FALSE(aCopiedSurface.IsNull()); + + // Verify the copy is functionally identical + EXPECT_DOUBLE_EQ(myOriginalSurface->Offset(), aCopiedSurface->Offset()); + + // Test evaluation at several points + for (Standard_Real u = -5.0; u <= 5.0; u += 2.5) + { + for (Standard_Real v = -5.0; v <= 5.0; v += 2.5) + { + gp_Pnt anOrigPnt = myOriginalSurface->Value(u, v); + gp_Pnt aCopyPnt = aCopiedSurface->Value(u, v); + EXPECT_TRUE(anOrigPnt.IsEqual(aCopyPnt, 1e-10)); + } + } +} + +TEST_F(Geom_OffsetSurface_Test, CopyIndependence) +{ + Handle(Geom_OffsetSurface) aCopiedSurface = new Geom_OffsetSurface(*myOriginalSurface); + + // Store original offset value + Standard_Real anOrigOffset = aCopiedSurface->Offset(); + + // Modify the original surface + myOriginalSurface->SetOffsetValue(15.0); + + // Verify the copied surface is not affected + EXPECT_DOUBLE_EQ(aCopiedSurface->Offset(), anOrigOffset); + EXPECT_NE(aCopiedSurface->Offset(), myOriginalSurface->Offset()); +} \ No newline at end of file diff --git a/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.cxx b/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.cxx index 6c7a86c93e..b60f415bf6 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.cxx @@ -95,17 +95,41 @@ static Standard_Boolean Rational(const TColStd_Array1OfReal& theWeights) Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const { - Handle(Geom_BSplineCurve) C; - if (IsRational()) - C = new Geom_BSplineCurve(poles->Array1(), - weights->Array1(), - knots->Array1(), - mults->Array1(), - deg, - periodic); - else - C = new Geom_BSplineCurve(poles->Array1(), knots->Array1(), mults->Array1(), deg, periodic); - return C; + return new Geom_BSplineCurve(*this); +} + +//================================================================================================= + +Geom_BSplineCurve::Geom_BSplineCurve(const Geom_BSplineCurve& theOther) + : rational(theOther.rational), + periodic(theOther.periodic), + knotSet(theOther.knotSet), + smooth(theOther.smooth), + deg(theOther.deg), + maxderivinv(theOther.maxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray1OfPnt(theOther.poles->Lower(), theOther.poles->Upper()); + poles->ChangeArray1() = theOther.poles->Array1(); + + knots = new TColStd_HArray1OfReal(theOther.knots->Lower(), theOther.knots->Upper()); + knots->ChangeArray1() = theOther.knots->Array1(); + + mults = new TColStd_HArray1OfInteger(theOther.mults->Lower(), theOther.mults->Upper()); + mults->ChangeArray1() = theOther.mults->Array1(); + + if (!theOther.flatknots.IsNull()) + { + flatknots = new TColStd_HArray1OfReal(theOther.flatknots->Lower(), theOther.flatknots->Upper()); + flatknots->ChangeArray1() = theOther.flatknots->Array1(); + } + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray1OfReal(theOther.weights->Lower(), theOther.weights->Upper()); + weights->ChangeArray1() = theOther.weights->Array1(); + } } //================================================================================================= diff --git a/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.hxx b/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.hxx index 613ecd7a9a..c63b9d13b3 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.hxx @@ -172,6 +172,10 @@ public: const Standard_Boolean Periodic = Standard_False, const Standard_Boolean CheckRational = Standard_True); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the BSpline curve to copy from + Standard_EXPORT Geom_BSplineCurve(const Geom_BSplineCurve& theOther); + //! Increases the degree of this BSpline curve to //! Degree. As a result, the poles, weights and //! multiplicities tables are modified; the knots table is diff --git a/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.cxx b/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.cxx index eb280375dc..b79768dbc0 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.cxx @@ -128,29 +128,65 @@ static void Rational(const TColStd_Array2OfReal& Weights, Handle(Geom_Geometry) Geom_BSplineSurface::Copy() const { - Handle(Geom_BSplineSurface) S; - if (urational || vrational) - S = new Geom_BSplineSurface(poles->Array2(), - weights->Array2(), - uknots->Array1(), - vknots->Array1(), - umults->Array1(), - vmults->Array1(), - udeg, - vdeg, - uperiodic, - vperiodic); - else - S = new Geom_BSplineSurface(poles->Array2(), - uknots->Array1(), - vknots->Array1(), - umults->Array1(), - vmults->Array1(), - udeg, - vdeg, - uperiodic, - vperiodic); - return S; + return new Geom_BSplineSurface(*this); +} + +//================================================================================================= + +Geom_BSplineSurface::Geom_BSplineSurface(const Geom_BSplineSurface& theOther) + : urational(theOther.urational), + vrational(theOther.vrational), + uperiodic(theOther.uperiodic), + vperiodic(theOther.vperiodic), + uknotSet(theOther.uknotSet), + vknotSet(theOther.vknotSet), + Usmooth(theOther.Usmooth), + Vsmooth(theOther.Vsmooth), + udeg(theOther.udeg), + vdeg(theOther.vdeg), + umaxderivinv(theOther.umaxderivinv), + vmaxderivinv(theOther.vmaxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray2OfPnt(theOther.poles->LowerRow(), + theOther.poles->UpperRow(), + theOther.poles->LowerCol(), + theOther.poles->UpperCol()); + poles->ChangeArray2() = theOther.poles->Array2(); + + uknots = new TColStd_HArray1OfReal(theOther.uknots->Lower(), theOther.uknots->Upper()); + uknots->ChangeArray1() = theOther.uknots->Array1(); + + vknots = new TColStd_HArray1OfReal(theOther.vknots->Lower(), theOther.vknots->Upper()); + vknots->ChangeArray1() = theOther.vknots->Array1(); + + umults = new TColStd_HArray1OfInteger(theOther.umults->Lower(), theOther.umults->Upper()); + umults->ChangeArray1() = theOther.umults->Array1(); + + vmults = new TColStd_HArray1OfInteger(theOther.vmults->Lower(), theOther.vmults->Upper()); + vmults->ChangeArray1() = theOther.vmults->Array1(); + + if (!theOther.ufknots.IsNull()) + { + ufknots = new TColStd_HArray1OfReal(theOther.ufknots->Lower(), theOther.ufknots->Upper()); + ufknots->ChangeArray1() = theOther.ufknots->Array1(); + } + + if (!theOther.vfknots.IsNull()) + { + vfknots = new TColStd_HArray1OfReal(theOther.vfknots->Lower(), theOther.vfknots->Upper()); + vfknots->ChangeArray1() = theOther.vfknots->Array1(); + } + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray2OfReal(theOther.weights->LowerRow(), + theOther.weights->UpperRow(), + theOther.weights->LowerCol(), + theOther.weights->UpperCol()); + weights->ChangeArray2() = theOther.weights->Array2(); + } } //================================================================================================= diff --git a/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.hxx b/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.hxx index 92f452fdd2..77954d4578 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.hxx @@ -228,6 +228,10 @@ public: const Standard_Boolean UPeriodic = Standard_False, const Standard_Boolean VPeriodic = Standard_False); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the BSpline surface to copy from + Standard_EXPORT Geom_BSplineSurface(const Geom_BSplineSurface& theOther); + //! Exchanges the u and v parametric directions on //! this BSpline surface. //! As a consequence: diff --git a/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.cxx b/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.cxx index fd8b7eddb6..e1fc65565b 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.cxx @@ -63,6 +63,25 @@ static Standard_Boolean Rational(const TColStd_Array1OfReal& W) //================================================================================================= +Geom_BezierCurve::Geom_BezierCurve(const Geom_BezierCurve& theOther) + : rational(theOther.rational), + closed(theOther.closed), + maxderivinv(theOther.maxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray1OfPnt(theOther.poles->Lower(), theOther.poles->Upper()); + poles->ChangeArray1() = theOther.poles->Array1(); + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray1OfReal(theOther.weights->Lower(), theOther.weights->Upper()); + weights->ChangeArray1() = theOther.weights->Array1(); + } +} + +//================================================================================================= + Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles) { Standard_Integer nbpoles = Poles.Length(); @@ -692,13 +711,7 @@ void Geom_BezierCurve::Resolution(const Standard_Real Tolerance3D, Standard_Real Handle(Geom_Geometry) Geom_BezierCurve::Copy() const { - - Handle(Geom_BezierCurve) C; - if (IsRational()) - C = new Geom_BezierCurve(poles->Array1(), weights->Array1()); - else - C = new Geom_BezierCurve(poles->Array1()); - return C; + return new Geom_BezierCurve(*this); } //================================================================================================= diff --git a/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.hxx b/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.hxx index da9db56c4a..73a4db2fda 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BezierCurve.hxx @@ -104,6 +104,10 @@ public: Standard_EXPORT Geom_BezierCurve(const TColgp_Array1OfPnt& CurvePoles, const TColStd_Array1OfReal& PoleWeights); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the Bezier curve to copy from + Standard_EXPORT Geom_BezierCurve(const Geom_BezierCurve& theOther); + //! Increases the degree of a bezier curve. Degree is the new //! degree of . Raises ConstructionError //! if Degree is greater than MaxDegree or lower than 2 diff --git a/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.cxx b/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.cxx index 9aa80513ed..077461d3b6 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.cxx @@ -359,6 +359,32 @@ static void DeleteRatPoleRow(const TColgp_Array2OfPnt& Poles, //================================================================================================= +Geom_BezierSurface::Geom_BezierSurface(const Geom_BezierSurface& theOther) + : urational(theOther.urational), + vrational(theOther.vrational), + umaxderivinv(theOther.umaxderivinv), + vmaxderivinv(theOther.vmaxderivinv), + maxderivinvok(Standard_False) +{ + // Deep copy all data arrays without validation + poles = new TColgp_HArray2OfPnt(theOther.poles->LowerRow(), + theOther.poles->UpperRow(), + theOther.poles->LowerCol(), + theOther.poles->UpperCol()); + poles->ChangeArray2() = theOther.poles->Array2(); + + if (!theOther.weights.IsNull()) + { + weights = new TColStd_HArray2OfReal(theOther.weights->LowerRow(), + theOther.weights->UpperRow(), + theOther.weights->LowerCol(), + theOther.weights->UpperCol()); + weights->ChangeArray2() = theOther.weights->Array2(); + } +} + +//================================================================================================= + Geom_BezierSurface::Geom_BezierSurface(const TColgp_Array2OfPnt& SurfacePoles) : maxderivinvok(Standard_False) { @@ -2036,8 +2062,7 @@ void Geom_BezierSurface::Resolution(const Standard_Real Tolerance3D, Handle(Geom_Geometry) Geom_BezierSurface::Copy() const { - Handle(Geom_BezierSurface) S = new Geom_BezierSurface(poles, weights, urational, vrational); - return S; + return new Geom_BezierSurface(*this); } //================================================================================================= diff --git a/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.hxx b/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.hxx index e006f04ca4..8e14758d11 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_BezierSurface.hxx @@ -127,6 +127,10 @@ public: //! U or V. Standard_EXPORT Geom_BezierSurface(const TColgp_Array2OfPnt& SurfacePoles); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the Bezier surface to copy from + Standard_EXPORT Geom_BezierSurface(const Geom_BezierSurface& theOther); + //! ---Purpose //! Creates a rational Bezier surface with a set of poles and a //! set of weights. diff --git a/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.cxx b/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.cxx index a2c5ae7881..471372e1f9 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.cxx @@ -44,10 +44,7 @@ static const Standard_Real MyAngularToleranceForG1 = Precision::Angular(); Handle(Geom_Geometry) Geom_OffsetCurve::Copy() const { - - Handle(Geom_OffsetCurve) C; - C = new Geom_OffsetCurve(basisCurve, offsetValue, direction); - return C; + return new Geom_OffsetCurve(*this); } //======================================================================= @@ -56,6 +53,18 @@ Handle(Geom_Geometry) Geom_OffsetCurve::Copy() const // offset curve. //======================================================================= +Geom_OffsetCurve::Geom_OffsetCurve(const Geom_OffsetCurve& theOther) + : basisCurve(Handle(Geom_Curve)::DownCast(theOther.basisCurve->Copy())), + direction(theOther.direction), + offsetValue(theOther.offsetValue), + myBasisCurveContinuity(theOther.myBasisCurveContinuity), + myEvaluator(new GeomEvaluator_OffsetCurve(basisCurve, offsetValue, direction)) +{ + // Deep copy without validation - source curve is already validated +} + +//======================================================================= + Geom_OffsetCurve::Geom_OffsetCurve(const Handle(Geom_Curve)& theCurve, const Standard_Real theOffset, const gp_Dir& theDir, diff --git a/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.hxx b/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.hxx index ee8a9e5a47..f98507126a 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.hxx @@ -101,6 +101,10 @@ public: const gp_Dir& V, const Standard_Boolean isNotCheckC0 = Standard_False); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the offset curve to copy from + Standard_EXPORT Geom_OffsetCurve(const Geom_OffsetCurve& theOther); + //! Changes the orientation of this offset curve. //! As a result: //! - the basis curve is reversed, diff --git a/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx b/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx index 733cdc0808..873d34c384 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx +++ b/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx @@ -70,8 +70,7 @@ static const Standard_Real MyAngularToleranceForG1 = Precision::Angular(); Handle(Geom_Geometry) Geom_OffsetSurface::Copy() const { - Handle(Geom_OffsetSurface) S(new Geom_OffsetSurface(basisSurf, offsetValue, Standard_True)); - return S; + return new Geom_OffsetSurface(*this); } //======================================================================= @@ -80,6 +79,21 @@ Handle(Geom_Geometry) Geom_OffsetSurface::Copy() const // offset surface. //======================================================================= +Geom_OffsetSurface::Geom_OffsetSurface(const Geom_OffsetSurface& theOther) + : basisSurf(Handle(Geom_Surface)::DownCast(theOther.basisSurf->Copy())), + equivSurf(theOther.equivSurf.IsNull() + ? Handle(Geom_Surface)() + : Handle(Geom_Surface)::DownCast(theOther.equivSurf->Copy())), + offsetValue(theOther.offsetValue), + myOscSurf(theOther.myOscSurf), + myBasisSurfContinuity(theOther.myBasisSurfContinuity), + myEvaluator(new GeomEvaluator_OffsetSurface(basisSurf, offsetValue, myOscSurf)) +{ + // Deep copy without validation - source surface is already validated +} + +//======================================================================= + Geom_OffsetSurface::Geom_OffsetSurface(const Handle(Geom_Surface)& theSurf, const Standard_Real theOffset, const Standard_Boolean isNotCheckC0) diff --git a/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx b/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx index 86916be97e..31831c3078 100644 --- a/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx +++ b/src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx @@ -101,6 +101,10 @@ public: Standard_EXPORT void SetBasisSurface(const Handle(Geom_Surface)& S, const Standard_Boolean isNotCheckC0 = Standard_False); + //! Copy constructor for optimized copying without validation. + //! @param[in] theOther the offset surface to copy from + Standard_EXPORT Geom_OffsetSurface(const Geom_OffsetSurface& theOther); + //! Changes this offset surface by assigning D as the offset value. Standard_EXPORT void SetOffsetValue(const Standard_Real D);