]> OCCT Git - occt-copy.git/commitdiff
Adding Unfolding and Helix component to OCCT MOTORS13
authorbugmaster <bugmaster@opencascade.com>
Mon, 22 Aug 2016 09:30:12 +0000 (12:30 +0300)
committerbugmaster <bugmaster@opencascade.com>
Mon, 22 Aug 2016 09:30:12 +0000 (12:30 +0300)
72 files changed:
adm/MODULES
adm/UDLIST
adm/cmake/vardescr.cmake
src/DrawResources/DrawPlugin
src/HelixBRep/FILES [new file with mode: 0644]
src/HelixBRep/HelixBRep_BuilderHelix.cxx [new file with mode: 0644]
src/HelixBRep/HelixBRep_BuilderHelix.hxx [new file with mode: 0644]
src/HelixGeom/FILES [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderApproxCurve.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelix.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelix.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixCoil.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixGen.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixGen.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_GHHelixCurve.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_GHHelixCurve_0.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HHelixCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HHelixCurve.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HelixCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HelixCurve.hxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_Tools.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_Tools.hxx [new file with mode: 0644]
src/HelixTest/FILES [new file with mode: 0644]
src/HelixTest/HelixTest.cxx [new file with mode: 0644]
src/HelixTest/HelixTest.hxx [new file with mode: 0644]
src/HelixTest/HelixTest_HelixCommands.cxx [new file with mode: 0644]
src/OS/FILES
src/OS/Helix.tcl [new file with mode: 0644]
src/OS/Modules.tcl
src/OS/Unfolding.tcl [new file with mode: 0644]
src/TKHelix/CMakeLists.txt [new file with mode: 0644]
src/TKHelix/EXTERNLIB [new file with mode: 0644]
src/TKHelix/FILES [new file with mode: 0644]
src/TKHelix/PACKAGES [new file with mode: 0644]
src/TKUnfolding/CMakeLists.txt [new file with mode: 0644]
src/TKUnfolding/EXTERNLIB [new file with mode: 0644]
src/TKUnfolding/FILES [new file with mode: 0644]
src/TKUnfolding/PACKAGES [new file with mode: 0644]
src/TKUnfoldingTest/CMakeLists.txt [new file with mode: 0644]
src/TKUnfoldingTest/EXTERNLIB [new file with mode: 0644]
src/TKUnfoldingTest/FILES [new file with mode: 0644]
src/TKUnfoldingTest/PACKAGES [new file with mode: 0644]
src/Unfolding/FILES [new file with mode: 0644]
src/Unfolding/Unfolding.cxx [new file with mode: 0644]
src/Unfolding/Unfolding.hxx [new file with mode: 0644]
src/Unfolding/Unfolding.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_Array2OfPoint.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_ErrorStatus.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_FunctionWithDerivative.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_FunctionWithDerivative.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_HArray2OfPoint.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_IndexedMapOfFaceDataContainer.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_Point.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Point.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_Point.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.hxx [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.lxx [new file with mode: 0644]
src/UnfoldingTest/FILES [new file with mode: 0644]
src/UnfoldingTest/UnfoldingTest.cxx [new file with mode: 0644]
src/UnfoldingTest/UnfoldingTest.hxx [new file with mode: 0644]

index e2ef48470dafa37682c9a898721cc94b741a67ad..ce5f361bec2d08a883d799cd24e25d83c6bd26a9 100644 (file)
@@ -5,3 +5,5 @@ Visualization TKService TKV3d TKOpenGl TKMeshVS TKIVtk TKD3DHost
 ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd FWOSPlugin TKTObj TKBinTObj TKXmlTObj TKVCAF
 DataExchange TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF
 Draw TKDraw TKTopTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
+Helix TKHelix
+Unfolding TKUnfolding TKUnfoldingTest
\ No newline at end of file
index b6d6b2fb69a63cca1064fecbc98e7472a4425981..7521b76e8e17513b8c2ab465e237cbe5a76fd687 100644 (file)
@@ -440,3 +440,11 @@ n IVtkDraw
 t TKIVtkDraw
 n Geom2dEvaluator
 t TKVCAF
+p HelixBRep
+p HelixGeom
+p HelixTest
+t TKHelix
+p Unfolding
+p UnfoldingTest
+t TKUnfolding
+t TKUnfoldingTest
index 9ffa0bb5e539e2fe3de8758ac08bd1f891fc61a8..30ba3488f1b4a637c3e64f90d25ced352dba1ed3 100644 (file)
@@ -92,7 +92,8 @@ BUILD_MODULE_MESSAGE (BUILD_MODULE_FoundationClasses    "FoundationClasses")
 BUILD_MODULE_MESSAGE (BUILD_MODULE_ModelingAlgorithms   "ModelingAlgorithms")
 BUILD_MODULE_MESSAGE (BUILD_MODULE_ModelingData         "ModelingData")
 BUILD_MODULE_MESSAGE (BUILD_MODULE_Visualization        "Visualization")
-
+BUILD_MODULE_MESSAGE (BUILD_MODULE_Helix "Helix")
+BUILD_MODULE_MESSAGE (BUILD_MODULE_Unfolding "Unfolding")
 
 set (BUILD_ADDITIONAL_TOOLKITS_DESCR
 "Semicolon-separated individual toolkits to include into build process. If you
index dc17bad4dbd09bd2034110c20241077da57c657e..584c73d2e1e16b4d6229f0581b482a0db212c474 100755 (executable)
@@ -37,8 +37,10 @@ DATAEXCHANGEKERNEL : XSDRAW
 OCAF               : VISUALIZATION, OCAFKERNEL
 DATAEXCHANGE       : XDE, VISUALIZATION
 XDE                : DATAEXCHANGEKERNEL, XDEDRAW
+HELIX              : TestHelix
+UNFOLDING          : TestUnfolding
 FULL               : MODELING, OCAFKERNEL, VISUALIZATION 
-ALL                : MODELING, OCAFKERNEL, DATAEXCHANGE
+ALL                : MODELING, OCAFKERNEL, DATAEXCHANGE, HELIX, UNFOLDING
 
 TOPTEST            : TKTopTest
 DCAF               : TKDCAF
@@ -49,3 +51,5 @@ TOBJ               : TKTObjDRAW
 DFBROWSER          : TKDFBrowser
 QAcommands         : TKQADraw
 VIS                : TKIVtkDraw
+TestHelix          : TKHelix
+TestUnfolding      : TKUnfoldingTest
\ No newline at end of file
diff --git a/src/HelixBRep/FILES b/src/HelixBRep/FILES
new file mode 100644 (file)
index 0000000..4059620
--- /dev/null
@@ -0,0 +1,2 @@
+HelixBRep_BuilderHelix.cxx
+HelixBRep_BuilderHelix.hxx
diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.cxx b/src/HelixBRep/HelixBRep_BuilderHelix.cxx
new file mode 100644 (file)
index 0000000..7bb0419
--- /dev/null
@@ -0,0 +1,637 @@
+// File:       HelixBRep_BuilderHelix.cxx
+
+
+#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>
+
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+HelixBRep_BuilderHelix::HelixBRep_BuilderHelix()
+
+{
+  gp_Pnt aP0(0.,0.,0);
+  //
+  myAxis3.SetDirection(gp::DZ());
+  myAxis3.SetLocation(aP0);
+  myDiams = NULL;
+  myHeights = NULL;
+  myPitches = NULL;
+  myIsPitches = NULL;
+  myNParts = 1;
+  myShape.Nullify();
+
+  //
+  myTolerance=0.0001;
+  myContinuity=GeomAbs_C1;
+  myMaxDegree=8;
+  myMaxSegments=1000;
+  //
+  myTolReached=99.;
+  //
+  myErrorStatus = 1;
+  myWarningStatus = 1;
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+HelixBRep_BuilderHelix::~HelixBRep_BuilderHelix()
+{
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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 = NULL;
+  myHeights = NULL;
+  myPitches = NULL;
+  myShape.Nullify();
+
+  myErrorStatus = 1;
+  myWarningStatus = 1;
+
+  if(myNParts != theHeights.Length() || myNParts != thePitches.Length() || myNParts != bIsPitches.Length()) {
+    Standard_ConstructionError::
+      Raise("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;
+  
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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);
+}
+
+//=======================================================================
+//function : SetApproxParameters
+//purpose  : 
+//=======================================================================
+void HelixBRep_BuilderHelix::SetApproxParameters(const Standard_Real aTolerance,
+                                              const Standard_Integer aMaxDegree,
+                                              const GeomAbs_Shape aCont) 
+{
+  myTolerance=aTolerance;
+  myMaxDegree=aMaxDegree;
+  myContinuity=aCont;
+}
+
+//=======================================================================
+//function : ToleranceReached
+//purpose  : 
+//=======================================================================
+Standard_Real HelixBRep_BuilderHelix::ToleranceReached()const
+{
+  return myTolReached;
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+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();
+
+}
+
+//=======================================================================
+//function : BuildPart
+//purpose  : 
+//=======================================================================
+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;
+  //
+  aTolPrec=myTolerance;
+  Standard_Real aTolAng = 1.e-7;
+  //
+
+  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.;
+
+  Standard_Boolean bIsOutWard = Standard_False;
+  if(theTaperAngle > 0.) bIsOutWard = Standard_True;
+  //
+  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;
+
+}
+
+//=======================================================================
+//function : Smoothing
+//purpose  : 
+//=======================================================================
+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();
+    }     
+  }
+
+}
+//=======================================================================
+//function : Smoothing
+//purpose  : 
+//=======================================================================
+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;             
+}  
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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()) {
+    Standard_ConstructionError::
+      Raise("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);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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()) {
+    Standard_ConstructionError::
+      Raise("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);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+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()) {
+    Standard_ConstructionError::
+      Raise("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);
+}
diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.hxx b/src/HelixBRep/HelixBRep_BuilderHelix.hxx
new file mode 100644 (file)
index 0000000..f86ca8d
--- /dev/null
@@ -0,0 +1,133 @@
+// File:       HelixBRep_BuilderHelix.cdl
+
+#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_Ax3;
+class TopoDS_Shape;
+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) < tolerancee
+//! 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
diff --git a/src/HelixGeom/FILES b/src/HelixGeom/FILES
new file mode 100644 (file)
index 0000000..3c9ee87
--- /dev/null
@@ -0,0 +1,16 @@
+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_GHHelixCurve.hxx
+HelixGeom_GHHelixCurve_0.cxx
+HelixGeom_HelixCurve.cxx
+HelixGeom_HelixCurve.hxx
+HelixGeom_HHelixCurve.cxx
+HelixGeom_HHelixCurve.hxx
+HelixGeom_Tools.cxx
+HelixGeom_Tools.hxx
diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx
new file mode 100644 (file)
index 0000000..aa857d7
--- /dev/null
@@ -0,0 +1,102 @@
+// File:       HelixGeom_BuilderApproxCurve.cxx
+
+
+#include <HelixGeom_BuilderApproxCurve.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderApproxCurve::HelixGeom_BuilderApproxCurve()
+{
+  myTolerance=0.0001;
+  myCont=GeomAbs_C2;
+  myMaxDegree=8;
+  myMaxSeg=150;
+  //
+  myTolReached=99.;
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderApproxCurve::~HelixGeom_BuilderApproxCurve()
+{
+}
+//=======================================================================
+//function : SetApproxParameters
+//purpose  : 
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::SetApproxParameters(const GeomAbs_Shape aCont,
+                                                    const Standard_Integer aMaxDegree,
+                                                    const Standard_Integer aMaxSeg)
+{
+  
+  myCont=aCont;
+  myMaxDegree=aMaxDegree;
+  myMaxSeg=aMaxSeg;
+}
+//=======================================================================
+//function : ApproxParameters
+//purpose  : 
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::ApproxParameters(GeomAbs_Shape& aCont,
+                                                 Standard_Integer& aMaxDegree,
+                                                 Standard_Integer& aMaxSeg)const
+{
+  aCont=myCont;
+  aMaxDegree=myMaxDegree;
+  aMaxSeg=myMaxSeg;
+}
+//=======================================================================
+//function : SetTolerance
+//purpose  : 
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::SetTolerance(const Standard_Real aTolerance)
+{
+  myTolerance=aTolerance;
+}
+//=======================================================================
+//function : Tolerance
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_BuilderApproxCurve::Tolerance()const
+{
+  return myTolerance;
+}
+//=======================================================================
+//function : ToleranceReached
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_BuilderApproxCurve::ToleranceReached()const
+{
+  return myTolReached;
+}
+
+//=======================================================================
+//function : Curves
+//purpose  : 
+//=======================================================================
+const TColGeom_SequenceOfCurve&  HelixGeom_BuilderApproxCurve::Curves()const
+{
+  return myCurves;
+}
+
+//=======================================================================   
+//function : ErrorStatus       
+//purpose  :                  
+//======================================================================= 
+Standard_Integer  HelixGeom_BuilderApproxCurve::ErrorStatus()const   
+{                                                    
+  return myErrorStatus;                  
+}      
+                        
+//=======================================================================    
+//function : WarningStatus    
+//purpose  :                 
+//=======================================================================
+Standard_Integer  HelixGeom_BuilderApproxCurve::WarningStatus()const
+{                            
+  return myWarningStatus;     
+}
diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.hxx b/src/HelixGeom/HelixGeom_BuilderApproxCurve.hxx
new file mode 100644 (file)
index 0000000..148d7ae
--- /dev/null
@@ -0,0 +1,86 @@
+// File:       HelixGeom_BuilderApproxCurve.cdl
+
+#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>
+
+//! Root class for algorithm of building helix curves
+class HelixGeom_BuilderApproxCurve 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Sets  aprroximation  parameters
+  Standard_EXPORT void SetApproxParameters (const GeomAbs_Shape aCont, const Standard_Integer aMaxDegree, const Standard_Integer aMaxSeg);
+  
+  //! Gets  aprroximation  parameters
+  Standard_EXPORT void ApproxParameters (GeomAbs_Shape& aCont, Standard_Integer& aMaxDegree, Standard_Integer& aMaxSeg) const;
+  
+  //! Sets  aprroximation  tolerance
+  Standard_EXPORT void SetTolerance (const Standard_Real aTolerance);
+  
+  //! Gets  aprroximation  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  coins.
+  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  aprroximation  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
diff --git a/src/HelixGeom/HelixGeom_BuilderHelix.cxx b/src/HelixGeom/HelixGeom_BuilderHelix.cxx
new file mode 100644 (file)
index 0000000..5230126
--- /dev/null
@@ -0,0 +1,165 @@
+// File:       HelixGeom_BuilderHelix.cxx
+
+
+#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>
+
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelix::HelixGeom_BuilderHelix()
+:
+  HelixGeom_BuilderHelixGen()
+{
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelix::~HelixGeom_BuilderHelix()
+{
+}
+//=======================================================================
+//function : SetPosition
+//purpose  : 
+//=======================================================================
+void HelixGeom_BuilderHelix::SetPosition(const gp_Ax2& aAx2)
+{
+  myPosition=aAx2;
+}
+//=======================================================================
+//function : Position
+//purpose  : 
+//=======================================================================
+const gp_Ax2& HelixGeom_BuilderHelix::Position()const
+{
+  return myPosition;
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void HelixGeom_BuilderHelix::Perform()
+{
+  myErrorStatus=0;
+  myWarningStatus=0;
+  //
+  Standard_Integer iErr, aN, i, aNbC;
+  Standard_Real aTwoPI, dT, aT1x, aT2x, aTR;
+  //HelixGeom_HelixCurve aHC;
+  HelixGeom_BuilderHelixCoil aBHC;
+  //
+  myCurves.Clear();
+  myTolReached=-1.;
+  aTwoPI=2.*M_PI;
+  //
+  aBHC.SetTolerance(myTolerance);
+  aBHC.SetApproxParameters(myCont, myMaxDegree, myMaxSeg);
+  //
+  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 {
+    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) {
+       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;
+       //
+       continue;
+      }
+       
+      aBHC.SetCurveParameters(aT1x, aT2x, 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);
+      aTR=aBHC.ToleranceReached();
+      if(aTR>myTolReached) {
+       myTolReached=aTR;
+      }
+      //
+      aT1x=aT2x;
+      aT2x=aT1x+aTwoPI;
+    } // for (i=1; i<=aN; ++i) {
+    //
+    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;
+      }
+      //
+      const TColGeom_SequenceOfCurve& aSC=aBHC.Curves();
+      const Handle(Geom_Curve)& aC=aSC(1);
+      myCurves.Append(aC);
+      aTR=aBHC.ToleranceReached();
+      if(aTR>myTolReached) {
+       myTolReached=aTR;
+      }
+    }
+  }
+  //
+  // Transformation
+  gp_Trsf aTrsf;
+  gp_Ax3 aAx3, aAx3x(myPosition);
+  //
+  aTrsf.SetDisplacement(aAx3, aAx3x);
+  //
+  aNbC=myCurves.Length();
+  for (i=1; i<=aNbC; ++i) {
+    Handle(Geom_Curve)& aC=myCurves(i);
+    aC->Transform(aTrsf);
+  }
+  //
+}
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelix.hxx b/src/HelixGeom/HelixGeom_BuilderHelix.hxx
new file mode 100644 (file)
index 0000000..9a8f846
--- /dev/null
@@ -0,0 +1,61 @@
+// File:       HelixGeom_BuilderHelix.cdl
+
+#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
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx
new file mode 100644 (file)
index 0000000..954332f
--- /dev/null
@@ -0,0 +1,63 @@
+// File:       HelixGeom_BuilderHelixCoil.cxx
+
+
+#include <Geom_BSplineCurve.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.hxx>
+#include <HelixGeom_Tools.hxx>
+
+//=======================================================================
+//function : HelixGeom_BuilderHelixCoil
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelixCoil::HelixGeom_BuilderHelixCoil()
+:
+  HelixGeom_BuilderHelixGen()
+{
+  myT1=0.;
+  myT2=2.*M_PI;
+  myPitch=1.;
+  myRStart=1.;
+  myTaperAngle=0.;
+  myIsClockWise=Standard_True;
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelixCoil::~HelixGeom_BuilderHelixCoil()
+{
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void  HelixGeom_BuilderHelixCoil::Perform()
+{
+  myErrorStatus=0;
+  myWarningStatus=0;
+  //
+  Standard_Integer iErr;
+  HelixGeom_HelixCurve aAdaptor;
+  Handle(HelixGeom_HHelixCurve) aHAdaptor;
+  Handle(Geom_BSplineCurve)aBC;
+  //
+  myCurves.Clear();
+  //
+  aAdaptor.Load(myT1, myT2, myPitch, myRStart, myTaperAngle, myIsClockWise);
+  aHAdaptor=new HelixGeom_HHelixCurve(aAdaptor);
+  //
+  iErr=HelixGeom_Tools::ApprCurve3D(aHAdaptor, 
+                                 myTolerance, myCont, myMaxSeg, myMaxDegree, 
+                                 aBC, myTolReached);
+  if(iErr) {
+    myErrorStatus=2;
+  }
+  else {
+    myCurves.Append(aBC);
+  }
+}
+
+
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixCoil.hxx b/src/HelixGeom/HelixGeom_BuilderHelixCoil.hxx
new file mode 100644 (file)
index 0000000..1502608
--- /dev/null
@@ -0,0 +1,52 @@
+// File:       HelixGeom_BuilderHelixCoil.cdl
+
+#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
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx b/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx
new file mode 100644 (file)
index 0000000..84f88ee
--- /dev/null
@@ -0,0 +1,59 @@
+// File:       HelixGeom_BuilderHelixGen.cxx
+
+
+#include <HelixGeom_BuilderHelixGen.hxx>
+
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelixGen::HelixGeom_BuilderHelixGen()
+:       
+  HelixGeom_BuilderApproxCurve()
+{
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+HelixGeom_BuilderHelixGen::~HelixGeom_BuilderHelixGen()
+{
+}
+//=======================================================================
+//function : SetCurveParameters
+//purpose  : 
+//=======================================================================
+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)
+{
+  myT1=aT1;
+  myT2=aT2;
+  myPitch=aPitch;
+  myRStart=aRStart;
+  myTaperAngle=aTaperAngle;
+  myIsClockWise=aIsCW;
+}
+//=======================================================================
+//function : CurveParameters
+//purpose  : 
+//=======================================================================
+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;
+}
+
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixGen.hxx b/src/HelixGeom/HelixGeom_BuilderHelixGen.hxx
new file mode 100644 (file)
index 0000000..3696f47
--- /dev/null
@@ -0,0 +1,62 @@
+// File:       HelixGeom_BuilderHelixGen.cdl
+
+#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>
+
+
+//! Root  class  for  algorithms  of  building  helix  curves
+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
diff --git a/src/HelixGeom/HelixGeom_GHHelixCurve.hxx b/src/HelixGeom/HelixGeom_GHHelixCurve.hxx
new file mode 100644 (file)
index 0000000..1e10ebf
--- /dev/null
@@ -0,0 +1,75 @@
+// File:       HelixGeom.cdl
+
+#ifndef _HelixGeom_GHHelixCurve_HeaderFile
+#define _HelixGeom_GHHelixCurve_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Type.hxx>
+
+#include <HelixGeom_HelixCurve.hxx>
+#include <Adaptor3d_HCurve.hxx>
+class Standard_OutOfRange;
+class Standard_NoSuchObject;
+class Standard_DomainError;
+class HelixGeom_HelixCurve;
+class Adaptor3d_Curve;
+
+
+class HelixGeom_GHHelixCurve;
+DEFINE_STANDARD_HANDLE(HelixGeom_GHHelixCurve, Adaptor3d_HCurve)
+
+
+class HelixGeom_GHHelixCurve : public Adaptor3d_HCurve
+{
+
+public:
+
+  
+  Standard_EXPORT HelixGeom_GHHelixCurve();
+  
+  Standard_EXPORT HelixGeom_GHHelixCurve(const HelixGeom_HelixCurve& C);
+  
+  Standard_EXPORT void Set (const HelixGeom_HelixCurve& C);
+  
+  Standard_EXPORT const Adaptor3d_Curve& Curve() const;
+  
+  Standard_EXPORT Adaptor3d_Curve& GetCurve();
+  
+    HelixGeom_HelixCurve& ChangeCurve();
+
+
+
+
+  DEFINE_STANDARD_RTTI_INLINE(HelixGeom_GHHelixCurve,Adaptor3d_HCurve)
+
+protected:
+
+
+  HelixGeom_HelixCurve myCurve;
+
+
+private:
+
+
+
+
+};
+
+#define TheCurve HelixGeom_HelixCurve
+#define TheCurve_hxx <HelixGeom_HelixCurve.hxx>
+#define Adaptor3d_GenHCurve HelixGeom_GHHelixCurve
+#define Adaptor3d_GenHCurve_hxx <HelixGeom_GHHelixCurve.hxx>
+#define Handle_Adaptor3d_GenHCurve Handle(HelixGeom_GHHelixCurve)
+
+#include <Adaptor3d_GenHCurve.lxx>
+
+#undef TheCurve
+#undef TheCurve_hxx
+#undef Adaptor3d_GenHCurve
+#undef Adaptor3d_GenHCurve_hxx
+#undef Handle_Adaptor3d_GenHCurve
+
+
+
+
+#endif // _HelixGeom_GHHelixCurve_HeaderFile
diff --git a/src/HelixGeom/HelixGeom_GHHelixCurve_0.cxx b/src/HelixGeom/HelixGeom_GHHelixCurve_0.cxx
new file mode 100644 (file)
index 0000000..0a589e0
--- /dev/null
@@ -0,0 +1,28 @@
+// File:       HelixGeom.cdl
+
+#include <HelixGeom_GHHelixCurve.hxx>
+
+#include <Standard_Type.hxx>
+
+#include <Standard_OutOfRange.hxx>
+#include <Standard_NoSuchObject.hxx>
+#include <Standard_DomainError.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <Adaptor3d_Curve.hxx>
+
+
+
+
+
+
+
+
+
+#define TheCurve HelixGeom_HelixCurve
+#define TheCurve_hxx <HelixGeom_HelixCurve.hxx>
+#define Adaptor3d_GenHCurve HelixGeom_GHHelixCurve
+#define Adaptor3d_GenHCurve_hxx <HelixGeom_GHHelixCurve.hxx>
+#define Handle_Adaptor3d_GenHCurve Handle(HelixGeom_GHHelixCurve)
+#include <Adaptor3d_GenHCurve.gxx>
+
diff --git a/src/HelixGeom/HelixGeom_HHelixCurve.cxx b/src/HelixGeom/HelixGeom_HHelixCurve.cxx
new file mode 100644 (file)
index 0000000..344f90c
--- /dev/null
@@ -0,0 +1,44 @@
+// File:       HelixGeom_HHelixCurve.cxx
+
+
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.hxx>
+#include <Standard_Type.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(HelixGeom_HHelixCurve,HelixGeom_GHHelixCurve)
+
+//=======================================================================
+//function : HelixGeom_HHelixCurve
+//purpose  : 
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve()
+{
+}
+//=======================================================================
+//function : HelixGeom_HHelixCurve// Lastly modified by :
+// +---------------------------------------------------------------------------+
+// !       ifv ! Creation                                !$Date: 2007-10-19 18:21:42 $! %V%-%L%!
+// +---------------------------------------------------------------------------+
+
+
+//purpose  : 
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve(const HelixGeom_HelixCurve& aC)
+: HelixGeom_GHHelixCurve(aC)
+{
+}
+//=======================================================================
+//function : HelixGeom_HHelixCurve
+//purpose  : 
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve(const Standard_Real aT1,
+                                        const Standard_Real aT2,
+                                        const Standard_Real aPitch,
+                                        const Standard_Real aRStart,
+                                        const Standard_Real aTaperAngle,
+                                        const Standard_Boolean aIsCW)
+{
+  ChangeCurve().Load(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsCW);
+}
+
+
diff --git a/src/HelixGeom/HelixGeom_HHelixCurve.hxx b/src/HelixGeom/HelixGeom_HHelixCurve.hxx
new file mode 100644 (file)
index 0000000..14860fb
--- /dev/null
@@ -0,0 +1,57 @@
+// File:       HelixGeom_HHelixCurve.cdl
+
+#ifndef _HelixGeom_HHelixCurve_HeaderFile
+#define _HelixGeom_HHelixCurve_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Type.hxx>
+
+#include <HelixGeom_GHHelixCurve.hxx>
+#include <Standard_Real.hxx>
+#include <Standard_Boolean.hxx>
+class HelixGeom_HelixCurve;
+
+
+class HelixGeom_HHelixCurve;
+DEFINE_STANDARD_HANDLE(HelixGeom_HHelixCurve, HelixGeom_GHHelixCurve)
+
+//! HAdaptor class for helix  curve
+class HelixGeom_HHelixCurve : public HelixGeom_GHHelixCurve
+{
+
+public:
+
+  
+  //! Empty  constructor
+  Standard_EXPORT HelixGeom_HHelixCurve();
+  
+  //! Constructor by  corresponding  adaptor  curve
+  Standard_EXPORT HelixGeom_HHelixCurve(const HelixGeom_HelixCurve& aC);
+  
+  //! Constructor by parameters
+  Standard_EXPORT HelixGeom_HHelixCurve(const Standard_Real aT1, const Standard_Real aT2, const Standard_Real aPitch, const Standard_Real aRStart, const Standard_Real aTaperAngle, const Standard_Boolean aIsCW);
+
+
+
+
+  DEFINE_STANDARD_RTTIEXT(HelixGeom_HHelixCurve,HelixGeom_GHHelixCurve)
+
+protected:
+
+
+
+
+private:
+
+
+
+
+};
+
+
+
+
+
+
+
+#endif // _HelixGeom_HHelixCurve_HeaderFile
diff --git a/src/HelixGeom/HelixGeom_HelixCurve.cxx b/src/HelixGeom/HelixGeom_HelixCurve.cxx
new file mode 100644 (file)
index 0000000..5583170
--- /dev/null
@@ -0,0 +1,292 @@
+// File:       HelixGeom_HelixCurve.cxx
+
+
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_DomainError.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <TColStd_Array1OfReal.hxx>
+
+#include <math.h>
+//=======================================================================
+//function : HelixGeom_HelixCurve
+//purpose  : 
+//=======================================================================
+HelixGeom_HelixCurve::HelixGeom_HelixCurve()
+{
+  myFirst=0.;
+  myLast=2.*M_PI;
+  myPitch=1.;
+  myRStart=1.;
+  myTaperAngle=0.;
+  myIsClockWise=Standard_True;
+  //
+  myC1=myPitch/myLast;
+  myTgBeta=0.;
+  myTolAngle=1.e-4;
+}
+//=======================================================================
+//function : Load
+//purpose  : 
+//=======================================================================
+void HelixGeom_HelixCurve::Load()
+{
+  Load(myFirst, myLast, myPitch, myRStart, myTaperAngle, myIsClockWise);
+}
+//=======================================================================
+//function : Load
+//purpose  : 
+//=======================================================================
+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;
+  //
+  aTwoPI=2.*M_PI;
+  aHalfPI=0.5*M_PI;
+  //
+  myFirst=aT1;
+  myLast=aT2;
+  myPitch=aPitch;
+  myRStart=aRStart;
+  myTaperAngle=aTaperAngle;
+  myIsClockWise=aIsCW;
+  //
+  if (aT1>=aT2) {
+    Standard_ConstructionError::Raise(buf);
+  }
+  if (myPitch<0.) {
+    Standard_ConstructionError::Raise(buf);
+  }
+  if (myRStart<0.) {
+    Standard_ConstructionError::Raise(buf);
+  }
+  if (myTaperAngle<=-aHalfPI ||
+      myTaperAngle>=aHalfPI) {
+    Standard_ConstructionError::Raise(buf);
+  }
+  //
+  myC1=myPitch/aTwoPI;
+  if (fabs(myTaperAngle)>myTolAngle) {
+    myTgBeta=tan(myTaperAngle);
+  }
+}
+//=======================================================================
+//function : FirstParameter
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::FirstParameter() const
+{
+  return myFirst;
+}
+//=======================================================================
+//function : LastParameter
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::LastParameter() const
+{
+  return myLast;
+}
+//=======================================================================
+//function : Continuity
+//purpose  : 
+//=======================================================================
+GeomAbs_Shape HelixGeom_HelixCurve::Continuity() const 
+{
+  return GeomAbs_CN;
+}
+//=======================================================================
+//function : NbIntervals
+//purpose  : 
+//=======================================================================
+Standard_Integer HelixGeom_HelixCurve::NbIntervals(const GeomAbs_Shape ) const
+{
+  return 1;
+}
+//=======================================================================
+//function : Intervals
+//purpose  : 
+//=======================================================================
+void HelixGeom_HelixCurve::Intervals(TColStd_Array1OfReal& T,
+                                  const GeomAbs_Shape) const
+{
+  T(1)=myFirst;
+  T(2)=myLast;
+}  
+//=======================================================================
+//function : Resolution
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::Resolution(const Standard_Real) const 
+{
+  Standard_NotImplemented::Raise("HelixGeom_HelixCurve::Resolution");
+  return 0.;
+}
+//=======================================================================
+//function : IsClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean HelixGeom_HelixCurve::IsClosed() const 
+{
+  Standard_NotImplemented::Raise("HelixGeom_HelixCurve::IsClosed");
+  return Standard_False;
+}
+//=======================================================================
+//function : IsPeriodic
+//purpose  : 
+//=======================================================================
+Standard_Boolean HelixGeom_HelixCurve::IsPeriodic() const 
+{
+  Standard_NotImplemented::Raise("HelixGeom_HelixCurve::IsPeriodic");
+  return Standard_False;
+}
+//=======================================================================
+//function : Period
+//purpose  : 
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::Period()const
+{
+  Standard_DomainError::Raise("HelixGeom_HelixCurve::Periodic");
+  return 0.;
+}
+//=======================================================================
+//function : Value
+//purpose  : 
+//=======================================================================
+gp_Pnt HelixGeom_HelixCurve::Value(const Standard_Real aT) const 
+{
+  Standard_Real aST, aCT, aX, aY, aZ, a1;
+  //
+  aCT=cos(aT);
+  aST=sin(aT);
+  a1=myRStart+myC1*myTgBeta*aT;
+  //
+  aX=a1*aCT;
+  aY=a1*aST;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=myC1*aT;
+  return gp_Pnt(aX, aY, aZ); 
+}
+//=======================================================================
+//function : D0
+//purpose  : 
+//=======================================================================
+void HelixGeom_HelixCurve::D0(const Standard_Real aT, 
+                           gp_Pnt& aP) const 
+{
+  aP=Value(aT);
+}
+//=======================================================================
+//function : D1
+//purpose  : 
+//=======================================================================
+void HelixGeom_HelixCurve::D1(const Standard_Real aT, 
+                           gp_Pnt& aP, 
+                           gp_Vec& aV1) const 
+{
+  Standard_Real aST, aCT, aX, aY, aZ, a1, a2;
+  //
+  aCT=cos(aT);
+  aST=sin(aT);
+  //
+  a1=myRStart+myC1*myTgBeta*aT;
+  //
+  aX=a1*aCT;
+  aY=a1*aST;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=myC1*aT;
+  aP.SetCoord(aX, aY, aZ);
+  //
+  a1=myC1*myTgBeta;
+  a2=myRStart+a1*aT;
+  //
+  aX=a1*aCT-a2*aST;
+  aY=a1*aST+a2*aCT;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=myC1;
+  aV1.SetCoord(aX, aY, aZ);
+}
+//=======================================================================
+//function : D2
+//purpose  : 
+//=======================================================================
+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;
+  //
+  aCT=cos(aT);
+  aST=sin(aT);
+  //
+  a1=myRStart+myC1*myTgBeta*aT;
+  //
+  aX=a1*aCT;
+  aY=a1*aST;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=myC1*aT;
+  aP.SetCoord(aX, aY, aZ);
+  //
+  a1=myC1*myTgBeta;
+  a2=myRStart+a1*aT;
+  //
+  aX=a1*aCT-a2*aST;
+  aY=a1*aST+a2*aCT;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=myC1;
+  aV1.SetCoord(aX, aY, aZ);
+  //
+  a1=2.*a1;
+  aX=-a2*aCT-a1*aST;
+  aY=-a2*aST-a1*aCT;
+  if (!myIsClockWise) {
+    aY=-aY;
+  }
+  aZ=0.;
+  aV2.SetCoord(aX, aY, aZ);
+}
+
+//=======================================================================
+//function : DN
+//purpose  : 
+//=======================================================================
+gp_Vec HelixGeom_HelixCurve::DN(const Standard_Real aT, 
+                             const Standard_Integer aN) const 
+{
+  gp_Pnt aP;
+  gp_Vec aV1, aV2;
+  //
+  switch (aN) {
+  case 1:
+    D1(aT, aP, aV1);
+    break;
+  case 2:
+    D2(aT, aP, aV1, aV2);
+    break;
+  default:
+    Standard_NotImplemented::Raise("HelixGeom_HelixCurve::DN");
+    break;
+  }
+  return gp_Vec(aV1);
+}
+
+
diff --git a/src/HelixGeom/HelixGeom_HelixCurve.hxx b/src/HelixGeom/HelixGeom_HelixCurve.hxx
new file mode 100644 (file)
index 0000000..836c25c
--- /dev/null
@@ -0,0 +1,117 @@
+// File:       HelixGeom_HelixCurve.cdl
+
+#ifndef _HelixGeom_HelixCurve_HeaderFile
+#define _HelixGeom_HelixCurve_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Real.hxx>
+#include <Standard_Boolean.hxx>
+#include <Adaptor3d_Curve.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <Standard_Integer.hxx>
+class Standard_ConstructionError;
+class Standard_OutOfRange;
+class Standard_DomainError;
+class gp_Pnt;
+class gp_Vec;
+
+
+//! Adaptor  class  for  calculation  helix  curve
+class HelixGeom_HelixCurve  : public Adaptor3d_Curve
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Adaptor  class  for  calculation  helix  curve
+  //! 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
diff --git a/src/HelixGeom/HelixGeom_Tools.cxx b/src/HelixGeom/HelixGeom_Tools.cxx
new file mode 100644 (file)
index 0000000..32a6834
--- /dev/null
@@ -0,0 +1,166 @@
+// File:       HelixGeom_Tools.cxx
+
+
+#include <Adaptor3d_HCurve.hxx>
+#include <AdvApprox_ApproxAFunction.hxx>
+#include <AdvApprox_DichoCutting.hxx>
+#include <AdvApprox_EvaluatorFunction.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.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_HCurve)& 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_HCurve) 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;
+  }
+}
+
+//=======================================================================
+//function : ApprCurve3D
+//purpose  : 
+//=======================================================================
+Standard_Integer HelixGeom_Tools::ApprCurve3D(Handle(Adaptor3d_HCurve)& 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;
+  //
+  Num1DSS=0; 
+  Num2DSS=0; 
+  Num3DSS=1;
+  ThreeDTol  = new TColStd_HArray1OfReal(1,Num3DSS);
+  ThreeDTol->Init(theTol); 
+  //
+  First = theHC->FirstParameter();
+  Last  = theHC->LastParameter();
+  //
+  HelixGeom_Tools_Eval ev (theHC);
+  AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS, 
+                                    OneDTolNul, TwoDTolNul, ThreeDTol,
+                                    First, Last, theCont,
+                                    theMaxDeg, theMaxSeg,
+                                    ev, aCutTool);
+  //
+  anIsDone = aApprox.IsDone();
+  if(!anIsDone) {
+    return 1;
+  }
+  //
+  theMaxError = 0.;
+  //
+  aHasResult = aApprox.HasResult();
+  if (!aHasResult) {
+    return 2;
+  }
+  //
+  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 0;
+}
+//=======================================================================
+//function : ApprHelix
+//purpose  : 
+//=======================================================================
+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_HHelixCurve) aHAdaptor;
+  //
+  aAdaptor.Load(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsCW);
+  aHAdaptor=new HelixGeom_HHelixCurve(aAdaptor);
+  //
+  aCont=GeomAbs_C2;
+  aMaxDegree = 8;
+  aMaxSeg=150;
+  //
+  iErr=HelixGeom_Tools::ApprCurve3D(aHAdaptor, 
+                                 theTol, aCont, aMaxSeg, aMaxDegree, 
+                                 theBSpl, theMaxError);
+  return iErr;
+}
+
diff --git a/src/HelixGeom/HelixGeom_Tools.hxx b/src/HelixGeom/HelixGeom_Tools.hxx
new file mode 100644 (file)
index 0000000..3af1585
--- /dev/null
@@ -0,0 +1,55 @@
+// File:       HelixGeom_Tools.cdl
+
+#ifndef _HelixGeom_Tools_HeaderFile
+#define _HelixGeom_Tools_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Integer.hxx>
+#include <Standard_Real.hxx>
+#include <Standard_Boolean.hxx>
+#include <GeomAbs_Shape.hxx>
+class Geom_BSplineCurve;
+class Adaptor3d_HCurve;
+
+
+//! Approximation  algorithms  for  bulding  helix  curves
+class HelixGeom_Tools 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Bulding  helix  curves
+  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);
+  
+  //! Reaprroximation  of  adaptor  curve
+  Standard_EXPORT static Standard_Integer ApprCurve3D (Handle(Adaptor3d_HCurve)& theHC, const Standard_Real theTol, const GeomAbs_Shape theCont, const Standard_Integer theMaxSeg, const Standard_Integer theMaxDeg, Handle(Geom_BSplineCurve)& theBSpl, Standard_Real& theMaxError);
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+
+};
+
+
+
+
+
+
+
+#endif // _HelixGeom_Tools_HeaderFile
diff --git a/src/HelixTest/FILES b/src/HelixTest/FILES
new file mode 100644 (file)
index 0000000..80ec4f0
--- /dev/null
@@ -0,0 +1,3 @@
+HelixTest.cxx
+HelixTest.hxx
+HelixTest_HelixCommands.cxx
diff --git a/src/HelixTest/HelixTest.cxx b/src/HelixTest/HelixTest.cxx
new file mode 100644 (file)
index 0000000..593677d
--- /dev/null
@@ -0,0 +1,36 @@
+// File:       HelixTest.cxx
+
+
+#include <HelixTest.hxx>
+
+#include <stdio.h>
+//=======================================================================
+//function : AllCommands
+//purpose  : 
+//=======================================================================
+  void HelixTest::AllCommands(Draw_Interpretor& theCommands)
+{
+  static Standard_Boolean done = Standard_False;
+  if (done) return;
+  done = Standard_True;
+  //
+  HelixTest::HelixCommands (theCommands);
+}
+//=======================================================================
+//function : Factory
+//purpose  : 
+//=======================================================================
+  void HelixTest::Factory(Draw_Interpretor& theCommands)
+{
+  static Standard_Boolean FactoryDone = Standard_False;
+  if (FactoryDone) return;
+
+  FactoryDone = Standard_True;
+
+  HelixTest::AllCommands(theCommands);
+  Printf(" Helix Plugin is loaded\n");
+}
+#include <Draw_PluginMacro.hxx>
+DPLUGIN(HelixTest)
+
+
diff --git a/src/HelixTest/HelixTest.hxx b/src/HelixTest/HelixTest.hxx
new file mode 100644 (file)
index 0000000..9aeceb2
--- /dev/null
@@ -0,0 +1,50 @@
+// File:       HelixTest.cdl
+
+#ifndef _HelixTest_HeaderFile
+#define _HelixTest_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Draw_Interpretor.hxx>
+
+
+
+class HelixTest 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  Standard_EXPORT static void AllCommands (Draw_Interpretor& aDI);
+  
+  Standard_EXPORT static void HelixCommands (Draw_Interpretor& aDI);
+  
+  Standard_EXPORT static void Factory (Draw_Interpretor& aDI);
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+
+};
+
+
+
+
+
+
+
+#endif // _HelixTest_HeaderFile
diff --git a/src/HelixTest/HelixTest_HelixCommands.cxx b/src/HelixTest/HelixTest_HelixCommands.cxx
new file mode 100644 (file)
index 0000000..b007013
--- /dev/null
@@ -0,0 +1,555 @@
+// File:       HelixTest_HelixCommands.cxx
+
+
+#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 <GeomAdaptor_HCurve.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 <HelixTest.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>
+
+//
+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 ** );
+//=======================================================================
+//function : HelixTest::HelixCommands
+//purpose  : 
+//=======================================================================
+  void HelixTest::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);
+}
+
+//=======================================================================
+//function : setaxis
+//purpose  : 
+//=======================================================================
+ 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;
+}
+//
+//=======================================================================
+//function : comphelix
+//purpose  : 
+//=======================================================================
+ 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]);
+    ++ic;
+  }
+  //
+
+  aBH.SetParameters(theHelixAxis, aDiams, aHeights, aPitches, bIsPitches);
+
+  aBH.Perform();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+    
+  return 0;
+}
+
+//=======================================================================
+//function : helix
+//purpose  : 
+//=======================================================================
+ 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;
+  for(i = 1; i <= 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]);
+    ++ic;
+  }
+  //
+
+  aBH.SetParameters(theHelixAxis, aDiams(1), aHeights, aPitches, bIsPitches);
+
+  aBH.Perform();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+    
+  return 0;
+}
+
+//=======================================================================
+//function : spiral
+//purpose  : 
+//=======================================================================
+ 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]);
+    ++ic;
+  }
+  //
+
+  aBH.SetParameters(theHelixAxis, aDiams(1), aDiams(2), aHeights, aPitches, bIsPitches);
+
+  aBH.Perform();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : comphelix2
+//purpose  : 
+//=======================================================================
+ 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();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+    
+  return 0;
+}
+
+//=======================================================================
+//function : helix2
+//purpose  : 
+//=======================================================================
+ 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;
+  for(i = 1; i <= 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(1), aPitches, aNbTurns);
+
+  aBH.Perform();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+    
+  return 0;
+}
+
+//=======================================================================
+//function : spiral2
+//purpose  : 
+//=======================================================================
+ 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();
+
+  if(aBH.ErrorStatus() == 0) {
+    Standard_Real aMaxError=aBH.ToleranceReached();
+    di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+    di << "ToleranceReached = " << aMaxError <<"\n";
+  //
+    const TopoDS_Shape& aW=aBH.Shape();
+    DBRep::Set(a[1], aW);
+  }
+  else {
+    di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+  }
+
+  return 0;
+}
index 5c94c2bb0addc9c751a4e3fd749ae0fc57e853e6..0c709d4839ff9776a3587f2cae9c46bb61acc9b4 100755 (executable)
@@ -6,3 +6,5 @@ srcinc:::ModelingAlgorithms.tcl
 srcinc:::ModelingData.tcl
 srcinc:::Modules.tcl
 srcinc:::Visualization.tcl
