]> OCCT Git - occt.git/commitdiff
Coding - Geom package Copy optimisation (#645)
authorPasukhin Dmitry <dpasukhi@opencascade.com>
Sat, 26 Jul 2025 16:38:46 +0000 (17:38 +0100)
committerGitHub <noreply@github.com>
Sat, 26 Jul 2025 16:38:46 +0000 (17:38 +0100)
- 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

29 files changed:
src/ModelingData/TKG2d/GTests/FILES.cmake
src/ModelingData/TKG2d/GTests/Geom2d_BSplineCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.cxx
src/ModelingData/TKG2d/Geom2d/Geom2d_BSplineCurve.hxx
src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.cxx
src/ModelingData/TKG2d/Geom2d/Geom2d_BezierCurve.hxx
src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.cxx
src/ModelingData/TKG2d/Geom2d/Geom2d_OffsetCurve.hxx
src/ModelingData/TKG3d/GTests/FILES.cmake
src/ModelingData/TKG3d/GTests/Geom_BSplineCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx [new file with mode: 0644]
src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.cxx
src/ModelingData/TKG3d/Geom/Geom_BSplineCurve.hxx
src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.cxx
src/ModelingData/TKG3d/Geom/Geom_BSplineSurface.hxx
src/ModelingData/TKG3d/Geom/Geom_BezierCurve.cxx
src/ModelingData/TKG3d/Geom/Geom_BezierCurve.hxx
src/ModelingData/TKG3d/Geom/Geom_BezierSurface.cxx
src/ModelingData/TKG3d/Geom/Geom_BezierSurface.hxx
src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.cxx
src/ModelingData/TKG3d/Geom/Geom_OffsetCurve.hxx
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.cxx
src/ModelingData/TKG3d/Geom/Geom_OffsetSurface.hxx

index 4dba436cee43b79a4a09d32448ac6b3165c63c60..7b063e35ee5b10558108086224fd810ba3364aa4 100644 (file)
@@ -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 (file)
index 0000000..0f294ee
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2d_BezierCurve_Test.cxx
new file mode 100644 (file)
index 0000000..17a7905
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2d_OffsetCurve_Test.cxx
new file mode 100644 (file)
index 0000000..362122c
--- /dev/null
@@ -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 <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
index 8953a6b4b3fcfe59b7496b0800bd4291fe0928c0..11c50d54800ead85d340d4a24e6d1ebf051b4421 100644 (file)
@@ -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();
+  }
 }
 
 //=================================================================================================
index 944304ff3815934679a12716ee9748573f54ba1f..d9bb51d308140bc97d12996778e421948a70d3e2 100644 (file)
@@ -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
index 7f9ab22120e4a71a761981ef3614a29b84c726b4..e3963aba0518aea96e29da09a7c64ae1bf06a511 100644 (file)
@@ -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);
 }
 
 //=================================================================================================
index f119160cb82fe670d21d16d9726984a12183836a..a157871e33f73a0bbc1fd204fe1103ca8b7981e1 100644 (file)
@@ -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 <me>.
   //! raises ConstructionError if Degree is greater than MaxDegree or lower than 2
index de15644a6a5b0ab3a6bb3c7eeca254ddd7d18e9f..18d4db28fa9e10c0c1deb243070ced4af4b54c43 100644 (file)
@@ -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();
index 12615d52fcc1cc77edaca33c3551a2e4b9243071..98d2060f64be89df486ff6e5b380d1152eeb1907 100644 (file)
@@ -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 <me>.
   //! As a result:
   //! - the basis curve is reversed,
index 28f2c9555d825d86bf8ffb543165d129232af4c5..cee3c93ea78bca7998ed6525b18a43f6ad56e2bb 100644 (file)
@@ -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 (file)
index 0000000..04d0aed
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BSplineSurface_Test.cxx
new file mode 100644 (file)
index 0000000..fb6bd81
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BezierCurve_Test.cxx
new file mode 100644 (file)
index 0000000..1ac1e84
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_BezierSurface_Test.cxx
new file mode 100644 (file)
index 0000000..8531104
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_OffsetCurve_Test.cxx
new file mode 100644 (file)
index 0000000..0de247e
--- /dev/null
@@ -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 <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
diff --git a/src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/Geom_OffsetSurface_Test.cxx
new file mode 100644 (file)
index 0000000..f812902
--- /dev/null
@@ -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 <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
index 6c7a86c93e4c9d2a7523fa425277a3eb7bc6525a..b60f415bf6cb1d351e2949857b8bdadaecf46e71 100644 (file)
@@ -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();
+  }
 }
 
 //=================================================================================================
index 613ecd7a9a1321be5eeb459ba1e3da1aacc1f1a9..c63b9d13b303551cd2ae1928850ca9759e142997 100644 (file)
@@ -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
index eb280375dc94b667ad61f33ba88ff519e97c1108..b79768dbc0a53f3acd9b08c348815b5d2659d0ad 100644 (file)
@@ -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();
+  }
 }
 
 //=================================================================================================
index 92f452fdd22f38c72822517597968899f8b9be11..77954d45784454a137058c2444f78d644d46dd01 100644 (file)
@@ -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:
index fd8b7eddb643777a8dffb44a3133d6b59b66f573..e1fc65565bb1ac9f16f2c9c50b504318df0ba6eb 100644 (file)
@@ -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);
 }
 
 //=================================================================================================
index da9db56c4a4dadb0d7d5fd5b91db1fabfcd9ac40..73a4db2fda48f43abe2b1100b239811ae6a2ccd0 100644 (file)
@@ -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 <me>. Raises ConstructionError
   //! if Degree is greater than MaxDegree or lower than 2
index 9aa80513ede7d4a23affa227582723310f57755f..077461d3b6e340b4f4f90d0d3041996343f4cf87 100644 (file)
@@ -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);
 }
 
 //=================================================================================================
index e006f04ca454af5cc5228cf1c63f493e34de1153..8e14758d119e864ce84c37dd1d8e68403bb69542 100644 (file)
@@ -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.
index a2c5ae7881e76d27820505e454ee6d853f1c7fde..471372e1f94ada54a80fd94bed2ccd3b4f0d7891 100644 (file)
@@ -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,
index ee8a9e5a47027daab0ffca78de05ad5f3496ff1f..f98507126a92317a894f06fb8c6e313d1bdddaea 100644 (file)
@@ -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,
index 733cdc080887dae98e50a63e889e04e95c00ae72..873d34c38485c1ceb8d8e0bad2bea7d3a3d0acad 100644 (file)
@@ -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)
index 86916be97e105cc9c25f44ed28c0b1ab6342ee35..31831c30780f75e2459ab5d3e350fceea9d889f8 100644 (file)
@@ -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);