- Adds copy constructors for 9 geometry classes (Bezier/BSpline curves and surfaces, offset curves and surfaces in both 2D and 3D)
- Updates Copy() methods to use the new copy constructors instead of recreating objects through standard constructors
- Includes comprehensive test coverage for all new copy constructors
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
)
--- /dev/null
+// 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_BSplineCurve.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <gp_Pnt2d.hxx>
+
+#include <gtest/gtest.h>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom2d_BezierCurve.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <gp_Pnt2d.hxx>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom2d_OffsetCurve.hxx>
+#include <Geom2d_Circle.hxx>
+#include <gp_Circ2d.hxx>
+#include <gp_Ax2d.hxx>
+#include <gp_Dir2d.hxx>
+#include <gp_Pnt2d.hxx>
+
+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
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();
+ }
}
//=================================================================================================
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
//=================================================================================================
+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())
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);
}
//=================================================================================================
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 <me>.
//! raises ConstructionError if Degree is greater than MaxDegree or lower than 2
Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy() const
{
- Handle(Geom2d_OffsetCurve) C;
- C = new Geom2d_OffsetCurve(basisCurve, offsetValue);
- return C;
+ return new Geom2d_OffsetCurve(*this);
}
//=======================================================================
//=================================================================================================
+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();
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 <me>.
//! As a result:
//! - the basis curve is reversed,
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
)
--- /dev/null
+// 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 <Geom_BSplineCurve.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <gp_Pnt.hxx>
+
+#include <gtest/gtest.h>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom_BSplineSurface.hxx>
+#include <TColgp_Array2OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <gp_Pnt.hxx>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom_BezierCurve.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <gp_Pnt.hxx>
+
+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
--- /dev/null
+// 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 <Geom_BezierSurface.hxx>
+#include <TColgp_Array2OfPnt.hxx>
+#include <TColStd_Array2OfReal.hxx>
+#include <gp_Pnt.hxx>
+
+#include <gtest/gtest.h>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom_OffsetCurve.hxx>
+#include <Geom_Circle.hxx>
+#include <gp_Circ.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Pnt.hxx>
+
+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
--- /dev/null
+// Copyright (c) 2025 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <gtest/gtest.h>
+
+#include <Geom_OffsetSurface.hxx>
+#include <Geom_Plane.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Dir.hxx>
+
+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
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();
+ }
}
//=================================================================================================
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
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();
+ }
}
//=================================================================================================
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:
//=================================================================================================
+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();
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);
}
//=================================================================================================
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 <me>. Raises ConstructionError
//! if Degree is greater than MaxDegree or lower than 2
//=================================================================================================
+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)
{
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);
}
//=================================================================================================
//! 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.
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);
}
//=======================================================================
// 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,
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,
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);
}
//=======================================================================
// 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)
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);