+srcinc:::Unfolding.tcl
+srcinc:::Helix.tcl
\ No newline at end of file
diff --git a/src/OS/Helix.tcl b/src/OS/Helix.tcl
new file mode 100644 (file)
index 0000000..2a48257
--- /dev/null
@@ -0,0 +1,36 @@
+# Definitions for a product: Helix
+
+# List of toolkits 
+proc Helix:toolkits { } {
+    return [list TKHelix]
+}
+
+# List of non-toolkits (resource units, executables etc., with associated info)
+proc Helix:ressources { } {
+    return {}
+}
+
+# Product name 
+proc Helix:name { } {
+    return Helix
+}
+
+# And short alias
+proc Helix:alias { } {
+    return Helix
+}
+
+# Dependency on other products
+proc Helix:depends { } {
+    return {}
+}
+
+proc Helix:CompileWith { } {
+}
+
+proc Helix:LinksoWith { } {
+}
+
+proc Helix:Export { } {
+    return [list source runtime wokadm api]
+}
index 2ca889cc09e4d5a542005c9b5ee6b66992f14135..3e1ef542cdeca943c31cd39f602b2360b31a58af 100644 (file)
@@ -22,6 +22,8 @@ proc OS:Modules { {plat ""} } {
           ApplicationFramework \
           DataExchange \
           Draw \
+          Helix \
+          Unfolding \
           ]
     return $ret
 }
