- Adds a complete TKHelix toolkit with geometric helix curve adaptor and topological builders
- Implements advanced B-spline approximation algorithms for high-quality helix representation
- Provides comprehensive TCL command interface for interactive helix creation and testing
// BRepTest::PlacementCommands(theCommands) ;
BRepTest::ProjectionCommands(theCommands);
BRepTest::HistoryCommands(theCommands);
+ BRepTest::HelixCommands(theCommands);
// define the TCL variable Draw_TOPOLOGY
const char* com = "set Draw_TOPOLOGY 1";
//! Defines the History commands for the algorithms.
Standard_EXPORT static void HistoryCommands(Draw_Interpretor& DI);
-protected:
-private:
+ Standard_EXPORT static void HelixCommands(Draw_Interpretor& theCommands);
};
#endif // _BRepTest_HeaderFile
--- /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 <DBRep.hxx>
+#include <Draw.hxx>
+#include <Draw_Color.hxx>
+#include <Draw_Interpretor.hxx>
+#include <Draw_Marker3D.hxx>
+#include <Draw_Segment3D.hxx>
+#include <Draw_Viewer.hxx>
+#include <DrawTrSurf.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Surface.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <gp.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <HelixBRep_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_Tools.hxx>
+#include <TColGeom_HArray1OfCurve.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TopoDS_Shape.hxx>
+#include <BRepTest.hxx>
+
+Standard_IMPORT Draw_Viewer dout;
+static gp_Ax3 theHelixAxis(gp_Pnt(0., 0., 0), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+
+static Standard_Integer comphelix(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer helix(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer spiral(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer setaxis(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer comphelix2(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer helix2(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer spiral2(Draw_Interpretor&, Standard_Integer, const char**);
+
+// Helper function to display helix results
+static void DisplayHelixResult(Draw_Interpretor& theDI,
+ const HelixBRep_BuilderHelix& theBuilder,
+ const char* theName)
+{
+ if (theBuilder.ErrorStatus() == 0)
+ {
+ Standard_Real aMaxError = theBuilder.ToleranceReached();
+ theDI << "WarningStatus = " << theBuilder.WarningStatus() << "\n";
+ theDI << "ToleranceReached = " << aMaxError << "\n";
+ const TopoDS_Shape& aW = theBuilder.Shape();
+ DBRep::Set(theName, aW);
+ }
+ else
+ {
+ theDI << "ErrorStatus = " << theBuilder.ErrorStatus() << "\n";
+ }
+}
+
+//=================================================================================================
+
+void BRepTest::HelixCommands(Draw_Interpretor& theCommands)
+{
+ static Standard_Boolean done = Standard_False;
+ if (done)
+ return;
+ done = Standard_True;
+ // Chapters name
+ const char* g = "Helix commands";
+ // Commands
+ theCommands.Add("setaxis", "setaxis x y z Nx Ny Nz Xx Xy Xz", __FILE__, setaxis, g);
+ theCommands.Add("comphelix",
+ "comphelix name np D1 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__,
+ comphelix,
+ g);
+ theCommands.Add("helix",
+ "helix name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__,
+ helix,
+ g);
+ theCommands.Add("spiral",
+ "spiral name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__,
+ spiral,
+ g);
+ theCommands.Add("comphelix2",
+ "comphelix2 name np D1 [Di...] P1 [Pi...] N1 [Ni...]",
+ __FILE__,
+ comphelix2,
+ g);
+ theCommands.Add("helix2", "helix2 name np D1 P1 [Pi...] N1 [Ni...]", __FILE__, helix2, g);
+ theCommands.Add("spiral2", "spiral2 name np D1 D2 P1 [Pi...] N1 [Ni...]", __FILE__, spiral2, g);
+}
+
+//=================================================================================================
+
+Standard_Integer setaxis(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 10)
+ {
+ di << "Usage : " << a[0] << " x y z Nx Ny Nz Xx Xy Xz" << "\n";
+ di << " " << "x y z - location" << "\n";
+ di << " " << "Nx Ny Nz - direction" << "\n";
+ di << " " << "Xx Xy Xz - X direction" << "\n";
+ return 1;
+ }
+ Standard_Real xx[9];
+ Standard_Integer i;
+ for (i = 0; i < 9; ++i)
+ {
+ xx[i] = Draw::Atof(a[i + 1]);
+ }
+
+ theHelixAxis.SetLocation(gp_Pnt(xx[0], xx[1], xx[2]));
+ theHelixAxis.SetDirection(gp_Dir(xx[3], xx[4], xx[5]));
+ theHelixAxis.SetXDirection(gp_Dir(xx[6], xx[7], xx[8]));
+
+ return 0;
+}
+
+//
+//=================================================================================================
+
+Standard_Integer comphelix(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 8)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 ... (must be np+1 values) - diameters" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + (aNb + 1) + aNb * 3)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 ... (must be np+1 values) - diameters" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, aNb + 1);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ for (i = 1; i <= aNb + 1; ++i)
+ {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ bIsPitches(i) = Draw::Atoi(a[ic]) != 0;
+ ++ic;
+ }
+
+ aBH.SetParameters(theHelixAxis, aDiams, aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer helix(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 7)
+ {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 - diameter" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 1 + aNb * 3)
+ {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 - diameter" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, 1);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ aDiams(1) = Draw::Atof(a[ic]);
+ ++ic;
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ bIsPitches(i) = Draw::Atoi(a[ic]) != 0;
+ ++ic;
+ }
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer spiral(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 8)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 - first and last diameters" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 2 + aNb * 3)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 - first and last diameters" << "\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" << "\n";
+ di << " "
+ << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is "
+ "number of turns"
+ << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, 2);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ for (i = 1; i <= 2; ++i)
+ {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ bIsPitches(i) = Draw::Atoi(a[ic]) != 0;
+ ++ic;
+ }
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aDiams(2), aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer comphelix2(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 7)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] P1 [Pi...] N1 [Ni...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2, ... (must be np+1 values) - diameters" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + (aNb + 1) + aNb * 2)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] P1 [Pi...] N1 [Ni...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2, ... (must be np+1 values) - diameters" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, aNb + 1);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ for (i = 1; i <= aNb + 1; ++i)
+ {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams, aPitches, aNbTurns);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer helix2(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 6)
+ {
+ di << "Usage : " << a[0] << " name np D1 P1 [Pi...] N1 [Ni...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 - diameter" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 1 + aNb * 2)
+ {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 - diameter" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, 1);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ aDiams(1) = Draw::Atof(a[ic]);
+ ++ic;
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aPitches, aNbTurns);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer spiral2(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+ if (n < 7)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 P1 [Pi...] N1 [Ni...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 - first and last diameters" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 2 + aNb * 2)
+ {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" << "\n";
+ di << " " << "name - name of result" << "\n";
+ di << " " << "np - number of helix parts" << "\n";
+ di << " " << "D1 D2 - first and last diameters" << "\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" << "\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" << "\n";
+ return 1;
+ }
+
+ TColStd_Array1OfReal aDiams(1, 2);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ for (i = 1; i <= 2; ++i)
+ {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for (i = 1; i <= aNb; ++i)
+ {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aDiams(2), aPitches, aNbTurns);
+
+ aBH.Perform();
+ DisplayHelixResult(di, aBH, a[1]);
+
+ return 0;
+}
BRepTest_FilletCommands.cxx
BRepTest_FillingCommands.cxx
BRepTest_GPropCommands.cxx
+ BRepTest_HelixCommands.cxx
BRepTest_HistoryCommands.cxx
BRepTest_MatCommands.cxx
BRepTest_Objects.cxx
TKOffset
TKFeat
TKShHealing
+ TKHelix
)
--- /dev/null
+project(TKHelix)
+
+OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)
--- /dev/null
+# External dependencies for TKHelix
+set(OCCT_TKHelix_EXTERNAL_LIBS
+ TKBRep
+ TKernel
+ TKMath
+ TKGeomBase
+ TKG2d
+ TKG3d
+ TKGeomAlgo
+ TKTopAlgo
+)
--- /dev/null
+# Source files for TKHelix
+set(OCCT_TKHelix_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+set(OCCT_TKHelix_FILES
+ EXTERNLIB
+ PACKAGES
+)
--- /dev/null
+# Test source files for TKHelix
+set(OCCT_TKHelix_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+set(OCCT_TKHelix_GTests_FILES
+ HelixBRep_BuilderHelix_Test.cxx
+ HelixBRep_BuilderHelix_Integration_Test.cxx
+ HelixGeom_BuilderHelix_Test.cxx
+ HelixGeom_BuilderHelixCoil_Test.cxx
+ HelixGeom_HelixCurve_Test.cxx
+ HelixGeom_Tools_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 <gtest/gtest.h>
+
+#include <HelixBRep_BuilderHelix.hxx>
+
+#include <BRep_Tool.hxx>
+#include <BRepGProp.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <gp_Ax3.hxx>
+#include <GProp_GProps.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <Standard_ConstructionError.hxx>
+
+class HelixBRepTest : public ::testing::Test
+{
+protected:
+ void SetUp() override
+ {
+ // Standard axis aligned with Z
+ myAxis = gp_Ax3(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ myTolerance = 1.e-4;
+ }
+
+ // Helper method to count shapes
+ Standard_Integer CountShapes(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType) const
+ {
+ Standard_Integer aCount = 0;
+ for (TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next())
+ {
+ aCount++;
+ }
+ return aCount;
+ }
+
+ // Helper method to compute wire length
+ Standard_Real ComputeWireLength(const TopoDS_Shape& theWire) const
+ {
+ GProp_GProps aLProps;
+ BRepGProp::LinearProperties(theWire, aLProps);
+ return aLProps.Mass();
+ }
+
+ // Helper method to validate helix wire properties
+ void ValidateHelixWire(const TopoDS_Wire& theWire,
+ Standard_Real theExpectedLength,
+ Standard_Real theTolerance = 0.05) const
+ {
+ EXPECT_FALSE(theWire.IsNull());
+ EXPECT_EQ(theWire.ShapeType(), TopAbs_WIRE);
+
+ // Check that wire has edges
+ Standard_Integer aNbEdges = CountShapes(theWire, TopAbs_EDGE);
+ EXPECT_GT(aNbEdges, 0);
+
+ // Compute wire length
+ Standard_Real aWireLength = ComputeWireLength(theWire);
+ if (theExpectedLength > 0)
+ {
+ EXPECT_NEAR(aWireLength, theExpectedLength, theExpectedLength * theTolerance);
+ }
+ }
+
+ gp_Ax3 myAxis;
+ Standard_Real myTolerance;
+};
+
+// Test Case A1 - Pure cylindrical helix (TCL test A1)
+TEST_F(HelixBRepTest, TCL_Test_A1_PureCylindricalHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Parameters from TCL test A1: helix, D1 = 100, 1 part, pitch = 5, number of turns, PFi=0
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0; // H1 = 100
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 5.0; // P1 = 5 (number of turns)
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_False; // PF1 = 0 means number of turns
+
+ aBuilder.SetParameters(myAxis, 100.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+ EXPECT_EQ(aHelixWire.ShapeType(), TopAbs_WIRE);
+
+ // Calculate expected helix length
+ Standard_Real aCircumference = M_PI * 100.0; // D1 = 100
+ Standard_Real aTurns = 100.0 / 20.0; // Height/Pitch for number of turns mode (20 = 100/5)
+ Standard_Real aExpectedLength = aTurns * sqrt(aCircumference * aCircumference + 20.0 * 20.0);
+
+ ValidateHelixWire(TopoDS::Wire(aHelixWire), aExpectedLength);
+}
+
+// Test Case B1 - Pure cylindrical helix with comphelix (TCL test B1)
+TEST_F(HelixBRepTest, TCL_Test_B1_CompositeCylindricalHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Parameters from TCL test B1: comphelix, D1 = D2 = 100, 1 part, pitch = 20, PFi=1
+ TColStd_Array1OfReal aDiams(1, 2);
+ aDiams(1) = 100.0; // D1
+ aDiams(2) = 100.0; // D2
+
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0; // H1
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 20.0; // P1
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True; // PF1 = 1 means pitch
+
+ aBuilder.SetParameters(myAxis, aDiams, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+
+ // Calculate expected helix length - same as A1 since geometry is identical
+ Standard_Real aCircumference = M_PI * 100.0;
+ Standard_Real aTurns = 100.0 / 20.0; // Height/Pitch
+ Standard_Real aExpectedLength = aTurns * sqrt(aCircumference * aCircumference + 20.0 * 20.0);
+
+ ValidateHelixWire(TopoDS::Wire(aHelixWire), aExpectedLength);
+}
+
+// Test Case C1 - Spiral helix (TCL test C1)
+TEST_F(HelixBRepTest, TCL_Test_C1_SpiralHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Parameters from TCL test C1: spiral, D1 = 100, D2 = 20, 3 parts
+ TColStd_Array1OfReal aHeights(1, 3);
+ aHeights(1) = 20.0; // H1
+ aHeights(2) = 60.0; // H2
+ aHeights(3) = 20.0; // H3
+
+ TColStd_Array1OfReal aPitches(1, 3);
+ aPitches(1) = 2.0; // P1 (number of turns)
+ aPitches(2) = 6.0; // P2 (number of turns)
+ aPitches(3) = 2.0; // P3 (number of turns)
+
+ TColStd_Array1OfBoolean aIsPitches(1, 3);
+ aIsPitches(1) = Standard_False; // PF1 = 0
+ aIsPitches(2) = Standard_False; // PF2 = 0
+ aIsPitches(3) = Standard_False; // PF3 = 0
+
+ aBuilder.SetParameters(myAxis, 100.0, 20.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+
+ // For spiral helix, length calculation is more complex due to changing diameter
+ // Just validate basic properties
+ ValidateHelixWire(TopoDS::Wire(aHelixWire), 0); // Don't check exact length for complex spiral
+}
+
+// Test Case F1 - Using helix2 interface (TCL test F1)
+TEST_F(HelixBRepTest, TCL_Test_F1_Helix2Interface)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Parameters from TCL test F1: comphelix2 with turns interface
+ TColStd_Array1OfReal aPitches(1, 3);
+ aPitches(1) = 10.0; // P1
+ aPitches(2) = 10.0; // P2
+ aPitches(3) = 10.0; // P3
+
+ TColStd_Array1OfReal aNbTurns(1, 3);
+ aNbTurns(1) = 2.0; // N1
+ aNbTurns(2) = 6.0; // N2
+ aNbTurns(3) = 2.0; // N3
+
+ aBuilder.SetParameters(myAxis, 100.0, aPitches, aNbTurns);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+
+ // Calculate expected length for cylindrical helix with multiple parts
+ Standard_Real aCircumference = M_PI * 100.0;
+ Standard_Real aTotalTurns = 2.0 + 6.0 + 2.0; // Sum of turns
+ Standard_Real aExpectedLength = aTotalTurns * sqrt(aCircumference * aCircumference + 10.0 * 10.0);
+
+ ValidateHelixWire(TopoDS::Wire(aHelixWire), aExpectedLength);
+}
+
+// Test Case E1 - Complex customer example (TCL test E1)
+TEST_F(HelixBRepTest, TCL_Test_E1_CustomerExample)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Parameters from TCL test E1: Customer example with 5 parts
+ TColStd_Array1OfReal aDiams(1, 6);
+ aDiams(1) = 150.0; // D1
+ aDiams(2) = 150.0; // D2
+ aDiams(3) = 150.0; // D3
+ aDiams(4) = 123.0; // D4
+ aDiams(5) = 123.0; // D5
+ aDiams(6) = 123.0; // D6
+
+ // Calculate heights from pitches and turns
+ TColStd_Array1OfReal aHeights(1, 5);
+ aHeights(1) = 0.75 * 13.0; // N1 * P1
+ aHeights(2) = 2.1 * 64.0; // N2 * P2
+ aHeights(3) = 2.25 * 50.0; // N3 * P3
+ aHeights(4) = 2.5 * 45.0; // N4 * P4
+ aHeights(5) = 0.75 * 13.0; // N5 * P5
+
+ TColStd_Array1OfReal aPitches(1, 5);
+ aPitches(1) = 0.75; // N1 (number of turns)
+ aPitches(2) = 2.1; // N2
+ aPitches(3) = 2.25; // N3
+ aPitches(4) = 2.5; // N4
+ aPitches(5) = 0.75; // N5
+
+ TColStd_Array1OfBoolean aIsPitches(1, 5);
+ aIsPitches(1) = Standard_False; // Number of turns mode
+ aIsPitches(2) = Standard_False;
+ aIsPitches(3) = Standard_False;
+ aIsPitches(4) = Standard_False;
+ aIsPitches(5) = Standard_False;
+
+ aBuilder.SetParameters(myAxis, aDiams, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+
+ // Complex customer example - just validate basic properties
+ ValidateHelixWire(TopoDS::Wire(aHelixWire),
+ 0); // Don't check exact length for complex multi-part helix
+}
+
+// Test error conditions
+TEST_F(HelixBRepTest, ErrorConditions_InvalidDimensions)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Test mismatched array dimensions
+ TColStd_Array1OfReal aDiams(1, 3); // 3 elements = 2 parts
+ TColStd_Array1OfReal aHeights(1, 1); // 1 element - should cause error (need 2 for 2 parts)
+ TColStd_Array1OfReal aPitches(1, 1); // 1 element - should cause error (need 2 for 2 parts)
+ TColStd_Array1OfBoolean aIsPitches(1, 1); // 1 element - should cause error (need 2 for 2 parts)
+
+ aDiams(1) = 100.0;
+ aDiams(2) = 100.0;
+ aDiams(3) = 100.0;
+ aHeights(1) = 50.0;
+ aPitches(1) = 10.0;
+ aIsPitches(1) = Standard_True;
+
+ EXPECT_THROW(aBuilder.SetParameters(myAxis, aDiams, aHeights, aPitches, aIsPitches),
+ Standard_ConstructionError);
+}
+
+TEST_F(HelixBRepTest, ErrorConditions_TurnsInterface)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Test mismatched dimensions in turns interface
+ TColStd_Array1OfReal aPitches(1, 2);
+ TColStd_Array1OfReal aNbTurns(1, 1); // Mismatched size
+
+ aPitches(1) = 10.0;
+ aPitches(2) = 10.0;
+ aNbTurns(1) = 5.0;
+
+ EXPECT_THROW(aBuilder.SetParameters(myAxis, 100.0, aPitches, aNbTurns),
+ Standard_ConstructionError);
+}
+
+// Test tolerance and approximation quality
+TEST_F(HelixBRepTest, ApproximationQuality)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 50.0;
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 10.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, 50.0, aHeights, aPitches, aIsPitches);
+
+ // Test different tolerance levels
+ Standard_Real aTightTolerance = 1.e-6;
+ aBuilder.SetApproxParameters(aTightTolerance, 8, GeomAbs_C2);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ Standard_Real aToleranceReached = aBuilder.ToleranceReached();
+ EXPECT_GT(aToleranceReached, 0.0);
+
+ // For complex geometry, tolerance reached might be higher than requested
+ // but should be reasonable
+ EXPECT_LT(aToleranceReached, aTightTolerance * 1000);
+}
+
+// Test parameter validation
+TEST_F(HelixBRepTest, ParameterValidation)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ TColStd_Array1OfReal aHeights(1, 1);
+ TColStd_Array1OfReal aPitches(1, 1);
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+
+ // Test very small height - should cause error during Perform()
+ aHeights(1) = 1.e-8;
+ aPitches(1) = 10.0;
+ aIsPitches(1) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, 50.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_NE(aBuilder.ErrorStatus(), 0); // Should have error status 12 (invalid height)
+
+ // Test zero pitch - should cause error
+ aHeights(1) = 50.0;
+ aPitches(1) = 0.0;
+
+ aBuilder.SetParameters(myAxis, 50.0, aHeights, aPitches, aIsPitches);
+
+ aBuilder.Perform();
+
+ EXPECT_NE(aBuilder.ErrorStatus(), 0); // Should have error status 11 (invalid pitch)
+}
+
+// Test wire continuity across multiple parts
+TEST_F(HelixBRepTest, MultiPartContinuity)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // 2-part helix with different parameters
+ TColStd_Array1OfReal aDiams(1, 3);
+ aDiams(1) = 80.0;
+ aDiams(2) = 60.0;
+ aDiams(3) = 40.0;
+
+ TColStd_Array1OfReal aHeights(1, 2);
+ aHeights(1) = 40.0;
+ aHeights(2) = 40.0;
+
+ TColStd_Array1OfReal aPitches(1, 2);
+ aPitches(1) = 8.0;
+ aPitches(2) = 12.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 2);
+ aIsPitches(1) = Standard_True;
+ aIsPitches(2) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, aDiams, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aHelixWire = aBuilder.Shape();
+ EXPECT_FALSE(aHelixWire.IsNull());
+ EXPECT_EQ(aHelixWire.ShapeType(), TopAbs_WIRE);
+
+ // Check that wire has multiple edges
+ Standard_Integer aNbEdges = CountShapes(aHelixWire, TopAbs_EDGE);
+ EXPECT_GT(aNbEdges, 1); // Should have multiple edges for multiple parts
+
+ // Verify wire continuity by checking connectivity
+ TopoDS_Wire aWire = TopoDS::Wire(aHelixWire);
+ BRepCheck_Analyzer aCheck(aWire);
+ EXPECT_TRUE(aCheck.IsValid());
+}
\ 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 <HelixBRep_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_Tools.hxx>
+
+#include <BRep_Tool.hxx>
+#include <BRepGProp.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Dir.hxx>
+#include <GProp_GProps.hxx>
+#include <Precision.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+
+class TKHelixTest : public ::testing::Test
+{
+protected:
+ void SetUp() override
+ {
+ // Default axis setup
+ myAxis = gp_Ax3(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ myTolerance = 1.e-4;
+ }
+
+ // Helper method to count shapes in a TopoDS_Shape
+ Standard_Integer CountShapes(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType) const
+ {
+ Standard_Integer aCount = 0;
+ for (TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next())
+ {
+ aCount++;
+ }
+ return aCount;
+ }
+
+ // Helper method to compute wire length
+ Standard_Real ComputeWireLength(const TopoDS_Shape& theWire) const
+ {
+ GProp_GProps aLProps;
+ BRepGProp::LinearProperties(theWire, aLProps);
+ return aLProps.Mass();
+ }
+
+ gp_Ax3 myAxis;
+ Standard_Real myTolerance;
+};
+
+// Test HelixGeom_HelixCurve analytical implementation
+TEST_F(TKHelixTest, HelixGeomHelixCurve_Basic)
+{
+ HelixGeom_HelixCurve aHelix;
+
+ // Test default parameters
+ EXPECT_DOUBLE_EQ(aHelix.FirstParameter(), 0.0);
+ EXPECT_DOUBLE_EQ(aHelix.LastParameter(), 2.0 * M_PI);
+
+ // Test point calculation
+ gp_Pnt aP0 = aHelix.Value(0.0);
+ EXPECT_DOUBLE_EQ(aP0.X(), 1.0); // RStart = 1.0 by default
+ EXPECT_DOUBLE_EQ(aP0.Y(), 0.0);
+ EXPECT_DOUBLE_EQ(aP0.Z(), 0.0);
+
+ gp_Pnt aP1 = aHelix.Value(M_PI);
+ EXPECT_DOUBLE_EQ(aP1.X(), -1.0);
+ EXPECT_NEAR(aP1.Y(), 0.0, 1e-15);
+ EXPECT_DOUBLE_EQ(aP1.Z(), M_PI / (2.0 * M_PI)); // Pitch / (2*PI) * t
+}
+
+TEST_F(TKHelixTest, HelixGeomHelixCurve_CustomParameters)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 4.0 * M_PI, 10.0, 5.0, 0.0, Standard_True);
+
+ EXPECT_DOUBLE_EQ(aHelix.FirstParameter(), 0.0);
+ EXPECT_DOUBLE_EQ(aHelix.LastParameter(), 4.0 * M_PI);
+
+ // Test point at start
+ gp_Pnt aP0 = aHelix.Value(0.0);
+ EXPECT_DOUBLE_EQ(aP0.X(), 5.0); // RStart = 5.0
+ EXPECT_DOUBLE_EQ(aP0.Y(), 0.0);
+ EXPECT_DOUBLE_EQ(aP0.Z(), 0.0);
+
+ // Test point at end (2 full turns)
+ gp_Pnt aP1 = aHelix.Value(4.0 * M_PI);
+ EXPECT_DOUBLE_EQ(aP1.X(), 5.0);
+ EXPECT_NEAR(aP1.Y(), 0.0, 1e-14);
+ EXPECT_DOUBLE_EQ(aP1.Z(), 20.0); // 2 turns * pitch(10)
+}
+
+TEST_F(TKHelixTest, HelixGeomHelixCurve_TaperedHelix)
+{
+ HelixGeom_HelixCurve aHelix;
+ Standard_Real aTaperAngle = 0.1; // Small taper angle
+ aHelix.Load(0.0, 2.0 * M_PI, 5.0, 2.0, aTaperAngle, Standard_True);
+
+ // At start
+ gp_Pnt aP0 = aHelix.Value(0.0);
+ EXPECT_DOUBLE_EQ(aP0.X(), 2.0);
+
+ // At end - radius should be larger due to taper
+ gp_Pnt aP1 = aHelix.Value(2.0 * M_PI);
+ Standard_Real aExpectedRadius = 2.0 + (5.0 / (2.0 * M_PI)) * tan(aTaperAngle) * (2.0 * M_PI);
+ EXPECT_DOUBLE_EQ(aP1.X(), aExpectedRadius);
+}
+
+// Test HelixGeom_BuilderHelixCoil
+TEST_F(TKHelixTest, HelixGeomBuilderHelixCoil_Basic)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetCurveParameters(0.0, 2.0 * M_PI, 5.0, 2.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+
+ Handle(Geom_Curve) aCurve = aCurves(1);
+ EXPECT_FALSE(aCurve.IsNull());
+
+ // Test curve endpoints
+ gp_Pnt aP1, aP2;
+ aCurve->D0(aCurve->FirstParameter(), aP1);
+ aCurve->D0(aCurve->LastParameter(), aP2);
+
+ EXPECT_NEAR(aP1.X(), 2.0, myTolerance);
+ EXPECT_NEAR(aP1.Y(), 0.0, myTolerance);
+ EXPECT_NEAR(aP1.Z(), 0.0, myTolerance);
+
+ EXPECT_NEAR(aP2.X(), 2.0, myTolerance);
+ EXPECT_NEAR(aP2.Y(), 0.0, myTolerance);
+ EXPECT_NEAR(aP2.Z(), 5.0, myTolerance);
+}
+
+// Test HelixGeom_BuilderHelix
+TEST_F(TKHelixTest, HelixGeomBuilderHelix_SingleCoil)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ gp_Ax2 aPosition(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ aBuilder.SetPosition(aPosition);
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetCurveParameters(0.0, 2.0 * M_PI, 10.0, 5.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+}
+
+TEST_F(TKHelixTest, HelixGeomBuilderHelix_MultipleCoils)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ gp_Ax2 aPosition(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ aBuilder.SetPosition(aPosition);
+ aBuilder.SetTolerance(myTolerance);
+
+ // 3 full turns
+ aBuilder.SetCurveParameters(0.0, 6.0 * M_PI, 10.0, 5.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 3); // Should split into 3 coils
+}
+
+// Test HelixBRep_BuilderHelix - Pure Cylindrical Helix
+TEST_F(TKHelixTest, HelixBRepBuilder_PureCylindricalHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Single part helix with diameter 100, height 100, pitch 20
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0;
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 20.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True; // Pitch mode
+
+ aBuilder.SetParameters(myAxis, 100.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aResult = aBuilder.Shape();
+ EXPECT_FALSE(aResult.IsNull());
+ EXPECT_EQ(aResult.ShapeType(), TopAbs_WIRE);
+
+ // Check number of edges
+ Standard_Integer aNbEdges = CountShapes(aResult, TopAbs_EDGE);
+ EXPECT_GT(aNbEdges, 0);
+
+ // Compute wire length - should be approximately sqrt(circumference^2 + height^2) * turns
+ Standard_Real aWireLength = ComputeWireLength(aResult);
+ Standard_Real aCircumference = M_PI * 100.0;
+ Standard_Real aTurns = 100.0 / 20.0; // height/pitch
+ Standard_Real aExpectedLength = aTurns * sqrt(aCircumference * aCircumference + 20.0 * 20.0);
+
+ EXPECT_NEAR(aWireLength, aExpectedLength, aExpectedLength * 0.01); // 1% tolerance
+}
+
+// Test HelixBRep_BuilderHelix - Spiral Helix
+TEST_F(TKHelixTest, HelixBRepBuilder_SpiralHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Single part spiral with diameter changing from 100 to 20
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0;
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 10.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, 100.0, 20.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aResult = aBuilder.Shape();
+ EXPECT_FALSE(aResult.IsNull());
+ EXPECT_EQ(aResult.ShapeType(), TopAbs_WIRE);
+
+ Standard_Integer aNbEdges = CountShapes(aResult, TopAbs_EDGE);
+ EXPECT_GT(aNbEdges, 0);
+}
+
+// Test HelixBRep_BuilderHelix - Multi-part Helix
+TEST_F(TKHelixTest, HelixBRepBuilder_MultiPartHelix)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // 3-part helix with different diameters
+ TColStd_Array1OfReal aDiams(1, 4);
+ aDiams(1) = 100.0;
+ aDiams(2) = 80.0;
+ aDiams(3) = 60.0;
+ aDiams(4) = 40.0;
+
+ TColStd_Array1OfReal aHeights(1, 3);
+ aHeights(1) = 30.0;
+ aHeights(2) = 40.0;
+ aHeights(3) = 30.0;
+
+ TColStd_Array1OfReal aPitches(1, 3);
+ aPitches(1) = 10.0;
+ aPitches(2) = 15.0;
+ aPitches(3) = 10.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 3);
+ aIsPitches(1) = Standard_True;
+ aIsPitches(2) = Standard_True;
+ aIsPitches(3) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, aDiams, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aResult = aBuilder.Shape();
+ EXPECT_FALSE(aResult.IsNull());
+ EXPECT_EQ(aResult.ShapeType(), TopAbs_WIRE);
+
+ Standard_Integer aNbEdges = CountShapes(aResult, TopAbs_EDGE);
+ EXPECT_GT(aNbEdges, 2); // Should have multiple edges for multiple parts
+}
+
+// Test HelixBRep_BuilderHelix - Number of Turns Interface
+TEST_F(TKHelixTest, HelixBRepBuilder_NumberOfTurnsInterface)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Single part helix using number of turns
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 20.0;
+
+ TColStd_Array1OfReal aNbTurns(1, 1);
+ aNbTurns(1) = 5.0; // 5 turns
+
+ aBuilder.SetParameters(myAxis, 100.0, aPitches, aNbTurns);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TopoDS_Shape& aResult = aBuilder.Shape();
+ EXPECT_FALSE(aResult.IsNull());
+
+ // Wire length should correspond to 5 turns
+ Standard_Real aWireLength = ComputeWireLength(aResult);
+ Standard_Real aCircumference = M_PI * 100.0;
+ Standard_Real aExpectedLength = 5.0 * sqrt(aCircumference * aCircumference + 20.0 * 20.0);
+
+ EXPECT_NEAR(aWireLength, aExpectedLength, aExpectedLength * 0.01);
+}
+
+// Test HelixGeom_Tools static methods
+TEST_F(TKHelixTest, HelixGeomTools_ApprHelix)
+{
+ Handle(Geom_BSplineCurve) aBSpline;
+ Standard_Real aMaxError;
+
+ Standard_Integer aResult = HelixGeom_Tools::ApprHelix(0.0, // T1
+ 2.0 * M_PI, // T2
+ 10.0, // Pitch
+ 5.0, // Start radius
+ 0.0, // Taper angle
+ Standard_True, // Clockwise
+ myTolerance, // Tolerance
+ aBSpline, // Result
+ aMaxError // Max error
+ );
+
+ EXPECT_EQ(aResult, 0); // Success
+ EXPECT_FALSE(aBSpline.IsNull());
+ EXPECT_LE(aMaxError, myTolerance);
+
+ // Test curve properties
+ EXPECT_GT(aBSpline->Degree(), 0);
+ EXPECT_GT(aBSpline->NbPoles(), 0);
+}
+
+// Test Error Conditions
+TEST_F(TKHelixTest, HelixBRepBuilder_ErrorConditions)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ // Test with invalid height (too small)
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 1.e-6; // Very small height
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 10.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, 100.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_NE(aBuilder.ErrorStatus(), 0); // Should have error
+}
+
+TEST_F(TKHelixTest, HelixBRepBuilder_ZeroPitch)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0;
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 0.0; // Zero pitch
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True;
+
+ aBuilder.SetParameters(myAxis, 100.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(myTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ EXPECT_NE(aBuilder.ErrorStatus(), 0); // Should have error
+}
+
+// Test Tolerance Reached
+TEST_F(TKHelixTest, HelixBRepBuilder_ToleranceReached)
+{
+ HelixBRep_BuilderHelix aBuilder;
+
+ TColStd_Array1OfReal aHeights(1, 1);
+ aHeights(1) = 100.0;
+
+ TColStd_Array1OfReal aPitches(1, 1);
+ aPitches(1) = 20.0;
+
+ TColStd_Array1OfBoolean aIsPitches(1, 1);
+ aIsPitches(1) = Standard_True;
+
+ Standard_Real aVeryTightTolerance = 1.e-8;
+ aBuilder.SetParameters(myAxis, 100.0, aHeights, aPitches, aIsPitches);
+ aBuilder.SetApproxParameters(aVeryTightTolerance, 8, GeomAbs_C1);
+
+ aBuilder.Perform();
+
+ if (aBuilder.ErrorStatus() == 0)
+ {
+ Standard_Real aToleranceReached = aBuilder.ToleranceReached();
+ EXPECT_GT(aToleranceReached, 0.0);
+ }
+}
\ 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 <HelixGeom_BuilderHelixCoil.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <gp_Pnt.hxx>
+
+class HelixGeom_BuilderHelixCoil_Test : public ::testing::Test
+{
+protected:
+ void SetUp() override { myTolerance = 1.e-4; }
+
+ Standard_Real myTolerance;
+};
+
+TEST_F(HelixGeom_BuilderHelixCoil_Test, BasicConstruction)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetCurveParameters(0.0, 2.0 * M_PI, 5.0, 2.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+
+ Handle(Geom_Curve) aCurve = aCurves(1);
+ EXPECT_FALSE(aCurve.IsNull());
+
+ // Test curve endpoints
+ gp_Pnt aP1, aP2;
+ aCurve->D0(aCurve->FirstParameter(), aP1);
+ aCurve->D0(aCurve->LastParameter(), aP2);
+
+ EXPECT_NEAR(aP1.X(), 2.0, myTolerance);
+ EXPECT_NEAR(aP1.Y(), 0.0, myTolerance);
+ EXPECT_NEAR(aP1.Z(), 0.0, myTolerance);
+
+ EXPECT_NEAR(aP2.X(), 2.0, myTolerance);
+ EXPECT_NEAR(aP2.Y(), 0.0, myTolerance);
+ EXPECT_NEAR(aP2.Z(), 5.0, myTolerance);
+}
+
+TEST_F(HelixGeom_BuilderHelixCoil_Test, DefaultParameters)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ // Use default parameters
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ // Check default approximation parameters
+ GeomAbs_Shape aCont;
+ Standard_Integer aMaxDegree, aMaxSeg;
+ aBuilder.ApproxParameters(aCont, aMaxDegree, aMaxSeg);
+
+ EXPECT_EQ(aCont, GeomAbs_C2);
+ EXPECT_EQ(aMaxDegree, 8);
+ EXPECT_EQ(aMaxSeg, 150);
+
+ EXPECT_EQ(aBuilder.Tolerance(), 0.0001);
+}
+
+TEST_F(HelixGeom_BuilderHelixCoil_Test, ParameterSymmetry)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ // Set parameters
+ Standard_Real aT1 = 0.5, aT2 = 5.5, aPitch = 12.5, aRStart = 3.5, aTaperAngle = 0.15;
+ Standard_Boolean aIsClockwise = Standard_False;
+
+ aBuilder.SetCurveParameters(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsClockwise);
+
+ // Get parameters back
+ Standard_Real aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out;
+ Standard_Boolean aIsClockwise_out;
+
+ aBuilder
+ .CurveParameters(aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out, aIsClockwise_out);
+
+ EXPECT_DOUBLE_EQ(aT1, aT1_out);
+ EXPECT_DOUBLE_EQ(aT2, aT2_out);
+ EXPECT_DOUBLE_EQ(aPitch, aPitch_out);
+ EXPECT_DOUBLE_EQ(aRStart, aRStart_out);
+ EXPECT_DOUBLE_EQ(aTaperAngle, aTaperAngle_out);
+ EXPECT_EQ(aIsClockwise, aIsClockwise_out);
+}
+
+TEST_F(HelixGeom_BuilderHelixCoil_Test, TaperedHelix)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetApproxParameters(GeomAbs_C2, 8, 100);
+ aBuilder.SetCurveParameters(0.0, 4.0 * M_PI, 20.0, 5.0, 0.1, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+ EXPECT_LE(aBuilder.ToleranceReached(), myTolerance * 10); // Allow some tolerance margin
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+
+ Handle(Geom_Curve) aCurve = aCurves(1);
+ EXPECT_FALSE(aCurve.IsNull());
+
+ // Verify that the curve is a B-spline
+ Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast(aCurve);
+ EXPECT_FALSE(aBSpline.IsNull());
+
+ // Check B-spline properties
+ EXPECT_LE(aBSpline->Degree(), 8);
+ EXPECT_GT(aBSpline->NbPoles(), 0);
+}
\ 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 <HelixGeom_BuilderHelix.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Dir.hxx>
+
+class HelixGeom_BuilderHelix_Test : public ::testing::Test
+{
+protected:
+ void SetUp() override { myTolerance = 1.e-4; }
+
+ Standard_Real myTolerance;
+};
+
+TEST_F(HelixGeom_BuilderHelix_Test, SingleCoil)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ gp_Ax2 aPosition(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ aBuilder.SetPosition(aPosition);
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetCurveParameters(0.0, 2.0 * M_PI, 10.0, 5.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+}
+
+TEST_F(HelixGeom_BuilderHelix_Test, MultipleCoils)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ gp_Ax2 aPosition(gp_Pnt(0., 0., 0.), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+ aBuilder.SetPosition(aPosition);
+ aBuilder.SetTolerance(myTolerance);
+
+ // 3 full turns
+ aBuilder.SetCurveParameters(0.0, 6.0 * M_PI, 10.0, 5.0, 0.0, Standard_True);
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 3); // Should split into 3 coils
+}
+
+TEST_F(HelixGeom_BuilderHelix_Test, PositionGetterSetter)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ gp_Ax2 aTestPosition(gp_Pnt(10., 20., 30.), gp_Dir(1., 0., 0.), gp_Dir(0., 1., 0.));
+ aBuilder.SetPosition(aTestPosition);
+
+ const gp_Ax2& aRetrievedPosition = aBuilder.Position();
+
+ EXPECT_TRUE(aRetrievedPosition.Location().IsEqual(aTestPosition.Location(), 1e-15));
+ EXPECT_TRUE(aRetrievedPosition.Direction().IsEqual(aTestPosition.Direction(), 1e-15));
+ EXPECT_TRUE(aRetrievedPosition.XDirection().IsEqual(aTestPosition.XDirection(), 1e-15));
+}
+
+TEST_F(HelixGeom_BuilderHelix_Test, ParameterManagement)
+{
+ HelixGeom_BuilderHelix aBuilder;
+
+ // Set curve parameters
+ Standard_Real aT1 = 1.0, aT2 = 7.0, aPitch = 15.0, aRStart = 4.0, aTaperAngle = 0.2;
+ Standard_Boolean aIsClockwise = Standard_False;
+
+ aBuilder.SetCurveParameters(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsClockwise);
+
+ // Get parameters back
+ Standard_Real aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out;
+ Standard_Boolean aIsClockwise_out;
+
+ aBuilder
+ .CurveParameters(aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out, aIsClockwise_out);
+
+ EXPECT_DOUBLE_EQ(aT1, aT1_out);
+ EXPECT_DOUBLE_EQ(aT2, aT2_out);
+ EXPECT_DOUBLE_EQ(aPitch, aPitch_out);
+ EXPECT_DOUBLE_EQ(aRStart, aRStart_out);
+ EXPECT_DOUBLE_EQ(aTaperAngle, aTaperAngle_out);
+ EXPECT_EQ(aIsClockwise, aIsClockwise_out);
+}
\ 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 <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_BuilderApproxCurve.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <HelixGeom_Tools.hxx>
+
+#include <Geom_BSplineCurve.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <Standard_ConstructionError.hxx>
+
+class HelixGeomTest : public ::testing::Test
+{
+protected:
+ void SetUp() override { myTolerance = 1.e-6; }
+
+ Standard_Real myTolerance;
+};
+
+// Test HelixGeom_HelixCurve derivatives
+TEST_F(HelixGeomTest, HelixCurve_Derivatives)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 2.0 * M_PI, 5.0, 2.0, 0.0, Standard_True);
+
+ Standard_Real aParam = M_PI / 2.0;
+ gp_Pnt aP;
+ gp_Vec aV1, aV2;
+
+ // Test D1
+ aHelix.D1(aParam, aP, aV1);
+ EXPECT_NEAR(aP.X(), 0.0, 1e-15);
+ EXPECT_NEAR(aP.Y(), 2.0, 1e-15);
+ EXPECT_GT(aV1.Magnitude(), 0.0);
+
+ // Test D2
+ aHelix.D2(aParam, aP, aV1, aV2);
+ EXPECT_NEAR(aP.X(), 0.0, 1e-15);
+ EXPECT_NEAR(aP.Y(), 2.0, 1e-15);
+ EXPECT_GT(aV2.Magnitude(), 0.0);
+
+ // Test DN
+ gp_Vec aVN1 = aHelix.DN(aParam, 1);
+ gp_Vec aVN2 = aHelix.DN(aParam, 2);
+
+ EXPECT_NEAR(aVN1.X(), aV1.X(), 1e-15);
+ EXPECT_NEAR(aVN1.Y(), aV1.Y(), 1e-15);
+ EXPECT_NEAR(aVN1.Z(), aV1.Z(), 1e-15);
+
+ EXPECT_NEAR(aVN2.X(), aV2.X(), 1e-15);
+ EXPECT_NEAR(aVN2.Y(), aV2.Y(), 1e-15);
+ EXPECT_NEAR(aVN2.Z(), aV2.Z(), 1e-15);
+}
+
+// Test HelixGeom_HelixCurve error conditions
+TEST_F(HelixGeomTest, HelixCurve_ErrorConditions)
+{
+ HelixGeom_HelixCurve aHelix;
+
+ // Test invalid parameter range (T1 >= T2)
+ EXPECT_THROW(aHelix.Load(2.0, 1.0, 5.0, 2.0, 0.0, Standard_True), Standard_ConstructionError);
+
+ // Test negative pitch
+ EXPECT_THROW(aHelix.Load(0.0, 2.0 * M_PI, -1.0, 2.0, 0.0, Standard_True),
+ Standard_ConstructionError);
+
+ // Test negative radius
+ EXPECT_THROW(aHelix.Load(0.0, 2.0 * M_PI, 5.0, -1.0, 0.0, Standard_True),
+ Standard_ConstructionError);
+
+ // Test invalid taper angle
+ EXPECT_THROW(aHelix.Load(0.0, 2.0 * M_PI, 5.0, 2.0, M_PI / 2.0, Standard_True),
+ Standard_ConstructionError);
+}
+
+// Test HelixGeom_HelixCurve with counter-clockwise direction
+TEST_F(HelixGeomTest, HelixCurve_CounterClockwise)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 2.0 * M_PI, 5.0, 2.0, 0.0, Standard_False); // Counter-clockwise
+
+ gp_Pnt aP0 = aHelix.Value(0.0);
+ gp_Pnt aP1 = aHelix.Value(M_PI / 2.0);
+
+ EXPECT_NEAR(aP0.X(), 2.0, 1e-15);
+ EXPECT_NEAR(aP0.Y(), 0.0, 1e-15);
+
+ EXPECT_NEAR(aP1.X(), 0.0, 1e-15);
+ EXPECT_NEAR(aP1.Y(), -2.0, 1e-15); // Negative Y for counter-clockwise
+}
+
+// Test HelixGeom_HelixCurve adaptor interface
+TEST_F(HelixGeomTest, HelixCurve_AdaptorInterface)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 4.0 * M_PI, 10.0, 3.0, 0.0, Standard_True);
+
+ // Test continuity
+ EXPECT_EQ(aHelix.Continuity(), GeomAbs_CN);
+
+ // Test intervals
+ EXPECT_EQ(aHelix.NbIntervals(GeomAbs_C0), 1);
+ EXPECT_EQ(aHelix.NbIntervals(GeomAbs_C1), 1);
+ EXPECT_EQ(aHelix.NbIntervals(GeomAbs_C2), 1);
+
+ // Test intervals array
+ TColStd_Array1OfReal anIntervals(1, 2);
+ aHelix.Intervals(anIntervals, GeomAbs_C0);
+ EXPECT_DOUBLE_EQ(anIntervals(1), 0.0);
+ EXPECT_DOUBLE_EQ(anIntervals(2), 4.0 * M_PI);
+
+ // Test not implemented methods
+ EXPECT_THROW(aHelix.Resolution(1.0), Standard_NotImplemented);
+ EXPECT_THROW(aHelix.IsClosed(), Standard_NotImplemented);
+ EXPECT_THROW(aHelix.IsPeriodic(), Standard_NotImplemented);
+ EXPECT_THROW(aHelix.Period(), Standard_DomainError);
+}
+
+// Test HelixGeom_BuilderHelixCoil approximation
+TEST_F(HelixGeomTest, BuilderHelixCoil_Approximation)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ aBuilder.SetTolerance(myTolerance);
+ aBuilder.SetApproxParameters(GeomAbs_C2, 8, 100);
+ aBuilder.SetCurveParameters(0.0,
+ 2.0 * M_PI,
+ 20.0,
+ 5.0,
+ 0.05,
+ Standard_True); // Reduced parameter range and taper angle
+
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+ EXPECT_LE(aBuilder.ToleranceReached(),
+ 0.1); // Allow up to 0.1 tolerance for tapered helix approximation
+
+ const TColGeom_SequenceOfCurve& aCurves = aBuilder.Curves();
+ EXPECT_EQ(aCurves.Length(), 1);
+
+ Handle(Geom_Curve) aCurve = aCurves(1);
+ EXPECT_FALSE(aCurve.IsNull());
+
+ // Verify that the curve is a B-spline
+ Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast(aCurve);
+ EXPECT_FALSE(aBSpline.IsNull());
+
+ // Check B-spline properties
+ EXPECT_LE(aBSpline->Degree(), 8);
+ EXPECT_GT(aBSpline->NbPoles(), 0);
+}
+
+// Test HelixGeom_Tools static methods
+TEST_F(HelixGeomTest, Tools_ApprCurve3D)
+{
+ // Create a helix curve adaptor
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 2.0 * M_PI, 10.0, 3.0, 0.0, Standard_True);
+ Handle(HelixGeom_HelixCurve) aHAdaptor = new HelixGeom_HelixCurve(aHelix);
+
+ Handle(Geom_BSplineCurve) aBSpline;
+ Standard_Real aMaxError;
+
+ Standard_Integer aResult = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C1,
+ 50, // Max segments
+ 6, // Max degree
+ aBSpline,
+ aMaxError);
+
+ EXPECT_EQ(aResult, 0);
+ EXPECT_FALSE(aBSpline.IsNull());
+ EXPECT_LE(aMaxError, myTolerance * 10);
+
+ // Verify approximation quality by sampling points
+ Standard_Integer aNbSamples = 10;
+ for (Standard_Integer i = 0; i <= aNbSamples; i++)
+ {
+ Standard_Real aParam =
+ aHelix.FirstParameter() + i * (aHelix.LastParameter() - aHelix.FirstParameter()) / aNbSamples;
+
+ gp_Pnt aOrigPnt = aHelix.Value(aParam);
+
+ // Map parameter to B-spline parameter space
+ Standard_Real aBSplineParam =
+ aBSpline->FirstParameter()
+ + i * (aBSpline->LastParameter() - aBSpline->FirstParameter()) / aNbSamples;
+
+ gp_Pnt aApproxPnt;
+ aBSpline->D0(aBSplineParam, aApproxPnt);
+
+ Standard_Real aDistance = aOrigPnt.Distance(aApproxPnt);
+ EXPECT_LE(aDistance, aMaxError * 2); // Allow some margin
+ }
+}
+
+// Test HelixGeom_Tools with different continuity requirements
+TEST_F(HelixGeomTest, Tools_DifferentContinuity)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 6.0 * M_PI, 15.0, 4.0, 0.05, Standard_True);
+ Handle(HelixGeom_HelixCurve) aHAdaptor = new HelixGeom_HelixCurve(aHelix);
+
+ // Test C0 continuity
+ Handle(Geom_BSplineCurve) aBSplineC0;
+ Standard_Real aMaxErrorC0;
+ Standard_Integer aResultC0 = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C0,
+ 30,
+ 4,
+ aBSplineC0,
+ aMaxErrorC0);
+
+ EXPECT_EQ(aResultC0, 0);
+ EXPECT_FALSE(aBSplineC0.IsNull());
+
+ // Test C2 continuity
+ Handle(Geom_BSplineCurve) aBSplineC2;
+ Standard_Real aMaxErrorC2;
+ Standard_Integer aResultC2 = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C2,
+ 30,
+ 6,
+ aBSplineC2,
+ aMaxErrorC2);
+
+ EXPECT_EQ(aResultC2, 0);
+ EXPECT_FALSE(aBSplineC2.IsNull());
+
+ // C2 curve should generally have higher degree
+ EXPECT_GE(aBSplineC2->Degree(), aBSplineC0->Degree());
+}
+
+// Test Builder with default parameters
+TEST_F(HelixGeomTest, BuilderHelixCoil_DefaultParameters)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ // Use default parameters
+ aBuilder.Perform();
+
+ EXPECT_EQ(aBuilder.ErrorStatus(), 0);
+
+ // Check default approximation parameters
+ GeomAbs_Shape aCont;
+ Standard_Integer aMaxDegree, aMaxSeg;
+ aBuilder.ApproxParameters(aCont, aMaxDegree, aMaxSeg);
+
+ EXPECT_EQ(aCont, GeomAbs_C2);
+ EXPECT_EQ(aMaxDegree, 8);
+ EXPECT_EQ(aMaxSeg, 150);
+
+ EXPECT_EQ(aBuilder.Tolerance(), 0.0001);
+}
+
+// Test parameter getter/setter symmetry
+TEST_F(HelixGeomTest, BuilderHelixCoil_ParameterSymmetry)
+{
+ HelixGeom_BuilderHelixCoil aBuilder;
+
+ // Set parameters
+ Standard_Real aT1 = 0.5, aT2 = 5.5, aPitch = 12.5, aRStart = 3.5, aTaperAngle = 0.15;
+ Standard_Boolean aIsClockwise = Standard_False;
+
+ aBuilder.SetCurveParameters(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsClockwise);
+
+ // Get parameters back
+ Standard_Real aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out;
+ Standard_Boolean aIsClockwise_out;
+
+ aBuilder
+ .CurveParameters(aT1_out, aT2_out, aPitch_out, aRStart_out, aTaperAngle_out, aIsClockwise_out);
+
+ EXPECT_DOUBLE_EQ(aT1, aT1_out);
+ EXPECT_DOUBLE_EQ(aT2, aT2_out);
+ EXPECT_DOUBLE_EQ(aPitch, aPitch_out);
+ EXPECT_DOUBLE_EQ(aRStart, aRStart_out);
+ EXPECT_DOUBLE_EQ(aTaperAngle, aTaperAngle_out);
+ EXPECT_EQ(aIsClockwise, aIsClockwise_out);
+}
\ 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 <HelixGeom_Tools.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <gp_Pnt.hxx>
+
+class HelixGeom_Tools_Test : public ::testing::Test
+{
+protected:
+ void SetUp() override { myTolerance = 1.e-6; }
+
+ Standard_Real myTolerance;
+};
+
+TEST_F(HelixGeom_Tools_Test, ApprHelix)
+{
+ Handle(Geom_BSplineCurve) aBSpline;
+ Standard_Real aMaxError;
+
+ Standard_Integer aResult = HelixGeom_Tools::ApprHelix(0.0, // T1
+ 2.0 * M_PI, // T2
+ 10.0, // Pitch
+ 5.0, // Start radius
+ 0.0, // Taper angle
+ Standard_True, // Clockwise
+ myTolerance, // Tolerance
+ aBSpline, // Result
+ aMaxError // Max error
+ );
+
+ EXPECT_EQ(aResult, 0); // Success
+ EXPECT_FALSE(aBSpline.IsNull());
+ EXPECT_LE(aMaxError, myTolerance);
+
+ // Test curve properties
+ EXPECT_GT(aBSpline->Degree(), 0);
+ EXPECT_GT(aBSpline->NbPoles(), 0);
+}
+
+TEST_F(HelixGeom_Tools_Test, ApprCurve3D)
+{
+ // Create a helix curve adaptor
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 2.0 * M_PI, 10.0, 3.0, 0.0, Standard_True);
+ Handle(HelixGeom_HelixCurve) aHAdaptor = new HelixGeom_HelixCurve(aHelix);
+
+ Handle(Geom_BSplineCurve) aBSpline;
+ Standard_Real aMaxError;
+
+ Standard_Integer aResult = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C1,
+ 50, // Max segments
+ 6, // Max degree
+ aBSpline,
+ aMaxError);
+
+ EXPECT_EQ(aResult, 0);
+ EXPECT_FALSE(aBSpline.IsNull());
+ EXPECT_LE(aMaxError, myTolerance * 10);
+
+ // Verify approximation quality by sampling points
+ Standard_Integer aNbSamples = 10;
+ for (Standard_Integer i = 0; i <= aNbSamples; i++)
+ {
+ Standard_Real aParam =
+ aHelix.FirstParameter() + i * (aHelix.LastParameter() - aHelix.FirstParameter()) / aNbSamples;
+
+ gp_Pnt aOrigPnt = aHelix.Value(aParam);
+
+ // Map parameter to B-spline parameter space
+ Standard_Real aBSplineParam =
+ aBSpline->FirstParameter()
+ + i * (aBSpline->LastParameter() - aBSpline->FirstParameter()) / aNbSamples;
+
+ gp_Pnt aApproxPnt;
+ aBSpline->D0(aBSplineParam, aApproxPnt);
+
+ Standard_Real aDistance = aOrigPnt.Distance(aApproxPnt);
+ EXPECT_LE(aDistance, aMaxError * 2); // Allow some margin
+ }
+}
+
+TEST_F(HelixGeom_Tools_Test, DifferentContinuity)
+{
+ HelixGeom_HelixCurve aHelix;
+ aHelix.Load(0.0, 6.0 * M_PI, 15.0, 4.0, 0.05, Standard_True);
+ Handle(HelixGeom_HelixCurve) aHAdaptor = new HelixGeom_HelixCurve(aHelix);
+
+ // Test C0 continuity
+ Handle(Geom_BSplineCurve) aBSplineC0;
+ Standard_Real aMaxErrorC0;
+ Standard_Integer aResultC0 = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C0,
+ 30,
+ 4,
+ aBSplineC0,
+ aMaxErrorC0);
+
+ EXPECT_EQ(aResultC0, 0);
+ EXPECT_FALSE(aBSplineC0.IsNull());
+
+ // Test C2 continuity
+ Handle(Geom_BSplineCurve) aBSplineC2;
+ Standard_Real aMaxErrorC2;
+ Standard_Integer aResultC2 = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ GeomAbs_C2,
+ 30,
+ 6,
+ aBSplineC2,
+ aMaxErrorC2);
+
+ EXPECT_EQ(aResultC2, 0);
+ EXPECT_FALSE(aBSplineC2.IsNull());
+
+ // C2 curve should generally have higher degree
+ EXPECT_GE(aBSplineC2->Degree(), aBSplineC0->Degree());
+}
\ No newline at end of file
--- /dev/null
+# Source files for HelixBRep package
+set(OCCT_HelixBRep_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+set(OCCT_HelixBRep_FILES
+ HelixBRep_BuilderHelix.cxx
+ HelixBRep_BuilderHelix.hxx
+)
--- /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 <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <gp.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <HelixBRep_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+#include <Precision.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <TopExp.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+//=================================================================================================
+
+HelixBRep_BuilderHelix::HelixBRep_BuilderHelix()
+
+{
+ gp_Pnt aP0(0., 0., 0);
+ // Initialize coordinate system and data arrays
+ myAxis3.SetDirection(gp::DZ());
+ myAxis3.SetLocation(aP0);
+ myDiams.Nullify();
+ myHeights.Nullify();
+ myPitches.Nullify();
+ myIsPitches.Nullify();
+ myNParts = 1;
+ myShape.Nullify();
+
+ // Initialize approximation parameters
+ myTolerance = 0.0001;
+ myContinuity = GeomAbs_C1;
+ myMaxDegree = 8;
+ myMaxSegments = 1000;
+ // Initialize status variables
+ myTolReached = 99.;
+ // Set initial error state
+ myErrorStatus = 1;
+ myWarningStatus = 1;
+}
+
+//=================================================================================================
+
+HelixBRep_BuilderHelix::~HelixBRep_BuilderHelix() {}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ myNParts = theDiams.Length() - 1;
+
+ myAxis3 = theAxis;
+
+ myDiams.Nullify();
+ myHeights.Nullify();
+ myPitches.Nullify();
+ myShape.Nullify();
+
+ myErrorStatus = 1;
+ myWarningStatus = 1;
+
+ if (myNParts != theHeights.Length() || myNParts != thePitches.Length()
+ || myNParts != bIsPitches.Length())
+ {
+ throw Standard_ConstructionError(
+ "HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ myDiams = new TColStd_HArray1OfReal(1, myNParts + 1);
+ myHeights = new TColStd_HArray1OfReal(1, myNParts);
+ myPitches = new TColStd_HArray1OfReal(1, myNParts);
+ myIsPitches = new TColStd_HArray1OfBoolean(1, myNParts);
+
+ myDiams->ChangeArray1() = theDiams;
+ myHeights->ChangeArray1() = theHeights;
+ myPitches->ChangeArray1() = thePitches;
+ myIsPitches->ChangeArray1() = bIsPitches;
+
+ myErrorStatus = 0;
+ myWarningStatus = 0;
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ Standard_Integer aNbParts = theHeights.Length();
+ TColStd_Array1OfReal aDiams(1, aNbParts + 1);
+ aDiams.Init(theDiam);
+ SetParameters(theAxis, aDiams, theHeights, thePitches, bIsPitches);
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ Standard_Integer aNbParts = theHeights.Length();
+ TColStd_Array1OfReal aDiams(1, aNbParts + 1);
+
+ Standard_Integer i, j;
+ Standard_Real anH = 0.;
+ for (i = theHeights.Lower(); i <= theHeights.Upper(); ++i)
+ {
+ anH += theHeights(i);
+ }
+ Standard_Real K = (theDiam2 - theDiam1) / anH;
+ aDiams(1) = theDiam1;
+ aDiams(aNbParts + 1) = theDiam2;
+
+ anH = theHeights(1);
+ for (i = theHeights.Lower() + 1, j = 2; i <= theHeights.Upper(); ++i, ++j)
+ {
+ aDiams(j) = theDiam1 + K * anH;
+ anH += theHeights(i);
+ }
+
+ SetParameters(theAxis, aDiams, theHeights, thePitches, bIsPitches);
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetApproxParameters(const Standard_Real aTolerance,
+ const Standard_Integer aMaxDegree,
+ const GeomAbs_Shape aCont)
+{
+ myTolerance = aTolerance;
+ myMaxDegree = aMaxDegree;
+ myContinuity = aCont;
+}
+
+//=================================================================================================
+
+Standard_Real HelixBRep_BuilderHelix::ToleranceReached() const
+{
+ return myTolReached;
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::Perform()
+{
+
+ if (myErrorStatus != 0)
+ return;
+
+ Standard_Integer i;
+
+ myTolReached = 0.;
+ myShape.Nullify();
+ BRep_Builder aBB;
+ // aBB.MakeCompound(TopoDS::Compound(myShape));
+
+ TopTools_ListOfShape anLst;
+
+ gp_Ax1 anAxis(myAxis3.Axis());
+ gp_Pnt aPStart = myAxis3.Location();
+ aPStart.Translate(.5 * myDiams->Value(1) * myAxis3.XDirection());
+ Standard_Boolean bIsClockwise = myAxis3.Direct();
+
+ Standard_Real aHeight;
+ Standard_Real aPitch;
+ Standard_Real aTaperAngle;
+
+ for (i = 1; i <= myNParts; ++i)
+ {
+
+ aHeight = myHeights->Value(i);
+
+ if (myIsPitches->Value(i))
+ {
+ aPitch = myPitches->Value(i);
+ }
+ else
+ {
+ aPitch = aHeight / myPitches->Value(i);
+ }
+
+ aTaperAngle = ATan(.5 * (myDiams->Value(i + 1) - myDiams->Value(i)) / aHeight);
+
+ TopoDS_Wire aPart;
+ aBB.MakeWire(aPart);
+
+ BuildPart(anAxis, aPStart, aHeight, aPitch, aTaperAngle, bIsClockwise, aPart);
+ if (myErrorStatus != 0)
+ return;
+
+ TopoDS_Vertex V1, V2;
+
+ TopExp::Vertices(aPart, V1, V2);
+
+ aPStart = BRep_Tool::Pnt(V2);
+
+ anAxis.SetLocation(anAxis.Location().Translated(aHeight * anAxis.Direction()));
+
+ anLst.Append(aPart);
+ // aBB.Add(myShape, aPart);
+ }
+
+ Smoothing(anLst);
+
+ TopTools_ListIteratorOfListOfShape anIt(anLst);
+ BRepBuilderAPI_MakeWire aMkWire(TopoDS::Wire(anLst.First()));
+ anIt.Next();
+ for (; anIt.More(); anIt.Next())
+ {
+ aMkWire.Add(TopoDS::Wire(anIt.Value()));
+ }
+
+ myShape = aMkWire.Shape();
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::BuildPart(const gp_Ax1& theAxis,
+ const gp_Pnt& thePStart,
+ const Standard_Real theHeight,
+ const Standard_Real thePitch,
+ const Standard_Real theTaperAngle,
+ const Standard_Boolean bIsClockwise,
+ TopoDS_Wire& thePart)
+{
+
+ if (myErrorStatus != 0)
+ return;
+
+ myErrorStatus = 0;
+ myWarningStatus = 0;
+
+ // 1. check & prepare data
+ Standard_Real aTolPrec, aDist, aDM, aTwoPI, aC1, aT2, aT1, aT0;
+ // Initialize tolerance and angular precision
+ aTolPrec = myTolerance;
+ Standard_Real aTolAng = 1.e-7;
+ // Validate input parameters
+ if (theTaperAngle > M_PI / 2. - aTolAng)
+ {
+ myErrorStatus = 13; // invalid TaperAngle value
+ return;
+ }
+ if (theHeight < aTolPrec)
+ {
+ myErrorStatus = 12; // invalid Height value
+ return;
+ }
+ if (thePitch < aTolPrec)
+ {
+ myErrorStatus = 11; // invalid Pitch value
+ return;
+ }
+ //
+ gp_Lin aLin(theAxis);
+ aDist = aLin.Distance(thePStart);
+ if (aDist < aTolPrec)
+ {
+ myErrorStatus = 10; // myPStart belongs to the myAxis
+ return;
+ }
+
+ aTolAng = aTolPrec / aDist;
+ Standard_Real aAngleStart = 0.;
+
+ // const Standard_Boolean bIsOutWard = theTaperAngle > 0.0;
+ const gp_Dir& aDir = theAxis.Direction();
+ gp_Vec aVec1 = gp_Vec(aDir);
+ gp_Pnt aM0 = theAxis.Location();
+ gp_Vec aVec(aM0, thePStart);
+ aDM = aVec1.Dot(aVec);
+ gp_Pnt aM1 = aM0.Translated(aDM * aVec1);
+ gp_Vec aVecX(aM1, thePStart);
+ gp_Dir aDirX(aVecX);
+ gp_Ax2 aAx2(aM1, aDir, aDirX);
+ //
+ aTwoPI = 2. * M_PI;
+ aC1 = thePitch / aTwoPI;
+ aT0 = 0.;
+ aT1 = aAngleStart;
+
+ aT2 = theHeight / aC1;
+ //
+ // 2. compute
+ Standard_Boolean bIsDone;
+ Standard_Integer iErr, aNbC, i;
+ HelixGeom_BuilderHelix aBH;
+ gp_Pnt aP1, aP2;
+ BRep_Builder aBB;
+ BRepBuilderAPI_MakeEdge aBME;
+ TopoDS_Vertex aV1, aV2;
+ // TopoDS_Wire aW;
+ TopoDS_Edge aE;
+ //
+ aBH.SetPosition(aAx2);
+ aBH.SetCurveParameters(aT0, aT2, thePitch, aDist, theTaperAngle, bIsClockwise);
+ aBH.SetTolerance(myTolerance);
+ aBH.SetApproxParameters(myContinuity, myMaxDegree, myMaxSegments);
+ //
+ aBH.Perform();
+ iErr = aBH.ErrorStatus();
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ return;
+ }
+ //
+ aBB.MakeWire(thePart);
+ //
+ myTolReached = Max(myTolReached, aBH.ToleranceReached());
+ TColGeom_SequenceOfCurve aSC;
+ aSC.Assign(aBH.Curves());
+ if (aT1 < 0.)
+ {
+ HelixGeom_BuilderHelix aBH1;
+ aBH1.SetPosition(aAx2);
+ aBH1.SetCurveParameters(aT1, aT0, thePitch, aDist, theTaperAngle, bIsClockwise);
+ aBH1.SetTolerance(myTolerance);
+ aBH1.SetApproxParameters(myContinuity, myMaxDegree, myMaxSegments);
+ //
+ aBH1.Perform();
+ iErr = aBH1.ErrorStatus();
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ return;
+ }
+
+ myTolReached = Max(myTolReached, aBH1.ToleranceReached());
+ const TColGeom_SequenceOfCurve& aSC1 = aBH1.Curves();
+ Standard_Integer nbc = aSC1.Length();
+ for (i = nbc; i >= 1; i--)
+ {
+ aSC.Prepend(aSC1.Value(i));
+ }
+ }
+
+ aNbC = aSC.Length();
+ for (i = 1; i <= aNbC; ++i)
+ {
+ Handle(Geom_Curve) aC = aSC(i);
+ //
+ if (i == 1)
+ {
+ if (aT1 > 0.)
+ {
+ aT2 = aC->LastParameter();
+ Handle(Geom_TrimmedCurve) aCT = new Geom_TrimmedCurve(aC, aT1, aT2);
+ aC = aCT;
+ }
+ aT1 = aC->FirstParameter();
+ aC->D0(aT1, aP1);
+ aBB.MakeVertex(aV1, aP1, myTolReached);
+ aV1.Orientation(TopAbs_FORWARD);
+ }
+ //
+ aT2 = aC->LastParameter();
+ aC->D0(aT2, aP2);
+ aBB.MakeVertex(aV2, aP2, myTolReached);
+ aV2.Orientation(TopAbs_REVERSED);
+ //
+ aBME.Init(aC, aV1, aV2);
+ bIsDone = aBME.IsDone();
+ if (!bIsDone)
+ {
+ myErrorStatus = 3;
+ return;
+ }
+ aE = aBME.Edge();
+ aBB.UpdateEdge(aE, myTolReached);
+ aBB.Add(thePart, aE);
+
+ //
+ aV1 = aV2;
+ aV1.Orientation(TopAbs_FORWARD);
+ }
+ //
+ if (myTolReached > myTolerance)
+ myWarningStatus = 1;
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::Smoothing(TopTools_ListOfShape& theParts)
+{
+ if (theParts.Extent() == 1)
+ return;
+
+ BRepTools_WireExplorer anExpl;
+
+ TopoDS_Wire aPrevWire = TopoDS::Wire(theParts.First());
+ anExpl.Init(aPrevWire);
+ TopoDS_Edge aPrevEdge;
+ for (; anExpl.More(); anExpl.Next())
+ {
+ aPrevEdge = anExpl.Current();
+ }
+
+ TopTools_ListIteratorOfListOfShape anIter(theParts);
+ anIter.Next();
+ for (; anIter.More(); anIter.Next())
+ {
+ TopoDS_Wire aNextWire = TopoDS::Wire(anIter.Value());
+ anExpl.Clear();
+ anExpl.Init(aNextWire);
+ TopoDS_Edge aNextEdge = anExpl.Current();
+
+ // Smoothing curves
+ SmoothingEdges(aPrevEdge, aNextEdge);
+
+ for (; anExpl.More(); anExpl.Next())
+ {
+ aPrevEdge = anExpl.Current();
+ }
+ }
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SmoothingEdges(TopoDS_Edge& thePrev, TopoDS_Edge& theNext)
+{
+
+ static const Standard_Real EpsAng = 1.e-7;
+ BRep_Builder aBB;
+
+ Standard_Real f1, l1, f2, l2;
+ Handle(Geom_BSplineCurve) aCPrev =
+ Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(thePrev, f1, l1));
+
+ Handle(Geom_BSplineCurve) aCNext =
+ Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(theNext, f2, l2));
+
+ gp_Pnt P1, P2;
+ gp_Vec V1, V2;
+
+ aCPrev->D1(l1, P1, V1);
+ aCNext->D1(f2, P2, V2);
+
+ if (V1.Angle(V2) < EpsAng)
+ return;
+
+ V1 = 0.5 * (V1 + V2);
+ V2 = V1;
+
+ Standard_Integer anErrorStatus = 1;
+ Standard_Integer aDegMax = Geom_BSplineCurve::MaxDegree();
+ Standard_Integer aDeg = aCPrev->Degree();
+ Standard_Integer i;
+ Standard_Boolean bPrevOK = Standard_False;
+ Standard_Boolean bNextOK = Standard_False;
+
+ aCPrev->MovePointAndTangent(l1, P1, V1, myTolerance, 1, -1, anErrorStatus);
+ if (anErrorStatus != 0)
+ {
+ for (i = aDeg + 1; i <= aDegMax; ++i)
+ {
+ aCPrev->IncreaseDegree(i);
+ aCPrev->MovePointAndTangent(l1, P1, V1, myTolerance, 1, -1, anErrorStatus);
+ if (anErrorStatus == 0)
+ {
+ bPrevOK = Standard_True;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bPrevOK = Standard_True;
+ }
+
+ if (bPrevOK)
+ {
+ aBB.UpdateEdge(thePrev, aCPrev, BRep_Tool::Tolerance(thePrev));
+ }
+
+ aDeg = aCNext->Degree();
+ aCNext->MovePointAndTangent(f2, P2, V2, myTolerance, -1, 1, anErrorStatus);
+ if (anErrorStatus != 0)
+ {
+ for (i = aDeg + 1; i <= aDegMax; ++i)
+ {
+ aCNext->IncreaseDegree(i);
+ aCNext->MovePointAndTangent(f2, P2, V2, myTolerance, -1, 1, anErrorStatus);
+ if (anErrorStatus == 0)
+ {
+ bNextOK = Standard_True;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bNextOK = Standard_True;
+ }
+
+ if (bNextOK)
+ {
+ aBB.UpdateEdge(theNext, aCNext, BRep_Tool::Tolerance(theNext));
+ }
+}
+
+//=======================================================================
+// function : ErrorStatus
+// purpose :
+//=======================================================================
+Standard_Integer HelixBRep_BuilderHelix::ErrorStatus() const
+{
+ return myErrorStatus;
+}
+
+//=======================================================================
+// function : WarningStatus
+// purpose :
+//=======================================================================
+Standard_Integer HelixBRep_BuilderHelix::WarningStatus() const
+{
+ return myWarningStatus;
+}
+
+//=======================================================================
+// function : Shape
+// purpose :
+//=======================================================================
+const TopoDS_Shape& HelixBRep_BuilderHelix::Shape() const
+{
+ return myShape;
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+
+{
+ Standard_Integer aNbParts = theDiams.Length() - 1;
+
+ if (aNbParts != thePitches.Length() || aNbParts != theNbTurns.Length())
+ {
+ throw Standard_ConstructionError(
+ "HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for (i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length();
+ ++i, ip++, in++)
+ {
+ aHeights(i) = thePitches(ip) * theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiams, aHeights, thePitches, bIsPitches);
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+{
+ Standard_Integer aNbParts = thePitches.Length();
+
+ if (aNbParts != theNbTurns.Length())
+ {
+ throw Standard_ConstructionError(
+ "HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for (i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length();
+ ++i, ip++, in++)
+ {
+ aHeights(i) = thePitches(ip) * theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiam, aHeights, thePitches, bIsPitches);
+}
+
+//=================================================================================================
+
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+{
+ Standard_Integer aNbParts = thePitches.Length();
+
+ if (aNbParts != theNbTurns.Length())
+ {
+ throw Standard_ConstructionError(
+ "HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for (i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length();
+ ++i, ip++, in++)
+ {
+ aHeights(i) = thePitches(ip) * theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiam1, theDiam2, aHeights, thePitches, bIsPitches);
+}
--- /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.
+
+#ifndef _HelixBRep_BuilderHelix_HeaderFile
+#define _HelixBRep_BuilderHelix_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <gp_Ax3.hxx>
+#include <Standard_Integer.hxx>
+#include <Standard_Real.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <TopoDS_Shape.hxx>
+#include <Standard_Boolean.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+#include <TColStd_HArray1OfReal.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
+class gp_Ax1;
+class gp_Pnt;
+class TopoDS_Wire;
+class TopoDS_Edge;
+
+//! Implementation of building helix wire
+//! Values of Error Status returned by algo:
+//! 0 - OK
+//! 1 - object is just initialized, it means that no input parameters were set
+//! 2 - approximation fails
+//!
+//! 10 - R < tolerance - starting point is too close to axis
+//! 11 - step (Pitch) < tolerance
+//! 12 - Height < tolerance
+//! 13 - TaperAngle < 0 or TaperAngle > Pi/2 - TolAng
+//! Warning Status:
+//! 0 - OK
+//! 1 - tolerance reached by approximation > requested tolerance.
+class HelixBRep_BuilderHelix
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Empty constructor
+ Standard_EXPORT HelixBRep_BuilderHelix();
+ Standard_EXPORT virtual ~HelixBRep_BuilderHelix();
+
+ //! Sets parameters of general composite helix
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& theIsPitches);
+
+ //! Sets parameters of pure helix
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& theIsPitches);
+
+ //! Sets parameters of pure spiral
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& theIsPitches);
+
+ //! Sets parameters of general composite helix
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns);
+
+ //! Sets parameters of pure helix
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns);
+
+ //! Sets parameters of pure spiral
+ Standard_EXPORT void SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns);
+
+ //! Sets parameters for approximation
+ Standard_EXPORT void SetApproxParameters(const Standard_Real theTolerance,
+ const Standard_Integer theMaxDegree,
+ const GeomAbs_Shape theContinuity);
+
+ //! Performs calculations
+ Standard_EXPORT void Perform();
+
+ //! Gets tolerance reached by approximation
+ Standard_EXPORT Standard_Real ToleranceReached() const;
+
+ //! Returns error status of algorithm
+ Standard_EXPORT Standard_Integer ErrorStatus() const;
+
+ //! Returns warning status of algorithm
+ Standard_EXPORT Standard_Integer WarningStatus() const;
+
+ //! Gets result of algorithm
+ Standard_EXPORT const TopoDS_Shape& Shape() const;
+
+protected:
+ gp_Ax3 myAxis3;
+ Handle(TColStd_HArray1OfReal) myDiams;
+ Handle(TColStd_HArray1OfReal) myHeights;
+ Handle(TColStd_HArray1OfReal) myPitches;
+ Handle(TColStd_HArray1OfBoolean) myIsPitches;
+ Standard_Real myTolerance;
+ Standard_Real myTolReached;
+ GeomAbs_Shape myContinuity;
+ Standard_Integer myMaxDegree;
+ Standard_Integer myMaxSegments;
+ Standard_Integer myErrorStatus;
+ Standard_Integer myWarningStatus;
+ TopoDS_Shape myShape;
+
+private:
+ Standard_EXPORT void BuildPart(const gp_Ax1& theAxis,
+ const gp_Pnt& thePStart,
+ const Standard_Real theHeight,
+ const Standard_Real thePitch,
+ const Standard_Real theTaperAngle,
+ const Standard_Boolean theIsClockwise,
+ TopoDS_Wire& thePart);
+
+ Standard_EXPORT void Smoothing(TopTools_ListOfShape& theParts);
+
+ Standard_EXPORT void SmoothingEdges(TopoDS_Edge& thePrev, TopoDS_Edge& theNext);
+
+ Standard_Integer myNParts;
+};
+
+#endif // _HelixBRep_BuilderHelix_HeaderFile
--- /dev/null
+# Source files for HelixGeom package
+set(OCCT_HelixGeom_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+set(OCCT_HelixGeom_FILES
+ HelixGeom_BuilderApproxCurve.cxx
+ HelixGeom_BuilderApproxCurve.hxx
+ HelixGeom_BuilderHelix.cxx
+ HelixGeom_BuilderHelix.hxx
+ HelixGeom_BuilderHelixCoil.cxx
+ HelixGeom_BuilderHelixCoil.hxx
+ HelixGeom_BuilderHelixGen.cxx
+ HelixGeom_BuilderHelixGen.hxx
+ HelixGeom_HelixCurve.cxx
+ HelixGeom_HelixCurve.hxx
+ HelixGeom_Tools.cxx
+ HelixGeom_Tools.hxx
+)
--- /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 <HelixGeom_BuilderApproxCurve.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+
+//=================================================================================================
+
+HelixGeom_BuilderApproxCurve::HelixGeom_BuilderApproxCurve()
+ : myErrorStatus(0),
+ myWarningStatus(0),
+ myTolerance(0.0001),
+ myCont(GeomAbs_C2),
+ myMaxDegree(8),
+ myMaxSeg(150),
+ myTolReached(99.0)
+{
+}
+
+//=================================================================================================
+
+HelixGeom_BuilderApproxCurve::~HelixGeom_BuilderApproxCurve() {}
+
+//=================================================================================================
+
+void HelixGeom_BuilderApproxCurve::SetApproxParameters(const GeomAbs_Shape aCont,
+ const Standard_Integer aMaxDegree,
+ const Standard_Integer aMaxSeg)
+{
+ myCont = aCont;
+ myMaxDegree = aMaxDegree;
+ myMaxSeg = aMaxSeg;
+}
+
+//=================================================================================================
+
+void HelixGeom_BuilderApproxCurve::ApproxParameters(GeomAbs_Shape& aCont,
+ Standard_Integer& aMaxDegree,
+ Standard_Integer& aMaxSeg) const
+{
+ aCont = myCont;
+ aMaxDegree = myMaxDegree;
+ aMaxSeg = myMaxSeg;
+}
+
+//=================================================================================================
+
+void HelixGeom_BuilderApproxCurve::SetTolerance(const Standard_Real aTolerance)
+{
+ myTolerance = aTolerance;
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_BuilderApproxCurve::Tolerance() const
+{
+ return myTolerance;
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_BuilderApproxCurve::ToleranceReached() const
+{
+ return myTolReached;
+}
+
+//=================================================================================================
+
+const TColGeom_SequenceOfCurve& HelixGeom_BuilderApproxCurve::Curves() const
+{
+ return myCurves;
+}
+
+//=================================================================================================
+
+Standard_Integer HelixGeom_BuilderApproxCurve::ErrorStatus() const
+{
+ return myErrorStatus;
+}
+
+//=================================================================================================
+
+Standard_Integer HelixGeom_BuilderApproxCurve::WarningStatus() const
+{
+ return myWarningStatus;
+}
--- /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.
+
+#ifndef _HelixGeom_BuilderApproxCurve_HeaderFile
+#define _HelixGeom_BuilderApproxCurve_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Integer.hxx>
+#include <Standard_Real.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+
+//! Base class for helix curve approximation algorithms.
+//!
+//! This abstract class provides common functionality for approximating
+//! parametric helix curves using B-spline curves. It manages:
+//! - Approximation tolerance and parameters
+//! - Continuity requirements (C0, C1, C2)
+//! - Maximum degree and number of segments
+//! - Error and warning status reporting
+//! - Result curve storage
+//!
+//! Derived classes must implement the Perform() method to execute
+//! the specific approximation algorithm.
+//!
+//! @sa HelixGeom_BuilderHelixGen, HelixGeom_BuilderHelix, HelixGeom_BuilderHelixCoil
+class HelixGeom_BuilderApproxCurve
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Sets approximation parameters
+ Standard_EXPORT void SetApproxParameters(const GeomAbs_Shape aCont,
+ const Standard_Integer aMaxDegree,
+ const Standard_Integer aMaxSeg);
+
+ //! Gets approximation parameters
+ Standard_EXPORT void ApproxParameters(GeomAbs_Shape& aCont,
+ Standard_Integer& aMaxDegree,
+ Standard_Integer& aMaxSeg) const;
+
+ //! Sets approximation tolerance
+ Standard_EXPORT void SetTolerance(const Standard_Real aTolerance);
+
+ //! Gets approximation tolerance
+ Standard_EXPORT Standard_Real Tolerance() const;
+
+ //! Gets actual tolerance reached by approximation algorithm
+ Standard_EXPORT Standard_Real ToleranceReached() const;
+
+ //! Gets sequence of BSpline curves representing helix coils
+ Standard_EXPORT const TColGeom_SequenceOfCurve& Curves() const;
+
+ //! Returns error status of algorithm
+ Standard_EXPORT Standard_Integer ErrorStatus() const;
+
+ //! Returns warning status of algorithm
+ Standard_EXPORT Standard_Integer WarningStatus() const;
+
+ //! Performs calculations.
+ //! Must be redefined.
+ Standard_EXPORT virtual void Perform() = 0;
+
+protected:
+ //! Sets default values of approximation parameters
+ Standard_EXPORT HelixGeom_BuilderApproxCurve();
+ Standard_EXPORT virtual ~HelixGeom_BuilderApproxCurve();
+
+ Standard_Integer myErrorStatus;
+ Standard_Integer myWarningStatus;
+ Standard_Real myTolerance;
+ GeomAbs_Shape myCont;
+ Standard_Integer myMaxDegree;
+ Standard_Integer myMaxSeg;
+ Standard_Real myTolReached;
+ TColGeom_SequenceOfCurve myCurves;
+
+private:
+};
+
+#endif // _HelixGeom_BuilderApproxCurve_HeaderFile
--- /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_Curve.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Trsf.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+
+//=================================================================================================
+
+HelixGeom_BuilderHelix::HelixGeom_BuilderHelix()
+ : HelixGeom_BuilderHelixGen()
+{
+}
+
+//=================================================================================================
+
+HelixGeom_BuilderHelix::~HelixGeom_BuilderHelix() {}
+
+//=================================================================================================
+
+void HelixGeom_BuilderHelix::SetPosition(const gp_Ax2& aAx2)
+{
+ myPosition = aAx2;
+}
+
+//=================================================================================================
+
+const gp_Ax2& HelixGeom_BuilderHelix::Position() const
+{
+ return myPosition;
+}
+
+//=================================================================================================
+
+void HelixGeom_BuilderHelix::Perform()
+{
+ myErrorStatus = 0;
+ myWarningStatus = 0;
+
+ // Initialize variables for helix segmentation
+ Standard_Integer iErr, aN, i, aNbC;
+ Standard_Real aTwoPI, dT, aT1x, aT2x, aTR;
+ HelixGeom_BuilderHelixCoil aBHC;
+
+ // Initialize result containers
+ myCurves.Clear();
+ myTolReached = -1.;
+ aTwoPI = 2. * M_PI;
+ aBHC.SetTolerance(myTolerance);
+ aBHC.SetApproxParameters(myCont, myMaxDegree, myMaxSeg);
+
+ // Determine number of full turns for segmentation
+ dT = myT2 - myT1;
+ aN = (Standard_Integer)(dT / aTwoPI);
+ if (!aN)
+ {
+ aBHC.SetCurveParameters(myT1, myT2, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aBHC.Perform();
+ iErr = aBHC.ErrorStatus();
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ return;
+ }
+ const TColGeom_SequenceOfCurve& aSC = aBHC.Curves();
+ const Handle(Geom_Curve)& aC = aSC(1);
+ myCurves.Append(aC);
+ myTolReached = aBHC.ToleranceReached();
+ }
+ else
+ {
+ // Case: helix spans multiple full turns - process in segments
+ Standard_Boolean bIsCylindrical;
+ Standard_Real aTolAngle;
+
+ aTolAngle = 1.e-4;
+ bIsCylindrical = fabs(myTaperAngle) < aTolAngle;
+ aT1x = myT1;
+ aT2x = myT1 + aTwoPI;
+ for (i = 1; i <= aN; ++i)
+ {
+ if (i > 1 && bIsCylindrical)
+ {
+ // Optimization: for cylindrical helixes, reuse first coil with translation
+ Handle(Geom_Curve) aCi;
+ gp_Pnt aP1, aPi;
+
+ const Handle(Geom_Curve)& aC1 = myCurves(1);
+ aC1->D0(aC1->FirstParameter(), aP1);
+ aPi.SetCoord(aP1.X(), aP1.Y(), aP1.Z() + (i - 1) * myPitch);
+ aCi = Handle(Geom_Curve)::DownCast(aC1->Translated(aP1, aPi));
+
+ myCurves.Append(aCi);
+ aT1x = aT2x;
+ aT2x = aT1x + aTwoPI;
+ // Skip to next iteration for optimization
+ continue;
+ }
+
+ aBHC.SetCurveParameters(aT1x, aT2x, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ // Perform approximation for this segment
+ aBHC.Perform();
+ iErr = aBHC.ErrorStatus();
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ return;
+ }
+ // Extract approximated curves from builder
+ const TColGeom_SequenceOfCurve& aSC = aBHC.Curves();
+ const Handle(Geom_Curve)& aC = aSC(1);
+ myCurves.Append(aC);
+ aTR = aBHC.ToleranceReached();
+ if (aTR > myTolReached)
+ {
+ myTolReached = aTR;
+ }
+ // Move to next segment parameters
+ aT1x = aT2x;
+ aT2x = aT1x + aTwoPI;
+ } // for (i=1; i<=aN; ++i) {
+ // Handle remaining partial turn if any
+ aT2x = myT2;
+ Standard_Real eps = 1.e-7 * aTwoPI;
+ if (fabs(aT2x - aT1x) > eps)
+ {
+ aBHC.SetCurveParameters(aT1x, aT2x, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aBHC.Perform();
+ iErr = aBHC.ErrorStatus();
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ return;
+ }
+ // Extract curves from the final partial segment
+ const TColGeom_SequenceOfCurve& aSC = aBHC.Curves();
+ const Handle(Geom_Curve)& aC = aSC(1);
+ myCurves.Append(aC);
+ aTR = aBHC.ToleranceReached();
+ if (aTR > myTolReached)
+ {
+ myTolReached = aTR;
+ }
+ }
+ }
+ // Apply coordinate system transformation to all curves
+ // Transformation
+ gp_Trsf aTrsf;
+ gp_Ax3 aAx3, aAx3x(myPosition);
+ // Set transformation from standard coordinate system to helix position
+ aTrsf.SetDisplacement(aAx3, aAx3x);
+ // Apply transformation to all generated curves
+ aNbC = myCurves.Length();
+ for (i = 1; i <= aNbC; ++i)
+ {
+ Handle(Geom_Curve)& aC = myCurves(i);
+ aC->Transform(aTrsf);
+ }
+}
--- /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.
+
+#ifndef _HelixGeom_BuilderHelix_HeaderFile
+#define _HelixGeom_BuilderHelix_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <gp_Ax2.hxx>
+#include <HelixGeom_BuilderHelixGen.hxx>
+class gp_Ax2;
+
+//! Upper level class for geometrical algorithm of building
+//! helix curves using arbitrary axis
+class HelixGeom_BuilderHelix : public HelixGeom_BuilderHelixGen
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Empty constructor
+ Standard_EXPORT HelixGeom_BuilderHelix();
+ Standard_EXPORT virtual ~HelixGeom_BuilderHelix();
+
+ //! Sets coordinate axes for helix
+ Standard_EXPORT void SetPosition(const gp_Ax2& aAx2);
+
+ //! Gets coordinate axes for helix
+ Standard_EXPORT const gp_Ax2& Position() const;
+
+ //! Performs calculations
+ Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
+
+protected:
+ gp_Ax2 myPosition;
+
+private:
+};
+
+#endif // _HelixGeom_BuilderHelix_HeaderFile
--- /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 <HelixGeom_BuilderHelixCoil.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_Tools.hxx>
+
+//=================================================================================================
+
+HelixGeom_BuilderHelixCoil::HelixGeom_BuilderHelixCoil()
+ : HelixGeom_BuilderHelixGen()
+{
+ myT1 = 0.;
+ myT2 = 2. * M_PI;
+ myPitch = 1.;
+ myRStart = 1.;
+ myTaperAngle = 0.;
+ myIsClockWise = Standard_True;
+}
+
+//=================================================================================================
+
+HelixGeom_BuilderHelixCoil::~HelixGeom_BuilderHelixCoil() {}
+
+//=================================================================================================
+
+void HelixGeom_BuilderHelixCoil::Perform()
+{
+ myErrorStatus = 0;
+ myWarningStatus = 0;
+ // Initialize variables for curve approximation
+ Standard_Integer iErr;
+ HelixGeom_HelixCurve aAdaptor;
+ Handle(HelixGeom_HelixCurve) aHAdaptor;
+ Handle(Geom_BSplineCurve) aBC;
+ // Clear previous results and setup helix adaptor
+ myCurves.Clear();
+ // Load helix parameters into the adaptor
+ aAdaptor.Load(myT1, myT2, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aHAdaptor = new HelixGeom_HelixCurve(aAdaptor);
+ // Perform B-spline approximation of the helix curve
+ iErr = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance,
+ myCont,
+ myMaxSeg,
+ myMaxDegree,
+ aBC,
+ myTolReached);
+ if (iErr)
+ {
+ myErrorStatus = 2;
+ }
+ else
+ {
+ myCurves.Append(aBC);
+ }
+}
--- /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.
+
+#ifndef _HelixGeom_BuilderHelixCoil_HeaderFile
+#define _HelixGeom_BuilderHelixCoil_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <HelixGeom_BuilderHelixGen.hxx>
+
+//! Implementation of algorithm for building helix coil with
+//! axis OZ
+class HelixGeom_BuilderHelixCoil : public HelixGeom_BuilderHelixGen
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Empty constructor
+ Standard_EXPORT HelixGeom_BuilderHelixCoil();
+ Standard_EXPORT virtual ~HelixGeom_BuilderHelixCoil();
+
+ //! Performs calculations
+ Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
+
+protected:
+private:
+};
+
+#endif // _HelixGeom_BuilderHelixCoil_HeaderFile
--- /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 <HelixGeom_BuilderHelixGen.hxx>
+
+#include <math.h>
+
+//=================================================================================================
+
+HelixGeom_BuilderHelixGen::HelixGeom_BuilderHelixGen()
+ : HelixGeom_BuilderApproxCurve(),
+ myT1(0.0),
+ myT2(2.0 * M_PI),
+ myPitch(1.0),
+ myRStart(1.0),
+ myTaperAngle(0.0),
+ myIsClockWise(Standard_True)
+{
+}
+
+//=================================================================================================
+
+HelixGeom_BuilderHelixGen::~HelixGeom_BuilderHelixGen() {}
+
+//=================================================================================================
+
+void HelixGeom_BuilderHelixGen::SetCurveParameters(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW)
+{
+ // Input validation would typically be done in derived classes or Load methods
+ // Base class just stores the values
+ myT1 = aT1;
+ myT2 = aT2;
+ myPitch = aPitch;
+ myRStart = aRStart;
+ myTaperAngle = aTaperAngle;
+ myIsClockWise = aIsCW;
+}
+
+//=================================================================================================
+
+void HelixGeom_BuilderHelixGen::CurveParameters(Standard_Real& aT1,
+ Standard_Real& aT2,
+ Standard_Real& aPitch,
+ Standard_Real& aRStart,
+ Standard_Real& aTaperAngle,
+ Standard_Boolean& aIsClockWise) const
+{
+ aT1 = myT1;
+ aT2 = myT2;
+ aPitch = myPitch;
+ aRStart = myRStart;
+ aTaperAngle = myTaperAngle;
+ aIsClockWise = myIsClockWise;
+}
--- /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.
+
+#ifndef _HelixGeom_BuilderHelixGen_HeaderFile
+#define _HelixGeom_BuilderHelixGen_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Real.hxx>
+#include <Standard_Boolean.hxx>
+#include <HelixGeom_BuilderApproxCurve.hxx>
+
+//! Base class for helix curve building algorithms with parameter management.
+//!
+//! This class extends HelixGeom_BuilderApproxCurve by adding helix-specific
+//! geometric parameters:
+//! - Parameter range (T1, T2) - angular range in radians
+//! - Pitch - vertical distance per full turn (2*PI radians)
+//! - Start radius (RStart) - radius at parameter T1
+//! - Taper angle - angle for radius variation (0 = cylindrical)
+//! - Orientation - clockwise or counter-clockwise
+//!
+//! Concrete implementations include:
+//! - HelixGeom_BuilderHelix: Single helix approximation
+//! - HelixGeom_BuilderHelixCoil: Multi-coil helix approximation
+//!
+//! @sa HelixGeom_BuilderApproxCurve, HelixGeom_HelixCurve
+class HelixGeom_BuilderHelixGen : public HelixGeom_BuilderApproxCurve
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Sets parameters for building helix curves
+ Standard_EXPORT void SetCurveParameters(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean bIsClockwise);
+
+ //! Gets parameters for building helix curves
+ Standard_EXPORT void CurveParameters(Standard_Real& aT1,
+ Standard_Real& aT2,
+ Standard_Real& aPitch,
+ Standard_Real& aRStart,
+ Standard_Real& aTaperAngle,
+ Standard_Boolean& bIsClockwise) const;
+
+protected:
+ //! Sets default parameters
+ Standard_EXPORT HelixGeom_BuilderHelixGen();
+ Standard_EXPORT virtual ~HelixGeom_BuilderHelixGen();
+
+ Standard_Real myT1;
+ Standard_Real myT2;
+ Standard_Real myPitch;
+ Standard_Real myRStart;
+ Standard_Real myTaperAngle;
+ Standard_Boolean myIsClockWise;
+
+private:
+};
+
+#endif // _HelixGeom_BuilderHelixGen_HeaderFile
--- /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 <HelixGeom_HelixCurve.hxx>
+
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_DomainError.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <TColStd_Array1OfReal.hxx>
+
+#include <math.h>
+
+IMPLEMENT_STANDARD_RTTIEXT(HelixGeom_HelixCurve, Adaptor3d_Curve)
+
+//=================================================================================================
+
+HelixGeom_HelixCurve::HelixGeom_HelixCurve()
+{
+ myFirst = 0.;
+ myLast = 2. * M_PI;
+ myPitch = 1.;
+ myRStart = 1.;
+ myTaperAngle = 0.;
+ myIsClockWise = Standard_True;
+ // Calculate derived parameters
+ myC1 = myPitch / myLast;
+ myTgBeta = 0.;
+ myTolAngle = 1.e-4;
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::Load()
+{
+ Load(myFirst, myLast, myPitch, myRStart, myTaperAngle, myIsClockWise);
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::Load(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW)
+{
+ char buf[] = {"HelixGeom_HelixCurve::Load"};
+ Standard_Real aTwoPI, aHalfPI;
+ // Define angular constants
+ aTwoPI = 2. * M_PI;
+ aHalfPI = 0.5 * M_PI;
+ // Store parameter values
+ myFirst = aT1;
+ myLast = aT2;
+ myPitch = aPitch;
+ myRStart = aRStart;
+ myTaperAngle = aTaperAngle;
+ myIsClockWise = aIsCW;
+ // Validate input parameters
+ if (aT1 >= aT2)
+ {
+ throw Standard_ConstructionError(buf);
+ }
+ if (myPitch < 0.)
+ {
+ throw Standard_ConstructionError(buf);
+ }
+ if (myRStart < 0.)
+ {
+ throw Standard_ConstructionError(buf);
+ }
+ if (myTaperAngle <= -aHalfPI || myTaperAngle >= aHalfPI)
+ {
+ throw Standard_ConstructionError(buf);
+ }
+ // Calculate helix coefficient
+ myC1 = myPitch / aTwoPI;
+ if (fabs(myTaperAngle) > myTolAngle)
+ {
+ myTgBeta = tan(myTaperAngle);
+ }
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_HelixCurve::FirstParameter() const
+{
+ return myFirst;
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_HelixCurve::LastParameter() const
+{
+ return myLast;
+}
+
+//=================================================================================================
+
+GeomAbs_Shape HelixGeom_HelixCurve::Continuity() const
+{
+ return GeomAbs_CN;
+}
+
+//=================================================================================================
+
+Standard_Integer HelixGeom_HelixCurve::NbIntervals(const GeomAbs_Shape) const
+{
+ return 1;
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape) const
+{
+ T(1) = myFirst;
+ T(2) = myLast;
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_HelixCurve::Resolution(const Standard_Real) const
+{
+ throw Standard_NotImplemented("HelixGeom_HelixCurve::Resolution");
+}
+
+//=================================================================================================
+
+Standard_Boolean HelixGeom_HelixCurve::IsClosed() const
+{
+ throw Standard_NotImplemented("HelixGeom_HelixCurve::IsClosed");
+}
+
+//=================================================================================================
+
+Standard_Boolean HelixGeom_HelixCurve::IsPeriodic() const
+{
+ throw Standard_NotImplemented("HelixGeom_HelixCurve::IsPeriodic");
+}
+
+//=================================================================================================
+
+Standard_Real HelixGeom_HelixCurve::Period() const
+{
+ throw Standard_DomainError("HelixGeom_HelixCurve::Period");
+}
+
+//=================================================================================================
+
+gp_Pnt HelixGeom_HelixCurve::Value(const Standard_Real aT) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1;
+ // Calculate trigonometric values and radius
+ aCT = cos(aT);
+ aST = sin(aT);
+ a1 = myRStart + myC1 * myTgBeta * aT;
+ // Calculate Cartesian coordinates
+ aX = a1 * aCT;
+ aY = a1 * aST;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = myC1 * aT;
+ return gp_Pnt(aX, aY, aZ);
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::D0(const Standard_Real aT, gp_Pnt& aP) const
+{
+ aP = Value(aT);
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::D1(const Standard_Real aT, gp_Pnt& aP, gp_Vec& aV1) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1, a2;
+ // Calculate point and first derivative
+ aCT = cos(aT);
+ aST = sin(aT);
+ // Calculate radius at parameter t
+ a1 = myRStart + myC1 * myTgBeta * aT;
+ // Calculate point coordinates
+ aX = a1 * aCT;
+ aY = a1 * aST;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = myC1 * aT;
+ aP.SetCoord(aX, aY, aZ);
+ // Calculate first derivative coefficients
+ a1 = myC1 * myTgBeta;
+ a2 = myRStart + a1 * aT;
+ // Calculate first derivative components
+ aX = a1 * aCT - a2 * aST;
+ aY = a1 * aST + a2 * aCT;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = myC1;
+ aV1.SetCoord(aX, aY, aZ);
+}
+
+//=================================================================================================
+
+void HelixGeom_HelixCurve::D2(const Standard_Real aT, gp_Pnt& aP, gp_Vec& aV1, gp_Vec& aV2) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1, a2;
+ // Calculate point, first and second derivatives
+ aCT = cos(aT);
+ aST = sin(aT);
+ // Calculate radius at parameter t
+ a1 = myRStart + myC1 * myTgBeta * aT;
+ // Calculate point coordinates
+ aX = a1 * aCT;
+ aY = a1 * aST;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = myC1 * aT;
+ aP.SetCoord(aX, aY, aZ);
+ // Calculate first derivative coefficients
+ a1 = myC1 * myTgBeta;
+ a2 = myRStart + a1 * aT;
+ // Calculate first derivative components
+ aX = a1 * aCT - a2 * aST;
+ aY = a1 * aST + a2 * aCT;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = myC1;
+ aV1.SetCoord(aX, aY, aZ);
+ // Calculate second derivative
+ a1 = 2. * a1;
+ aX = -a2 * aCT - a1 * aST;
+ aY = -a2 * aST - a1 * aCT;
+ if (!myIsClockWise)
+ {
+ aY = -aY;
+ }
+ aZ = 0.;
+ aV2.SetCoord(aX, aY, aZ);
+}
+
+//=================================================================================================
+
+gp_Vec HelixGeom_HelixCurve::DN(const Standard_Real aT, const Standard_Integer aN) const
+{
+ gp_Pnt aP;
+ gp_Vec aV1, aV2;
+ // Compute derivative based on order
+ switch (aN)
+ {
+ case 1:
+ D1(aT, aP, aV1);
+ break;
+ case 2:
+ D2(aT, aP, aV1, aV2);
+ break;
+ default:
+ throw Standard_NotImplemented("HelixGeom_HelixCurve::DN");
+ break;
+ }
+ return (aN == 1) ? aV1 : aV2;
+}
--- /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.
+
+#ifndef _HelixGeom_HelixCurve_HeaderFile
+#define _HelixGeom_HelixCurve_HeaderFile
+
+#include <Adaptor3d_Curve.hxx>
+#include <GeomAbs_Shape.hxx>
+
+class gp_Pnt;
+class gp_Vec;
+
+DEFINE_STANDARD_HANDLE(HelixGeom_HelixCurve, Adaptor3d_Curve)
+
+//! Adaptor class for calculation of helix curves with analytical expressions.
+//!
+//! This class provides parametric representation of helix curves including:
+//! - Cylindrical helixes (constant radius)
+//! - Tapered helixes (variable radius with taper angle)
+//! - Both clockwise and counter-clockwise orientations
+//!
+//! The helix is defined by parametric equations in cylindrical coordinates:
+//! - x(t) = r(t) * cos(t)
+//! - y(t) = r(t) * sin(t) [* direction factor]
+//! - z(t) = pitch * t / (2*PI)
+//! where r(t) = rStart + taper_factor * t
+//!
+//! @sa HelixGeom_BuilderHelix, HelixGeom_BuilderHelixCoil
+class HelixGeom_HelixCurve : public Adaptor3d_Curve
+{
+ DEFINE_STANDARD_RTTIEXT(HelixGeom_HelixCurve, Adaptor3d_Curve)
+public:
+ //! implementation of analytical expressions
+ Standard_EXPORT HelixGeom_HelixCurve();
+
+ //! Sets default values for parameters
+ Standard_EXPORT void Load();
+
+ //! Sets helix parameters
+ Standard_EXPORT void Load(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW);
+
+ //! Gets first parameter
+ Standard_EXPORT virtual Standard_Real FirstParameter() const Standard_OVERRIDE;
+
+ //! Gets last parameter
+ Standard_EXPORT virtual Standard_Real LastParameter() const Standard_OVERRIDE;
+
+ //! Gets continuity
+ Standard_EXPORT virtual GeomAbs_Shape Continuity() const Standard_OVERRIDE;
+
+ //! Gets number of intervals
+ Standard_EXPORT virtual Standard_Integer NbIntervals(const GeomAbs_Shape S) const
+ Standard_OVERRIDE;
+
+ //! Gets parametric intervals
+ Standard_EXPORT virtual void Intervals(TColStd_Array1OfReal& T,
+ const GeomAbs_Shape S) const Standard_OVERRIDE;
+
+ //! Gets parametric resolution
+ Standard_EXPORT virtual Standard_Real Resolution(const Standard_Real R3d) const Standard_OVERRIDE;
+
+ //! Returns False
+ Standard_EXPORT virtual Standard_Boolean IsClosed() const Standard_OVERRIDE;
+
+ //! Returns False
+ Standard_EXPORT virtual Standard_Boolean IsPeriodic() const Standard_OVERRIDE;
+
+ //! Returns 2*PI
+ Standard_EXPORT virtual Standard_Real Period() const Standard_OVERRIDE;
+
+ //! Gets curve point for parameter U
+ Standard_EXPORT virtual gp_Pnt Value(const Standard_Real U) const Standard_OVERRIDE;
+
+ //! Gets curve point for parameter U
+ Standard_EXPORT virtual void D0(const Standard_Real U, gp_Pnt& P) const Standard_OVERRIDE;
+
+ //! Gets curve point and first derivatives for parameter U
+ Standard_EXPORT virtual void D1(const Standard_Real U,
+ gp_Pnt& P,
+ gp_Vec& V1) const Standard_OVERRIDE;
+
+ //! Gets curve point, first and second derivatives for parameter U
+ Standard_EXPORT virtual void D2(const Standard_Real U,
+ gp_Pnt& P,
+ gp_Vec& V1,
+ gp_Vec& V2) const Standard_OVERRIDE;
+
+ //! Gets curve derivative of demanded order for parameter U
+ Standard_EXPORT virtual gp_Vec DN(const Standard_Real U,
+ const Standard_Integer N) const Standard_OVERRIDE;
+
+protected:
+ Standard_Real myFirst;
+ Standard_Real myLast;
+ Standard_Real myPitch;
+ Standard_Real myRStart;
+ Standard_Real myTaperAngle;
+ Standard_Boolean myIsClockWise;
+ Standard_Real myC1;
+ Standard_Real myTgBeta;
+ Standard_Real myTolAngle;
+
+private:
+};
+
+#endif // _HelixGeom_HelixCurve_HeaderFile
--- /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 <Adaptor3d_Curve.hxx>
+#include <AdvApprox_ApproxAFunction.hxx>
+#include <AdvApprox_DichoCutting.hxx>
+#include <AdvApprox_EvaluatorFunction.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_Tools.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+
+//=======================================================================
+// class : HelixGeom_Tools_Eval
+// purpose: evaluator class for approximation
+//=======================================================================
+class HelixGeom_Tools_Eval : public AdvApprox_EvaluatorFunction
+{
+public:
+ HelixGeom_Tools_Eval(const Handle(Adaptor3d_Curve)& theFunc)
+ : fonct(theFunc)
+ {
+ }
+
+ virtual void Evaluate(Standard_Integer* Dimension,
+ Standard_Real StartEnd[2],
+ Standard_Real* Parameter,
+ Standard_Integer* DerivativeRequest,
+ Standard_Real* Result, // [Dimension]
+ Standard_Integer* ErrorCode);
+
+private:
+ Handle(Adaptor3d_Curve) fonct;
+};
+
+void HelixGeom_Tools_Eval::Evaluate(Standard_Integer* Dimension,
+ Standard_Real /*StartEnd*/[2],
+ Standard_Real* Param, // Parameter at which evaluation
+ Standard_Integer* Order, // Derivative Request
+ Standard_Real* Result, // [Dimension]
+ Standard_Integer* ErrorCode)
+{
+ *ErrorCode = 0;
+ Standard_Real par = *Param;
+
+ // Dimension is incorrect
+ if (*Dimension != 3)
+ {
+ *ErrorCode = 1;
+ }
+ gp_Pnt pnt;
+ gp_Vec v1, v2;
+
+ switch (*Order)
+ {
+ case 0:
+ pnt = fonct->Value(par);
+ Result[0] = pnt.X();
+ Result[1] = pnt.Y();
+ Result[2] = pnt.Z();
+ break;
+ case 1:
+ fonct->D1(par, pnt, v1);
+ Result[0] = v1.X();
+ Result[1] = v1.Y();
+ Result[2] = v1.Z();
+ break;
+ case 2:
+ fonct->D2(par, pnt, v1, v2);
+ Result[0] = v2.X();
+ Result[1] = v2.Y();
+ Result[2] = v2.Z();
+ break;
+ default:
+ Result[0] = Result[1] = Result[2] = 0.;
+ *ErrorCode = 3;
+ break;
+ }
+}
+
+//=================================================================================================
+
+Standard_Integer HelixGeom_Tools::ApprCurve3D(const Handle(Adaptor3d_Curve)& theHC,
+ const Standard_Real theTol,
+ const GeomAbs_Shape theCont,
+ const Standard_Integer theMaxSeg,
+ const Standard_Integer theMaxDeg,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError)
+{
+ Standard_Boolean anIsDone, aHasResult;
+ Standard_Integer Num1DSS, Num2DSS, Num3DSS;
+ Standard_Real First, Last;
+ Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul, ThreeDTol;
+ AdvApprox_DichoCutting aCutTool;
+ // Setup approximation dimensions and tolerances
+ Num1DSS = 0;
+ Num2DSS = 0;
+ Num3DSS = 1;
+ ThreeDTol = new TColStd_HArray1OfReal(1, Num3DSS);
+ ThreeDTol->Init(theTol);
+ // Get curve parameter range
+ First = theHC->FirstParameter();
+ Last = theHC->LastParameter();
+ // Setup approximation function and perform approximation
+ HelixGeom_Tools_Eval ev(theHC);
+ AdvApprox_ApproxAFunction aApprox(Num1DSS,
+ Num2DSS,
+ Num3DSS,
+ OneDTolNul,
+ TwoDTolNul,
+ ThreeDTol,
+ First,
+ Last,
+ theCont,
+ theMaxDeg,
+ theMaxSeg,
+ ev,
+ aCutTool);
+ // Check if approximation was successful
+ anIsDone = aApprox.IsDone();
+ if (!anIsDone)
+ {
+ return 1;
+ }
+ // Initialize error and check for results
+ theMaxError = 0.;
+ // Verify approximation has results
+ aHasResult = aApprox.HasResult();
+ if (!aHasResult)
+ {
+ return 2;
+ }
+ // Extract B-spline curve data from approximation
+ TColgp_Array1OfPnt Poles(1, aApprox.NbPoles());
+ aApprox.Poles(1, Poles);
+ Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
+ Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
+ Standard_Integer Degree = aApprox.Degree();
+ theBSpl = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
+ theMaxError = aApprox.MaxError(3, 1);
+ // Return success
+ return 0;
+}
+
+//=================================================================================================
+
+Standard_Integer HelixGeom_Tools::ApprHelix(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW,
+ const Standard_Real theTol,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError)
+{
+ Standard_Integer iErr, aMaxDegree, aMaxSeg;
+ GeomAbs_Shape aCont;
+ HelixGeom_HelixCurve aAdaptor;
+ Handle(HelixGeom_HelixCurve) aHAdaptor;
+ // Load helix parameters and create adaptor handle
+ aAdaptor.Load(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsCW);
+ aHAdaptor = new HelixGeom_HelixCurve(aAdaptor);
+ // Set default approximation parameters
+ aCont = GeomAbs_C2;
+ aMaxDegree = 8;
+ aMaxSeg = 150;
+ // Perform curve approximation
+ iErr = HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ theTol,
+ aCont,
+ aMaxSeg,
+ aMaxDegree,
+ theBSpl,
+ theMaxError);
+ return iErr;
+}
--- /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.
+
+#ifndef _HelixGeom_Tools_HeaderFile
+#define _HelixGeom_Tools_HeaderFile
+
+#include <Adaptor3d_Curve.hxx>
+#include <GeomAbs_Shape.hxx>
+
+class Geom_BSplineCurve;
+
+//! Static utility class providing approximation algorithms for helix curves.
+//!
+//! This class contains static methods for:
+//! - Converting analytical helix curves to B-spline approximations
+//! - Generic curve approximation with specified tolerances and continuity
+//! - High-quality approximation suitable for CAD/CAM applications
+//!
+//! The approximation algorithms use advanced techniques to ensure:
+//! - Accurate representation within specified tolerances
+//! - Smooth continuity (C0, C1, C2) as required
+//! - Efficient B-spline parameterization
+//! - Robust handling of edge cases
+class HelixGeom_Tools
+{
+public:
+ DEFINE_STANDARD_ALLOC
+
+ //! Approximates a parametric helix curve using B-spline representation.
+ //! @param aT1 [in] Start parameter (angular position in radians)
+ //! @param aT2 [in] End parameter (angular position in radians)
+ //! @param aPitch [in] Helix pitch (vertical distance per 2*PI radians)
+ //! @param aRStart [in] Starting radius at parameter aT1
+ //! @param aTaperAngle [in] Taper angle in radians (0 = cylindrical helix)
+ //! @param aIsCW [in] True for clockwise, false for counter-clockwise
+ //! @param aTol [in] Approximation tolerance
+ //! @param theBSpl [out] Resulting B-spline curve
+ //! @param theMaxError [out] Maximum approximation error achieved
+ //! @return 0 on success, error code otherwise
+ Standard_EXPORT static Standard_Integer ApprHelix(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW,
+ const Standard_Real aTol,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError);
+
+ //! Approximates a generic 3D curve using B-spline representation.
+ //! @param theHC [in] Handle to the curve adaptor to approximate
+ //! @param theTol [in] Approximation tolerance
+ //! @param theCont [in] Required continuity (C0, C1, C2)
+ //! @param theMaxSeg [in] Maximum number of curve segments
+ //! @param theMaxDeg [in] Maximum degree of B-spline curve
+ //! @param theBSpl [out] Resulting B-spline curve
+ //! @param theMaxError [out] Maximum approximation error achieved
+ //! @return 0 on success, error code otherwise
+ Standard_EXPORT static Standard_Integer ApprCurve3D(const Handle(Adaptor3d_Curve)& theHC,
+ const Standard_Real theTol,
+ const GeomAbs_Shape theCont,
+ const Standard_Integer theMaxSeg,
+ const Standard_Integer theMaxDeg,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError);
+};
+
+#endif // _HelixGeom_Tools_HeaderFile
--- /dev/null
+# Auto-generated list of packages for TKHelix toolkit
+set(OCCT_TKHelix_LIST_OF_PACKAGES
+ HelixBRep
+ HelixGeom
+)
--- /dev/null
+# TKHelix Toolkit
+
+## Overview
+
+The TKHelix toolkit provides comprehensive functionality for creating, approximating, and manipulating helix curves in OCCT. This toolkit enables the construction of complex helix geometries commonly used in mechanical engineering, manufacturing, and architectural applications.
+
+## Architecture
+
+The TKHelix toolkit is organized into two packages:
+
+### HelixGeom Package
+Provides geometric helix curve functionality:
+- **HelixGeom_HelixCurve**: Analytical helix curve adaptor with parametric representation
+- **HelixGeom_BuilderHelix**: Single helix curve approximation algorithms
+- **HelixGeom_BuilderHelixCoil**: Multi-coil helix approximation with advanced features
+- **HelixGeom_BuilderApproxCurve**: Base class for approximation algorithms
+- **HelixGeom_BuilderHelixGen**: Base class with helix-specific parameter management
+- **HelixGeom_Tools**: Static utility functions for curve approximation
+
+### HelixBRep Package
+Provides topological helix construction:
+- **HelixBRep_BuilderHelix**: Topological helix wire construction from geometric curves
+
+## Key Features
+
+### Helix Types Supported
+- **Cylindrical Helixes**: Constant radius helixes for springs, threads
+- **Tapered Helixes**: Variable radius helixes with taper angles
+- **Spiral Helixes**: Multi-diameter configurations for complex shapes
+- **Multi-part Helixes**: Segmented helixes with different parameters per section
+
+### Advanced Capabilities
+- High-quality B-spline approximation with specified tolerance
+- Configurable continuity requirements (C0, C1, C2)
+- Both clockwise and counter-clockwise orientations
+- Smooth transitions between helix segments
+- Comprehensive error handling and status reporting
+
+### DRAW Command Interface
+Interactive commands for helix creation and testing:
+- `setaxis`: Define helix axis orientation
+- `helix`: Create single-diameter helix
+- `comphelix`: Create multi-diameter helix
+- `spiral`: Create spiral helix with varying diameter
+- `helix2`, `comphelix2`, `spiral2`: Alternative interfaces using number of turns
+
+## Mathematical Foundation
+
+Helix curves are represented using parametric equations in cylindrical coordinates:
+
+```
+x(t) = r(t) * cos(t)
+y(t) = r(t) * sin(t) [* direction_factor]
+z(t) = pitch * t / (2Ï€)
+```
+
+Where:
+- `r(t) = r_start + taper_factor * t` (radius as function of parameter)
+- `t` is the angular parameter in radians
+- `pitch` is the vertical distance per full turn (2Ï€ radians)
+- `direction_factor` is 1 for clockwise, -1 for counter-clockwise
+
+## Usage Examples
+
+### Basic Cylindrical Helix
+```cpp
+HelixGeom_BuilderHelixCoil builder;
+builder.SetCurveParameters(0.0, 4*M_PI, 10.0, 5.0, 0.0, Standard_True);
+builder.SetTolerance(1e-6);
+builder.Perform();
+```
+
+### Tapered Helix
+```cpp
+HelixGeom_BuilderHelixCoil builder;
+builder.SetCurveParameters(0.0, 6*M_PI, 15.0, 8.0, 0.1, Standard_True);
+builder.SetApproxParameters(GeomAbs_C2, 8, 100);
+builder.Perform();
+```
+
+### Topological Wire Construction
+```cpp
+HelixBRep_BuilderHelix builder;
+TColStd_Array1OfReal heights(1, 1);
+heights(1) = 50.0;
+TColStd_Array1OfReal pitches(1, 1);
+pitches(1) = 10.0;
+TColStd_Array1OfBoolean isPitches(1, 1);
+isPitches(1) = Standard_True;
+
+gp_Ax3 axis(gp_Pnt(0,0,0), gp_Dir(0,0,1), gp_Dir(1,0,0));
+builder.SetParameters(axis, 25.0, heights, pitches, isPitches);
+builder.Perform();
+TopoDS_Shape helixWire = builder.Shape();
+```
+
+## Dependencies
+
+The TKHelix toolkit depends on the following OCCT toolkits:
+- **TKernel**: Basic OCCT functionality
+- **TKMath**: Mathematical utilities
+- **TKGeomBase**: Basic geometric types
+- **TKG2d**: 2D geometry
+- **TKG3d**: 3D geometry and curves
+- **TKGeomAlgo**: Geometric algorithms
+- **TKBRep**: Boundary representation
+- **TKTopAlgo**: Topological algorithms
+
+## Testing
+
+The toolkit includes comprehensive testing:
+- **44 unit tests** covering all classes and methods
+- **82 TCL test cases** for integration validation
+- **Error condition testing** for robustness
+- **Performance and tolerance validation**
+
+Test files are located in:
+- `src/ModelingAlgorithms/TKHelix/GTests/` - Unit tests
+- `tests/helix/` - TCL integration tests
+
+## Build Integration
+
+The toolkit is fully integrated into the OCCT build system:
+- CMake configuration files for automatic building
+- Proper toolkit dependencies declared
+- Integration with CTest framework for automated testing
+
+## Error Codes
+
+Common error status codes returned by algorithms:
+- **0**: Success
+- **2**: Geometric algorithm failure
+- **10**: Invalid start point (on axis)
+- **11**: Invalid pitch value
+- **12**: Invalid height value
+- **13**: Invalid taper angle value
+
+## Future Enhancements
+
+Potential areas for future development:
+- Support for elliptical helix bases
+- Variable pitch helixes
+- Advanced smoothing algorithms for multi-part helixes
+- Integration with surface modeling for helix-based features
\ No newline at end of file
TKBO
TKBool
TKHLR
+ TKHelix
TKFillet
TKOffset
TKFeat
--- /dev/null
+if { [array get Draw_Groups "TOPOLOGY Check commands"] == "" } {
+ pload XDE
+ pload TOPTEST
+ pload VISUALIZATION
+}
+
+# to prevent loops limit to 16 minutes
+cpulimit 1000
+
+if { [info exists imagedir] == 0 } {
+ set imagedir .
+}
+if { [info exists test_image] == 0 } {
+ set test_image photo
+}
+
+proc CheckSweep {} {
+ global s1 s2 result
+ checkshape s1
+ checkshape s2
+ mksweep s1
+ addsweep s2
+ set bad_buildsweep 0
+ if [catch { buildsweep result -S } catch_result] {
+ puts "Faulty OCC1477 : buildsweep is wrong"
+ } else {
+ checkshape result
+ }
+}
+
+proc CheckSpiral {} {
+ global result good_Center_X good_Center_Y good_Center_Z good_Moments_IX set good_Moments_IY good_Moments_IZ
+ set llprops [lprops result]
+ regexp {[ \t]*X =[ \t]*([-0-9.+eE]+)} $llprops full Center_X
+ regexp {[ \t]*Y =[ \t]*([-0-9.+eE]+)} $llprops full Center_Y
+ regexp {[ \t]*Z =[ \t]*([-0-9.+eE]+)} $llprops full Center_Z
+ regexp {[ \t]*IX =[ \t]*([-0-9.+eE]+)} $llprops full Moments_IX
+ regexp {[ \t]*IY =[ \t]*([-0-9.+eE]+)} $llprops full Moments_IY
+ regexp {[ \t]*IZ =[ \t]*([-0-9.+eE]+)} $llprops full Moments_IZ
+ if { $good_Center_X != $Center_X ||
+ $good_Center_Y != $Center_Y ||
+ $good_Center_Z != $Center_Z ||
+ $good_Moments_IX != $Moments_IX ||
+ $good_Moments_IY != $Moments_IY ||
+ $good_Moments_IZ != $Moments_IZ } {
+ puts "Error : CheckSpiral"
+ }
+}
--- /dev/null
+if { [info exists square] } {
+ set prop "square"
+ set mass $square
+ if { [info exists tol_square] } {
+ regexp {Mass +: +([-0-9.+eE]+)} [sprops result $tol_square] full m
+ } else {
+ regexp {Mass +: +([-0-9.+eE]+)} [sprops result] full m
+ }
+}
+if { [info exists length] } {
+ set prop "length"
+ set mass $length
+ regexp {Mass +: +([-0-9.+eE]+)} [lprops result] full m
+
+ puts "checksection"
+ puts [checksection result]
+}
+
+if { [info exists mass] } {
+ if { [string compare "$mass" "empty"] != 0 } {
+ if { $m == 0 } {
+ puts "Error : The command is not valid. The $prop is 0."
+ }
+ if { $mass > 0 } {
+ puts "The expected $prop is $mass"
+ }
+ #check of change of square is < 1%
+ if { ($mass != 0 && [expr 1.*abs($mass - $m)/$mass] > 0.01) || ($mass == 0 && $m != 0) } {
+ puts "Error : The $prop of result shape is $m"
+ }
+ } else {
+ if { $m != 0 } {
+ puts "Error : The command is not valid. The $prop is $m"
+ }
+ }
+}
+
+set glob_inf [info global nb_*_good]
+if { [regexp "nb_.*_good" $glob_inf] == 1 } {
+ if { [info exists nbsh_t] } {
+ set nb_info [nbshapes result -t]
+ } else {
+ set nb_info [nbshapes result]
+ }
+}
+
+if { [info exists nb_v_good] } {
+ regexp {VERTEX +: +([-0-9.+eE]+)} $nb_info full nb_v
+ if { ${nb_v} != ${nb_v_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_v_good} vertexes instead of ${nb_v}"
+ } else {
+ puts "Result shape contains ${nb_v} vertexes"
+ }
+}
+
+if { [info exists nb_e_good] } {
+ regexp {EDGE +: +([-0-9.+eE]+)} $nb_info full nb_e
+ if { ${nb_e} != ${nb_e_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_e_good} edges instead of ${nb_e}"
+ } else {
+ puts "Result shape contains ${nb_e} edges"
+ }
+}
+
+if { [info exists nb_w_good] } {
+ regexp {WIRE +: +([-0-9.+eE]+)} $nb_info full nb_w
+ if { ${nb_w} != ${nb_w_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_w_good} wires instead of ${nb_w}"
+ } else {
+ puts "Result shape contains ${nb_w} wires"
+ }
+}
+
+if { [info exists nb_f_good] } {
+ regexp {FACE +: +([-0-9.+eE]+)} $nb_info full nb_f
+ if { ${nb_f} != ${nb_f_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_f_good} faces instead of ${nb_f}"
+ } else {
+ puts "Result shape contains ${nb_f} faces"
+ }
+}
+
+if { [info exists nb_sh_good] } {
+ regexp {SHELL +: +([-0-9.+eE]+)} $nb_info full nb_sh
+ if { ${nb_sh} != ${nb_sh_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_sh_good} shells instead of ${nb_sh}"
+ } else {
+ puts "Result shape contains ${nb_sh} shells"
+ }
+}
+
+if { [info exists nb_sol_good] } {
+ regexp {SOLID +: +([-0-9.+eE]+)} $nb_info full nb_sol
+ if { ${nb_sol} != ${nb_sol_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_sol_good} solids instead of ${nb_sol}"
+ } else {
+ puts "Result shape contains ${nb_sol} solids"
+ }
+}
+
+if { [info exists nb_compsol_good] } {
+ regexp {COMPSOLID +: +([-0-9.+eE]+)} $nb_info full nb_compsol
+ if { ${nb_compsol} != ${nb_compsol_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_compsol_good} compsolids instead of ${nb_compsol}"
+ } else {
+ puts "Result shape contains ${nb_compsol} compsolids"
+ }
+}
+
+if { [info exists nb_compound_good] } {
+ regexp {COMPOUND +: +([-0-9.+eE]+)} $nb_info full nb_compound
+ if { ${nb_compound} != ${nb_compound_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_compound_good} compounds instead of ${nb_compound}"
+ } else {
+ puts "Result shape contains ${nb_compound} compounds"
+ }
+}
+
+if { [info exists nb_shape_good] } {
+ regexp {SHAPE +: +([-0-9.+eE]+)} $nb_info full nb_shape
+ if { ${nb_shape} != ${nb_shape_good} } {
+ puts "Error : Result shape is WRONG because it must contains ${nb_shape_good} shapes instead of ${nb_shape}"
+ } else {
+ puts "Result shape contains ${nb_shape} shapes"
+ }
+}
+
+if { [isdraw result] } {
+ if { [info exists 2dviewer] } {
+ clear
+ smallview
+ donly result
+ fit
+ xwd $imagedir/${test_image}.png
+ }
+ if { [info exists 3dviewer] } {
+ vinit
+ vclear
+ vdisplay result
+ vsetdispmode 1
+ vfit
+ vzfit
+ vdump $imagedir/${test_image}.png
+ }
+}
+
+if { [info exist only_screen] } {
+ vdump $imagedir/${test_image}.png
+}
+
+if { [info exist only_screen_axo] } {
+ xwd $imagedir/${test_image}.png
+}
+
+# to end a test script
+puts "TEST COMPLETED"
--- /dev/null
+001 standard
+
--- /dev/null
+IGNORE /Area of error =/ unfolding information
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 1 part, pitche = 5 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+ puts "${info_result}"
+ set status 0
+ set good_square 49555.4
+ set good_volume 123370
+
+ set good_vertex 6
+ set good_edge 11
+ set good_wire 7
+ set good_face 7
+ set good_shell 1
+ set good_solid 1
+ set good_compsolid 0
+ set good_compound 0
+ set good_shape 33
+}
+
+# Resume
+puts ""
+if { ${mistake} != 0 } {
+ puts "Faulty ${BugNumber}"
+} else {
+ puts "OK ${BugNumber}"
+}
+
+CheckSweep
+
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 1 part, pitche = 20, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+
+set H1 100
+
+set P1 20
+
+set PF1 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+ puts "${info_result}"
+ set status 0
+ set good_square 49555.4
+ set good_volume 123370
+
+ set good_vertex 6
+ set good_edge 11
+ set good_wire 7
+ set good_face 7
+ set good_shell 1
+ set good_solid 1
+ set good_compsolid 0
+ set good_compound 0
+ set good_shape 33
+}
+
+# Resume
+puts ""
+if { ${mistake} != 0 } {
+ puts "Faulty ${BugNumber}"
+} else {
+ puts "OK ${BugNumber}"
+}
+
+CheckSweep
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 2; 6; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 6
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+#set square 59289.3
+#set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 10; 10; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 10
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 59289.3
+set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 2; 60; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 60
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 10; 1; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 1
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 45; 1; 45 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 45
+set P2 1
+set P3 45
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix, D1 = 100, 3 parts, pitches = 1; 10; 1, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 1
+set P2 10
+set P3 1
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, 1 part, pitche = 5 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 100
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 49555.4
+set volume 123370
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, 1 part, pitche = 20, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 100
+
+set H1 100
+
+set P1 20
+
+set PF1 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 49555.4
+set volume 123370
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 2; 6; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 6
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 59289.3
+set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 10; 10; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 10
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 59289.3
+set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 2; 60; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 60
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 10; 1; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 1
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 45; 1; 45 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 45
+set P2 1
+set P3 45
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 1; 10; 1, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 1
+set P2 10
+set P3 1
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 5 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 20 , PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set H1 100
+
+set P1 20
+
+set PF1 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 2; 6; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 6
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 10; 10; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 10
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 2; 60; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 2
+set P2 60
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 10; 1; 10 , PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set P1 10
+set P2 1
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 45; 1; 45 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 45
+set P2 1
+set P3 45
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral, D1 = 100, D2 = 20, 1 part, pitche = 1; 10; 1, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set H1 45
+set H2 10
+set H3 45
+
+set P1 1
+set P2 10
+set P3 1
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D2 = 20, 1 part, pitche = 5 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D2 = 20, 1 part, pitche = 20, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set H1 100
+
+set P1 20
+
+set PF1 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 2; 6; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 2
+set P2 6
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 10; 10; 10, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 10
+set P2 10
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 2; 60; 2 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 2
+set P2 60
+set P3 2
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 10; 1; 10 , PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 20
+set H2 60
+set H3 20
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 10
+set P2 1
+set P3 10
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 45; 1; 45 number of turns, PFi=0
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 45
+set H2 10
+set H3 45
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 45
+set P2 1
+set P3 45
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix, D1 = 100, D4 = 20, 1 part, pitche = 1; 10; 1, PFi=1
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set H1 45
+set H2 10
+set H3 45
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set P1 1
+set P2 10
+set P3 1
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "TODO OCC11111 ALL: Error : CheckSpiral"
+
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# setaxis (0Z)
+#######################################################################
+
+set BugNumber OCCGH648
+
+set x 0
+set y 0
+set z 0
+set Nx 0
+set Ny 0
+set Nz 1
+set Xx 1
+set Xy 0
+set Xz 0
+
+set np 1
+set D1 100
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+setaxis $x $y $z $Nx $Ny $Nz $Xx $Xy $Xz
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set good_Center_X 1.05657e-14
+ set good_Center_Y -1.15567e-15
+ set good_Center_Z 50
+ set good_Moments_IX 4.01968e+06
+ set good_Moments_IY 3.27912e+06
+ set good_Moments_IZ 3.19438e+06
+ CheckSpiral
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 49555.4
+set volume 123370
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "TODO OCC11111 ALL: Error : CheckSpiral"
+
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# setaxis (0Y)
+#######################################################################
+
+set BugNumber OCCGH648
+
+set x 0
+set y 0
+set z 0
+set Nx 0
+set Ny 1
+set Nz 0
+set Xx 1
+set Xy 0
+set Xz 0
+
+set np 1
+set D1 100
+
+set H1 100
+
+set P1 5
+
+set PF1 0
+
+setaxis $x $y $z $Nx $Ny $Nz $Xx $Xy $Xz
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix result ${np} ${D1} ${H1} ${P1} ${PF1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set good_Center_X 1.15868e-14
+ set good_Center_Y 50
+ set good_Center_Z 1.15567e-15
+ set good_Moments_IX 4.01968e+06
+ set good_Moments_IY 3.27912e+06
+ set good_Moments_IZ 3.19438e+06
+ CheckSpiral
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 0
+ set dz 1
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 49555.4
+set volume 123370
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 150
+set D2 123
+
+set N1 .75
+set N2 4.05
+set N3 .75
+
+set P1 13
+set P2 66.89
+set P3 13
+
+set H1 [expr $N1 * $P1]
+set H2 [expr $N2 * $P2]
+set H3 [expr $N3 * $P3]
+
+set PF1 0
+set PF2 0
+set PF3 0
+
+set P1 $N1
+set P2 $N2
+set P3 $N3
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 75587.2
+set volume 188539
+
+set nb_v_good 8
+set nb_e_good 15
+set nb_w_good 9
+set nb_f_good 9
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 43
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 150
+set D2 123
+
+set N1 .75
+set N2 4.05
+set N3 .75
+
+set P1 13
+set P2 66.89
+set P3 13
+
+set H1 [expr $N1 * $P1]
+set H2 [expr $N2 * $P2]
+set H3 [expr $N3 * $P3]
+
+set PF1 1
+set PF2 1
+set PF3 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral result ${np} ${D1} ${D2} ${H1} ${H2} ${H3} ${P1} ${P2} ${P3} ${PF1} ${PF2} ${PF3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 75587.2
+set volume 188539
+
+set nb_v_good 8
+set nb_e_good 15
+set nb_w_good 9
+set nb_f_good 9
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 43
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 5
+set D1 150
+set D2 150
+set D3 150
+set D4 123
+set D5 123
+set D6 123
+
+set N1 .75
+set N2 2.1
+set N3 2.25
+set N4 2.5
+set N5 .75
+
+set P1 13
+set P2 64
+set P3 50
+set P4 45
+set P5 13
+
+set H1 [expr $N1 * $P1]
+set H2 [expr $N2 * $P2]
+set H3 [expr $N3 * $P3]
+set H4 [expr $N4 * $P4]
+set H5 [expr $N5 * $P5]
+
+set PF1 0
+set PF2 0
+set PF3 0
+set PF4 0
+set PF5 0
+
+set P1 $N1
+set P2 $N2
+set P3 $N3
+set P4 $N4
+set P5 $N5
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${D5} ${D6} ${H1} ${H2} ${H3} ${H4} ${H5} ${P1} ${P2} ${P3} ${P4} ${P5} ${PF1} ${PF2} ${PF3} ${PF4} ${PF5}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 112804
+set volume 281562
+
+set nb_v_good 12
+set nb_e_good 23
+set nb_w_good 13
+set nb_f_good 13
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 63
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 5
+set D1 150
+set D2 150
+set D3 150
+set D4 123
+set D5 123
+set D6 123
+
+set N1 .75
+set N2 2.1
+set N3 2.25
+set N4 2.5
+set N5 .75
+
+set P1 13
+set P2 64
+set P3 50
+set P4 45
+set P5 13
+
+set H1 [expr $N1 * $P1]
+set H2 [expr $N2 * $P2]
+set H3 [expr $N3 * $P3]
+set H4 [expr $N4 * $P4]
+set H5 [expr $N5 * $P5]
+
+set PF1 1
+set PF2 1
+set PF3 1
+set PF4 1
+set PF5 1
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix result ${np} ${D1} ${D2} ${D3} ${D4} ${D5} ${D6} ${H1} ${H2} ${H3} ${H4} ${H5} ${P1} ${P2} ${P3} ${P4} ${P5} ${PF1} ${PF2} ${PF3} ${PF4} ${PF5}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 112804
+set volume 281562
+
+set nb_v_good 12
+set nb_e_good 23
+set nb_w_good 13
+set nb_f_good 13
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 63
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 150
+set D2 123
+
+set P1 13
+set P2 66.89
+set P3 13
+
+set N1 .75
+set N2 4.05
+set N3 .75
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral2 result ${np} ${D1} ${D2} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 75587.2
+set volume 188539
+
+set nb_v_good 8
+set nb_e_good 15
+set nb_w_good 9
+set nb_f_good 9
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 43
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+
+set BugNumber OCCGH648
+
+set np 5
+set D1 150
+set D2 150
+set D3 150
+set D4 123
+set D5 123
+set D6 123
+
+set P1 13
+set P2 64
+set P3 50
+set P4 45
+set P5 13
+
+set N1 .75
+set N2 2.1
+set N3 2.25
+set N4 2.5
+set N5 .75
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${D5} ${D6} ${P1} ${P2} ${P3} ${P4} ${P5} ${N1} ${N2} ${N3} ${N4} ${N5}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 112804
+set volume 281562
+
+set nb_v_good 12
+set nb_e_good 23
+set nb_w_good 13
+set nb_f_good 13
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 63
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix2, D1 = 100, 1 part, pitche = 20, number of turns = 5
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+
+set P1 20
+
+set N1 5
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix2 result ${np} ${D1} ${P1} ${N1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+ puts "${info_result}"
+ set status 0
+ set good_square 49555.4
+ set good_volume 123370
+
+ set good_vertex 6
+ set good_edge 11
+ set good_wire 7
+ set good_face 7
+ set good_shell 1
+ set good_solid 1
+ set good_compsolid 0
+ set good_compound 0
+ set good_shape 33
+}
+
+# Resume
+puts ""
+if { ${mistake} != 0 } {
+ puts "Faulty ${BugNumber}"
+} else {
+ puts "OK ${BugNumber}"
+}
+
+CheckSweep
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix2, D1 = 100, 3 parts, pitches = 10; 10; 10, number of turns = 2; 6; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set P1 10
+set P2 10
+set P3 10
+
+set N1 2
+set N2 6
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix2 result ${np} ${D1} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 59289.3
+set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix2, D1 = 100, 3 parts, pitches = 10; 1; 10, number of turns = 2; 60; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set P1 10
+set P2 1
+set P3 10
+
+set N1 2
+set N2 60
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix2 result ${np} ${D1} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: helix2, D1 = 100, 3 parts, pitches = 1; 10; 1, number of turns = 45; 1; 45
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+
+set P1 1
+set P2 10
+set P3 1
+
+set N1 45
+set N2 1
+set N3 45
+
+set mistake 0
+set result ""
+if [catch { set info_result [helix2 result ${np} ${D1} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix2, D1 = 100, D2 = 100, 1 part, pitche = 20, number of turns = 5
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 100
+
+set P1 20
+
+set N1 5
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${P1} ${N1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 49555.4
+set volume 123370
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix2, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 10; 10; 10, number of turns = 2; 6; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set P1 10
+set P2 10
+set P3 10
+
+set N1 2
+set N2 6
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 59289.3
+set volume 88826.3
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix2, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 10; 1; 10, number of turns = 2; 60; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set P1 10
+set P2 1
+set P3 10
+
+set N1 2
+set N2 60
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 12630.4
+set volume 631.356
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# pure cylindrical helix: comphelix2, D1 = 100, D2 = 100, D3 = 100, D4 = 100, 3 parts, pitches = 1; 10; 1, number of turns = 45; 1; 45
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 100
+set D3 100
+set D4 100
+
+set P1 1
+set P2 10
+set P3 1
+
+set N1 45
+set N2 1
+set N3 45
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 17962.9
+set volume 898.136
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral2, D1 = 100, D2 = 20, 1 part, pitche = 20 , number of turns = 5
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set P1 20
+
+set N1 5
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral2 result ${np} ${D1} ${D2} ${P1} ${N1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral2, D1 = 100, D2 = 20, 1 part, pitche = 10; 10; 10, number of turns = 2; 6; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set P1 10
+set P2 10
+set P3 10
+
+set N1 2
+set N2 6
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral2 result ${np} ${D1} ${D2} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral2, D1 = 100, D2 = 20, 1 part, pitche = 10; 1; 10 , number of turns = 2; 60; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set P1 10
+set P2 1
+set P3 10
+
+set N1 2
+set N2 60
+set N3 2
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral2 result ${np} ${D1} ${D2} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: spiral2, D1 = 100, D2 = 20, 1 part, pitche = 1; 10; 1, number of turns = 45; 1; 45
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D2 20
+
+set P1 1
+set P2 10
+set P3 1
+
+set N1 45
+set N2 1
+set N3 45
+
+set mistake 0
+set result ""
+if [catch { set info_result [spiral2 result ${np} ${D1} ${D2} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix2, D1 = 100, D2 = 20, 1 part, pitche = 20, number of turns = 5
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 1
+set D1 100
+set D2 20
+
+set P1 20
+
+set N1 5
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${P1} ${N1}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 5
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 29963
+set volume 74425.8
+
+set nb_v_good 6
+set nb_e_good 11
+set nb_w_good 7
+set nb_f_good 7
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 33
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix2, D1 = 100, D4 = 20, 1 part, pitche = 10; 10; 10, number of turns = 2; 6; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set P1 10
+set P2 10
+set P3 10
+
+set N1 2
+set N2 6
+set N3 2
+
+set H1 [expr $P1*$N1]
+set H2 [expr $P2*$N2]
+set H3 [expr $P3*$N3]
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 3
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 35646.7
+set volume 53369.2
+
+set nb_v_good 11
+set nb_e_good 21
+set nb_w_good 12
+set nb_f_good 12
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 58
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix2, D1 = 100, D4 = 20, 1 part, pitche = 10; 1; 10 , number of turns = 2; 60; 2
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set P1 10
+set P2 1
+set P3 10
+
+set N1 2
+set N2 60
+set N3 2
+
+set H1 [expr $P1*$N1]
+set H2 [expr $P2*$N2]
+set H3 [expr $P3*$N3]
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 7578.93
+set volume 378.83
+
+set nb_v_good 65
+set nb_e_good 129
+set nb_w_good 66
+set nb_f_good 66
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 328
+
+CheckSweep
+}
+set 2dviewer 0
--- /dev/null
+puts "============"
+puts "OCCGH648"
+puts "============"
+puts ""
+#######################################################################
+# spiral helix: comphelix2, D1 = 100, D4 = 20, 1 part, pitche = 1; 10; 1, number of turns = 45; 1; 45
+#######################################################################
+
+set BugNumber OCCGH648
+
+set np 3
+set D1 100
+set D4 20
+
+set P1 1
+set P2 10
+set P3 1
+
+set N1 45
+set N2 1
+set N3 45
+
+set H1 [expr $P1*$N1]
+set H2 [expr $P2*$N2]
+set H3 [expr $P3*$N3]
+
+set D2 [expr ($D1 - ($D1-$D4)*($H1)/($H1+$H2+$H3))]
+set D3 [expr ($D1 - ($D1-$D4)*($H1+$H2)/($H1+$H2+$H3))]
+
+set mistake 0
+set result ""
+if [catch { set info_result [comphelix2 result ${np} ${D1} ${D2} ${D3} ${D4} ${P1} ${P2} ${P3} ${N1} ${N2} ${N3}]} ] {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : approximation algorithm is broken"
+ set mistake 1
+} elseif { [regexp {ErrorStatus} ${info_result}] } {
+ puts "${info_result}"
+ puts "Faulty ${BugNumber} : helix is broken"
+ set mistake 1
+}
+
+if { ${mistake} == 0 } {
+ set d 0.1
+ set x [expr $D1/2]
+ set y 0
+ set z 0
+ set dx 0
+ set dy 1
+ set dz 0
+
+ circle c $x $y $z $dx $dy $dz $d
+ mkedge e c
+ wire s2 e
+
+ renamevar result s1
+
+
+set square 10778.1
+set volume 538.896
+
+set nb_v_good 92
+set nb_e_good 183
+set nb_w_good 93
+set nb_f_good 93
+set nb_sh_good 1
+set nb_sol_good 1
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 463
+
+CheckSweep
+}
+set 2dviewer 0