diff --git a/src/OS/Unfolding.tcl b/src/OS/Unfolding.tcl
new file mode 100644 (file)
index 0000000..41ef7ee
--- /dev/null
@@ -0,0 +1,36 @@
+# Definitions for a product: Unfolding
+
+# List of toolkits 
+proc Unfolding:toolkits { } {
+    return [list TKUnfolding TKUnfoldingTest]
+}
+
+# List of non-toolkits (resource units, executables etc., with associated info)
+proc Unfolding:ressources { } {
+    return {}
+}
+
+# Product name 
+proc Unfolding:name { } {
+    return Unfolding
+}
+
+# And short alias
+proc Unfolding:alias { } {
+    return Unfolding
+}
+
+# Dependency on other products
+proc Unfolding:depends { } {
+    return {}
+}
+
+proc Unfolding:CompileWith { } {
+}
+
+proc Unfolding:LinksoWith { } {
+}
+
+proc Unfolding:Export { } {
+    return [list source runtime wokadm api]
+}
diff --git a/src/TKHelix/CMakeLists.txt b/src/TKHelix/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5e76118
--- /dev/null
@@ -0,0 +1,3 @@
+project(TKHelix)
+
+OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)
diff --git a/src/TKHelix/EXTERNLIB b/src/TKHelix/EXTERNLIB
new file mode 100644 (file)
index 0000000..f48ab6c
--- /dev/null
@@ -0,0 +1,7 @@
+TKBRep
+TKMath
+TKernel
+TKG2d
+TKG3d
+TKDraw
+TKTopAlgo
diff --git a/src/TKHelix/FILES b/src/TKHelix/FILES
new file mode 100644 (file)
index 0000000..ee6f705
--- /dev/null
@@ -0,0 +1 @@
+EXTERNLIB
diff --git a/src/TKHelix/PACKAGES b/src/TKHelix/PACKAGES
new file mode 100644 (file)
index 0000000..2be7474
--- /dev/null
@@ -0,0 +1,3 @@
+HelixGeom
+HelixBRep
+HelixTest
diff --git a/src/TKUnfolding/CMakeLists.txt b/src/TKUnfolding/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e77e2f4
--- /dev/null
@@ -0,0 +1,3 @@
+project(TKUnfolding)
+
+OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)
diff --git a/src/TKUnfolding/EXTERNLIB b/src/TKUnfolding/EXTERNLIB
new file mode 100644 (file)
index 0000000..aede3a7
--- /dev/null
@@ -0,0 +1,10 @@
+TKBRep
+TKMath
+TKernel
+TKG2d
+TKG3d
+TKDraw
+TKTopAlgo
+TKGeomAlgo
+TKShHealing
+TKGeomBase
diff --git a/src/TKUnfolding/FILES b/src/TKUnfolding/FILES
new file mode 100644 (file)
index 0000000..ee6f705
--- /dev/null
@@ -0,0 +1 @@
+EXTERNLIB
diff --git a/src/TKUnfolding/PACKAGES b/src/TKUnfolding/PACKAGES
new file mode 100644 (file)
index 0000000..66fa871
--- /dev/null
@@ -0,0 +1 @@
+Unfolding
diff --git a/src/TKUnfoldingTest/CMakeLists.txt b/src/TKUnfoldingTest/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d09b497
--- /dev/null
@@ -0,0 +1,3 @@
+project(TKUnfoldingTest)
+
+OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit)
diff --git a/src/TKUnfoldingTest/EXTERNLIB b/src/TKUnfoldingTest/EXTERNLIB
new file mode 100644 (file)
index 0000000..683e029
--- /dev/null
@@ -0,0 +1,6 @@
+TKBRep
+TKMath
+TKernel
+TKG3d
+TKDraw
+TKUnfolding
\ No newline at end of file
diff --git a/src/TKUnfoldingTest/FILES b/src/TKUnfoldingTest/FILES
new file mode 100644 (file)
index 0000000..ee6f705
--- /dev/null
@@ -0,0 +1 @@
+EXTERNLIB
diff --git a/src/TKUnfoldingTest/PACKAGES b/src/TKUnfoldingTest/PACKAGES
new file mode 100644 (file)
index 0000000..1626bec
--- /dev/null
@@ -0,0 +1 @@
+UnfoldingTest
diff --git a/src/Unfolding/FILES b/src/Unfolding/FILES
new file mode 100644 (file)
index 0000000..1c5f8c9
--- /dev/null
@@ -0,0 +1,24 @@
+Unfolding.cxx
+Unfolding.hxx
+Unfolding.lxx
+Unfolding_Array2OfPoint.hxx
+Unfolding_ErrorStatus.hxx
+Unfolding_FaceDataContainer.cxx
+Unfolding_FaceDataContainer.hxx
+Unfolding_FaceDataContainer.lxx
+Unfolding_FaceDataMapHasher.cxx
+Unfolding_FaceDataMapHasher.hxx
+Unfolding_FaceDataMapHasher.lxx
+Unfolding_FunctionWithDerivative.cxx
+Unfolding_FunctionWithDerivative.hxx
+Unfolding_HArray2OfPoint.hxx
+Unfolding_IndexedMapOfFaceDataContainer.hxx
+Unfolding_Point.cxx
+Unfolding_Point.hxx
+Unfolding_Point.lxx
+Unfolding_Shell.cxx
+Unfolding_Shell.hxx
+Unfolding_Shell.lxx
+Unfolding_Surface.cxx
+Unfolding_Surface.hxx
+Unfolding_Surface.lxx
diff --git a/src/Unfolding/Unfolding.cxx b/src/Unfolding/Unfolding.cxx
new file mode 100644 (file)
index 0000000..2e036d7
--- /dev/null
@@ -0,0 +1,162 @@
+// File:       Unfolding.cxx
+// Created:    Wed Sep 17 09:16:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+
+
+#include <Unfolding.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+#include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2d_BezierCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+
+//=======================================================================
+//function : ToShell
+//purpose  : 
+//=======================================================================
+
+TopoDS_Shell Unfolding::ToShell(const TopoDS_Shape          &theShape,
+                               const Standard_Real          theTolerance,
+                                     Unfolding_ErrorStatus &theStatus)
+{
+  TopoDS_Shell     aShell;
+  TopAbs_ShapeEnum aType = theShape.ShapeType();
+
+  if (aType != TopAbs_COMPOUND && aType != TopAbs_COMPSOLID &&
+      aType != TopAbs_SOLID    && aType != TopAbs_SHELL) {
+    theStatus = Unfolding_InvalidInput;
+    return aShell;
+  }
+
+  if (aType == TopAbs_SHELL) {
+    // theShape is a shell. Nothing to be done.
+    theStatus = Unfolding_Done;
+    aShell    = TopoDS::Shell(theShape);
+    return aShell;
+  }
+
+  BRepBuilderAPI_Sewing aSewing(theTolerance);
+
+  aSewing.Add(theShape);
+  aSewing.Perform();
+
+  const TopoDS_Shape &aShape = aSewing.SewedShape();
+
+  if (aShape.IsNull()) {
+    theStatus = Unfolding_Failure;
+    return aShell;
+  }
+
+  // Explore shape to extract a shell.
+  TopExp_Explorer anExp(aShape, TopAbs_SHELL);
+
+  if (!anExp.More()) {
+    theStatus = Unfolding_InvalidShape;
+    return aShell;
+  }
+
+  TopoDS_Shape aSingleShell = anExp.Current();
+
+  anExp.Next();
+
+  if (anExp.More()) {
+    theStatus = Unfolding_ComplexShape;
+    return aShell;
+  }
+
+  // Check if there is no other redundant shapes that are not in the shell.
+  anExp.Init(aShape, TopAbs_VERTEX, TopAbs_SHELL);
+
+  if (anExp.More()) {
+    theStatus = Unfolding_ComplexShape;
+    return aShell;
+  }
+
+  // Get the single shell.
+  theStatus = Unfolding_Done;
+  aShell    = TopoDS::Shell(aSingleShell);
+
+  return aShell;
+}
+
+//=======================================================================
+//function : ToShell
+//purpose  : 
+//=======================================================================
+
+Standard_Integer Unfolding::NbSamples(const TopoDS_Edge          &theEdge,
+                                     const TopTools_ListOfShape &theFaces,
+                                     const Standard_Real         theTolerance)
+{
+  Standard_Integer aNbPointsLimit = Unfolding::GetMaxNbSamples() / 2;
+  Standard_Integer aMaxNbPoints = 11;
+  Standard_Integer aNbPoints;
+  TopTools_ListIteratorOfListOfShape anIt( theFaces );
+
+  for ( ; anIt.More(); anIt.Next() ) {
+    TopoDS_Shape aCurShape = anIt.Value();
+    TopoDS_Face aFace = TopoDS::Face( aCurShape );
+    aFace.Orientation(TopAbs_FORWARD);
+
+    Standard_Integer aNbPnt = 2;
+    Standard_Real         aParam[2];
+    Handle(Geom2d_Curve)  aCurve = 
+      BRep_Tool::CurveOnSurface(theEdge, aFace, aParam[0], aParam[1]);
+    Handle(Standard_Type) aType  = aCurve->DynamicType();
+
+    while (aType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
+      Handle(Geom2d_TrimmedCurve) aTrCurve =
+       Handle(Geom2d_TrimmedCurve)::DownCast(aCurve);
+      aCurve = aTrCurve->BasisCurve();
+      aType  = aCurve->DynamicType();
+    }
+    
+    if        (aType == STANDARD_TYPE(Geom2d_BezierCurve)) {
+      Handle(Geom2d_BezierCurve) aBezier =
+       Handle(Geom2d_BezierCurve)::DownCast(aCurve);
+      aNbPnt = 3 + aBezier->NbPoles();
+
+
+      if (aNbPnt < 11)
+       aNbPnt = 11;
+    } else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
+      Handle(Geom2d_BSplineCurve) aBSpline =
+       Handle(Geom2d_BSplineCurve)::DownCast(aCurve);
+      aNbPnt  = aBSpline->NbKnots()*aBSpline->Degree();
+      
+      if (aNbPnt < 11)
+       aNbPnt = 11;
+    } else {
+      aNbPnt = 11;
+    }
+    aMaxNbPoints = ( aMaxNbPoints < aNbPnt ) ? aNbPnt : aMaxNbPoints;
+
+    Geom2dAdaptor_Curve aCurve1(aCurve);
+    Standard_Real L = GCPnts_AbscissaPoint::Length(aCurve1, aParam[0], aParam[1]) ;
+    // estimate number of points taking into account the curvature of radius myTolContour * 2.
+    Standard_Real sizeR = 0.125 * L / theTolerance + 2; 
+
+    if ( aNbPointsLimit > sizeR )
+      aNbPointsLimit = (Standard_Integer) sizeR;
+  }
+
+  // Check if the number of points exceeds the maximum number of points.
+
+  if(aMaxNbPoints > aNbPointsLimit)
+    aMaxNbPoints = aNbPointsLimit;
+
+  aNbPoints = aMaxNbPoints;
+
+  return aNbPoints;
+}
diff --git a/src/Unfolding/Unfolding.hxx b/src/Unfolding/Unfolding.hxx
new file mode 100644 (file)
index 0000000..5f2d5d6
--- /dev/null
@@ -0,0 +1,92 @@
+// File:       Unfolding.cdl
+// Created:    Tue Jul 22 12:48:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef _Unfolding_HeaderFile
+#define _Unfolding_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Real.hxx>
+#include <Unfolding_ErrorStatus.hxx>
+#include <Standard_Integer.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+class TopoDS_Shell;
+class TopoDS_Shape;
+class TopoDS_Edge;
+class Unfolding_Surface;
+class Unfolding_Point;
+class Unfolding_FunctionWithDerivative;
+class Unfolding_Shell;
+class Unfolding_FaceDataContainer;
+class Unfolding_FaceDataMapHasher;
+
+
+//! This package contains a tool for unfolding a surface on a plane.
+class Unfolding 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! This method converts theShape to a shell. It sewes faces of the
+  //! shell if it is necessary and possible with the given tolerance.
+  //! If it is not possible to construct a single shell from theShape,
+  //! this method returns null shell and the corresponding error
+  //! status. The status can have the following values:
+  //! -  Unfolding_Done: the operation succeeded
+  //! -  Unfolding_InvalidInput: input shape type is less then
+  //! TopAbs_SHELL.
+  //! -  Unfolding_Failure: sewing failure.
+  //! -  Unfolding_InvalidShape: the shape after sewing does not
+  //! contain shells.
+  //! -  Unfolding_ComplexShape: the shape after sewing contains
+  //! either more then one shell or one shell and other not
+  //! connected shapes.
+  Standard_EXPORT static TopoDS_Shell ToShell (const TopoDS_Shape& theShape, const Standard_Real theTolerance, Unfolding_ErrorStatus& theStatus);
+  
+  //! This method returns the number of sample points for theEdge.
+  //! theFaces is a list of faces that contain theEdge.
+  //! This method returns the maximal number of points for sampling of
+  //! edges and/or faces.
+    static Standard_Integer NbSamples (const TopoDS_Edge& theEdge, const TopTools_ListOfShape& theFaces, const Standard_Real theTolerance);
+  
+  Standard_EXPORT static Standard_Integer GetMaxNbSamples();
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+friend class Unfolding_Surface;
+friend class Unfolding_Point;
+friend class Unfolding_FunctionWithDerivative;
+friend class Unfolding_Shell;
+friend class Unfolding_FaceDataContainer;
+friend class Unfolding_FaceDataMapHasher;
+
+};
+
+
+#include <Unfolding.lxx>
+
+
+
+
+
+#endif // _Unfolding_HeaderFile
diff --git a/src/Unfolding/Unfolding.lxx b/src/Unfolding/Unfolding.lxx
new file mode 100644 (file)
index 0000000..9116d7b
--- /dev/null
@@ -0,0 +1,12 @@
+// File:       Unfolding.lxx
+// Created:    Tue Jul 22 13:12:24 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+inline Standard_Integer Unfolding::GetMaxNbSamples()
+{
+  static Standard_Integer aMaxNbSamples = 1000;
+
+  return aMaxNbSamples;
+}
diff --git a/src/Unfolding/Unfolding_Array2OfPoint.hxx b/src/Unfolding/Unfolding_Array2OfPoint.hxx
new file mode 100644 (file)
index 0000000..a6187b3
--- /dev/null
@@ -0,0 +1,16 @@
+// File:       Unfolding.cdl
+// Created:    Tue Jul 22 12:48:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef Unfolding_Array2OfPoint_HeaderFile
+#define Unfolding_Array2OfPoint_HeaderFile
+
+#include <Unfolding_Point.hxx>
+#include <NCollection_Array2.hxx>
+
+typedef NCollection_Array2<Unfolding_Point> Unfolding_Array2OfPoint;
+
+
+#endif
diff --git a/src/Unfolding/Unfolding_ErrorStatus.hxx b/src/Unfolding/Unfolding_ErrorStatus.hxx
new file mode 100644 (file)
index 0000000..b3d4420
--- /dev/null
@@ -0,0 +1,22 @@
+// File:       Unfolding.cdl
+// Created:    Tue Jul 22 12:48:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef _Unfolding_ErrorStatus_HeaderFile
+#define _Unfolding_ErrorStatus_HeaderFile
+
+
+enum Unfolding_ErrorStatus
+{
+Unfolding_Done,
+Unfolding_NotDone,
+Unfolding_Failure,
+Unfolding_InvalidSurface,
+Unfolding_InvalidInput,
+Unfolding_InvalidShape,
+Unfolding_ComplexShape
+};
+
+#endif // _Unfolding_ErrorStatus_HeaderFile
diff --git a/src/Unfolding/Unfolding_FaceDataContainer.cxx b/src/Unfolding/Unfolding_FaceDataContainer.cxx
new file mode 100644 (file)
index 0000000..bb1873d
--- /dev/null
@@ -0,0 +1,116 @@
+// File:       Unfolding_FaceDataContainer.cxx
+// Created:    Tue Jul 22 13:12:24 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <BRepBuilderAPI_Transform.hxx>
+#include <gp_Trsf.hxx>
+#include <Standard_Type.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <Unfolding_FaceDataContainer.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Unfolding_FaceDataContainer,MMgt_TShared)
+
+//=======================================================================
+//function : SetFace
+//purpose  : 
+//=======================================================================
+void Unfolding_FaceDataContainer::SetFace(const TopoDS_Face &theFace)
+{
+  Standard_Boolean isSame = theFace.IsSame(myFace);
+  myFace = theFace;
+
+  if (!isSame) {
+    // Update the map myEdgeMap
+    myEdgeMap.Clear();
+
+    TopExp_Explorer      anExp(myFace, TopAbs_EDGE);
+    TopTools_ListOfShape anEmptyList;
+
+    for (; anExp.More(); anExp.Next()) {
+      const TopoDS_Shape &anEdge = anExp.Current();
+
+      myEdgeMap.Bind(anEdge, anEmptyList);
+    }
+  }
+}
+
+//=======================================================================
+//function : ApplyTrsf
+//purpose  : 
+//=======================================================================
+
+void Unfolding_FaceDataContainer::ApplyTrsf(const gp_Trsf &theTrsf)
+{
+  BRepBuilderAPI_Transform aTrsf(theTrsf);
+
+  if (!myUnfoldedFace.IsNull()) {
+    aTrsf.Perform(myUnfoldedFace);
+
+    if (aTrsf.IsDone())
+      myUnfoldedFace = TopoDS::Face(aTrsf.Shape());
+  }
+
+  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape anEdgeIter(myEdgeMap);
+  TopTools_ListIteratorOfListOfShape                  aUEIter;
+
+  for (; anEdgeIter.More(); anEdgeIter.Next()) {
+    const TopoDS_Shape   &anEdge  = anEdgeIter.Key();
+    TopTools_ListOfShape &anEdges = myEdgeMap.ChangeFind(anEdge);
+    TopTools_ListOfShape  aTrsfEdges;
+
+    for (aUEIter.Initialize(anEdges); aUEIter.More(); aUEIter.Next()) {
+      const TopoDS_Shape &aUEdge = aUEIter.Value();
+
+      aTrsf.Perform(aUEdge);
+
+      if (aTrsf.IsDone())
+       aTrsfEdges.Append(aTrsf.Shape());
+    }
+
+    anEdges.Clear();
+    anEdges.Append(aTrsfEdges);
+  }
+}
+
+//=======================================================================
+//function : SetEdgesForEdge
+//purpose  : 
+//=======================================================================
+
+void Unfolding_FaceDataContainer::SetEdgesForEdge
+                             (const TopoDS_Edge          &theEdge,
+                             const TopTools_ListOfShape &theUnfoldedEdges)
+{
+  if (myEdgeMap.IsBound(theEdge)) {
+    TopTools_ListOfShape &anEdges = myEdgeMap.ChangeFind(theEdge);
+
+    anEdges = theUnfoldedEdges;
+  }
+}
+
+//=======================================================================
+//function : GetEdgesForEdge
+//purpose  : 
+//=======================================================================
+
+const TopTools_ListOfShape &Unfolding_FaceDataContainer::GetEdgesForEdge
+                                          (const TopoDS_Edge &theEdge) const
+{
+  if (myEdgeMap.IsBound(theEdge)) {
+    const TopTools_ListOfShape &anEdges = myEdgeMap.Find(theEdge);
+
+    return anEdges;
+  }
+
+  static TopTools_ListOfShape anEmptyList;
+
+  return anEmptyList;
+}
diff --git a/src/Unfolding/Unfolding_FaceDataContainer.hxx b/src/Unfolding/Unfolding_FaceDataContainer.hxx
new file mode 100644 (file)
index 0000000..40a9fd2
--- /dev/null
@@ -0,0 +1,101 @@
+// File:       Unfolding_FaceDataContainer.cdl
+// Created:    Fri Sep 19 16:52:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+//-Copyright:   Matra Datavision 2008
+
+#ifndef _Unfolding_FaceDataContainer_HeaderFile
+#define _Unfolding_FaceDataContainer_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Type.hxx>
+
+#include <TopoDS_Face.hxx>
+#include <TopTools_DataMapOfShapeListOfShape.hxx>
+#include <Standard_Real.hxx>
+#include <MMgt_TShared.hxx>
+
+class TopoDS_Face;
+class gp_Trsf;
+class TopoDS_Edge;
+class Unfolding_FaceDataContainer;
+
+DEFINE_STANDARD_HANDLE(Unfolding_FaceDataContainer, MMgt_TShared)
+
+//! This class represents a data container for data constructed
+//! during unfolding operation.
+class Unfolding_FaceDataContainer : public MMgt_TShared
+{
+
+public:
+
+  
+  //! Empty constructor
+  Standard_EXPORT Unfolding_FaceDataContainer();
+  
+  //! Sets the original face.
+  Standard_EXPORT void SetFace (const TopoDS_Face& theFace);
+  
+  //! Returns the original face.
+    const TopoDS_Face& GetFace() const;
+  
+  //! Sets the unfolded face for the original one.
+    void SetUnfoldedFace (const TopoDS_Face& theUnfoldedFace);
+  
+  //! Returns the unfolded face for the original one.
+    const TopoDS_Face& GetUnfoldedFace() const;
+  
+  //! Sets the distortion area.
+    void SetDistortionArea (const Standard_Real theDistortionArea);
+  
+  //! Returns the distortion area.
+    Standard_Real GetDistortionArea() const;
+  
+  //! Sets the maximal Gauss curvature.
+    void SetMaxGaussCurvature (const Standard_Real theCurvature);
+  
+  //! Returns the maximal Gauss curvature.
+    Standard_Real GetMaxGaussCurvature() const;
+  
+  //! Resets the data container.
+    void Reset();
+  
+  //! Applies the transformation to all unfolded shapes.
+  Standard_EXPORT void ApplyTrsf (const gp_Trsf& theTrsf);
+  
+  //! Associates unfolded edges with the source edge.
+  Standard_EXPORT void SetEdgesForEdge (const TopoDS_Edge& theEdge, const TopTools_ListOfShape& theUnfoldedEdges);
+  
+  //! Returns unfolded edges associated to the source edge.
+  Standard_EXPORT const TopTools_ListOfShape& GetEdgesForEdge (const TopoDS_Edge& theEdge) const;
+
+
+
+
+  DEFINE_STANDARD_RTTIEXT(Unfolding_FaceDataContainer,MMgt_TShared)
+
+protected:
+
+
+
+
+private:
+
+
+  TopoDS_Face myFace;
+  TopoDS_Face myUnfoldedFace;
+  TopTools_DataMapOfShapeListOfShape myEdgeMap;
+  Standard_Real myDistortionArea;
+  Standard_Real myCurvature;
+
+
+};
+
+
+#include <Unfolding_FaceDataContainer.lxx>
+
+
+
+
+
+#endif // _Unfolding_FaceDataContainer_HeaderFile
diff --git a/src/Unfolding/Unfolding_FaceDataContainer.lxx b/src/Unfolding/Unfolding_FaceDataContainer.lxx
new file mode 100644 (file)
index 0000000..86f7702
--- /dev/null
@@ -0,0 +1,101 @@
+// File:       Unfolding_FaceDataContainer.lxx
+// Created:    Tue Jul 22 13:12:24 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+//=======================================================================
+//function : Empty constructor
+//purpose  : 
+//=======================================================================
+
+inline Unfolding_FaceDataContainer::Unfolding_FaceDataContainer()
+     : myDistortionArea(0.),
+       myCurvature(0.)
+{
+}
+
+//=======================================================================
+//function : GetFace
+//purpose  : 
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_FaceDataContainer::GetFace() const
+{
+  return myFace;
+}
+
+//=======================================================================
+//function : SetUnfoldedFace
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetUnfoldedFace
+                                      (const TopoDS_Face &theUnfoldedFace)
+{
+  myUnfoldedFace = theUnfoldedFace;
+}
+
+//=======================================================================
+//function : GetUnfoldedFace
+//purpose  : 
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_FaceDataContainer::GetUnfoldedFace() const
+{
+  return myUnfoldedFace;
+}
+
+//=======================================================================
+//function : SetDistortionArea
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetDistortionArea
+                                     (const Standard_Real theDistortionArea)
+{
+  myDistortionArea = theDistortionArea;
+}
+
+//=======================================================================
+//function : GetDistortionArea
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_FaceDataContainer::GetDistortionArea() const
+{
+  return myDistortionArea;
+}
+
+//=======================================================================
+//function : SetMaxGaussCurvature
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetMaxGaussCurvature
+                                            (const Standard_Real theCurvature)
+{
+  myCurvature = theCurvature;
+}
+
+//=======================================================================
+//function : GetMaxGaussCurvature
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_FaceDataContainer::GetMaxGaussCurvature() const
+{
+  return myCurvature;
+}
+
+//=======================================================================
+//function : Reset
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::Reset()
+{
+  myUnfoldedFace.Nullify();
+  myDistortionArea = 0.;
+  myCurvature      = 0.;
+}
diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.cxx b/src/Unfolding/Unfolding_FaceDataMapHasher.cxx
new file mode 100644 (file)
index 0000000..693e3ee
--- /dev/null
@@ -0,0 +1,8 @@
+// File:       Unfolding_FaceDataMapHasher.cxx
+// Created:    Mon Sep 22 09:01:04 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+
+
+#include <Unfolding_FaceDataContainer.hxx>
+#include <Unfolding_FaceDataMapHasher.hxx>
diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.hxx b/src/Unfolding/Unfolding_FaceDataMapHasher.hxx
new file mode 100644 (file)
index 0000000..1aa1be2
--- /dev/null
@@ -0,0 +1,60 @@
+// File:       Unfolding_FaceDataMapHasher.cdl
+// Created:    Fri Sep 19 16:52:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+//-Copyright:   Matra Datavision 2008
+
+#ifndef _Unfolding_FaceDataMapHasher_HeaderFile
+#define _Unfolding_FaceDataMapHasher_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_Integer.hxx>
+#include <Standard_Boolean.hxx>
+class Unfolding_FaceDataContainer;
+
+
+//! Hash tool, used for generating maps of face data containers.
+class Unfolding_FaceDataMapHasher 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Returns a HasCode value  for  the  Key <K>  in the
+  //! range 0..theUpper.
+    static Standard_Integer HashCode (const Handle(Unfolding_FaceDataContainer)& theKey, const Standard_Integer theUpper);
+  
+  //! Returns True  when the two  keys are the same. Two
+  //! same  keys  must   have  the  same  hashcode,  the
+  //! contrary is not necessary.
+    static Standard_Boolean IsEqual (const Handle(Unfolding_FaceDataContainer)& theKey1, const Handle(Unfolding_FaceDataContainer)& theKey2);
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+
+};
+
+
+#include <Unfolding_FaceDataMapHasher.lxx>
+
+
+
+
+
+#endif // _Unfolding_FaceDataMapHasher_HeaderFile
diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.lxx b/src/Unfolding/Unfolding_FaceDataMapHasher.lxx
new file mode 100644 (file)
index 0000000..fd132b7
--- /dev/null
@@ -0,0 +1,30 @@
+// File:       Unfolding_FaceDataMapHasher.lxx
+// Created:    Mon Sep 22 08:54:51 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+
+
+//=======================================================================
+//function : HashCode
+//purpose  : 
+//=======================================================================
+
+inline Standard_Integer Unfolding_FaceDataMapHasher::HashCode
+                (const Handle(Unfolding_FaceDataContainer) &theKey,
+                const Standard_Integer                     theUpper)
+{
+  return (theKey.IsNull()) ? 0 : theKey->GetFace().HashCode(theUpper);
+}
+
+//=======================================================================
+//function : IsEqual
+//purpose  : 
+//=======================================================================
+
+inline Standard_Boolean Unfolding_FaceDataMapHasher::IsEqual
+                          (const Handle(Unfolding_FaceDataContainer) &theKey1,
+                          const Handle(Unfolding_FaceDataContainer) &theKey2)
+{
+  return !theKey1.IsNull() && !theKey2.IsNull() &&
+          theKey1->GetFace().IsSame(theKey2->GetFace());
+}
diff --git a/src/Unfolding/Unfolding_FunctionWithDerivative.cxx b/src/Unfolding/Unfolding_FunctionWithDerivative.cxx
new file mode 100644 (file)
index 0000000..4935d91
--- /dev/null
@@ -0,0 +1,249 @@
+// File:       Unfolding_FunctionWithDerivative.cxx
+// Created:    Fri Sep  5 17:51:58 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+
+
+#include <gp_Dir2d.hxx>
+#include <gp_Trsf2d.hxx>
+#include <TColgp_Array1OfXY.hxx>
+#include <Unfolding_FunctionWithDerivative.hxx>
+
+static Standard_Boolean ComputeArea(const TColgp_Array1OfXY& theMasterPolyLine,
+                                   const TColgp_Array1OfXY& theSlavePolyLine,
+                                   const gp_Dir2d&            theShiftDir,
+                                   const Standard_Real&     theShift,
+                                   const gp_Trsf2d          theTrsf,
+                                   Standard_Real&           theArea);
+
+
+static Standard_Boolean ComputeAreaDeriv(const TColgp_Array1OfXY& theMasterPolyLine,
+                                        const TColgp_Array1OfXY& theSlavePolyLine,
+                                        const gp_Dir2d&          theShiftDir,
+                                        const Standard_Real&     theShift,
+                                        const gp_Trsf2d          theTrsf,
+                                        Standard_Real&           theArea,
+                                        Standard_Real&           theDeriv);
+
+
+//=============================================================================
+// function: Constructor
+//=============================================================================
+Unfolding_FunctionWithDerivative::Unfolding_FunctionWithDerivative(const TColgp_Array1OfXY& theMaster,
+                                                                  const TColgp_Array1OfXY& theSlave,
+                                                                  const gp_Dir2d& theDir,
+                                                                  const gp_Trsf2d& theTrsf):
+myMasterPolyLine(theMaster.Lower(), theMaster.Upper()),
+mySlavePolyLine(theSlave.Lower(), theSlave.Upper())
+{
+ myMasterPolyLine.Assign(theMaster);
+ mySlavePolyLine.Assign(theSlave);
+ myTrsf = theTrsf;
+ myShiftDir = theDir;
+ myShift = 0.;
+ myArea = 0.;
+}
+
+
+//=============================================================================
+// function: Value
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Value(const Standard_Real X,Standard_Real& F) 
+{
+  myShift = X;
+  F = 0.;
+  Standard_Real A = 0.;
+  Standard_Real D = 0.;
+  if ( !ComputeAreaDeriv(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift, myTrsf, A, D) )
+    return Standard_False;
+
+  myArea = A;
+
+  gp_XY aP1P2(0, A);
+  gp_XY vecD(1,D);
+  Standard_Real modD = vecD.Modulus();
+  if ( modD < gp::Resolution() ) {
+    Standard_Real delta = 1.e-7;
+    if ( !ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift - delta, myTrsf, A) )
+      return Standard_False;
+    gp_XY P1(0,A);
+    if ( !ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift + delta, myTrsf, A) )
+      return Standard_False;
+    gp_XY P2(0,A);
+    gp_XY V = P2-P1;
+    modD = V.Modulus();
+    if ( modD < gp::Resolution() )
+      return Standard_False;
+  }
+  F = aP1P2 * vecD;
+  F /= modD;
+
+  return Standard_True;
+}
+
+//=============================================================================
+// function: Derivative
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Derivative(const Standard_Real X,Standard_Real& D) 
+{
+  Standard_Real F = 0.;
+  return Values(X,F,D);
+}
+
+//=============================================================================
+// function: Values
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Values(const Standard_Real X,Standard_Real& F,Standard_Real& D) 
+{
+  Standard_Real F1 = 0., F2 = 0.;
+  Standard_Real aDelta = 1.e-05;
+  if ( fabs(X) > aDelta )
+    aDelta = fabs(X) * aDelta;
+  if ( !Value(X + aDelta, F2) )
+    return Standard_False;
+
+  if ( !Value(X, F1) )
+    return Standard_False;
+
+  myShift = X;
+  F = F1;
+  D = F2 - F1;
+  D /= aDelta;
+
+  return Standard_True;
+}
+
+//=============================================================================
+// function: GetStateNumber
+//=============================================================================
+Standard_Integer Unfolding_FunctionWithDerivative::GetStateNumber() 
+{
+  ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift, myTrsf, myArea);
+  return 0;
+}
+
+//=============================================================================
+// function: Area
+//=============================================================================
+Standard_Real Unfolding_FunctionWithDerivative::Area() const
+{
+  return myArea;
+}
+
+//-----------------------------------------------------------------------------
+// function: ComputeAreaDeriv
+//-----------------------------------------------------------------------------
+static Standard_Boolean ComputeAreaDeriv(const TColgp_Array1OfXY& theMasterPolyLine,
+                                        const TColgp_Array1OfXY& theSlavePolyLine,
+                                        const gp_Dir2d&          theShiftDir,
+                                        const Standard_Real&     theShift,
+                                        const gp_Trsf2d          theTrsf,
+                                        Standard_Real&           theArea,
+                                        Standard_Real&           theDeriv)
+{
+  theArea = 0.;
+  theDeriv = 0.;
+  Standard_Real X = theShift;
+  Standard_Real F1 = 0., F2 = 0.;
+  if ( !ComputeArea(theMasterPolyLine, theSlavePolyLine, theShiftDir, X, theTrsf, F1) )
+    return Standard_False;
+  theArea = F1;
+  Standard_Real aDelta = 1.e-05;
+  if ( fabs(X) > aDelta )
+    aDelta = fabs(X) * aDelta;
+  if ( !ComputeArea(theMasterPolyLine, theSlavePolyLine, theShiftDir, X + aDelta, theTrsf, F2) )
+    return Standard_False;
+
+  theDeriv = F2 - F1;
+  theDeriv /= aDelta;
+  return Standard_True;
+}
+
+//-----------------------------------------------------------------------------
+// function: ComputeArea
+//-----------------------------------------------------------------------------
+static Standard_Boolean ComputeArea(const TColgp_Array1OfXY& theMasterPolyLine,
+                                   const TColgp_Array1OfXY& theSlavePolyLine,
+                                   const gp_Dir2d&            theShiftDir,
+                                   const Standard_Real&     theShift,
+                                   const gp_Trsf2d          theTrsf,
+                                   Standard_Real&           theArea)
+{
+  if ( ( theMasterPolyLine.Length() < 2 ) || ( theSlavePolyLine.Length() < 2 ) ||
+      ( theSlavePolyLine.Length() != theMasterPolyLine.Length() ) )
+    return Standard_False;
+  theArea = 0.;
+
+  gp_Vec2d aTranslation( theShiftDir.XY() * theShift );
+
+  gp_Trsf2d aTransTrsf;
+  aTransTrsf.SetTranslation( aTranslation );
+  gp_Trsf2d aTrans;
+  aTrans = aTransTrsf * theTrsf;
+
+  //
+  TColgp_Array1OfXY aTransformedSlave(theSlavePolyLine.Lower(), theSlavePolyLine.Upper());
+  Standard_Integer i = 0;
+  for ( i = aTransformedSlave.Lower(); i <= aTransformedSlave.Upper(); i++ ) {
+    gp_Pnt2d aP( theSlavePolyLine.Value( i ) );
+    aP.Transform( aTrans );
+    aTransformedSlave.SetValue( i, aP.XY() );
+  }
+  //
+
+  // compute area
+  // This method assumes that the polylines shape is similar
+  // if the shape is completely different, the compute area will be wrong.
+  // But it will grow, that can be considered as a condition of distortion.
+  // So, the method can be acceptable.
+  gp_XY aFirstPoint = aTransformedSlave( aTransformedSlave.Lower() );
+  aFirstPoint += theMasterPolyLine( theMasterPolyLine.Lower() );
+  aFirstPoint *= 0.5;
+
+  gp_XY aLastPoint = aTransformedSlave( aTransformedSlave.Upper() );
+  aLastPoint += theMasterPolyLine( theMasterPolyLine.Upper() );
+  aLastPoint *= 0.5;
+  Standard_Integer nIndexDif = theMasterPolyLine.Lower() - aTransformedSlave.Lower();
+
+  gp_XY aP1 = aFirstPoint;
+  gp_XY aP3 = aFirstPoint;
+
+  for ( i = theMasterPolyLine.Lower() + 1; i <= theMasterPolyLine.Upper(); i++ ) {
+    gp_XY aP2 = theMasterPolyLine(i);
+    gp_XY aP4 = aTransformedSlave(i-nIndexDif);
+    if ( i == theMasterPolyLine.Upper() ) {
+      aP2 = aLastPoint;
+      aP4 = aLastPoint;
+    }
+    gp_XY aP1P4 = aP4 - aP1;
+    gp_XY aP1P2 = aP2 - aP1;
+    gp_XY aP1P3 = aP3 - aP1;
+    Standard_Real aprod1 = aP1P4 ^ aP1P3;
+    Standard_Real aprod2 = aP1P4 ^ aP1P2;
+    if ( aprod1 * aprod2 <= 0. ) {
+      theArea += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+    }
+    else {
+      gp_XY aP3P2 = aP2 - aP3;
+      gp_XY aP3P4 = aP4 - aP3;
+      gp_XY aP3P1 = -aP1P3;
+
+      Standard_Real asum = 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+      aprod1 = aP3P2 ^ aP3P4;
+      aprod2 = aP3P2 ^ aP3P1;
+      if ( aprod1 * aprod2 <= 0. ) {
+       theArea += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+      }
+      else {
+       asum += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+       asum *= 0.5;
+       theArea += asum;
+      }
+    }
+
+    aP1 = aP2;
+    aP3 = aP4;
+  }
+
+  return Standard_True;
+}
diff --git a/src/Unfolding/Unfolding_FunctionWithDerivative.hxx b/src/Unfolding/Unfolding_FunctionWithDerivative.hxx
new file mode 100644 (file)
index 0000000..2264f5b
--- /dev/null
@@ -0,0 +1,87 @@
+// File:       Unfolding_FunctionWithDerivative.cdl
+// Created:    Fri Sep  5 17:44:29 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef _Unfolding_FunctionWithDerivative_HeaderFile
+#define _Unfolding_FunctionWithDerivative_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <TColgp_Array1OfXY.hxx>
+#include <gp_Trsf2d.hxx>
+#include <gp_Dir2d.hxx>
+#include <Standard_Real.hxx>
+#include <math_FunctionWithDerivative.hxx>
+#include <Standard_Boolean.hxx>
+#include <Standard_Integer.hxx>
+#include <TColgp_Array1OfXY.hxx>
+
+class gp_Dir2d;
+class gp_Trsf2d;
+
+
+
+class Unfolding_FunctionWithDerivative  : public math_FunctionWithDerivative
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  Standard_EXPORT Unfolding_FunctionWithDerivative(const TColgp_Array1OfXY& theMaster, const TColgp_Array1OfXY& theSlave, const gp_Dir2d& theDir, const gp_Trsf2d& theTrsf);
+  
+  //! Computes the value <F>of the function for the variable <X>.
+  //! Returns True if the calculation were successfully done,
+  //! False otherwise.
+  Standard_EXPORT virtual Standard_Boolean Value (const Standard_Real X, Standard_Real& F) Standard_OVERRIDE;
+  
+  //! Computes the derivative <D> of the function
+  //! for the variable <X>.
+  //! Returns True if the calculation were successfully done,
+  //! False otherwise.
+  Standard_EXPORT virtual Standard_Boolean Derivative (const Standard_Real X, Standard_Real& D) Standard_OVERRIDE;
+  
+  //! Computes the value <F> and the derivative <D> of the
+  //! function for the variable <X>.
+  //! Returns True if the calculation were successfully done,
+  //! False otherwise.
+  Standard_EXPORT virtual Standard_Boolean Values (const Standard_Real X, Standard_Real& F, Standard_Real& D) Standard_OVERRIDE;
+  
+  Standard_EXPORT virtual Standard_Integer GetStateNumber() Standard_OVERRIDE;
+  
+  Standard_EXPORT Standard_Real Area() const;
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+  TColgp_Array1OfXY myMasterPolyLine;
+  TColgp_Array1OfXY mySlavePolyLine;
+  gp_Trsf2d myTrsf;
+  gp_Dir2d myShiftDir;
+  Standard_Real myShift;
+  Standard_Real myArea;
+
+
+};
+
+
+
+
+
+
+
+#endif // _Unfolding_FunctionWithDerivative_HeaderFile
diff --git a/src/Unfolding/Unfolding_HArray2OfPoint.hxx b/src/Unfolding/Unfolding_HArray2OfPoint.hxx
new file mode 100644 (file)
index 0000000..7d132dc
--- /dev/null
@@ -0,0 +1,17 @@
+// File:       Unfolding.cdl
+// Created:    Tue Jul 22 12:48:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef Unfolding_HArray2OfPoint_HeaderFile
+#define Unfolding_HArray2OfPoint_HeaderFile
+
+#include <Unfolding_Point.hxx>
+#include <Unfolding_Array2OfPoint.hxx>
+#include <NCollection_DefineHArray2.hxx>
+
+DEFINE_HARRAY2(Unfolding_HArray2OfPoint, Unfolding_Array2OfPoint)
+
+
+#endif
diff --git a/src/Unfolding/Unfolding_IndexedMapOfFaceDataContainer.hxx b/src/Unfolding/Unfolding_IndexedMapOfFaceDataContainer.hxx
new file mode 100644 (file)
index 0000000..c011b20
--- /dev/null
@@ -0,0 +1,17 @@
+// File:       Unfolding.cdl
+// Created:    Tue Jul 22 12:48:05 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef Unfolding_IndexedMapOfFaceDataContainer_HeaderFile
+#define Unfolding_IndexedMapOfFaceDataContainer_HeaderFile
+
+#include <Unfolding_FaceDataContainer.hxx>
+#include <Unfolding_FaceDataMapHasher.hxx>
+#include <NCollection_IndexedMap.hxx>
+
+typedef NCollection_IndexedMap<Handle(Unfolding_FaceDataContainer),Unfolding_FaceDataMapHasher> Unfolding_IndexedMapOfFaceDataContainer;
+
+
+#endif
diff --git a/src/Unfolding/Unfolding_Point.cxx b/src/Unfolding/Unfolding_Point.cxx
new file mode 100644 (file)
index 0000000..d5f0873
--- /dev/null
@@ -0,0 +1,8 @@
+// File:       Unfolding_Point.cxx
+// Created:    Mon Jul 28 15:27:34 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <Unfolding_Point.hxx>
+
diff --git a/src/Unfolding/Unfolding_Point.hxx b/src/Unfolding/Unfolding_Point.hxx
new file mode 100644 (file)
index 0000000..662d05b
--- /dev/null
@@ -0,0 +1,92 @@
+// File:       Unfolding_Point.cdl
+// Created:    Mon Jul 28 14:56:12 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:   Matra Datavision 2008
+
+#ifndef _Unfolding_Point_HeaderFile
+#define _Unfolding_Point_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <gp_XY.hxx>
+#include <gp_XYZ.hxx>
+#include <Standard_Real.hxx>
+class gp_XYZ;
+class gp_XY;
+
+
+//! This class represents a data container for a point. It contains
+//! a point  on a  surface, its  U and V  parameters on  a surface,
+//! corresponding point on an unfolding plane.
+class Unfolding_Point 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Empty constructor.
+  Standard_EXPORT Unfolding_Point();
+  
+  //! Sets the point on a surface.
+    void SetPointOnSurface (const gp_XYZ& thePOnSurface);
+  
+  //! Returns the point on a surface.
+    const gp_XYZ& GetPointOnSurface() const;
+  
+  //! Sets the U and V parameters of the point on a surface.
+    void SetParameters (const Standard_Real theU, const Standard_Real theV);
+  
+  //! Returns the U and V parameters of the point on a surface.
+    void GetParameters (Standard_Real& theU, Standard_Real& theV) const;
+  
+  //! Returns the U parameter of the point on a surface.
+    Standard_Real GetU() const;
+  
+  //! Returns the V parameter of the point on a surface.
+    Standard_Real GetV() const;
+  
+  //! Sets the angle between DU and DV directions.
+    void SetAngle (const Standard_Real theAngle);
+  
+  //! Returns the angle between DU and DV directions.
+    Standard_Real GetAngle() const;
+  
+  //! Sets the point on an unfolding plane.
+    void SetPointOnPlane (const gp_XY& thePOnPlane);
+  
+  //! Returns the point on an unfolding plane.
+    const gp_XY& GetPointOnPlane() const;
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+  gp_XY myPoint2d;
+  gp_XYZ myPOnSurface;
+  gp_XY myPOnPlane;
+  Standard_Real myAngle;
+
+
+};
+
+
+#include <Unfolding_Point.lxx>
+
+
+
+
+
+#endif // _Unfolding_Point_HeaderFile
diff --git a/src/Unfolding/Unfolding_Point.lxx b/src/Unfolding/Unfolding_Point.lxx
new file mode 100644 (file)
index 0000000..566b2a0
--- /dev/null
@@ -0,0 +1,116 @@
+// File:       Unfolding_Point.lxx
+// Created:    Mon Jul 28 15:18:15 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+//=======================================================================
+//function : Empty constructor
+//purpose  : 
+//=======================================================================
+
+inline Unfolding_Point::Unfolding_Point()
+     : myAngle(-1.)
+{
+}
+
+//=======================================================================
+//function : SetPointOnSurface
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Point::SetPointOnSurface(const gp_XYZ &thePOnSurface)
+{
+  myPOnSurface = thePOnSurface;
+}
+//=======================================================================
+//function : GetPointOnSurface
+//purpose  : 
+//=======================================================================
+
+inline const gp_XYZ &Unfolding_Point::GetPointOnSurface() const
+{
+  return myPOnSurface;
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Point::SetParameters(const Standard_Real theU,
+                                          const Standard_Real theV)
+{
+  myPoint2d.SetCoord(theU, theV);
+}
+
+//=======================================================================
+//function : GetParameters
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Point::GetParameters(Standard_Real &theU,
+                                          Standard_Real &theV) const
+{
+  myPoint2d.Coord(theU, theV);
+}
+
+//=======================================================================
+//function : GetU
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetU() const
+{
+  return myPoint2d.X();
+}
+
+//=======================================================================
+//function : GetV
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetV() const
+{
+  return myPoint2d.Y();
+}
+
+//=======================================================================
+//function : GetAngle
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Point::SetAngle(const Standard_Real theAngle)
+{
+  myAngle = theAngle;
+}
+
+//=======================================================================
+//function : GetAngle
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetAngle() const
+{
+  return myAngle;
+}
+
+//=======================================================================
+//function : SetPointOnPlane
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Point::SetPointOnPlane(const gp_XY &thePOnPlane)
+{
+  myPOnPlane = thePOnPlane;
+}
+
+//=======================================================================
+//function : GetPointOnPlane
+//purpose  : 
+//=======================================================================
+
+inline const gp_XY &Unfolding_Point::GetPointOnPlane() const
+{
+  return myPOnPlane;
+}
diff --git a/src/Unfolding/Unfolding_Shell.cxx b/src/Unfolding/Unfolding_Shell.cxx
new file mode 100644 (file)
index 0000000..cdc6d5a
--- /dev/null
@@ -0,0 +1,781 @@
+// File:       Unfolding_Shell.cxx
+// Created:    Tue Sep  9 17:14:33 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <Geom_Plane.hxx>
+#include <gp_Pln.hxx>
+#include <math_FunctionRoot.hxx>
+#include <math_NewtonFunctionRoot.hxx>
+#include <ShapeAnalysis_FreeBoundData.hxx>
+#include <ShapeAnalysis_FreeBoundsProperties.hxx>
+#include <TColgp_Array1OfXY.hxx>
+#include <TColgp_HArray1OfXY.hxx>
+#include <TColgp_SequenceOfXY.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <Unfolding.hxx>
+#include <Unfolding_FaceDataContainer.hxx>
+#include <Unfolding_FunctionWithDerivative.hxx>
+#include <Unfolding_Shell.hxx>
+#include <Unfolding_Surface.hxx>
+
+static Standard_Boolean CombineCurves(const TColgp_Array1OfXY& theMasterPolyLine,
+                                     const TColgp_Array1OfXY& theSlavePolyLine,
+                                     const Standard_Boolean   IsFixed,
+                                     const Standard_Real      theConfTolerance, 
+                                     const Standard_Real      theAreaTolerance, 
+                                     gp_Trsf2d&               theTransformation,
+                                     Standard_Real&           theDistortionArea);
+
+// ==============================================================================
+// function: GetCommonEdges
+// purpose : This function returns the list of common edges of two faces.
+// ==============================================================================
+static void GetCommonEdges(const TopoDS_Face          &theFace1,
+                          const TopoDS_Face          &theFace2,
+                                TopTools_ListOfShape &theCommonEdges)
+{
+  TopTools_IndexedMapOfShape aMapEdges1;
+  TopExp_Explorer            anExp2(theFace2, TopAbs_EDGE);
+
+  TopExp::MapShapes(theFace1, TopAbs_EDGE, aMapEdges1);
+  theCommonEdges.Clear();
+
+  for (; anExp2.More(); anExp2.Next()) {
+    const TopoDS_Shape &anEdge2 = anExp2.Current();
+
+    if (aMapEdges1.Contains(anEdge2))
+      theCommonEdges.Append(anEdge2);
+  }
+}
+
+// ==============================================================================
+// function: GetWires
+// purpose : This function returns a list of wires edges composed from theEdges.
+// ==============================================================================
+static Standard_Boolean GetWires(const TopTools_ListOfShape &theEdges,
+                                      TopTools_ListOfShape &theWires)
+{
+  TopTools_ListIteratorOfListOfShape anEdgeIter(theEdges);
+  TopTools_DataMapOfShapeListOfShape aMapVE;
+  TopExp_Explorer                    anExp;
+  TopTools_MapOfShape                aMapUsed;
+
+  for (; anEdgeIter.More(); anEdgeIter.Next()) {
+    const TopoDS_Shape &anEdge = anEdgeIter.Value();
+
+    if (!aMapUsed.Add(anEdge) || BRep_Tool::Degenerated(TopoDS::Edge(anEdge)))
+      continue;
+
+    for (anExp.Init(anEdge, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
+      const TopoDS_Shape &aVertex = anExp.Current();
+
+      if (!aMapVE.IsBound(aVertex)) {
+       TopTools_ListOfShape aList;
+       aMapVE.Bind(aVertex, aList);
+      }
+
+      TopTools_ListOfShape &aListAncEdges = aMapVE.ChangeFind(aVertex);
+
+      aListAncEdges.Append(anEdge);
+    }
+  }
+
+  // Construct wires as chains of edges.
+  Standard_Boolean isToTreat = Standard_True;
+  TopoDS_Vertex    aFirstVtx;
+  TopoDS_Edge      aCurEdge;
+  TopoDS_Vertex    aV[2];
+  BRep_Builder     aBuilder;
+
+  for(;;) {
+    isToTreat = Standard_False;
+
+    // Get the bounding vertex, i.e. the vertex that contains only one edge in
+    // the list of ancestors.
+    TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aMapIter(aMapVE);
+
+    for (; aMapIter.More(); aMapIter.Next()) {
+      const TopTools_ListOfShape &anEdges = aMapIter.Value();
+
+      if (anEdges.Extent() == 1) {
+       isToTreat = Standard_True;
+       break;
+      }
+    }
+
+    if (!isToTreat) {
+      // Get a closed loop.
+      for (aMapIter.Initialize(aMapVE); aMapIter.More(); aMapIter.Next()) {
+       const TopTools_ListOfShape &anEdges = aMapIter.Value();
+
+       if (anEdges.Extent() == 1) {
+         isToTreat = Standard_True;
+         break;
+       }
+      }
+    }
+
+    // Stop treatment if there is no more edges.
+    if (!isToTreat)
+      break;
+
+    // Treat the list of edges starting from the current iterator.
+    TopoDS_Wire aWire;
+
+    aBuilder.MakeWire(aWire);
+    aFirstVtx = TopoDS::Vertex(aMapIter.Key());
+
+    while (!aFirstVtx.IsNull()) {
+      const TopTools_ListOfShape &anEdges = aMapVE.ChangeFind(aFirstVtx);
+
+      aCurEdge  = TopoDS::Edge(anEdges.First());
+      TopExp::Vertices(aCurEdge, aV[0], aV[1], Standard_True);
+
+      if (aFirstVtx.IsSame(aV[1])) {
+       aV[1] = aV[0];
+       aV[0] = aFirstVtx;
+       aCurEdge.Reverse();
+      }
+
+      aBuilder.Add(aWire, aCurEdge);
+
+      TopTools_ListOfShape &anEdges1 = aMapVE.ChangeFind(aV[0]);
+      TopTools_ListOfShape &anEdges2 = aMapVE.ChangeFind(aV[1]);
+
+      // Remove the current edge from aMapVE.
+      anEdges1.RemoveFirst();
+
+      if (anEdges1.IsEmpty())
+       aMapVE.UnBind(aV[0]);
+
+      if (anEdges2.IsEmpty() || anEdges2.Extent() > 2)
+       return Standard_False;
+
+      if (aCurEdge.IsSame(anEdges2.First())) {
+       // Remove first element.
+       anEdges2.RemoveFirst();
+      } else if (aCurEdge.IsSame(anEdges2.Last())) {
+       // Remove last element.
+       TopTools_ListIteratorOfListOfShape anEdgeIt(anEdges2);
+
+       anEdgeIt.Next();
+       anEdges2.Remove(anEdgeIt);
+      } else {
+       return Standard_False;
+      }
+
+      if (anEdges2.IsEmpty()) {
+       aMapVE.UnBind(aV[1]);
+       aFirstVtx.Nullify();
+      } else {
+       aFirstVtx = aV[1];
+      }
+    }
+
+    theWires.Append(aWire);
+  }
+
+  return Standard_True;
+}
+
+// ==============================================================================
+// function: Constructor
+// ==============================================================================
+Unfolding_Shell::Unfolding_Shell()
+     : myTolContour(0.001),
+       myTolCurvature(0.001),
+       myDeflection(0.001),
+       myDistortionArea(0.),
+       myCurvature(0.)
+{
+  Reset();
+}
+
+// ==============================================================================
+// function: Constructor
+// ==============================================================================
+Unfolding_Shell::Unfolding_Shell(const TopoDS_Shell& theShell,
+                                const gp_Pln&       thePlane,
+                                const Standard_Real theContourTolerance,
+                                const Standard_Real theCurvatureTolerance,
+                                const Standard_Real theDeflection)
+     : myShell(theShell),
+       myPlane(thePlane),
+       myTolContour(theContourTolerance),
+       myTolCurvature(theCurvatureTolerance),
+       myDeflection(theDeflection),
+       myDistortionArea(0.),
+       myCurvature(0.)
+{
+  Reset();
+}
+
+// ==============================================================================
+// function: Perform
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::Perform() 
+{
+  // Check if the operation is already performed and there is nothing to do.
+  if (myErrorStatus != Unfolding_NotDone)
+    return (myErrorStatus == Unfolding_Done);
+  
+  // Check input data validity.
+  if (myShell.IsNull() || 
+      ( myTolContour <= RealEpsilon() ) ||
+      ( myTolCurvature <= RealEpsilon() ) ||
+      ( myDeflection <= RealEpsilon() ) ) {
+    myErrorStatus = Unfolding_InvalidInput;
+    return Standard_False;
+  }
+
+  // Compute number of samples for each edge of the shell.
+  TopTools_DataMapOfShapeInteger            aMapEdgeNbSamples;
+  TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+  Standard_Integer                          i;
+  Standard_Integer                          aNbEdges;
+  
+
+  TopExp::MapShapesAndAncestors(myShell, TopAbs_EDGE, TopAbs_FACE, aMapEF);
+  aNbEdges = aMapEF.Extent();
+
+  for (i = 1; i <= aNbEdges; i++) {
+    TopoDS_Edge                 anEdge    = TopoDS::Edge(aMapEF.FindKey(i));
+    const TopTools_ListOfShape &aFaces    = aMapEF.FindFromIndex(i);
+    Standard_Integer            aNbPoints = Unfolding::NbSamples(anEdge, aFaces,
+                                                                myTolContour);
+
+    aMapEdgeNbSamples.Bind(anEdge, aNbPoints);
+  }
+
+  // Perform unfolding of each face.
+  TopTools_ListOfShape aList2Sew;
+  myDistortionArea = 0.;
+  myCurvature = 0.;
+  TopExp_Explorer anExp( myShell, TopAbs_FACE );
+  Standard_Boolean isFirstReversed = Standard_False;
+
+  for ( ; anExp.More(); anExp.Next() ) {
+    TopoDS_Face aFaceOriginal = TopoDS::Face( anExp.Current() );
+    TopoDS_Face aFace = aFaceOriginal;
+    aFace.Orientation( TopAbs_FORWARD );
+
+    Unfolding_Surface anUnfoldFace(aFace, myPlane, myTolContour, 
+                                  myTolCurvature, myDeflection);
+
+    Standard_Boolean                    isDone    =
+                                   anUnfoldFace.Perform(aMapEdgeNbSamples);
+    Handle(Unfolding_FaceDataContainer) aFaceData = anUnfoldFace.GetDataContainer();
+
+    // Keep the original orientation of unfolding data container.
+    aFaceData->SetFace(aFaceOriginal);
+
+    if ( myCurvature < aFaceData->GetMaxGaussCurvature() )
+      myCurvature = aFaceData->GetMaxGaussCurvature();
+    myDistortionArea += aFaceData->GetDistortionArea();
+
+    if ( !isDone ) {
+      myErrorStatus = anUnfoldFace.ErrorStatus();
+      return Standard_False;
+    }
+    if ( myMapFaceData.IsEmpty() ) {
+      isFirstReversed = ( aFaceOriginal.Orientation() == TopAbs_REVERSED );
+    }
+
+    TopoDS_Face aNewFace = aFaceData->GetUnfoldedFace();
+
+    Standard_Boolean toReverse = ( aFaceOriginal.Orientation() == TopAbs_REVERSED );
+    if ( isFirstReversed ) 
+      toReverse = !toReverse;
+    gp_Trsf aTrsfPln;
+
+    if ( toReverse ) {
+      // Take into account the faces of different orientation are unfolded
+      // as mirror compared to the first unfolded face representation
+      aTrsfPln.SetMirror( gp_Ax1( myPlane.Location(), myPlane.Position().XDirection() ) );
+      aFaceData->ApplyTrsf(aTrsfPln);
+    }
+
+    myMapFaceData.Add(aFaceData);
+  }
+  //
+
+  if ( !ComputeTransformed( aList2Sew ) ) {
+    return Standard_False;
+  }
+
+  //
+  BRep_Builder                       aBuilder;
+  TopoDS_Compound                    aCompound;
+  TopTools_ListIteratorOfListOfShape anIt( aList2Sew );
+
+  aBuilder.MakeCompound(aCompound);
+
+  for ( ; anIt.More(); anIt.Next() )
+    aBuilder.Add(aCompound, anIt.Value());
+
+  Unfolding_ErrorStatus aStatus;
+  TopoDS_Shell          aShell = Unfolding::ToShell(aCompound,
+                                                   myTolContour, aStatus);
+
+  if (aShell.IsNull()) {
+    switch (aStatus) {
+    case Unfolding_ComplexShape:
+      myErrorStatus = Unfolding_ComplexShape;
+      break;
+    case Unfolding_InvalidShape:
+      myErrorStatus = Unfolding_InvalidShape;
+      break;
+    default:
+      myErrorStatus = Unfolding_Failure;
+      break;
+    }
+    return Standard_False;
+  }
+
+  ShapeAnalysis_FreeBoundsProperties aFreeBoundAlgo(aShell);
+
+  if ( !aFreeBoundAlgo.Perform() ) {
+    myErrorStatus = Unfolding_Failure;
+    return Standard_False;
+  }
+
+  Handle(ShapeAnalysis_HSequenceOfFreeBounds) aSeqWire;
+  aSeqWire = aFreeBoundAlgo.ClosedFreeBounds();
+
+  BRepBuilderAPI_MakeFace aFaceMaker(myPlane);   
+
+  if ( !aSeqWire.IsNull() ) {
+    for ( Standard_Integer w = 1; w <= aSeqWire->Length(); w++ ) {
+      aFaceMaker.Add( aSeqWire->Value(w)->FreeBound() );
+    }
+  }
+  myResult = aFaceMaker.Face();
+
+#ifdef DEB
+  cout << "Checking the result..."   << endl;
+#endif
+  BRepCheck_Analyzer aChecker( myResult, Standard_True );
+  if ( !aChecker.IsValid() ) {
+    myErrorStatus = Unfolding_ComplexShape;
+    return Standard_False;
+  }
+  return Standard_True;
+}
+
+// ==============================================================================
+// function: ComputeTransformed
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::ComputeTransformed(TopTools_ListOfShape& theResult) 
+{
+  theResult.Clear();
+
+  // If the map of face data is empty, nothing to do.
+  if (myMapFaceData.IsEmpty())
+    return Standard_True;
+
+  TopTools_MapOfShape                       aMapTreated;
+  TColStd_MapOfInteger                      aMapTreatedIndices;
+  TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+  Standard_Integer                          i;
+  Standard_Integer                          aNbFaces = myMapFaceData.Extent();
+  TColStd_ListOfInteger                     aListToTreat;
+  Handle(Unfolding_FaceDataContainer)       aDummyFaceData;
+
+  aDummyFaceData = new Unfolding_FaceDataContainer;
+  TopExp::MapShapesAndAncestors( myShell, TopAbs_EDGE, TopAbs_FACE, aMapEF );
+
+  for (i = 1; i <= aNbFaces; i++) {
+    // Skip index already treated.
+    if (aMapTreatedIndices.Contains(i))
+      continue;
+
+    aListToTreat.Append(i);
+
+    while (!aListToTreat.IsEmpty()) {
+      Standard_Integer anIndex = aListToTreat.First();
+
+      if (!aMapTreatedIndices.Add(anIndex))
+       continue;
+
+      aListToTreat.RemoveFirst();
+
+      const Handle(Unfolding_FaceDataContainer) &aFaceData =
+                                               myMapFaceData.FindKey(anIndex);
+      const TopoDS_Face                         &aFace     =
+                                              aFaceData->GetFace();
+
+      aMapTreated.Add(aFace);
+
+      TopExp_Explorer anEdgeExp(aFace, TopAbs_EDGE);
+
+      for ( ; anEdgeExp.More(); anEdgeExp.Next() ) {
+       const TopoDS_Shape &anEdge = anEdgeExp.Current();
+
+       if (!aMapTreated.Add(anEdge) || !aMapEF.Contains(anEdge)) {
+         // This edge is already treated or it is absent in aMapEF. Skip it.
+         continue;
+       }
+
+       // Treat faces share the edge anEdge with the face aFace.
+       const TopTools_ListOfShape         &aFaces = aMapEF.FindFromKey(anEdge);
+       TopTools_ListIteratorOfListOfShape  aFaceIter(aFaces);
+
+       for (; aFaceIter.More(); aFaceIter.Next()) {
+         const TopoDS_Shape &aNeighborFace = aFaceIter.Value();
+
+         // Skip aFace
+         if (aFace.IsSame(aNeighborFace))
+           continue;
+
+         aDummyFaceData->SetFace(TopoDS::Face(aNeighborFace));
+
+         Standard_Boolean isFixed        = !aMapTreated.Add(aNeighborFace);
+         Standard_Integer aNeighborIndex = myMapFaceData.FindIndex(aDummyFaceData);
+
+         if (aNeighborIndex == 0) {
+           myErrorStatus = Unfolding_Failure;
+
+           return Standard_False; // This is an invalid case.
+         }
+
+         const Handle(Unfolding_FaceDataContainer) &aNeighborFaceData =
+                                           myMapFaceData.FindKey(aNeighborIndex);
+         TopTools_ListOfShape aCommonEdges;
+
+         GetCommonEdges(aFace, aNeighborFaceData->GetFace(), aCommonEdges);
+
+         if (!MoveFace2ToFace1(aFaceData, aNeighborFaceData,
+                               aCommonEdges, isFixed))
+           return Standard_False;
+
+         // Add common edge to the map of treated shapes.
+         TopTools_ListIteratorOfListOfShape anEdgeIter(aCommonEdges);
+
+         for (; anEdgeIter.More(); anEdgeIter.Next())
+           aMapTreated.Add(anEdgeIter.Value());
+
+         if (!isFixed)
+           aListToTreat.Append(aNeighborIndex);
+       }
+      }
+
+      theResult.Append(aFaceData->GetUnfoldedFace());
+    }
+  }
+
+  return Standard_True;
+}
+
+
+// ==============================================================================
+// function: MoveFace2ToFace1
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::MoveFace2ToFace1
+                     (const Handle(Unfolding_FaceDataContainer) &theFaceData1,
+                     const Handle(Unfolding_FaceDataContainer) &theFaceData2,
+                     const TopTools_ListOfShape                &theCommonEdges,
+                     const Standard_Boolean                     theIsFixed) 
+{
+  TopTools_ListOfShape aWires;
+
+  if (!GetWires(theCommonEdges, aWires)) {
+    myErrorStatus = Unfolding_Failure;
+
+    return Standard_False;
+  }
+
+  // Get a wire with the greatest distance between first and last vertices.
+  TopoDS_Wire                        aRefWire;
+  TopoDS_Wire                        aWire;
+  TopTools_ListIteratorOfListOfShape anIter(aWires);
+  Standard_Real                      aMaxDist = -1;
+  Standard_Real                      aDist;
+  TopoDS_Vertex                      aV[2];
+
+  for (; anIter.More(); anIter.Next()) {
+    aWire = TopoDS::Wire(anIter.Value());
+    TopExp::Vertices(aWire, aV[0], aV[1]);
+
+    gp_Pnt aP1 = BRep_Tool::Pnt(aV[0]);
+    gp_Pnt aP2 = BRep_Tool::Pnt(aV[1]);
+
+    aDist = aP1.Distance(aP2);
+
+    if (aDist > aMaxDist) {
+      aMaxDist = aDist;
+      aRefWire = aWire;
+    }
+  }
+
+  if (aRefWire.IsNull()) {
+    myErrorStatus = Unfolding_Failure;
+
+    return Standard_False;
+  }
+
+  // Compute points.
+  Standard_Boolean isReversedOn1 = Standard_False;
+  Standard_Boolean isReversedOn2 = Standard_False;
+  TopExp_Explorer  anExp(aRefWire, TopAbs_EDGE);
+
+  if (anExp.More()) {
+    TopoDS_Edge aFirstEdge = TopoDS::Edge(anExp.Current());
+    TopoDS_Face aFace1     = theFaceData1->GetFace();
+    TopoDS_Face aFace2     = theFaceData2->GetFace();
+
+    TopExp_Explorer aFaceExp(aFace1, TopAbs_EDGE);
+
+    for (; aFaceExp.More(); aFaceExp.Next()) {
+      const TopoDS_Shape &anEdgeOnF1 = aFaceExp.Current();
+
+      if (aFirstEdge.IsSame(anEdgeOnF1)) {
+       if (aFirstEdge.Orientation() != anEdgeOnF1.Orientation())
+         isReversedOn1 = Standard_True;
+
+       break;
+      }
+    }
+
+    // If aFirstEdge is not found on the face1. It is not possible by construction.
+    // Return with error status.
+    if (!aFaceExp.More()) {
+      myErrorStatus = Unfolding_Failure;
+
+      return Standard_False;
+    }
+
+    if (aFace1.Orientation() == aFace2.Orientation())
+      isReversedOn2 = !isReversedOn1;
+    else
+      isReversedOn2 =  isReversedOn1;
+  }
+
+  // Collect points.
+  TopoDS_Shape         aFace1   = theFaceData1->GetUnfoldedFace();
+  TopoDS_Shape         aFace2   = theFaceData2->GetUnfoldedFace();
+  TColgp_SequenceOfXY  aMasterPoints;
+  TColgp_SequenceOfXY  aSlavePoints;
+  gp_Pnt2d             aUV[2];
+  Handle(Geom_Surface) aSurface = new Geom_Plane(myPlane);
+  TopLoc_Location      aLoc;
+
+  for (; anExp.More(); anExp.Next()) {
+    TopoDS_Edge                 anEdge   = TopoDS::Edge(anExp.Current());
+    const TopTools_ListOfShape &anUnfld1 = theFaceData1->GetEdgesForEdge(anEdge);
+    const TopTools_ListOfShape &anUnfld2 = theFaceData2->GetEdgesForEdge(anEdge);
+
+    // Fill aMasterPoints.
+    for (anIter.Initialize(anUnfld1); anIter.More(); anIter.Next()) {
+      TopoDS_Edge anUnfoldEdge = TopoDS::Edge(anIter.Value());
+
+      if (isReversedOn1)
+       BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[1], aUV[0]);
+      else
+       BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[0], aUV[1]);
+
+      // Add the first point if the collection is empty.
+      if (aMasterPoints.IsEmpty())
+       aMasterPoints.Append(aUV[0].XY());
+
+      // Add the last point.
+      if (isReversedOn1)
+       aMasterPoints.Prepend(aUV[1].XY());
+      else
+       aMasterPoints.Append(aUV[1].XY());
+    }
+
+    // Fill aSlavePoints.
+    for (anIter.Initialize(anUnfld2); anIter.More(); anIter.Next()) {
+      TopoDS_Edge anUnfoldEdge = TopoDS::Edge(anIter.Value());
+
+      if (isReversedOn2)
+       BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[1], aUV[0]);
+      else
+       BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[0], aUV[1]);
+
+      // Add the first point if the collection is empty.
+      if (aSlavePoints.IsEmpty())
+       aSlavePoints.Append(aUV[0].XY());
+
+      // Add the last point.
+      if (isReversedOn2)
+       aSlavePoints.Prepend(aUV[1].XY());
+      else
+       aSlavePoints.Append(aUV[1].XY());
+    }
+  }
+
+  // Construct array of points.
+  Handle(TColgp_HArray1OfXY) aMasterPolyLine;
+  Handle(TColgp_HArray1OfXY) aSlavePolyLine;
+  Standard_Integer           i = 0;
+
+  aMasterPolyLine = new TColgp_HArray1OfXY( 1, aMasterPoints.Length() );
+  aSlavePolyLine  = new TColgp_HArray1OfXY( 1, aSlavePoints.Length() );
+
+  for ( i = aMasterPolyLine->Lower(); i <= aMasterPolyLine->Upper(); i++ )
+    aMasterPolyLine->SetValue( i, aMasterPoints(i) );
+
+  for ( i = aSlavePolyLine->Lower(); i <= aSlavePolyLine->Upper(); i++ )
+    aSlavePolyLine->SetValue( i, aSlavePoints(i) );
+
+  // Compute transformation
+  gp_Trsf2d     aTransformation2d;
+  Standard_Real aDistortionArea;
+
+  if ( !CombineCurves(aMasterPolyLine->Array1(), aSlavePolyLine->Array1(),
+                     theIsFixed, myTolContour, myTolContour*myTolContour,
+                     aTransformation2d, aDistortionArea) ) {
+    myDistortionArea += aDistortionArea;
+    myErrorStatus     = Unfolding_InvalidSurface;
+
+    return Standard_False;
+  }
+
+  myDistortionArea += aDistortionArea;
+
+  // Trasform face
+  if (!theIsFixed) {
+    gp_Trsf aTrsf2dTo3d( aTransformation2d );
+    gp_Trsf aTrsfPln1, aTrsfPln2;
+    gp_Ax3  anAx3( gp_Pnt(0,0,0), gp_Dir(0,0,1), gp_Dir(1,0,0));
+
+    aTrsfPln1.SetDisplacement( myPlane.Position(), anAx3 );
+    aTrsfPln2.SetDisplacement( anAx3, myPlane.Position() );
+
+    gp_Trsf aTransformation = aTrsf2dTo3d * aTrsfPln1;
+
+    aTransformation = aTrsfPln2 * aTransformation;
+    theFaceData2->ApplyTrsf(aTransformation);
+  }
+
+  return Standard_True;
+}
+
+//-----------------------------------------------------------------------
+//function : CombineCurves
+//purpose  : 
+//-----------------------------------------------------------------------
+static Standard_Boolean CombineCurves(const TColgp_Array1OfXY& theMasterPolyLine,
+                                     const TColgp_Array1OfXY& theSlavePolyLine,
+                                     const Standard_Boolean   IsFixed,
+                                     const Standard_Real      theConfTolerance, 
+                                     const Standard_Real      theAreaTolerance, 
+                                     gp_Trsf2d&               theTransformation,
+                                     Standard_Real&           theDistortionArea)
+{
+  theDistortionArea = 0.;
+
+  if ( ( theMasterPolyLine.Length() < 2 ) || ( theSlavePolyLine.Length() < 2 ) )
+    return Standard_False;
+
+  gp_XY aPMasterFirst = theMasterPolyLine.Value(theMasterPolyLine.Lower());
+  gp_XY aPMasterLast = theMasterPolyLine.Value(theMasterPolyLine.Upper());
+  gp_XY aPSlaveFirst = theSlavePolyLine.Value(theSlavePolyLine.Lower());
+  gp_XY aPSlaveLast = theSlavePolyLine.Value(theSlavePolyLine.Upper());
+
+  if (aPMasterFirst.IsEqual(aPMasterLast, theConfTolerance) ||
+      aPSlaveFirst.IsEqual(aPSlaveLast, theConfTolerance)) {
+    // One of polylines is closed. Get the points previous to the last ones.
+    aPMasterLast = theMasterPolyLine.Value(theMasterPolyLine.Upper() - 1);
+    aPSlaveLast  = theSlavePolyLine.Value(theSlavePolyLine.Upper() - 1);
+    
+    if (aPMasterFirst.IsEqual(aPMasterLast, theConfTolerance) ||
+       aPSlaveFirst.IsEqual(aPSlaveLast, theConfTolerance))
+      return Standard_False;
+  }
+
+  Standard_Real aRotation = 0.;
+  gp_XY aTranslation;
+      
+  gp_Vec2d aLineDir1(aPMasterLast - aPMasterFirst);
+  gp_Vec2d aLineDir2(aPSlaveLast - aPSlaveFirst);
+
+  aTranslation = aPMasterFirst - aPSlaveFirst;
+  Standard_Real aLen1 = aLineDir1.Magnitude();
+  Standard_Real aLen2 = aLineDir2.Magnitude();
+  Standard_Real aShift = ( aLen2 - aLen1 ) * 0.5;
+  if ( aLen1 > gp::Resolution() ) {
+    aTranslation = aTranslation - aLineDir1.XY() * (aShift / aLen1);
+    if ( aLen2 > gp::Resolution() )
+      aRotation = aLineDir1.Angle( aLineDir2 );
+  }
+
+  // compute base transformation
+  gp_Trsf2d aRotTrsf;
+  aRotTrsf.SetRotation(aPSlaveFirst, -aRotation);
+
+  gp_Trsf2d aTransTrsf;
+  aTransTrsf.SetTranslation( gp_Vec2d(aTranslation) );
+
+  theTransformation = aTransTrsf * aRotTrsf;
+  //
+
+  // Compute transformation of shift to minimize the area of 
+  // poly-lines difference
+  gp_Dir2d aDir(1,0);
+  if ( aLen1 > gp::Resolution() )
+    aDir = gp_Dir2d( gp_XY(-aLineDir1.Y(), aLineDir1.X() ) ) ;
+  Unfolding_FunctionWithDerivative aFunc( theMasterPolyLine, theSlavePolyLine, aDir, theTransformation );
+
+  if (IsFixed) {
+    Standard_Real aVal;
+
+    aFunc.Value(0, aVal);
+    theDistortionArea = aFunc.Area();    
+    
+    return Standard_True;
+  } else {
+    Standard_Real aBoundary = aShift * 20.;
+    const Standard_Real aTolX = 1.e-05;
+    if ( fabs(aBoundary) < aTolX * 2. ) {
+      Standard_Real aVal = 0.;
+      aFunc.Value(0, aVal);
+      theDistortionArea = aFunc.Area();    
+      return Standard_True;
+    }
+    const Standard_Real aTolF = ( theAreaTolerance < 1.e-06 ) ? 1.e-06 : theAreaTolerance;
+  
+    math_NewtonFunctionRoot R( aFunc, 0., aTolX, aTolF, -aBoundary, aBoundary, 10 );
+
+    if ( R.IsDone() ) {
+      gp_Trsf2d aTransTrsfAdd;
+      aTransTrsfAdd.SetTranslation( gp_Vec2d(aDir.XY() * R.Root() ) );
+      theTransformation = aTransTrsfAdd * theTransformation;
+      theDistortionArea = aFunc.Area();
+    }
+    else {
+      math_FunctionRoot R2( aFunc, 0., aTolX, -aBoundary, aBoundary );
+      if ( R2.IsDone() ) {
+       gp_Trsf2d aTransTrsfAdd;
+       aTransTrsfAdd.SetTranslation( gp_Vec2d(aDir.XY() * R2.Root() ) );
+       theTransformation = aTransTrsfAdd * theTransformation;
+       theDistortionArea = aFunc.Area();
+      }
+    }
+  }
+
+  return Standard_True;
+}
diff --git a/src/Unfolding/Unfolding_Shell.hxx b/src/Unfolding/Unfolding_Shell.hxx
new file mode 100644 (file)
index 0000000..146c81c
--- /dev/null
@@ -0,0 +1,153 @@
+// File:       Unfolding_Shell.cdl
+// Created:    Tue Sep  9 16:56:09 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef _Unfolding_Shell_HeaderFile
+#define _Unfolding_Shell_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <TopoDS_Shell.hxx>
+#include <gp_Pln.hxx>
+#include <Standard_Real.hxx>
+#include <Unfolding_IndexedMapOfFaceDataContainer.hxx>
+#include <TopoDS_Face.hxx>
+#include <Unfolding_ErrorStatus.hxx>
+#include <Standard_Boolean.hxx>
+class TopoDS_Shell;
+class gp_Pln;
+class TopoDS_Face;
+#include <TopTools_ListOfShape.hxx>
+class Unfolding_FaceDataContainer;
+
+
+//! This class is used to perform unfolding of a shell onto a plane.
+//! To perform  this  operation it  is necessary  to initialize the
+//! object by a  shell to  be unfolded,  a plane and a tolerance for
+//! operation. Then to call  the method Perform. The  result planar
+//! shell can be  obtained using the  method GetResult. Error status
+//! can be obtained by the method ErrorStatus.
+class Unfolding_Shell 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Empty constructor
+  Standard_EXPORT Unfolding_Shell();
+  
+  //! Constructor. Initializes the object with the shell, the plane and
+  //! the tolerances for operation.
+  Standard_EXPORT Unfolding_Shell(const TopoDS_Shell& theShell, const gp_Pln& thePlane, const Standard_Real theContourTolerance, const Standard_Real theCurvatureTolerance = 0.001, const Standard_Real theDeflection = 0.001);
+  
+  //! Sets the face.
+    void SetShell (const TopoDS_Shell& theShell);
+  
+  //! Returns the shell.
+    const TopoDS_Shell& GetShell() const;
+  
+  //! Sets the plane.
+    void SetPlane (const gp_Pln& thePlane);
+  
+  //! Returns the plane.
+    const gp_Pln& GetPlane() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetCurvatureTolerance (const Standard_Real theTolerance);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetCurvatureTolerance() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetContourTolerance (const Standard_Real theTolerance);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetContourTolerance() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetDeflection (const Standard_Real theDeflection);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetDeflection() const;
+  
+  //! Performs computation of  the unfolded surface. It returns
+  //! Standard_True if the operation succeeds otherwise returns
+  //! Standard_False. It is possible to get the error status of
+  //! the performed operation using the method ErrorStatus().
+  Standard_EXPORT Standard_Boolean Perform();
+  
+  //! Returns error status of the operation. The error status can have
+  //! one of the following values:
+  //! - Unfolding_Done: operation is succeeded;
+  //! - Unfolding_NotDone: the method Perform() is not called yet;
+  //! - Unfolding_Failure: the operation is failed;
+  //! - Unfolding_InvalidSurface: the surface cannot be unfolded
+  //! without distortion;
+  //! - Unfolding_InvalidInput: invalid input for the operation;
+  //! - Unfolding_InvalidShape: can be returned by
+  //! Unfolding::ToShape method;
+  //! - Unfolding_ComplexShape: can be returned by
+  //! Unfolding::ToShape method;
+    Unfolding_ErrorStatus ErrorStatus() const;
+  
+  //! Returns the result of the operation. If the operation is failed,
+  //! it returns a null shape.
+    const TopoDS_Face& GetResult() const;
+  
+  //! Returns the area cumulated during primitive patches mergin.
+  //! It shows computed distortion.
+    Standard_Real GetAreaError() const;
+  
+  //! Returns the gauss curvature computed in the mesh points.
+    Standard_Real GetMaxGaussCurvature() const;
+
+
+
+
+protected:
+
+  
+  //! Resets data to the initial state.
+    void Reset();
+
+
+
+
+private:
+
+  
+  Standard_EXPORT Standard_Boolean ComputeTransformed (TopTools_ListOfShape& theResult);
+  
+  //! Perform transformation of unfolded face2 to glue with unfolded
+  //! face1. If theIsFixed is Standard_True, the face 2 is not
+  //! transformed only estimations of distortions are performed.
+  Standard_EXPORT Standard_Boolean MoveFace2ToFace1 (const Handle(Unfolding_FaceDataContainer)& theFaceData1, const Handle(Unfolding_FaceDataContainer)& theFaceData2, const TopTools_ListOfShape& theCommonEdges, const Standard_Boolean theIsFixed);
+
+
+  TopoDS_Shell myShell;
+  gp_Pln myPlane;
+  Standard_Real myTolContour;
+  Standard_Real myTolCurvature;
+  Standard_Real myDeflection;
+  Unfolding_IndexedMapOfFaceDataContainer myMapFaceData;
+  TopoDS_Face myResult;
+  Unfolding_ErrorStatus myErrorStatus;
+  Standard_Real myDistortionArea;
+  Standard_Real myCurvature;
+
+
+};
+
+
+#include <Unfolding_Shell.lxx>
+
+
+
+
+
+#endif // _Unfolding_Shell_HeaderFile
diff --git a/src/Unfolding/Unfolding_Shell.lxx b/src/Unfolding/Unfolding_Shell.lxx
new file mode 100644 (file)
index 0000000..5a3cc7a
--- /dev/null
@@ -0,0 +1,99 @@
+// File:       Unfolding_Shell.lxx
+// Created:    Tue Sep  9 17:14:56 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+
+
+inline void Unfolding_Shell::SetShell(const TopoDS_Shell& theShell) 
+{
+  myShell = theShell;
+}
+
+inline const TopoDS_Shell& Unfolding_Shell::GetShell() const
+{
+  return myShell;
+}
+
+inline void Unfolding_Shell::SetPlane(const gp_Pln& thePlane) 
+{
+  myPlane = thePlane;
+}
+
+inline const gp_Pln& Unfolding_Shell::GetPlane() const
+{
+  return myPlane;
+}
+
+inline void Unfolding_Shell::SetCurvatureTolerance(const Standard_Real theTolerance) 
+{
+  myTolCurvature = theTolerance;
+}
+
+inline Standard_Real Unfolding_Shell::GetCurvatureTolerance() const
+{
+  return myTolCurvature;
+}
+
+inline void Unfolding_Shell::SetContourTolerance(const Standard_Real theTolerance) 
+{
+  myTolContour = theTolerance;
+}
+
+inline Standard_Real Unfolding_Shell::GetContourTolerance() const
+{
+  return myTolContour;
+}
+
+inline void Unfolding_Shell::SetDeflection(const Standard_Real theDeflection) 
+{
+  myDeflection = theDeflection;
+}
+
+inline Standard_Real Unfolding_Shell::GetDeflection() const
+{
+  return myDeflection;
+}
+
+inline Unfolding_ErrorStatus Unfolding_Shell::ErrorStatus() const
+{
+  return myErrorStatus;
+}
+
+inline const TopoDS_Face& Unfolding_Shell::GetResult() const
+{
+  return myResult;
+}
+
+inline Standard_Real Unfolding_Shell::GetAreaError() const
+{
+  return myDistortionArea;
+}
+
+inline Standard_Real Unfolding_Shell::GetMaxGaussCurvature() const
+{
+  return myCurvature;
+}
+
+inline void Unfolding_Shell::Reset() 
+{
+  myDistortionArea = 0.;
+  myCurvature = 0.;
+  myErrorStatus = Unfolding_NotDone;
+
+  myMapFaceData.Clear();
+  myResult.Nullify();
+}
diff --git a/src/Unfolding/Unfolding_Surface.cxx b/src/Unfolding/Unfolding_Surface.cxx
new file mode 100644 (file)
index 0000000..2de862a
--- /dev/null
@@ -0,0 +1,1543 @@
+// File:       Unfolding_Surface.cxx
+// Created:    Tue Jul 22 13:12:24 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <Unfolding_Surface.hxx>
+#include <Unfolding.hxx>
+#include <Unfolding_HArray2OfPoint.hxx>
+#include <Unfolding_Point.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
+#include <ElSLib.hxx>
+#include <GccAna_Circ2d3Tan.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_ConicalSurface.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_SurfaceOfLinearExtrusion.hxx>
+#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_ToroidalSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <gp_Circ.hxx>
+#include <IntAna2d_AnaIntersection.hxx>
+#include <TColgp_Array2OfPnt.hxx>
+#include <TColgp_SequenceOfXY.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+
+static Standard_Integer aLimitNumber = 1000;
+
+static void AdjustToDeflection(      Standard_Integer     &theNbPointsU, 
+                                    Standard_Integer     &theNbPointsV,
+                              const Handle(Geom_Surface) &theSurface, 
+                              const Standard_Real         theUMin,
+                              const Standard_Real         theUMax,
+                              const Standard_Real         theVMin,
+                              const Standard_Real         theVMax,
+                              const Standard_Real         theDeflection);
+
+//=======================================================================
+//function : MakeCirc
+//purpose  : This method constructs a circle that passes through 3 points.
+//           theNorm is a normal to the plane that is formed by theP1, theP2
+//           and theP3. Three points should not be on the same line and should
+//           not coincide. All these conditions are not checked. Their respect
+//           is under responsibility of the caller.
+//=======================================================================
+
+static Standard_Boolean MakeCirc(const gp_Pnt  &theP1,
+                                const gp_Pnt  &theP2,
+                                const gp_Pnt  &theP3,
+                                const gp_Dir  &theNorm,
+                                      gp_Circ &theCircle)
+{
+  gp_Dir        aX(theP3.XYZ().Subtracted(theP1.XYZ()));
+  gp_Ax3        aPlnAxis(theP1, theNorm, aX);
+  Standard_Real aU;
+  Standard_Real aV;
+  gp_Pnt2d      aP1(0., 0.);
+
+  ElSLib::PlaneParameters(aPlnAxis, theP2, aU, aV);
+
+  gp_Pnt2d aP2(aU, aV);
+
+  ElSLib::PlaneParameters(aPlnAxis, theP3, aU, aV);
+
+  gp_Pnt2d aP3(aU, aV);
+
+  GccAna_Circ2d3Tan aCircTan(aP1, aP2, aP3, Precision::Confusion());
+
+  if (!aCircTan.IsDone() || aCircTan.NbSolutions() != 1)
+    return Standard_False;
+
+  gp_Circ2d aCirc2d = aCircTan.ThisSolution(1);
+
+  // Convert 2d circle to 3d.
+  const gp_Pnt2d &a2dLoc  = aCirc2d.Location();
+  gp_Pnt          a3dLoc  = ElSLib::PlaneValue(a2dLoc.X(), a2dLoc.Y(), aPlnAxis);
+  gp_Dir          a3dX(theP1.XYZ().Subtracted(a3dLoc.XYZ()));
+  gp_Ax2          aCircAxis(a3dLoc, theNorm, a3dX);
+  Standard_Real   aRadius = aCirc2d.Radius();
+
+  theCircle.SetPosition(aCircAxis);
+  theCircle.SetRadius(aRadius);
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : CrvDistance
+//purpose  : Returns the approximate curvelinear distance between two
+//           points on surface. The distance is approximated by length of
+//           the circular arc started at thePoint1 and ended at thePoint2
+//           that is passed through the middle in UV space point.
+//=======================================================================
+
+static Standard_Real CrvDistance(const Unfolding_Point      &thePoint1,
+                                const Unfolding_Point      &thePoint2,
+                                const Handle(Geom_Surface) &theSurface,
+                                const Standard_Real        &theTolerance)
+{
+  const gp_XYZ  &aP1      = thePoint1.GetPointOnSurface();
+  const gp_XYZ  &aP2      = thePoint2.GetPointOnSurface();
+  gp_XYZ         aP12     = aP2.Subtracted(aP1);
+  Standard_Real  aLinDist = aP12.Modulus();
+
+  if (aLinDist <= theTolerance)
+    return aLinDist;
+
+  // Get middle point.
+  Standard_Real aUMid;
+  Standard_Real aVMid;
+  Standard_Real aU;
+  Standard_Real aV;
+  gp_Pnt        aPntMid;
+
+  thePoint1.GetParameters(aUMid, aVMid);
+  thePoint2.GetParameters(aU, aV);
+
+  aUMid = 0.5*(aUMid + aU);
+  aVMid = 0.5*(aVMid + aV);
+
+  theSurface->D0(aUMid, aVMid, aPntMid);
+
+  const gp_XYZ &aPMid = aPntMid.XYZ();
+
+  // Compute distance from aPMid to aP12.
+  aP12.Divide(aLinDist);
+
+  gp_XYZ aDistCoord(aPMid.Subtracted(aP1));
+
+  aDistCoord.Cross(aP12);
+
+  Standard_Real aDist = aDistCoord.Modulus();
+
+  if (aDist < 0.01*theTolerance)
+    return aLinDist;
+
+  // Find a distance along an arc.
+  gp_Pnt  aPnt1(aP1);
+  gp_Pnt  aPnt2(aP2);
+  gp_Dir  aNorm(aDistCoord);
+  gp_Circ aCirc;
+
+  if (!MakeCirc(aPnt1, aPntMid, aPnt2, aNorm, aCirc))
+    return 0.;
+
+  const gp_Ax2  &anAxis      = aCirc.Position();
+  Standard_Real  anAngle     = ElCLib::CircleParameter(anAxis, aPnt2);
+  Standard_Real  aCircParMid = ElCLib::CircleParameter(anAxis, aPntMid);
+  Standard_Real  aRadius     = aCirc.Radius();
+
+  if (anAngle < aCircParMid)
+    anAngle = 2.*M_PI - anAngle;
+
+  Standard_Real aCrvDist = anAngle*aRadius;
+
+  return aCrvDist;
+}
+
+//=======================================================================
+//function : GetCell
+//purpose  : Returns the indices of a cell thePoint belongs to. The cell (i, j)
+//           is defined between grid's points (i, j) - (i + 1, j) -
+//           (i + 1, j + 1) - (i, j + 1). If the point is outside the grid,
+//           its index is equal to 0 in case if corresponding index is lower
+//           then the lower bound or NbPoints if it is greater then the upper
+//           bound.
+//=======================================================================
+
+static void GetCell(const gp_XY                            &thePoint,
+                   const Handle(Unfolding_HArray2OfPoint) &theGrid,
+                   const Standard_Real                    &theTolerance,
+                         Standard_Integer                 &theI,
+                         Standard_Integer                 &theJ)
+{
+  Standard_Integer       iStart = theGrid->LowerRow();
+  Standard_Integer       jStart = theGrid->LowerCol();
+  Standard_Integer       iEnd   = theGrid->UpperRow();
+  Standard_Integer       jEnd   = theGrid->UpperCol();
+  const Unfolding_Point &aPff   = theGrid->Value(iStart, jStart);
+  const Unfolding_Point &aPll   = theGrid->Value(iEnd,   jEnd);
+  Standard_Real          aU     = thePoint.X();
+
+  // Compute theI.
+  if (aU < aPff.GetU() - theTolerance)
+    theI = iStart - 1;
+  else if (aU >= aPll.GetU() - theTolerance)
+    theI = iEnd;
+  else {
+    Standard_Real aStep = (aPll.GetU() - aPff.GetU())/(iEnd - iStart + 1);
+
+    theI = Standard_Integer(Round((aU - aPff.GetU())/aStep)) + iStart;
+
+    if (theI < iStart)
+      theI = iStart;
+
+    if (theI > iEnd)
+      theI = iEnd;
+
+    while (theI >= iStart &&
+          aU < theGrid->Value(theI, jStart).GetU() - theTolerance)
+      theI--;
+
+    while (theI < iEnd &&
+          aU >= theGrid->Value(theI + 1, jStart).GetU() - theTolerance)
+      theI++;
+  }
+
+  // Compute theI.
+  Standard_Real aV = thePoint.Y();
+
+  if (aV < aPff.GetV() - theTolerance)
+    theJ = jStart - 1;
+  else if (aV >= aPll.GetV() - theTolerance)
+    theJ = jEnd;
+  else {
+    Standard_Real aStep = (aPll.GetV() - aPff.GetV())/(jEnd - jStart + 1);
+
+    theJ = Standard_Integer(Round((aV - aPff.GetV())/aStep)) + jStart;
+
+    if (theJ < jStart)
+      theJ = jStart;
+
+    if (theJ > jEnd)
+      theJ = jEnd;
+
+    while (theJ >= jStart &&
+          aV < theGrid->Value(iStart, theJ).GetV() - theTolerance)
+      theJ--;
+
+    while (theJ < jEnd &&
+          aV >= theGrid->Value(iStart, theJ + 1).GetV() - theTolerance)
+      theJ++;
+  }
+}
+
+//=======================================================================
+//function : Empty constructor
+//purpose  : This method constructs and returns the curve that is passed
+//           through three points. It can be either a line if these three
+//           points lie on the same line or a circle. In case of failure
+//           it returns a null handle.
+//=======================================================================
+
+static Handle(Geom_Curve) MakeCurve(const gp_Pnt        &thePFirst,
+                                   const gp_Pnt        &thePMid,
+                                   const gp_Pnt        &thePLast,
+                                   const gp_Pln        &thePlane,
+                                   const Standard_Real  theTolerance)
+{
+  Handle(Geom_Curve) aCurve;
+  gp_Vec             aDFL(thePLast.XYZ().Subtracted(thePFirst.XYZ()));
+  Standard_Real      aLinDist = aDFL.Magnitude();
+
+  if (aLinDist > theTolerance) {
+    // compute distance between thePMid and the segment [thePFirst, thePLast].
+    gp_XYZ aDPMidFirst = thePMid.XYZ();
+
+    aDFL.Divide(aLinDist);
+    aDPMidFirst.Subtract(thePFirst.XYZ());
+    aDPMidFirst.Cross(aDFL.XYZ());
+
+    Standard_Real aDist = aDPMidFirst.Modulus();
+
+    // Line criteria like in the CrvDistance function.
+    if (aDist < 0.01*theTolerance) {
+      aCurve = new Geom_Line(thePFirst, gp_Dir(aDFL));
+    } else {
+      // Compute a circle
+      gp_Circ aCirc;
+
+      if (!MakeCirc(thePFirst, thePMid, thePLast,
+                   thePlane.Position().Direction(), aCirc))
+           return aCurve;
+
+      aCurve = new Geom_Circle(aCirc);
+
+      // Trim the curve by the circle parameters.
+      const gp_Ax2  &anAxis      = aCirc.Position();
+      Standard_Real  aCircPar1   = 0.; // By construction
+      Standard_Real  aCircPar2   = ElCLib::CircleParameter(anAxis, thePLast);
+      Standard_Real  aCircParMid = ElCLib::CircleParameter(anAxis, thePMid);
+
+      if (aCircParMid > aCircPar2)
+       aCurve = new Geom_TrimmedCurve(aCurve, aCircPar1,
+                                      aCircPar2, Standard_False);
+      else
+       aCurve = new Geom_TrimmedCurve(aCurve, aCircPar1, aCircPar2);
+    }
+  }
+
+  return aCurve;
+}
+
+//=======================================================================
+// function : Analyse
+// purpose  : Computes the numbers of samples along U and V direction using
+//            the array of poles.
+//=======================================================================
+
+static void Analyse(const TColgp_Array2OfPnt &array2,
+                         Standard_Integer   &theNbSamplesU,
+                         Standard_Integer   &theNbSamplesV)
+{
+  gp_Vec Vi,Vip1;
+  Standard_Integer sh,nbch,i,j;
+  const Standard_Integer nbup = array2.UpperRow() - array2.LowerRow() + 1;
+  const Standard_Integer nbvp = array2.UpperCol() - array2.LowerCol() + 1;
+
+  sh = 1;
+  nbch = 0;
+  if(nbvp>2) {
+
+    for(i = array2.LowerRow(); i <= array2.UpperRow(); i++) {
+      const gp_Pnt& A=array2.Value(i,1);
+      const gp_Pnt& B=array2.Value(i,2);
+      const gp_Pnt& C=array2.Value(i,3);
+      Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
+                 C.Y()-B.Y()-B.Y()+A.Y(),
+                 C.Z()-B.Z()-B.Z()+A.Z());
+      Standard_Integer locnbch=0;
+
+      for(j = array2.LowerCol() + 2; j < array2.UpperCol();j++) {  //-- essai
+       const gp_Pnt& Ax=array2.Value(i,j-1);
+       const gp_Pnt& Bx=array2.Value(i,j);
+       const gp_Pnt& Cx=array2.Value(i,j+1);
+       Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
+                     Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
+                     Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
+       Standard_Real pd = Vi.Dot(Vip1);
+       Vi=Vip1;
+       if(pd>1.0e-7 || pd<-1.0e-7) {
+         if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
+         else {        if(sh==1) {  sh=-1; locnbch++;  }  }
+       }
+      }
+      if(locnbch>nbch) {
+       nbch=locnbch;
+      }
+    }
+  }
+  theNbSamplesV = nbch+5;
+
+
+  nbch=0;
+  if(nbup > 2) {
+    for(j = array2.LowerCol(); j <= array2.UpperCol(); j++) {
+      const gp_Pnt& A=array2.Value(array2.LowerRow(),     j);
+      const gp_Pnt& B=array2.Value(array2.LowerRow() + 1, j);
+      const gp_Pnt& C=array2.Value(array2.LowerRow() + 2, j);
+      Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
+                 C.Y()-B.Y()-B.Y()+A.Y(),
+                 C.Z()-B.Z()-B.Z()+A.Z());
+      Standard_Integer locnbch=0;
+
+      for(i = array2.LowerRow() + 2; i < array2.UpperRow(); i++) {  //-- essai
+       const gp_Pnt& Ax=array2.Value(i-1,j);
+       const gp_Pnt& Bx=array2.Value(i,j);
+       const gp_Pnt& Cx=array2.Value(i+1,j);
+       Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
+                   Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
+                   Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
+       Standard_Real pd = Vi.Dot(Vip1);
+       Vi=Vip1;
+       if(pd>1.0e-7 || pd<-1.0e-7) {
+         if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
+         else {        if(sh==1) {  sh=-1; locnbch++;  }  }
+       }
+      }
+      if(locnbch>nbch) nbch=locnbch;
+    }
+  }
+  theNbSamplesU = nbch+5;
+}
+
+//=======================================================================
+//function : Empty constructor
+//purpose  : 
+//=======================================================================
+
+Unfolding_Surface::Unfolding_Surface()
+     : myTolContour(0.001),
+       myTolCurvature(0.001),
+       myDeflection(0.001)
+{
+  myDataContainer = new Unfolding_FaceDataContainer;
+  Reset();
+}
+
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+
+Unfolding_Surface::Unfolding_Surface(const TopoDS_Face   &theFace,
+                                    const gp_Pln        &thePlane,
+                                    const Standard_Real  theContourTolerance,
+                                    const Standard_Real  theCurvatureTolerance,
+                                    const Standard_Real  theDeflection)
+     : myPlane(thePlane),
+       myTolContour(theContourTolerance),
+       myTolCurvature(theCurvatureTolerance),
+       myDeflection(theDeflection)
+{
+  myDataContainer = new Unfolding_FaceDataContainer;
+  myDataContainer->SetFace(theFace);
+  Reset();
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::Perform
+                  (const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples)
+{
+  // Check if the operation is already performed and there is nothing to do.
+  if (myErrorStatus != Unfolding_NotDone)
+    return (myErrorStatus == Unfolding_Done);
+
+  // Check input data validity.
+  if (myDataContainer->GetFace().IsNull() || 
+      ( myTolContour <= RealEpsilon() ) ||
+      ( myTolCurvature <= RealEpsilon() ) ||
+      ( myDeflection <= RealEpsilon() ) ) {
+    myErrorStatus = Unfolding_InvalidInput;
+    return Standard_False;
+  }
+
+  // Initialize the grid on the surface.
+  Standard_Boolean isOK = InitGrid();
+
+  if (isOK) {
+    // Perform unfolding
+    isOK = Unfolding();
+
+    if (isOK) {
+      // Construct a planar face.
+      isOK = BuildPlanarFace(theMapEdgeNbSamples);
+    }
+  }
+
+  return isOK;
+}
+
+//=======================================================================
+//function : InitGrid
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::InitGrid()
+{
+  // Get Bounding box of the face.
+  Standard_Real      aUMin;
+  Standard_Real      aUMax;
+  Standard_Real      aVMin;
+  Standard_Real      aVMax;
+  const TopoDS_Face &aFace = myDataContainer->GetFace();
+
+  BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax);
+
+  // Compute number of samples.
+  Standard_Integer aNbPntsU;
+  Standard_Integer aNbPntsV;
+
+  NbPoints(aUMin, aUMax, aVMin, aVMax, aNbPntsU, aNbPntsV);
+
+
+  // Construct a grid.
+  myGrid = new Unfolding_HArray2OfPoint(1, aNbPntsU, 1, aNbPntsV);
+
+  // Fill in the grid.
+  Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
+  Standard_Real        aUStep   = (aUMax - aUMin)/(aNbPntsU - 1);
+  Standard_Real        aVStep   = (aVMax - aVMin)/(aNbPntsV - 1);
+  Standard_Real        aUPar;
+  Standard_Real        aVPar;
+  Standard_Integer     i;
+  Standard_Integer     j;
+  gp_Pnt               aPnt;
+  gp_Vec               aD1U;
+  gp_Vec               aD1V;
+  gp_Vec               aD2U;
+  gp_Vec               aD2V;
+  gp_Vec               aD2UV;
+  gp_Vec               aNorm;
+  Standard_Real        aL;
+  Standard_Real        aM;
+  Standard_Real        aN;
+  Standard_Real        aMaxCurvature = 0.;
+
+  for (aUPar = aUMin, i = 1; i <= aNbPntsU; i++) {
+    for (aVPar = aVMin, j = 1; j <= aNbPntsV; j++) {
+      aSurface->D2(aUPar, aVPar, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
+
+      // Check Gauss curvature
+      aNorm = aD1U.Crossed(aD1V);
+      aNorm.Normalize();
+      aL    = aD2U.Dot(aNorm);
+      aN    = aD2V.Dot(aNorm);
+      aM    = aD2UV.Dot(aNorm);
+      const Standard_Real aCurvature = Abs(aL*aN - aM*aM);
+      aMaxCurvature = ( aMaxCurvature < aCurvature ) ? aCurvature : aMaxCurvature;
+
+      if (aCurvature > myTolCurvature) {
+       myDataContainer->SetMaxGaussCurvature(aMaxCurvature);
+       myErrorStatus = Unfolding_InvalidSurface;
+       return Standard_False;
+      }
+
+      // Initialize the point.
+      Unfolding_Point &aPoint = myGrid->ChangeValue(i, j);
+
+      aPoint.SetParameters(aUPar, aVPar);
+      aPoint.SetPointOnSurface(aPnt.XYZ());
+
+      aVPar = (j == aNbPntsV - 1) ? aVMax : aVPar + aVStep;
+    }
+
+    aUPar = (i == aNbPntsU - 1) ? aUMax : aUPar + aUStep;
+  }
+
+  myDataContainer->SetMaxGaussCurvature(aMaxCurvature);
+
+  // Initialize points by angles in DU and DV directions.
+  Standard_Real aTolConf = 0.01*Max(myTolContour,myDeflection);
+  gp_XYZ        aDX;
+  gp_XYZ        aDY;
+
+  for (i = 1; i <= aNbPntsU; i++) {
+    for (j = 1; j <= aNbPntsV; j++) {
+      Unfolding_Point &aP = myGrid->ChangeValue(i, j);
+
+      if (i == aNbPntsU || j == aNbPntsV) {
+       aP.SetAngle(0.);
+      } else {
+       const Unfolding_Point &aPX = myGrid->Value(i + 1, j);
+
+       aDX = aPX.GetPointOnSurface();
+       aDX.Subtract(aP.GetPointOnSurface());
+
+       if (aDX.Modulus() <= aTolConf) {
+         aP.SetAngle(0.);
+       } else {
+         const Unfolding_Point &aPY = myGrid->Value(i, j + 1);
+
+         aDY = aPY.GetPointOnSurface();
+         aDY.Subtract(aP.GetPointOnSurface());
+
+         if (aDY.Modulus() <= aTolConf) {
+           aP.SetAngle(0.);
+         } else {
+           aP.SetAngle(gp_Vec(aDX).Angle(gp_Vec(aDY)));
+         }
+       }
+      }
+    }
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : NbPoints
+//purpose  : 
+//=======================================================================
+
+void Unfolding_Surface::NbPoints(const Standard_Real     theUMin,
+                                const Standard_Real     theUMax,
+                                const Standard_Real     theVMin,
+                                const Standard_Real     theVMax,
+                                      Standard_Integer &theNbPointsU,
+                                      Standard_Integer &theNbPointsV) const
+{
+  Handle(Geom_Surface)  aSurface =
+                            BRep_Tool::Surface(myDataContainer->GetFace());
+  Handle(Standard_Type) aType    = aSurface->DynamicType();
+
+  while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+    Handle(Geom_RectangularTrimmedSurface) aTrSurf =
+          Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+    aSurface = aTrSurf->BasisSurface();
+    aType    = aSurface->DynamicType();
+  }
+
+  if        (aType == STANDARD_TYPE(Geom_Plane)) {
+    // PLANE
+    theNbPointsU = 11;
+    theNbPointsV = 11;
+  } else if (aType == STANDARD_TYPE(Geom_CylindricalSurface)) {
+    // CYLINDER
+    Handle(Geom_CylindricalSurface) aCyl        =
+          Handle(Geom_CylindricalSurface)::DownCast(aSurface);
+    Standard_Real                   aRadius     = aCyl->Radius();
+    Standard_Real                   aMaxAngle   = M_PI *0.5;
+
+    if(aRadius > myDeflection) {
+      aMaxAngle = ACos(1. - myDeflection/aRadius)*2.;
+    }
+    if(aMaxAngle > Precision::Angular())
+      theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+    else
+      theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+    theNbPointsV  = (Standard_Integer)(theVMax - theVMin);
+    theNbPointsV /= 10;
+
+    if (theNbPointsU < 3)
+      theNbPointsU = 3;
+
+    if (theNbPointsV < 3)
+      theNbPointsV = 3;
+  } else if (aType == STANDARD_TYPE(Geom_ConicalSurface)) {
+    // CONE
+    Handle(Geom_ConicalSurface) aConeSurf =
+          Handle(Geom_ConicalSurface)::DownCast(aSurface);
+    gp_Cone                     aCone     = aConeSurf->Cone();
+    gp_Circ                     aCircle   = ElSLib::ConeVIso(aCone.Position(),
+                                                            aCone.RefRadius(),
+                                                            aCone.SemiAngle(),
+                                                            theVMin);
+    Standard_Real               aRadius   = aCircle.Radius();
+    aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(),
+                              aCone.SemiAngle(), theVMax);
+
+    if(aRadius < aCircle.Radius())
+      aRadius = aCircle.Radius();
+
+    Standard_Real aMaxAngle   = M_PI*0.5;
+
+    if(aRadius > myDeflection)
+      aMaxAngle = ACos(1. - myDeflection/aRadius)*2.;
+
+    if(aMaxAngle > Precision::Angular())
+      theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+    else
+      theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+    theNbPointsV  = (Standard_Integer)(theVMax - theVMin);
+    theNbPointsV /= 10;
+
+    if (theNbPointsU < 11)
+      theNbPointsU = 11;
+
+    if (theNbPointsV < 11)
+      theNbPointsV = 11;
+  } else if (aType == STANDARD_TYPE(Geom_SphericalSurface) ||
+            aType == STANDARD_TYPE(Geom_ToroidalSurface)) {
+    // SPHERE or TORUS
+    gp_Circ       aCircle;
+    Standard_Real aRadius1;
+    Standard_Real aRadius2;
+
+    if (aType == STANDARD_TYPE(Geom_SphericalSurface)) {
+      // SPHERE
+      Handle(Geom_SphericalSurface) aSphSurf =
+       Handle(Geom_SphericalSurface)::DownCast(aSurface);
+      gp_Sphere aSphere = aSphSurf->Sphere();
+
+      aRadius1 = aSphere.Radius();
+      aRadius2 = aSphere.Radius();
+    } else {
+      Handle(Geom_ToroidalSurface) aTorusSurf =
+       Handle(Geom_ToroidalSurface)::DownCast(aSurface);
+      // TORUS
+      gp_Torus aTorus = aTorusSurf->Torus();
+
+      aCircle  = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(),
+                                 aTorus.MinorRadius(), theUMin);
+      aRadius2 = aCircle.Radius();
+      aCircle  = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(),
+                                  aTorus.MinorRadius(), theUMax);
+      aRadius2 = (aRadius2 < aCircle.Radius()) ? aCircle.Radius() : aRadius2;
+      aCircle  = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(),
+                                  aTorus.MinorRadius(), theVMin);
+      aRadius1 = aCircle.Radius();
+      aCircle  = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(),
+                                  aTorus.MinorRadius(), theVMax);
+      aRadius1 = (aRadius1 < aCircle.Radius()) ? aCircle.Radius() : aRadius1;
+    }
+
+    Standard_Real aMaxAngle = M_PI*0.5;
+
+    if(aRadius1 > myDeflection)
+      aMaxAngle = ACos(1. - myDeflection/aRadius1)*2.;
+
+    if(aMaxAngle > Precision::Angular())
+      theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+    else
+      theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+    aMaxAngle = M_PI*0.5;
+
+    if(aRadius2 > myDeflection)
+      aMaxAngle = ACos(1. - myDeflection/aRadius2)*2.;
+
+    if(aMaxAngle > Precision::Angular())
+      theNbPointsV = Standard_Integer((theVMax - theVMin)/aMaxAngle);
+    else
+      theNbPointsV = (Standard_Integer)(theVMax - theVMin);
+
+    if (theNbPointsU < 11)
+      theNbPointsU = 11;
+
+    if (theNbPointsV < 11)
+      theNbPointsV = 11;
+  } else if (aType == STANDARD_TYPE(Geom_BezierSurface)) {
+    Handle(Geom_BezierSurface) aBezier =
+          Handle(Geom_BezierSurface)::DownCast(aSurface);
+    // BEZIER
+    theNbPointsU = 3 + aBezier->NbUPoles();
+    theNbPointsV = 3 + aBezier->NbVPoles();
+
+    if(theNbPointsU > 11 || theNbPointsV > 11) {
+      TColgp_Array2OfPnt array2(1, aBezier->NbUPoles(), 1, aBezier->NbVPoles());
+      aBezier->Poles(array2);
+      Analyse(array2, theNbPointsU, theNbPointsV);
+    }
+    AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface, 
+                       theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+    if(theNbPointsU < 11)
+      theNbPointsU = 11;
+
+    if(theNbPointsV < 11)
+      theNbPointsV = 11;
+  } else if (aType == STANDARD_TYPE(Geom_BSplineSurface)) {
+    // BSPLINE
+    Handle(Geom_BSplineSurface) aBSpline =
+          Handle(Geom_BSplineSurface)::DownCast(aSurface);
+
+    theNbPointsU  = aBSpline->NbUKnots();
+    theNbPointsU *= aBSpline->UDegree();
+    theNbPointsV  = aBSpline->NbVKnots();
+    theNbPointsV *= aBSpline->VDegree();
+
+    if(theNbPointsU > 11 || theNbPointsU > 11) {
+      TColgp_Array2OfPnt array2(1, aBSpline->NbUPoles(),
+                               1, aBSpline->NbVPoles());
+      aBSpline->Poles(array2);
+      Analyse(array2, theNbPointsU, theNbPointsV);
+    }
+    AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface, 
+                       theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+    if(theNbPointsU < 11)
+      theNbPointsU = 11;
+
+    if(theNbPointsV < 11)
+      theNbPointsV = 11;
+  } else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
+    // EXTRUSION
+    theNbPointsU  = 15;
+    theNbPointsV  = (Standard_Integer)(theVMax - theVMin);
+    theNbPointsV /= 10;
+
+    AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface, 
+                      theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+    if(theNbPointsV < 15)
+      theNbPointsV = 15;
+  } else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution)) {
+    // REVOLUTION
+    theNbPointsU = 15;
+    theNbPointsV = 15;
+
+    AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface, 
+                       theUMin, theUMax, theVMin, theVMax, myDeflection );
+  } else {
+    // OTHER
+    theNbPointsU = 11;
+    theNbPointsV = 11;
+    AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface, 
+                      theUMin, theUMax, theVMin, theVMax, myDeflection );
+  }
+
+  // Check if the number of points exceeds the maximum number of points.
+  const Standard_Integer aMaxNbPoints = aLimitNumber;
+
+  if(theNbPointsU > aMaxNbPoints) {
+    if ( theNbPointsU < theNbPointsV ) {
+      theNbPointsU = aMaxNbPoints;
+    }
+    else {
+      Standard_Integer alim = aMaxNbPoints * aMaxNbPoints / theNbPointsV;
+      theNbPointsU = ( theNbPointsU > alim ) ? alim : theNbPointsU;
+    }
+  }
+
+  if(theNbPointsV > aMaxNbPoints) {
+    if ( theNbPointsV < theNbPointsU ) {
+      theNbPointsV = aMaxNbPoints;
+    }
+    else {
+      Standard_Integer alim = aMaxNbPoints * aMaxNbPoints / theNbPointsU;
+      theNbPointsV = ( theNbPointsV > alim ) ? alim : theNbPointsV;
+    }
+  }
+}
+
+//=======================================================================
+//function : Unfolding
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::Unfolding()
+{
+  Handle(Geom_Surface) aSurface = BRep_Tool::Surface(myDataContainer->GetFace());
+  Standard_Integer     iStart   = myGrid->LowerRow();
+  Standard_Integer     jStart   = myGrid->LowerCol();
+  Standard_Integer     iEnd     = myGrid->UpperRow();
+  Standard_Integer     jEnd     = myGrid->UpperCol();
+  Standard_Integer     i;
+  Standard_Integer     j;
+
+  // Initialize the array of 4 points on a plane. For a couple of indices (i, j)
+  // the points on a plane are initialized as follows:
+  // aPonPln[0] -> (i,     j + 1)
+  // aPonPln[1] -> (i,     j)
+  // aPonPln[2] -> (i + 1, j)
+  // aPonPln[3] -> (i + 1, j + 1)
+  gp_XY         aPonPln[4];
+  Standard_Real aCrvDist;
+  Standard_Real aCrvDist2;
+  gp_XY         aDirX;
+  gp_XY         aDirY;
+  Standard_Real aTolConf = 0.01*Max(myTolContour, myDeflection);
+  Standard_Real aNorm;
+  Standard_Real aDistortionArea = 0.;
+
+  for (j = jStart; j < jEnd; j++) {
+    // Step 1: Get or compute aPonPln[1].
+    Unfolding_Point &aP1 = myGrid->ChangeValue(iStart, j);
+
+    // Add the first point aPonPln[1].
+    if (j == jStart)
+      aP1.SetPointOnPlane(gp_XY(0., 0.));
+
+    // Get aPonPln[1].
+    aPonPln[1] = aP1.GetPointOnPlane();
+
+    // Step 2: Compute aPonPln[0].
+    Unfolding_Point &aP2 = myGrid->ChangeValue(iStart, j + 1);
+
+    // Compute a curvelinear distance.
+    aCrvDist = CrvDistance(aP1, aP2, aSurface, myTolContour);
+
+    if (aCrvDist <= aTolConf) {
+      aPonPln[0] = aPonPln[1];
+    } else {
+      // Compute the Y direction.
+      if (j == jStart) {
+       aDirY.SetCoord(0., 1.);
+      } else {
+       Unfolding_Point &aP21 = myGrid->ChangeValue(iStart + 1, j);
+
+       aDirX = aP21.GetPointOnPlane().Subtracted(aPonPln[1]);
+       aNorm = aDirX.Modulus();
+
+       if (aNorm <= aTolConf) {
+         // Invalid case.
+         myErrorStatus = Unfolding_InvalidSurface;
+         return Standard_False;
+       }
+
+       // Compute the Y direction.
+       aDirX.Divide(aNorm);
+
+       gp_Vec2d aVecX(aDirX);
+       aVecX.Rotate(aP1.GetAngle());
+       aDirY = aVecX.XY();
+      }
+
+      // Compute point on plane.
+      aPonPln[0] = aPonPln[1].Added(aDirY.Multiplied(aCrvDist));
+    }
+
+    aP2.SetPointOnPlane(aPonPln[0]);
+
+    for (i = iStart; i < iEnd; i++) {
+      Unfolding_Point &aP11 = myGrid->ChangeValue(i,     j);
+      Unfolding_Point &aP21 = myGrid->ChangeValue(i + 1, j);
+      Unfolding_Point &aP22 = myGrid->ChangeValue(i + 1, j + 1);
+      Unfolding_Point &aP12 = myGrid->ChangeValue(i,     j + 1);
+
+      // Step 3: Compute aPonPln[2].
+      aCrvDist = CrvDistance(aP11, aP21, aSurface, myTolContour);
+
+      if (aCrvDist <= aTolConf) {
+       if (j > jStart) {
+         // Invalid case.
+         myErrorStatus = Unfolding_InvalidSurface;
+         return Standard_False;
+       }
+       aPonPln[2] = aPonPln[1];
+      } else {
+       aDirY = aPonPln[0].Subtracted(aPonPln[1]);
+       aNorm = aDirY.Modulus();
+
+       if (aNorm <= aTolConf) {
+         if (i == iStart) {
+           aDirX.SetCoord(1., 0.);
+         } else {
+           // Invalid case.
+           myErrorStatus = Unfolding_InvalidSurface;
+           return Standard_False;
+         }
+       } else {
+         // Compute the X direction.
+         aDirY.Divide(aNorm);
+
+         gp_Vec2d aVecY(aDirY);
+
+         aVecY.Rotate(-aP11.GetAngle());
+         aDirX  = aVecY.XY();
+       }
+
+       aPonPln[2] = aPonPln[1].Added(aDirX.Multiplied(aCrvDist));
+      }
+
+      if (j == jStart) {
+       aP21.SetPointOnPlane(aPonPln[2]);
+       aCrvDist2 = CrvDistance(aP21, aP22, aSurface, myTolContour);
+      } else {
+       aCrvDist2 = CrvDistance(aP21, aP22, aSurface, myTolContour);
+       Standard_Real aDif = aPonPln[2].Subtracted(aP21.GetPointOnPlane()).Modulus();
+//     aDistortionArea += aDif * aCrvDist * 0.5;
+       Standard_Real area = aDif * aCrvDist * 0.5;
+       if ( aCrvDist > gp::Resolution() ) {
+         Standard_Real aSinVal = 1. - (0.25*aDif*aDif / (aCrvDist*aCrvDist));
+         if ( aSinVal > 0. )
+           aSinVal = sqrt( aSinVal );
+         area *= aSinVal;
+       }
+       aDistortionArea += area;
+//     if (!aPonPln[2].IsEqual(aP21.GetPointOnPlane(), myTolContour)) {
+       if ( aDif > ( aCrvDist2 + aCrvDist ) ) {
+         // The surface cannot be unfolded.
+         myErrorStatus = Unfolding_InvalidSurface;
+         return Standard_False;
+       }
+
+       // Keep old point
+       aPonPln[2] = aP21.GetPointOnPlane();
+      }
+
+      // Step 4: Compute aPonPln[3].
+      gp_XY         aDiag  = aPonPln[2].Subtracted(aPonPln[0]);
+      Standard_Real aDDiag = aDiag.Modulus();
+
+      if (aDDiag <= aTolConf) {
+       // Invalid case.
+       myErrorStatus = Unfolding_InvalidSurface;
+       return Standard_False;
+      }
+
+      aCrvDist = CrvDistance(aP12, aP22, aSurface, myTolContour);
+
+      if (aCrvDist <= aTolConf) {
+       if (j < jEnd - 1) {
+         // Invalid case.
+         myErrorStatus = Unfolding_InvalidSurface;
+         return Standard_False;
+       }
+       aPonPln[3] = aPonPln[0];
+      } else {
+
+       if (aCrvDist2 <= aTolConf) {
+         if (i < iEnd - 1) {
+           // Invalid case.
+           myErrorStatus = Unfolding_InvalidSurface;
+           return Standard_False;
+         }
+         aPonPln[3] = aPonPln[2];
+       } else {
+         if (aCrvDist + aCrvDist2 <= aDDiag + aTolConf) {
+           // Invalid case.
+           myErrorStatus = Unfolding_InvalidSurface;
+           return Standard_False;
+         }
+
+         // Construct two circles
+         gp_Dir2d  aX(1., 0.);
+         gp_Ax22d  aCirc1Axis = gp_Ax22d(gp_Pnt2d(aPonPln[0]), aX);
+         gp_Ax22d  aCirc2Axis = gp_Ax22d(gp_Pnt2d(aPonPln[2]), aX);
+         gp_Circ2d aCirc1(aCirc1Axis, aCrvDist);
+         gp_Circ2d aCirc2(aCirc2Axis, aCrvDist2);
+
+         // Analytic intersection of two circles.
+         IntAna2d_AnaIntersection anInter(aCirc1, aCirc2);
+
+         if (!anInter.IsDone() || anInter.NbPoints() != 2) {
+           // Invalid case.
+           myErrorStatus = Unfolding_InvalidSurface;
+           return Standard_False;
+         }
+
+         gp_Pnt2d anIntP = anInter.Point(1).Value();
+         gp_XY    aD30(anIntP.XY().Subtracted(aPonPln[0]));
+
+         if (aD30.Crossed(aDiag) > 0.) {
+           anIntP = anInter.Point(2).Value();
+           aD30   = anIntP.XY().Subtracted(aPonPln[0]);
+
+           if (aD30.Crossed(aDiag) > 0.) {
+             // Invalid case.
+             myErrorStatus = Unfolding_InvalidSurface;
+             return Standard_False;
+           }
+         }
+
+         aPonPln[3] = anIntP.XY();
+       }
+      }
+
+      aP22.SetPointOnPlane(aPonPln[3]);
+
+      // Prepare points for next iterations.
+      aPonPln[0] = aPonPln[3];
+      aPonPln[1] = aPonPln[2];
+    }
+  }
+
+  myDataContainer->SetDistortionArea(aDistortionArea);
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : BuildPlanarFace
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::BuildPlanarFace
+                (const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples)
+{
+  Handle(Geom_Surface) aPlane   = new Geom_Plane(myPlane);
+  BRep_Builder         aBuilder;
+  TopoDS_Face          aPlanarFace;
+  Standard_Real        aTopoTol = Precision::Confusion();
+
+  aBuilder.MakeFace(aPlanarFace, aPlane, aTopoTol);
+
+  // Build wires.
+  TopExp_Explorer anExp(myDataContainer->GetFace(), TopAbs_WIRE);
+  TopoDS_Wire     aWire;
+
+  for (; anExp.More(); anExp.Next()) {
+    TopoDS_Wire aPlanarWire;
+
+    aWire = TopoDS::Wire(anExp.Current());
+
+    if (!BuildPlanarWire(aWire, theMapEdgeNbSamples, aPlanarWire)) {
+      myErrorStatus = Unfolding_Failure;
+
+      return Standard_False;
+    }
+
+    aBuilder.Add(aPlanarFace, aPlanarWire);
+  }
+
+  myDataContainer->SetUnfoldedFace(aPlanarFace);
+  myErrorStatus = Unfolding_Done;
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : BuildPlanarWire
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::BuildPlanarWire
+                      (const TopoDS_Wire                    &theWire,
+                      const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples,
+                            TopoDS_Wire                    &thePlanarWire)
+{
+  BRep_Builder           aBuilder;
+  BRepTools_WireExplorer aWExp(theWire, myDataContainer->GetFace());
+  TopoDS_Vertex          aV[2];
+  TopoDS_Vertex          aVEmpty;
+  TopoDS_Vertex          aVFirst[2];
+  gp_XY                  aBndPnt[2] = { gp_XY(0., 0.), gp_XY(0., 0.) };
+  gp_XY                  aPntFirst;
+
+  aBuilder.MakeWire(thePlanarWire);
+
+  for (; aWExp.More();) {
+    TopoDS_Edge anEdge = aWExp.Current();
+
+    aWExp.Next();
+    // Skip degenerated edges as they cannot be unfolded.
+    if (BRep_Tool::Degenerated(anEdge))
+      continue;
+
+    aV[0] = TopExp::LastVertex(anEdge, Standard_True);
+
+    if (!aVFirst[0].IsNull() && !aWExp.More() && aVFirst[0].IsSame(aV[0])) {
+      // Close the edge
+      aVEmpty    = aVFirst[1];
+      aBndPnt[1] = aPntFirst;
+    }
+
+    // Perform unfolding
+    TopTools_ListOfShape anEdges;
+
+    if (!UnfoldEdge(anEdge, aV[1], aVEmpty, theMapEdgeNbSamples,
+                   aBndPnt[0], aBndPnt[1], anEdges))
+      return Standard_False;
+    myDataContainer->SetEdgesForEdge(anEdge, anEdges);
+
+    if (anEdges.IsEmpty())
+      return Standard_False;
+
+    // Build result.
+    TopTools_ListIteratorOfListOfShape anIter(anEdges);
+
+    for (; anIter.More(); anIter.Next()) {
+      const TopoDS_Shape &aPlnEdge = anIter.Value();
+
+      aBuilder.Add(thePlanarWire, aPlnEdge);
+    }
+
+    if (aVFirst[1].IsNull()) {
+      aVFirst[0] = TopExp::FirstVertex(anEdge, Standard_True);
+      aVFirst[1] = TopExp::FirstVertex(TopoDS::Edge(anEdges.First()));
+      aPntFirst  = aBndPnt[0];
+    }
+
+    aV[1]      = TopExp::LastVertex(TopoDS::Edge(anEdges.Last()));
+    aBndPnt[0] = aBndPnt[1];
+  }
+
+  thePlanarWire.Closed(Standard_True);
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : UnfoldEdge
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::UnfoldEdge
+                         (const TopoDS_Edge                    &theEdge,
+                         const TopoDS_Vertex                  &theStartVtx,
+                         const TopoDS_Vertex                  &theEndVtx,
+                         const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples,
+                               gp_XY                          &theStartPnt,
+                               gp_XY                          &theEndPnt,
+                               TopTools_ListOfShape           &thePlnEdges) const
+{
+  Standard_Boolean      isReversed = theEdge.Orientation() == TopAbs_REVERSED;
+  Standard_Real         aTol       = BRep_Tool::Tolerance(theEdge);
+  Standard_Real         aParam[2];
+  const TopoDS_Face    &aFace      = myDataContainer->GetFace();
+  Handle(Geom2d_Curve)  a2dCurve   = BRep_Tool::CurveOnSurface
+                                      (theEdge, aFace, aParam[0], aParam[1]);
+  Standard_Integer     aNbPoints;
+
+  if (theMapEdgeNbSamples.IsBound(theEdge)) {
+    // Get already computed sampling.
+    aNbPoints = theMapEdgeNbSamples.Find(theEdge);
+  } else {
+    // Compute sampling
+    TopTools_ListOfShape aFaces;
+
+    aFaces.Append(aFace);
+    aNbPoints = Unfolding::NbSamples(theEdge, aFaces, myTolContour);
+  }
+
+  // Make sampling with middle points.
+  aNbPoints *= 2;
+  aNbPoints--;
+
+  Standard_Real       aCurPar = aParam[0];
+  Standard_Real       aStep   = (aParam[1] - aParam[0])/(aNbPoints - 1);
+  Standard_Integer    i       = 1;
+  gp_Pnt2d            aPUV;
+  gp_XY               aPOnP;
+  TColgp_SequenceOfXY aSeqPnts;
+  Standard_Integer    aNbIter = aNbPoints;
+
+  if (!theStartVtx.IsNull()) {
+    // Do not compute the first point.
+    if (isReversed)
+      aNbIter--;
+    else {
+      aCurPar += aStep;
+      i++;
+    }
+  }
+
+  if (!theEndVtx.IsNull()) {
+    // Do not compute the last point.
+    if (isReversed) {
+      aCurPar += aStep;
+      i++;
+    } else
+      aNbIter--;
+  }
+
+  for (; i <= aNbIter; i++) {
+    a2dCurve->D0(aCurPar, aPUV);
+
+    if (!ComputePointOnPlane(aPUV.XY(), aTol, aPOnP))
+      return Standard_False;
+
+    if (isReversed)
+      aSeqPnts.Prepend(aPOnP);
+    else
+      aSeqPnts.Append(aPOnP);
+
+    aCurPar = (i == aNbPoints - 1) ? aParam[1] : aCurPar + aStep;
+  }
+
+  // Prepend theStartPnt to the sequence of points if it was computed before.
+  if (!theStartVtx.IsNull())
+    aSeqPnts.Prepend(theStartPnt);
+  else
+    theStartPnt = aSeqPnts.First();
+
+  // Append theEndPoint to the sequence of points if it was computed before.
+  if (!theEndVtx.IsNull())
+    aSeqPnts.Append(theEndPnt);
+  else
+    theEndPnt = aSeqPnts.Last();
+
+  // Compute edges.
+  if (aSeqPnts.IsEmpty())
+    return Standard_False;
+
+  TopoDS_Vertex    aV[2];
+  Standard_Boolean isClosed = Standard_False;
+
+  TopExp::Vertices(theEdge, aV[0], aV[1], Standard_True);
+
+  if (aV[0].IsSame(aV[1])) {
+    gp_Pnt2d aP2d[2];
+
+    a2dCurve->D0(aParam[0], aP2d[0]);
+    a2dCurve->D0(aParam[1], aP2d[1]);
+    isClosed = aP2d[0].IsEqual(aP2d[1], aTol);
+  }
+
+  // Check if the first point coincides with theStartVtx.
+  Handle(Geom_Surface)  aPlane  = new Geom_Plane(myPlane);
+  const gp_XY          &aFirst  = aSeqPnts.First();
+  const gp_XY          &aLast   = aSeqPnts.Last();
+  gp_Pnt                aPFirst;
+  gp_Pnt                aPLast;
+
+  aPlane->D0(aFirst.X(), aFirst.Y(), aPFirst);
+  aPlane->D0(aLast.X(), aLast.Y(), aPLast);
+
+  if (!theStartVtx.IsNull()) {
+    gp_Pnt        aPStartVtx = BRep_Tool::Pnt(theStartVtx);
+    Standard_Real aVtxTol    = BRep_Tool::Tolerance(theStartVtx);
+    Standard_Real aTolConf   = Max(aVtxTol, myTolContour);
+
+    if (!aPFirst.IsEqual(aPStartVtx, aTolConf))
+      return Standard_False;
+
+    if (isClosed && !aPLast.IsEqual(aPStartVtx, aTolConf))
+      return Standard_False;
+  }
+
+  // Check if the last point coincides with theEndVtx.
+  if (!theEndVtx.IsNull()) {
+    gp_Pnt        aPEndVtx = BRep_Tool::Pnt(theEndVtx);
+    Standard_Real aVtxTol  = BRep_Tool::Tolerance(theEndVtx);
+    Standard_Real aTolConf = Max(aVtxTol, myTolContour);
+
+    if (!aPLast.IsEqual(aPEndVtx, aTolConf))
+      return Standard_False;
+  }
+
+  // Construct edges.
+  gp_Pnt             aPOnPln[2];
+  gp_Pnt             aPMid;
+  Standard_Real      aTopoTol = Precision::Confusion();
+  BRep_Builder       aBuilder;
+  Handle(Geom_Curve) aCurve;
+
+  for (i = 1; i <= aNbPoints; i += 2) {
+    const gp_XY &aP = aSeqPnts.Value(i);
+
+    aPlane->D0(aP.X(), aP.Y(), aPOnPln[1]);
+
+    // Get or compute aV[1].
+    if (i == 1 && !theStartVtx.IsNull()) {
+      aV[1] = theStartVtx;
+    } else if (i == aNbPoints) {
+      if (isClosed && !theStartVtx.IsNull())
+       aV[1] = theStartVtx;
+      else if(!theEndVtx.IsNull())
+       aV[1] = theEndVtx;
+      else
+       aBuilder.MakeVertex(aV[1], aPOnPln[1], aTopoTol);
+    } else
+      aBuilder.MakeVertex(aV[1], aPOnPln[1], aTopoTol);
+
+    if (i == 1) {
+      aV[0] = aV[1];
+      continue;
+    }
+
+    // Compute a curve
+    const gp_XY &aPm1 = aSeqPnts.Value(i - 1);
+
+    aPOnPln[0] = BRep_Tool::Pnt(aV[0]);
+    aPlane->D0(aPm1.X(), aPm1.Y(), aPMid);
+
+    aCurve = MakeCurve(aPOnPln[0], aPMid, aPOnPln[1], myPlane, myTolContour);
+
+    if (aCurve.IsNull())
+      return Standard_False;
+
+    // Construct the edge.
+    BRepBuilderAPI_MakeEdge aMkEdge(aCurve, aV[0], aV[1]);
+
+    if (!aMkEdge.IsDone())
+      return Standard_False;
+
+    const TopoDS_Edge &anEdge = aMkEdge.Edge();
+
+    thePlnEdges.Append(anEdge);
+    aV[0] = aV[1];
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : ComputePointOnPlane
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::ComputePointOnPlane
+                   (const gp_XY         &thePoint,
+                   const Standard_Real  theEdgeTol,
+                         gp_XY         &thePointOnPlane) const
+{
+  Standard_Integer i;
+  Standard_Integer j;
+  Standard_Integer iStart = myGrid->LowerRow();
+  Standard_Integer jStart = myGrid->LowerCol();
+  Standard_Integer iEnd   = myGrid->UpperRow();
+  Standard_Integer jEnd   = myGrid->UpperCol();
+
+  GetCell(thePoint, myGrid, theEdgeTol, i, j);
+
+  if (i < iStart)
+    i++;
+
+  if (j < jStart)
+    j++;
+
+  const Unfolding_Point &aP11     = myGrid->Value(i, j);
+  gp_Pnt                 aPOnSurf;
+  gp_XYZ                 aDP;
+  Handle(Geom_Surface)   aSurface =
+                            BRep_Tool::Surface(myDataContainer->GetFace());
+
+  aSurface->D0(thePoint.X(), thePoint.Y(), aPOnSurf);
+  aDP = aPOnSurf.XYZ();
+  aDP.Subtract(aP11.GetPointOnSurface());
+
+  if (aDP.Modulus() < myTolContour) {
+    thePointOnPlane = aP11.GetPointOnPlane();
+    return Standard_True;
+  }
+
+  gp_XY  aDP2d = thePoint.Subtracted(gp_XY(aP11.GetU(), aP11.GetV()));
+  gp_XYZ aDIso;
+  gp_XY  aDIso2d;
+  gp_XY  aDIsoSurf;
+
+  // Get direction along V.
+  if (j == jEnd) {
+    const Unfolding_Point &aP1M1 = myGrid->Value(i, j - 1);
+    aDIso     = aP11.GetPointOnSurface() - aP1M1.GetPointOnSurface();
+    aDIso2d   = aP11.GetPointOnPlane()   - aP1M1.GetPointOnPlane();
+    aDIsoSurf.SetCoord(aP11.GetU() - aP1M1.GetU(), aP11.GetV() - aP1M1.GetV());
+  } else {
+    const Unfolding_Point &aP12 = myGrid->Value(i, j + 1);
+    aDIso    = aP12.GetPointOnSurface() - aP11.GetPointOnSurface();
+    aDIso2d  = aP12.GetPointOnPlane()   - aP11.GetPointOnPlane();
+    aDIsoSurf.SetCoord(aP12.GetU() - aP11.GetU(), aP12.GetV() - aP11.GetV());
+  }
+
+  if (aDIso.Modulus() <= myTolContour) {
+    // Get direction along U.
+    if (i == iEnd) {
+      const Unfolding_Point &aPM11 = myGrid->Value(i - 1, j);
+      aDIso    = aP11.GetPointOnSurface() - aPM11.GetPointOnSurface();
+      aDIso2d  = aP11.GetPointOnPlane()   - aPM11.GetPointOnPlane();
+      aDIsoSurf.SetCoord(aP11.GetU() - aPM11.GetU(), aP11.GetV() - aPM11.GetV());
+    } else {
+      const Unfolding_Point &aP21 = myGrid->Value(i + 1, j);
+      aDIso    = aP21.GetPointOnSurface() - aP11.GetPointOnSurface();
+      aDIso2d  = aP21.GetPointOnPlane()   - aP11.GetPointOnPlane();
+      aDIsoSurf.SetCoord(aP21.GetU() - aP11.GetU(), aP21.GetV() - aP11.GetV());
+    }
+  }
+
+  if (aDIso.Modulus() <= myTolContour)
+    return Standard_False;
+
+  // Compute angle between aDP and aDIso
+  gp_Vec        aVecIso(aDIso);
+  Standard_Real anAngle = aVecIso.Angle(gp_Vec(aDP));
+
+  if (aDP2d.Crossed(aDIsoSurf) < 0.)
+    anAngle = -anAngle;
+
+  // Rotate DIso2d by anAngle.
+  gp_Dir2d aPDir(aDIso2d);
+
+  aPDir.Rotate(-anAngle);
+
+  Unfolding_Point aPoint;
+  Standard_Real   aCrvDist;
+
+  aPoint.SetPointOnSurface(aPOnSurf.XYZ());
+  aPoint.SetParameters(thePoint.X(), thePoint.Y());
+  aCrvDist = CrvDistance(aP11, aPoint, aSurface, myTolContour);
+
+  // Compute point on plane
+  thePointOnPlane  = aP11.GetPointOnPlane();
+  thePointOnPlane += aPDir.XY().Multiplied(aCrvDist);
+
+  return Standard_True;
+}
+
+static void AdjustToDeflection(      Standard_Integer     &theNbPointsU, 
+                                    Standard_Integer     &theNbPointsV,
+                              const Handle(Geom_Surface) &theSurface, 
+                              const Standard_Real         theUMin,
+                              const Standard_Real         theUMax,
+                              const Standard_Real         theVMin,
+                              const Standard_Real         theVMax,
+                              const Standard_Real         theDeflection)
+{
+  if ( theNbPointsU < 2 )
+    theNbPointsU = 2;
+
+  if ( theNbPointsV < 2 )
+    theNbPointsV = 2;
+  Standard_Real        aUStep   = (theUMax - theUMin)/(theNbPointsU - 1);
+  Standard_Real        aVStep   = (theVMax - theVMin)/(theNbPointsV - 1);
+  Standard_Real        aUPar;
+  Standard_Real        aVPar;
+  Standard_Integer     i;
+  Standard_Integer     j;
+  TColgp_Array2OfPnt   aMesh(1, theNbPointsU, 1, theNbPointsV);
+  gp_Pnt               aPnt;
+  
+
+  for (aUPar = theUMin, i = 1; i <= theNbPointsU; i++) {
+    for (aVPar = theVMin, j = 1; j <= theNbPointsV; j++) {
+      aPnt = theSurface->Value(aUPar, aVPar);
+      aMesh.SetValue(i, j, aPnt);
+      aVPar = (j == theNbPointsV - 1) ? theVMax : aVPar + aVStep;
+    }
+    aUPar = (i == theNbPointsU - 1) ? theUMax : aUPar + aUStep;
+  }
+  Standard_Real aMaxDist = 0.;
+  Standard_Real aMaxDifU = 0.;
+  Standard_Real aMaxDifV = 0.;
+
+  for (aUPar = theUMin + aUStep, i = 2; i <= theNbPointsU; i++) {
+    for (aVPar = theVMin + aVStep, j = 2; j <= theNbPointsV; j++) {
+      aPnt = theSurface->Value(aUPar-aUStep*0.5, aVPar-aVStep*0.5);
+      gp_XYZ xyz = aMesh.Value(i,j).XYZ();
+      xyz += aMesh.Value(i-1,j).XYZ();
+      xyz += aMesh.Value(i,j-1).XYZ();
+      xyz += aMesh.Value(i-1,j-1).XYZ();
+      xyz /= 4.;
+      Standard_Real aVal = aMesh.Value(i,j).SquareDistance(aMesh.Value(i-1,j));
+      if ( aMaxDifU < aVal )
+       aMaxDifU = aVal;
+
+      aVal = aMesh.Value(i,j-1).SquareDistance(aMesh.Value(i-1,j-1));
+      if ( aMaxDifU < aVal )
+       aMaxDifU = aVal;
+
+      aVal = aMesh.Value(i,j).SquareDistance(aMesh.Value(i,j-1));
+      if ( aMaxDifV < aVal )
+       aMaxDifV = aVal;
+
+      aVal = aMesh.Value(i-1,j).SquareDistance(aMesh.Value(i-1,j-1));
+      if ( aMaxDifV < aVal )
+       aMaxDifV = aVal;
+
+      Standard_Real aDist = aPnt.SquareDistance(gp_Pnt(xyz));
+      if ( aMaxDist < aDist )
+       aMaxDist = aDist;
+
+      aVPar = (j == theNbPointsV - 1) ? theVMax : aVPar + aVStep;
+    }
+    aUPar = (i == theNbPointsU - 1) ? theUMax : aUPar + aUStep;
+  }
+  aMaxDist = sqrt( aMaxDist );
+
+  if ( aMaxDist > theDeflection ) {
+    aMaxDifU = sqrt( aMaxDifU );
+    aMaxDifV = sqrt( aMaxDifV );
+
+    Standard_Real anewdifu = theDeflection * aMaxDifU / aMaxDist;
+    Standard_Real anewdifv = theDeflection * aMaxDifV / aMaxDist;
+
+    Standard_Real aVal = ( theUMax - theUMin ) / anewdifu;
+    if ( aVal > aLimitNumber )
+      aVal = aLimitNumber;
+    theNbPointsU = ( theNbPointsU < aVal ) ? Standard_Integer (aVal) : theNbPointsU;
+
+    aVal = ( theVMax - theVMin ) / anewdifv;
+    if ( aVal > aLimitNumber )
+      aVal = aLimitNumber;
+    theNbPointsV = ( theNbPointsV < aVal ) ? Standard_Integer (aVal) : theNbPointsV;
+  }
+}
diff --git a/src/Unfolding/Unfolding_Surface.hxx b/src/Unfolding/Unfolding_Surface.hxx
new file mode 100644 (file)
index 0000000..c86aae9
--- /dev/null
@@ -0,0 +1,167 @@
+// File:       Unfolding_Surface.cdl
+// Created:    Tue Jul 22 12:50:10 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:  Open CASCADE 2008
+
+#ifndef _Unfolding_Surface_HeaderFile
+#define _Unfolding_Surface_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <gp_Pln.hxx>
+#include <Standard_Real.hxx>
+#include <Unfolding_HArray2OfPoint.hxx>
+#include <Unfolding_ErrorStatus.hxx>
+#include <Standard_Boolean.hxx>
+#include <Standard_Integer.hxx>
+#include <TopTools_ListOfShape.hxx>
+class Unfolding_FaceDataContainer;
+class TopoDS_Face;
+class gp_Pln;
+#include <TopTools_DataMapOfShapeInteger.hxx>
+class TopoDS_Wire;
+class TopoDS_Edge;
+class TopoDS_Vertex;
+class gp_XY;
+
+//! This class is used to perform unfolding of a face onto a plane.
+//! To perform  this  operation it  is necessary  to initialize the
+//! object by a  face to  be unfolded,  a plane and a tolerance for
+//! operation. Then to call  the method Perform. The  result planar
+//! face can be  obtained using the  method GetResult. Error status
+//! can be obtained by the method ErrorStatus.
+class Unfolding_Surface 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Empty constructor
+  Standard_EXPORT Unfolding_Surface();
+  
+  //! Constructor. Initializes the object with the face, the plane and
+  //! the tolerance for operation.
+  Standard_EXPORT Unfolding_Surface(const TopoDS_Face& theFace, const gp_Pln& thePlane, const Standard_Real theContourTolerance, const Standard_Real theCurvatureTolerance = 0.001, const Standard_Real theDeflection = 0.001);
+  
+  //! Sets the face.
+    void SetFace (const TopoDS_Face& theFace);
+  
+  //! Returns the face.
+    const TopoDS_Face& GetFace() const;
+  
+  //! Sets the plane.
+    void SetPlane (const gp_Pln& thePlane);
+  
+  //! Returns the plane.
+    const gp_Pln& GetPlane() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetCurvatureTolerance (const Standard_Real theTolerance);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetCurvatureTolerance() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetContourTolerance (const Standard_Real theTolerance);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetContourTolerance() const;
+  
+  //! Sets the tolerance for the operation.
+    void SetDeflection (const Standard_Real theDeflection);
+  
+  //! Returns the tolerance for the operation.
+    Standard_Real GetDeflection() const;
+  
+  //! Performs computation of  the unfolded  surface. It returns
+  //! Standard_True if the operation  succeeds otherwise returns
+  //! Standard_False. It is  possible to get the error status of
+  //! the  performed operation  using the  method ErrorStatus().
+  //! theMapEdgeNbSamples  is  the  map  of  edges as  keys  and
+  //! number of samples  for this  edge  as item. It is required
+  //! for predefined sampling of  edges of a face. If an edge is
+  //! absent in this map its sampling is automatically computed.
+  //! This feature is used to get same sampling for shared edges
+  //! on different faces.
+  Standard_EXPORT Standard_Boolean Perform (const TopTools_DataMapOfShapeInteger& theMapEdgeNbSamples);
+  
+  //! Returns error status of the operation. The error status can have
+  //! one of the following values:
+  //! - Unfolding_Done: operation is succeeded;
+  //! - Unfolding_NotDone: the method Perform() is not called yet;
+  //! - Unfolding_Failure: the operation is failed;
+  //! - Unfolding_InvalidSurface: the surface cannot be unfolded
+  //! without distortion;
+  //! - Unfolding_InvalidInput: invalid input for the operation.
+    Unfolding_ErrorStatus ErrorStatus() const;
+  
+  //! Returns data container. That stores all results of the operation.
+    Handle(Unfolding_FaceDataContainer) GetDataContainer() const;
+
+
+
+
+protected:
+
+  
+  //! Resets data to the initial state.
+    void Reset();
+
+
+
+
+private:
+
+  
+  //! Initializes the grid on surface. Computes a rectangular grid in
+  //! the parametric space of the face and computes the corresponding
+  //! 3d points on the surface.
+  Standard_EXPORT Standard_Boolean InitGrid();
+  
+  //! Computes and returns the numbers of sampling points
+  //! for U and V directions.
+  Standard_EXPORT void NbPoints (const Standard_Real theUMin, const Standard_Real theUMax, const Standard_Real theVMin, const Standard_Real theVMax, Standard_Integer& theNbPointsU, Standard_Integer& theNbPointsV) const;
+  
+  //! Performs unfolding of the grid of points onto the plane. Returns
+  //! Standard_True in  case of success and  Standard_False otherwise.
+  //! Initializes the error status of the operation.
+  Standard_EXPORT Standard_Boolean Unfolding();
+  
+  //! Constructs and returns a planar face.
+  Standard_EXPORT Standard_Boolean BuildPlanarFace (const TopTools_DataMapOfShapeInteger& theMapEdgeNbSamples);
+  
+  //! Constructs and returns planar unfolded wire from original one.
+  Standard_EXPORT Standard_Boolean BuildPlanarWire (const TopoDS_Wire& theWire, const TopTools_DataMapOfShapeInteger& theMapEdgeNbSamples, TopoDS_Wire& thePlanarWire);
+  
+  //! Constructs and returns a set of planar unfolded edges
+  //! from theEdge.
+  Standard_EXPORT Standard_Boolean UnfoldEdge (const TopoDS_Edge& theEdge, const TopoDS_Vertex& theStartVtx, const TopoDS_Vertex& theEndVtx, const TopTools_DataMapOfShapeInteger& theMapEdgeNbSamples, gp_XY& theStartPnt, gp_XY& theEndPnt, TopTools_ListOfShape& thePlnEdges) const;
+  
+  //! Computes and returns a point on plane that corresponds
+  //! to a point on a surface.
+  Standard_EXPORT Standard_Boolean ComputePointOnPlane (const gp_XY& thePoint, const Standard_Real theEdgeTol, gp_XY& thePointOnPlane) const;
+
+
+  Handle(Unfolding_FaceDataContainer) myDataContainer;
+  gp_Pln myPlane;
+  Standard_Real myTolContour;
+  Standard_Real myTolCurvature;
+  Standard_Real myDeflection;
+  Handle(Unfolding_HArray2OfPoint) myGrid;
+  Unfolding_ErrorStatus myErrorStatus;
+
+
+};
+
+
+#include <Unfolding_Surface.lxx>
+
+
+
+
+
+#endif // _Unfolding_Surface_HeaderFile
diff --git a/src/Unfolding/Unfolding_Surface.lxx b/src/Unfolding/Unfolding_Surface.lxx
new file mode 100644 (file)
index 0000000..ff7ff98
--- /dev/null
@@ -0,0 +1,132 @@
+// File:       Unfolding_Surface.lxx
+// Created:    Tue Jul 22 16:13:39 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <Unfolding_FaceDataContainer.hxx>
+
+
+//=======================================================================
+//function : SetFace
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Surface::SetFace (const TopoDS_Face &theFace)
+{
+  myDataContainer->SetFace(theFace);
+  Reset();
+}
+
+//=======================================================================
+//function : GetFace
+//purpose  : 
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_Surface::GetFace () const
+{
+  return myDataContainer->GetFace();
+}
+
+//=======================================================================
+//function : SetPlane
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Surface::SetPlane (const gp_Pln &thePlane)
+{
+  myPlane = thePlane;
+  Reset();
+}
+
+//=======================================================================
+//function : GetPlane
+//purpose  : 
+//=======================================================================
+
+inline const gp_Pln &Unfolding_Surface::GetPlane () const
+{
+  return myPlane;
+}
+
+//=======================================================================
+//function : SetTolerance
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Surface::SetContourTolerance (const Standard_Real theTolerance)
+{
+  myTolContour = theTolerance;
+  Reset();
+}
+
+//=======================================================================
+//function : GetTolerance
+//purpose  : 
+//=======================================================================
+
+inline Standard_Real Unfolding_Surface::GetContourTolerance () const
+{
+  return myTolContour;
+}
+
+inline void Unfolding_Surface::SetCurvatureTolerance(const Standard_Real theTolerance) 
+{
+  myTolCurvature = theTolerance;
+  Reset();
+}
+
+inline Standard_Real Unfolding_Surface::GetCurvatureTolerance() const
+{
+  return myTolCurvature;
+}
+
+inline void Unfolding_Surface::SetDeflection(const Standard_Real theDeflection) 
+{
+  myDeflection = theDeflection;
+  Reset();
+}
+
+inline Standard_Real Unfolding_Surface::GetDeflection() const
+{
+  return myDeflection;
+}
+
+
+//=======================================================================
+//function : ErrorStatus
+//purpose  : 
+//=======================================================================
+
+inline Unfolding_ErrorStatus Unfolding_Surface::ErrorStatus () const
+{
+  return myErrorStatus;
+}
+
+//=======================================================================
+//function : GetDataContainer
+//purpose  : 
+//=======================================================================
+
+inline Handle(Unfolding_FaceDataContainer)
+                                Unfolding_Surface::GetDataContainer() const
+{
+  return myDataContainer;
+}
+
+//=======================================================================
+//function : Reset
+//purpose  : 
+//=======================================================================
+
+inline void Unfolding_Surface::Reset()
+{
+  myDataContainer->Reset();
+  myErrorStatus = Unfolding_NotDone;
+
+  if (!myGrid.IsNull())
+    myGrid.Nullify();
+}
diff --git a/src/UnfoldingTest/FILES b/src/UnfoldingTest/FILES
new file mode 100644 (file)
index 0000000..082d500
--- /dev/null
@@ -0,0 +1,2 @@
+UnfoldingTest.cxx
+UnfoldingTest.hxx
diff --git a/src/UnfoldingTest/UnfoldingTest.cxx b/src/UnfoldingTest/UnfoldingTest.cxx
new file mode 100644 (file)
index 0000000..ae08ecd
--- /dev/null
@@ -0,0 +1,272 @@
+// File:       UnfoldingTest.cxx
+// Created:    Tue Jul 22 18:35:23 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <UnfoldingTest.hxx>
+#include <Draw.hxx>
+#include <Draw_PluginMacro.hxx>
+#include <Draw_Interpretor.hxx>
+#include <TopoDS_Shape.hxx>
+#include <DBRep.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <Geom_Surface.hxx>
+#include <DrawTrSurf.hxx>
+#include <Geom_Plane.hxx>
+#include <Unfolding_Surface.hxx>
+#include <Unfolding_Shell.hxx>
+#include <Unfolding.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+
+
+//=======================================================================
+//function : dumpError
+//purpose  : 
+//=======================================================================
+
+static void dumpError (Draw_Interpretor       &di,
+                      const Standard_Integer  theStatus)
+{
+  di << "  Status: ";
+
+  switch (theStatus) {
+  case Unfolding_Done:
+    di << "Done";
+    break;
+  case Unfolding_NotDone:
+    di << "NotDone";
+    break;
+  case Unfolding_Failure:
+    di << "Failure";
+    break;
+  case Unfolding_InvalidSurface:
+    di << "InvalidSurface";
+    break;
+  case Unfolding_InvalidInput:
+    di << "InvalidInput";
+    break;
+  case Unfolding_InvalidShape:
+    di << "InvalidShape";
+    break;
+  case Unfolding_ComplexShape:
+    di << "ComplexShape";
+    break;
+  default:
+    di << "Unknown";
+    break;
+  }
+
+  di << " \n";
+}
+
+//=======================================================================
+//function : unfolding
+//purpose  : 
+//=======================================================================
+static Standard_Integer unfolding (Draw_Interpretor &di,
+                                   Standard_Integer  n, const char** a)
+{
+  if (n < 4 || n > 7) {
+    di << "Usage: " << a[0] << " result face|shell plane [tol_contour] [tol_curvature] [deflection]" << "\n";
+    return 1;
+  }
+
+  // Get a shape from a[2].
+  TopoDS_Shape aShape = DBRep::Get(a[2]);
+
+  if (aShape.IsNull()) {
+    di << a[2] << " is not a shape!" << "\n";
+    return 1;
+  }
+
+  // Check if the shape is a face.
+  if (aShape.ShapeType() != TopAbs_FACE &&
+      aShape.ShapeType() != TopAbs_SHELL) {
+    di << a[2] << " is not a face or shell!" << "\n";
+    return 1;
+  }
+  TopoDS_Shell aShell;
+  TopoDS_Face aFace;
+  if (aShape.ShapeType() == TopAbs_FACE) {
+    aFace = TopoDS::Face( aShape );
+    if (aFace.IsNull()) {
+      di << a[2] << " is not a face!" << "\n";
+      return 1;
+    }
+  }
+  else {
+    aShell = TopoDS::Shell( aShape );
+  }
+
+  // Get a surface from a[3].
+  Handle(Geom_Surface) aSurface = DrawTrSurf::GetSurface(a[3]);
+
+  if (aSurface.IsNull()) {
+    di << a[3] << " is not a surface!" << "\n";
+    return 1;
+  }
+
+  // Cast the surface to a plane.
+  Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
+
+  if (aPlane.IsNull()) {
+    di << a[3] << " is not a plane!" << "\n";
+    return 1;
+  }
+
+  // Get the tolerance value.
+  Standard_Real aTolContour = 0.001;
+
+  if (n >= 5) {
+         aTolContour = Draw::Atof(a[4]);
+  } else {
+    di << "tolerance value is not provided. The default value " << aTolContour << " is used" << "\n";
+  }
+
+  // Get the curvature tolerance value.
+  Standard_Real aTolCurv = 0.001;
+
+  if (n >= 6) {
+    aTolCurv = Draw::Atof(a[5]);
+  } else {
+    di << "curvature value is not provided. The default value " << aTolCurv << " is used" << "\n";
+  }
+
+  // Get the curvature tolerance value.
+  Standard_Real aDefl = 0.001;
+
+  if (n == 7) {
+    aDefl = Draw::Atof(a[6]);
+  } else {
+    di << "deflection value is not provided. The default value " << aDefl << " is used" << "\n";
+  }
+
+
+  // Initialization of the unfolding algorithm
+  Standard_Boolean  isOK = Standard_False;
+  TopoDS_Shape aResult;
+  Standard_Integer aErrorStatus = 0;
+
+  if ( !aFace.IsNull() ) {
+    TopTools_DataMapOfShapeInteger anEmptyMap;
+    Unfolding_Surface anUnfold(aFace, aPlane->Pln(), aTolContour, aTolCurv, aDefl);
+    isOK = anUnfold.Perform(anEmptyMap);
+
+    Handle(Unfolding_FaceDataContainer) aData = anUnfold.GetDataContainer();
+
+    di << "Gauss curvature =" << aData->GetMaxGaussCurvature() << "\n";
+    di << "Area of error =" << aData->GetDistortionArea() << "\n";
+    if ( isOK )
+      aResult = aData->GetUnfoldedFace();
+    aErrorStatus = anUnfold.ErrorStatus();
+  }
+  else if ( !aShell.IsNull() ) {
+    Unfolding_Shell anUnfold(aShell, aPlane->Pln(), aTolContour, aTolCurv, aDefl);
+    isOK = anUnfold.Perform();
+
+    di << "Gauss curvature =" << anUnfold.GetMaxGaussCurvature() << "\n";
+    di << "Area of error =" << anUnfold.GetAreaError() << "\n";
+    if ( isOK )
+      aResult = anUnfold.GetResult();
+    aErrorStatus = anUnfold.ErrorStatus();
+  }
+
+  if (isOK) {
+    DBRep::Set(a[1], aResult);
+  } else {
+    di << "Unfolding failure!" << "\n";
+    dumpError(di, aErrorStatus);
+
+    return 1;
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : toshell
+//purpose  : 
+//=======================================================================
+
+static Standard_Integer toshell (Draw_Interpretor &di,
+                                Standard_Integer  n, const char** a)
+{
+  if (n != 3 && n != 4) {
+    di << "Usage: " << a[0] << " result shape [tolerance]" << "\n";;
+    return 1;
+  }
+
+  // Get a shape from a[2].
+  TopoDS_Shape aShape = DBRep::Get(a[2]);
+
+  if (aShape.IsNull()) {
+    di << a[2] << " is not a shape!" << "\n";
+    return 1;
+  }
+
+  // Get the tolerance value.
+  Standard_Real aTolerance = 1.e-6;
+
+  if (n == 4) {
+    aTolerance = Draw::Atof(a[3]);
+  } else {
+    di << "tolerance value is not provided. The default value " << aTolerance << " is used" << "\n";
+  }
+
+  Unfolding_ErrorStatus aStatus;
+  TopoDS_Shell          aResult = Unfolding::ToShell(aShape, aTolerance, aStatus);
+
+  if (aResult.IsNull()) {
+    di << "toshell failure!" << "\n";
+    dumpError(di, aStatus);
+
+    return 1;
+  }
+
+  DBRep::Set(a[1], aResult);
+
+  return 0;
+}
+
+//=======================================================================
+//function : Commands
+//purpose  : 
+//=======================================================================
+
+void UnfoldingTest::Commands(Draw_Interpretor &theDI)
+{
+  static Standard_Boolean done = Standard_False;
+
+  if (done)
+    return;
+
+  done = Standard_True;
+
+  // Chapter's name
+  const char* group = "Unfolding commands";
+
+  theDI.Add("unfolding","unfolding result face|shell plane [tol_contour] [tol_curvature] [deflection]",
+            __FILE__, unfolding, group);
+
+  theDI.Add("toshell","toshell result shape [tolerance]",
+            __FILE__, toshell, group);
+}
+
+//=======================================================================
+//function : Factory
+//purpose  : 
+//=======================================================================
+
+void UnfoldingTest::Factory(Draw_Interpretor &theDI)
+{
+  UnfoldingTest::Commands(theDI);
+#ifdef DEB
+      theDI << "Draw Plugin : Unfolding commands are loaded" << "\n";
+#endif
+}
+
+// Declare entry point PLUGINFACTORY
+DPLUGIN(UnfoldingTest)
diff --git a/src/UnfoldingTest/UnfoldingTest.hxx b/src/UnfoldingTest/UnfoldingTest.hxx
new file mode 100644 (file)
index 0000000..4f168ca
--- /dev/null
@@ -0,0 +1,55 @@
+// File:       UnfoldingTest.cdl
+// Created:    Tue Jul 22 18:15:41 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+//-Copyright:   Matra Datavision 2008
+
+#ifndef _UnfoldingTest_HeaderFile
+#define _UnfoldingTest_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Draw_Interpretor.hxx>
+
+
+//! This package defines a set of Draw commands for testing of
+//! functionality of the package Unfolding.
+class UnfoldingTest 
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! Adds Draw commands to the draw interpretor.
+  Standard_EXPORT static void Commands (Draw_Interpretor& theDI);
+  
+  //! Plugin entry point function.
+  Standard_EXPORT static void Factory (Draw_Interpretor& theDI);
+
+
+
+
+protected:
+
+
+
+
+
+private:
+
+
+
+
+
+};
+
+
+
+
+
+
+
+#endif // _UnfoldingTest_HeaderFile