]> OCCT Git - occt-copy.git/commitdiff
Preparing OCCT development branch
authorbugmaster <bugmaster@opencascade.com>
Tue, 10 Nov 2015 10:09:07 +0000 (13:09 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 10 Nov 2015 10:09:07 +0000 (13:09 +0300)
61 files changed:
src/DrawResources/DrawPlugin
src/DrawResources/DrawPlugin.bak [new file with mode: 0644]
src/HelixBRep/HelixBRep.cdl [new file with mode: 0644]
src/HelixBRep/HelixBRep_BuilderHelix.cdl [new file with mode: 0644]
src/HelixBRep/HelixBRep_BuilderHelix.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelix.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelix.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixCoil.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixGen.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_BuilderHelixGen.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HHelixCurve.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_HHelixCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_HelixCurve.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_HelixCurve.cxx [new file with mode: 0644]
src/HelixGeom/HelixGeom_Tools.cdl [new file with mode: 0644]
src/HelixGeom/HelixGeom_Tools.cxx [new file with mode: 0644]
src/HelixTest/FILES [new file with mode: 0644]
src/HelixTest/HelixTest.cdl [new file with mode: 0644]
src/HelixTest/HelixTest.cxx [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/QABugs/QABugs_19.cxx
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/EXTERNLIB [new file with mode: 0644]
src/TKUnfolding/FILES [new file with mode: 0644]
src/TKUnfolding/PACKAGES [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/Unfolding.cdl [new file with mode: 0644]
src/Unfolding/Unfolding.cxx [new file with mode: 0644]
src/Unfolding/Unfolding.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataContainer.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_FaceDataMapHasher.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_FunctionWithDerivative.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_FunctionWithDerivative.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Point.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_Point.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Point.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Shell.lxx [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.cdl [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.cxx [new file with mode: 0644]
src/Unfolding/Unfolding_Surface.lxx [new file with mode: 0644]
src/UnfoldingTest/UnfoldingTest.cdl [new file with mode: 0644]
src/UnfoldingTest/UnfoldingTest.cxx [new file with mode: 0644]
src/ViewerTest/ViewerTest_ViewerCommands.cxx

index dc17bad4dbd09bd2034110c20241077da57c657e..42bee02a08d23da6495293f7240016b0f537c410 100755 (executable)
@@ -37,8 +37,11 @@ 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 +52,5 @@ TOBJ               : TKTObjDRAW
 DFBROWSER          : TKDFBrowser
 QAcommands         : TKQADraw
 VIS                : TKIVtkDraw
+TestHelix          : TKHelix
+TestUnfolding      : TKUnfoldingTest
\ No newline at end of file
diff --git a/src/DrawResources/DrawPlugin.bak b/src/DrawResources/DrawPlugin.bak
new file mode 100644 (file)
index 0000000..dc17bad
--- /dev/null
@@ -0,0 +1,51 @@
+! Description of available plugins for DRAW Test Harness
+! *****************************************************************************
+!
+! Format of the file is compliant with the standard Open CASCADE resource files
+! (see the Resource_Manager.cdl file for details).
+!
+! Each key defines a sequence of either further keys or a name of the dynamic
+! library. Keys can be nested down to an arbitrary level. However, make sure
+! there are no cyclic dependencies (internal checks are not performed).
+! 
+! For details how to implement a DRAW plugin refer to the Test Harness User's
+! Guide.
+!
+! To load a plugin use the following command in DRAW:
+!
+! Draw> pload [-PluginFileName] [[Key1] [Key2]...], where:
+!     <-PluginFileName> - Defines the name of a resource file.
+!                         If this parameter is omitted then the default name DrawPlugin
+!                         is used.
+!                         According to the Open CASCADE resource file management rules
+!                         the environment variable CSF_<PluginFileName>Defaults must
+!                         be set and point to the directory storing the file. If it is
+!                         omitted then it defaults to $CASROOT/src/DrawResources.
+!     [Key]             - Defines the key(s) enumerating plugins to be loaded.
+!                         If no keys are specified then the key named DEFAULT is used
+!                         (if there is no such in the file then no plugins are loaded).
+!
+!
+! NOTE: Make sure the DATAEXCHANGE or XDE key succeeds the OCAF key in a sequence
+!
+
+DEFAULT            : MODELING
+MODELING           : TOPTEST
+VISUALIZATION      : AISV
+OCAFKERNEL         : DCAF
+DATAEXCHANGEKERNEL : XSDRAW
+OCAF               : VISUALIZATION, OCAFKERNEL
+DATAEXCHANGE       : XDE, VISUALIZATION
+XDE                : DATAEXCHANGEKERNEL, XDEDRAW
+FULL               : MODELING, OCAFKERNEL, VISUALIZATION 
+ALL                : MODELING, OCAFKERNEL, DATAEXCHANGE
+
+TOPTEST            : TKTopTest
+DCAF               : TKDCAF
+AISV               : TKViewerTest
+XSDRAW             : TKXSDRAW
+XDEDRAW            : TKXDEDRAW
+TOBJ               : TKTObjDRAW
+DFBROWSER          : TKDFBrowser
+QAcommands         : TKQADraw
+VIS                : TKIVtkDraw
diff --git a/src/HelixBRep/HelixBRep.cdl b/src/HelixBRep/HelixBRep.cdl
new file mode 100644 (file)
index 0000000..07617d0
--- /dev/null
@@ -0,0 +1,21 @@
+-- File:       HelixBRep.cdl
+
+
+package HelixBRep 
+
+       ---Purpose: 
+
+uses  
+    gp, 
+    TopoDS, 
+    GeomAbs, 
+    TColStd, 
+    TopTools,
+    HelixGeom
+    
+is  
+    class BuilderHelix; 
+
+    
+end HelixBRep;
+
diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.cdl b/src/HelixBRep/HelixBRep_BuilderHelix.cdl
new file mode 100644 (file)
index 0000000..54df5d2
--- /dev/null
@@ -0,0 +1,145 @@
+-- File:       HelixBRep_BuilderHelix.cdl
+
+class  BuilderHelix  from  HelixBRep 
+       ---Purpose:  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.
+        
+uses 
+     Ax1  from  gp, 
+     Ax3  from  gp, 
+     Pnt  from  gp,  
+     Array1OfReal  from TColStd,
+     HArray1OfReal  from TColStd,
+     Array1OfBoolean  from TColStd,
+     HArray1OfBoolean  from TColStd,
+     Shape  from  GeomAbs,
+     Shape  from  TopoDS, 
+     Wire  from  TopoDS,  
+     Edge  from  TopoDS,
+     ListOfShape  from  TopTools     
+is 
+    Create
+       ---Purpose:  Empty  constructor
+       returns BuilderHelix from HelixBRep; 
+    ---C++: alias "Standard_EXPORT virtual ~HelixBRep_BuilderHelix();"      
+                          
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiams:  Array1OfReal  from  TColStd; 
+                          theHeights:  Array1OfReal  from TColStd ; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theIsPitches:   Array1OfBoolean  from  TColStd); 
+       ---Purpose:  Sets  parameters  of  general  composite  helix
+                          
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiam:  Real  from  Standard; 
+                          theHeights:  Array1OfReal  from TColStd ; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theIsPitches:   Array1OfBoolean  from  TColStd); 
+       ---Purpose:  Sets  parameters  of pure  helix
+                          
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiam1:  Real  from  Standard; 
+                          theDiam2:  Real  from  Standard; 
+                          theHeights:  Array1OfReal  from TColStd ; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theIsPitches:   Array1OfBoolean  from  TColStd); 
+       ---Purpose:  Sets  parameters  of pure spiral
+                          
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiams:  Array1OfReal  from  TColStd; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theNbTurns:  Array1OfReal  from TColStd); 
+       ---Purpose:  Sets  parameters  of  general  composite  helix
+                          
+                                 
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiam:  Real  from  Standard; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theNbTurns:  Array1OfReal  from TColStd); 
+       ---Purpose:  Sets  parameters  of pure  helix
+                          
+    SetParameters(me:out;  theAxis:  Ax3  from  gp;   
+                          theDiam1:  Real  from  Standard; 
+                          theDiam2:  Real  from  Standard; 
+                          thePitches:  Array1OfReal  from TColStd ; 
+                          theNbTurns:  Array1OfReal  from TColStd); 
+       ---Purpose:  Sets  parameters  of pure spiral
+                          
+                          
+    SetApproxParameters(me:out;  theTolerance:  Real  from  Standard; 
+                                 theMaxDegree:  Integer  from  Standard; 
+                                theContinuity:  Shape  from  GeomAbs); 
+       ---Purpose:  Sets  parameters for  approximation
+                                 
+                          
+    Perform(me:out) ; 
+       ---Purpose:  Performs  calculations
+     
+    ToleranceReached(me)  returns  Real  from  Standard;                                  
+       ---Purpose:  Gets  tolerance  reached  by  approximation 
+                                     
+    ErrorStatus(me)           
+        ---Purpose: Returns  error  status  of  algorithm 
+        returns Integer from Standard;  
+                              
+    WarningStatus(me)        
+        ---Purpose: Returns  warning  status  of  algorithm   
+        returns Integer from Standard;   
+       
+    Shape(me)  returns  Shape  from  TopoDS;  
+        ---Purpose:  Gets  result  of  algorithm 
+    ---C++: return const &    
+     
+    BuildPart(me:in  out;  theAxis:  Ax1  from  gp;   
+                           thePStart:  Pnt  from  gp; 
+                          theHeight:  Real  from  Standard; 
+                          thePitch:  Real  from  Standard; 
+                          theTaperAngle:  Real  from  Standard; 
+                          theIsClockwise:  Boolean  from  Standard; 
+                          thePart:  out  Wire  from  TopoDS)
+                           
+                          is  private; 
+                           
+    Smoothing(me:  in  out;  theParts: in out  ListOfShape  from  TopTools) 
+       is  private;     
+
+    SmoothingEdges(me:  in  out; thePrev, theNext:  in  out  Edge  from  TopoDS) 
+       is  private;
+         
+fields 
+    myAxis3:  Ax3  from  gp  is  protected;  
+    myDiams:  HArray1OfReal  from  TColStd is  protected;
+    myHeights:  HArray1OfReal  from  TColStd is  protected; 
+    myPitches:  HArray1OfReal  from  TColStd is  protected; 
+    myIsPitches:  HArray1OfBoolean  from  TColStd  is  protected;  
+    myNParts:  Integer  from  Standard;     
+         
+    myTolerance:  Real  from  Standard  is  protected;
+    myTolReached:  Real  from  Standard  is  protected;
+    myContinuity:  Shape  from  GeomAbs  is  protected; 
+    myMaxDegree:  Integer  from  Standard  is  protected;
+    myMaxSegments:  Integer  from  Standard  is  protected; 
+     
+    myErrorStatus   : Integer from Standard is protected; 
+    myWarningStatus : Integer from Standard is protected; 
+    
+    myShape:  Shape  from  TopoDS  is  protected;    
+    
+     
+end  BuilderHelix;    
+
diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.cxx b/src/HelixBRep/HelixBRep_BuilderHelix.cxx
new file mode 100644 (file)
index 0000000..d58e1f4
--- /dev/null
@@ -0,0 +1,630 @@
+// File:       HelixBRep_BuilderHelix.cxx
+
+#include <HelixBRep_BuilderHelix.ixx>
+
+#include <HelixGeom_BuilderHelix.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <gp_Pnt.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Wire.hxx>
+#include <gp.hxx>
+#include <Precision.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Vec.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Vec.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <TopExp.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <Geom_BSplineCurve.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/HelixGeom/HelixGeom.cdl b/src/HelixGeom/HelixGeom.cdl
new file mode 100644 (file)
index 0000000..62d0ac4
--- /dev/null
@@ -0,0 +1,35 @@
+-- File:       HelixGeom.cdl
+
+
+package HelixGeom 
+
+       ---Purpose: 
+
+uses  
+    MMgt,
+    gp, 
+    TColStd,
+    GeomAbs,  
+    Geom,  
+    TColGeom,
+    GeomAdaptor, 
+    Adaptor3d, 
+    GeomFill 
+    
+is  
+    
+    deferred class BuilderApproxCurve;
+    deferred class BuilderHelixGen;
+     
+    class HelixCurve;  
+    class HHelixCurve;   
+    class BuilderHelixCoil;
+    class BuilderHelix;
+    class Tools; 
+
+    -- 
+    private class GHHelixCurve instantiates GenHCurve from Adaptor3d
+            (HelixCurve from HelixGeom);
+
+end HelixGeom;
+
diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl
new file mode 100644 (file)
index 0000000..b2292ee
--- /dev/null
@@ -0,0 +1,72 @@
+-- File:       HelixGeom_BuilderApproxCurve.cdl
+
+
+deferred class BuilderApproxCurve from HelixGeom 
+
+       ---Purpose: Root class for algorithm of building helix curves
+
+uses 
+    Shape from GeomAbs, 
+    SequenceOfCurve from TColGeom
+
+--raises
+
+is 
+    Initialize 
+       ---Purpose: Sets  default  values  of  aprroximation  parameters
+       returns BuilderApproxCurve from HelixGeom; 
+    ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderApproxCurve();"  
+     
+    SetApproxParameters(me:out; 
+           aCont     : Shape from GeomAbs;  
+           aMaxDegree: Integer from Standard; 
+           aMaxSeg   : Integer from Standard); 
+       ---Purpose: Sets  aprroximation  parameters
+        
+    ApproxParameters(me; 
+           aCont     :out Shape from GeomAbs;  
+           aMaxDegree:out Integer from Standard; 
+           aMaxSeg   :out Integer from Standard);     
+       ---Purpose: Gets  aprroximation  parameters
+
+    SetTolerance(me:out; 
+           aTolerance: Real from Standard); 
+       ---Purpose: Sets  aprroximation  tolerance
+            
+    Tolerance(me) 
+       returns Real from Standard;  
+       ---Purpose: Gets  aprroximation  tolerance
+
+    ToleranceReached(me)  
+       ---Purpose: Gets actual tolerance reached by  approximation  algorithm
+       returns  Real from Standard; 
+
+    Curves(me)   
+       ---Purpose: Gets sequence of Bspline  curves  representing  helix  coins.
+       returns SequenceOfCurve from TColGeom; 
+    ---C++: return const &      
+    
+    ErrorStatus(me)           
+        ---Purpose: Returns  error  status  of  algorithm
+        returns Integer from Standard;   
+       
+    WarningStatus(me)          
+        ---Purpose: Returns  warning  status  of  algorithm 
+        returns Integer from Standard;    
+       
+    Perform(me:out)            
+        ---Purpose: Performs  calculations.  
+        --  Must  be  redefined. 
+        is deferred;             
+fields 
+   myErrorStatus   : Integer from Standard is protected;
+   myWarningStatus : Integer from Standard is protected;
+   myTolerance  : Real from Standard is protected;  
+   myCont       : Shape from GeomAbs is protected; 
+   myMaxDegree  : Integer from Standard is protected; 
+   myMaxSeg     : Integer from Standard is protected; 
+   --     
+   myTolReached : Real from Standard is protected;   
+   myCurves     : SequenceOfCurve from TColGeom is protected; 
+
+end BuilderApproxCurve;
diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx
new file mode 100644 (file)
index 0000000..925d4d6
--- /dev/null
@@ -0,0 +1,100 @@
+// File:       HelixGeom_BuilderApproxCurve.cxx
+
+#include <HelixGeom_BuilderApproxCurve.ixx>
+
+//=======================================================================
+//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_BuilderHelix.cdl b/src/HelixGeom/HelixGeom_BuilderHelix.cdl
new file mode 100644 (file)
index 0000000..1ea1958
--- /dev/null
@@ -0,0 +1,38 @@
+-- File:       HelixGeom_BuilderHelix.cdl
+
+
+class BuilderHelix from HelixGeom 
+       inherits BuilderHelixGen from HelixGeom  
+       
+       ---Purpose: Upper level class for geometrical algorithm of building 
+       --          helix curves using arbitrary axis
+
+uses
+    Ax2 from gp
+
+--raises
+
+is   
+    Create 
+       ---Purpose: Empty  constructor 
+       returns BuilderHelix from HelixGeom; 
+    ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelix();"  
+      
+    SetPosition (me:out;  
+       ---Purpose: Sets coordinate axes for helix 
+           aAx2 : Ax2 from gp);
+
+    Position (me)   
+       ---Purpose: Gets coordinate axes for helix 
+       returns Ax2 from gp; 
+    ---C++: return const &      
+
+    Perform(me:out) 
+       ---Purpose: Performs  calculations 
+       is redefined; 
+
+fields 
+    myPosition: Ax2 from gp is protected; 
+     
+end BuilderHelix;
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelix.cxx b/src/HelixGeom/HelixGeom_BuilderHelix.cxx
new file mode 100644 (file)
index 0000000..732998e
--- /dev/null
@@ -0,0 +1,165 @@
+// File:       HelixGeom_BuilderHelix.cxx
+
+
+#include <HelixGeom_BuilderHelix.ixx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <Geom_Curve.hxx>
+#include <gp_Trsf.hxx>
+#include <gp_Ax3.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_BuilderHelixCoil.cdl b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cdl
new file mode 100644 (file)
index 0000000..175dbed
--- /dev/null
@@ -0,0 +1,24 @@
+-- File:       HelixGeom_BuilderHelixCoil.cdl
+
+class BuilderHelixCoil from HelixGeom  
+       inherits BuilderHelixGen from HelixGeom 
+
+       ---Purpose: Implementation  of  algorithm  for  building  helix  coil  with 
+       --          axis  OZ
+
+--uses
+--raises
+
+is 
+    Create 
+       ---Purpose: Empty  constructor
+       returns BuilderHelixCoil from HelixGeom; 
+    ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelixCoil();"   
+    
+    Perform(me:out) 
+       ---Purpose: Performs  calculations
+       is redefined; 
+        
+end BuilderHelixCoil;
+
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx
new file mode 100644 (file)
index 0000000..2021fc4
--- /dev/null
@@ -0,0 +1,63 @@
+// File:       HelixGeom_BuilderHelixCoil.cxx
+
+
+#include <HelixGeom_BuilderHelixCoil.ixx>
+#include <HelixGeom_Tools.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.hxx>
+#include <Geom_BSplineCurve.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_BuilderHelixGen.cdl b/src/HelixGeom/HelixGeom_BuilderHelixGen.cdl
new file mode 100644 (file)
index 0000000..e5f82b9
--- /dev/null
@@ -0,0 +1,45 @@
+-- File:       HelixGeom_BuilderHelixGen.cdl
+
+deferred class BuilderHelixGen from HelixGeom  
+       inherits BuilderApproxCurve from HelixGeom 
+
+       ---Purpose: Root  class  for  algorithms  of  building  helix  curves
+       
+
+--uses
+--raises
+
+is 
+    Initialize 
+       ---Purpose: Sets  default  parameters
+       returns BuilderHelixGen from HelixGeom; 
+    ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelixGen();" 
+     
+    SetCurveParameters(me:out; 
+           aT1          :Real from Standard;
+           aT2          :Real from Standard; 
+           aPitch       :Real from Standard;
+           aRStart      :Real from Standard;
+           aTaperAngle  :Real from Standard; 
+           bIsClockwise :Boolean from Standard); 
+       ---Purpose: Sets  parameters  for  building  helix  curves
+                            
+    CurveParameters(me; 
+           aT1          :out Real from Standard;
+           aT2          :out Real from Standard;
+           aPitch       :out Real from Standard;
+           aRStart      :out Real from Standard;
+           aTaperAngle  :out Real from Standard; 
+           bIsClockwise :out Boolean from Standard); 
+       ---Purpose: Gets  parameters  for  building  helix  curves
+
+fields
+    myT1         : Real from Standard is protected;     
+    myT2         : Real from Standard is protected;     
+    myPitch      : Real from Standard is protected;     
+    myRStart     : Real from Standard is protected;     
+    myTaperAngle : Real from Standard is protected;     
+    myIsClockWise: Boolean from Standard is protected; 
+
+end BuilderHelixGen;
+
diff --git a/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx b/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx
new file mode 100644 (file)
index 0000000..fd0117c
--- /dev/null
@@ -0,0 +1,58 @@
+// File:       HelixGeom_BuilderHelixGen.cxx
+
+#include <HelixGeom_BuilderHelixGen.ixx>
+
+//=======================================================================
+//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_HHelixCurve.cdl b/src/HelixGeom/HelixGeom_HHelixCurve.cdl
new file mode 100644 (file)
index 0000000..1750654
--- /dev/null
@@ -0,0 +1,35 @@
+-- File:       HelixGeom_HHelixCurve.cdl
+
+class HHelixCurve from HelixGeom  
+    inherits  GHHelixCurve from HelixGeom  
+       
+       ---Purpose: HAdaptor class for helix  curve
+
+uses
+    HelixCurve from HelixGeom
+
+--raises
+
+is 
+    Create  
+       ---Purpose: Empty  constructor
+       returns HHelixCurve from HelixGeom; 
+        
+    Create(aC: HelixCurve from HelixGeom)  
+       ---Purpose: Constructor by  corresponding  adaptor  curve
+       returns HHelixCurve from HelixGeom;  
+
+    Create(aT1:Real from Standard;
+          aT2:Real from Standard;
+          aPitch:Real from Standard;
+          aRStart:Real from Standard;
+          aTaperAngle:Real from Standard;
+          aIsCW:Boolean from Standard) 
+       ---Purpose: Constructor by parameters
+       returns HHelixCurve from HelixGeom;  
+
+--fields
+
+end HHelixCurve;
+
+
diff --git a/src/HelixGeom/HelixGeom_HHelixCurve.cxx b/src/HelixGeom/HelixGeom_HHelixCurve.cxx
new file mode 100644 (file)
index 0000000..afb2dc3
--- /dev/null
@@ -0,0 +1,39 @@
+// File:       HelixGeom_HHelixCurve.cxx
+
+#include <HelixGeom_HHelixCurve.ixx>
+
+//=======================================================================
+//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_HelixCurve.cdl b/src/HelixGeom/HelixGeom_HelixCurve.cdl
new file mode 100644 (file)
index 0000000..6be3528
--- /dev/null
@@ -0,0 +1,140 @@
+-- File:       HelixGeom_HelixCurve.cdl
+
+class HelixCurve from HelixGeom  
+    inherits Curve from Adaptor3d
+
+       ---Purpose: Adaptor  class  for  calculation  helix  curve
+
+uses
+    Shape from GeomAbs, 
+    Pnt from gp, 
+    Vec from gp,
+    Array1OfReal from TColStd 
+    
+raises 
+    ConstructionError from Standard,
+    OutOfRange from Standard, 
+    DomainError from Standard
+is 
+    Create  
+       ---Purpose: Adaptor  class  for  calculation  helix  curve 
+       --          implementation  of  analytical  expressions
+       returns HelixCurve from HelixGeom;  
+        
+    Load(me:out); 
+       ---Purpose:  Sets  default  values  for  parameters
+     
+    Load(me:out; 
+           aT1:Real from Standard;
+           aT2:Real from Standard;
+           aPitch:Real from Standard;
+           aRStart:Real from Standard;
+           aTaperAngle:Real from Standard;
+           aIsCW:Boolean from Standard) 
+       ---Purpose:  Sets  helix  parameters
+       raises ConstructionError from Standard; 
+        
+    FirstParameter(me)  
+       ---Purpose:  Gets  first  parameter
+       returns Real from Standard 
+       is redefined; 
+        
+    LastParameter(me)  
+       ---Purpose:  Gets  last  parameter
+       returns Real from Standard 
+       is redefined; 
+        
+    Continuity(me)  
+       ---Purpose:  Gets  continuity
+       returns Shape from GeomAbs
+       is redefined;  
+
+    NbIntervals(me;  
+           S : Shape from GeomAbs)  
+       ---Purpose:  Gets number  of  intervals
+       returns Integer from Standard
+       is redefined;  
+        
+    Intervals(me;  
+           T :out Array1OfReal from TColStd; 
+           S : Shape from GeomAbs) 
+       ---Purpose:  Gets  parametric  intervals
+       is redefined; 
+        
+    Resolution(me; R3d :Real  from Standard)  
+       ---Purpose:  Gets  parametric  resolution
+       returns Real from Standard
+       is redefined; 
+        
+    IsClosed(me)  
+       ---Purpose:  Returns  False
+       returns Boolean from Standard
+       is redefined; 
+     
+    IsPeriodic(me)  
+       ---Purpose:  Returns  False
+       returns Boolean from Standard
+       is redefined; 
+        
+    Period(me)  
+       ---Purpose:  Returns  2*PI
+       returns Real from Standard
+       raises DomainError from Standard 
+       is redefined; 
+        
+    Value(me;  
+           U : Real from Standard)  
+       ---Purpose:  Gets  curve  point  for  parameter  U
+       returns Pnt from gp
+       is redefined; 
+     
+    D0 (me;  
+           U : Real from Standard;  
+           P : out Pnt from gp) 
+       ---Purpose:  Gets  curve  point  for  parameter  U
+       is redefined; 
+        
+    D1 (me;  
+           U : Real from Standard;  
+           P : out Pnt from gp;  
+           V1: out Vec from gp) 
+       ---Purpose:  Gets  curve  point  and  first  derivatives   
+        --           for  parameter  U
+       is redefined;  
+        
+        
+    D2 (me;  
+           U : Real from Standard;  
+           P  : out Pnt from gp;  
+           V1 : out Vec from gp; 
+           V2 : out Vec from gp) 
+       ---Purpose:  Gets  curve  point,  first and  second derivatives   
+        --           for  parameter  U
+       is redefined; 
+        
+        
+    DN (me;  
+           U : Real from Standard; 
+           N : Integer from Standard) 
+       ---Purpose:  Gets  curve  derivative  of  demanded  order  
+        --           for  parameter  U
+       returns Vec from gp 
+       raises  OutOfRange from Standard
+       is redefined;  
+        
+fields 
+    myFirst      : Real from Standard is protected;
+    myLast       : Real from Standard is protected; 
+    myPitch      : Real from Standard is protected; 
+    myRStart     : Real from Standard is protected; 
+    myTaperAngle : Real from Standard is protected; 
+    myIsClockWise: Boolean from Standard is protected; 
+    -- 
+    -- private
+    myC1         : Real from Standard is protected; 
+    myTgBeta     : Real from Standard is protected; 
+    myTolAngle   : Real from Standard is protected; 
+    
+end HelixCurve;
+
+
diff --git a/src/HelixGeom/HelixGeom_HelixCurve.cxx b/src/HelixGeom/HelixGeom_HelixCurve.cxx
new file mode 100644 (file)
index 0000000..48f8e08
--- /dev/null
@@ -0,0 +1,288 @@
+// File:       HelixGeom_HelixCurve.cxx
+
+#include <HelixGeom_HelixCurve.ixx>
+#include <math.h>
+#include <gp_Vec.hxx>
+#include <gp_Pnt.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_DomainError.hxx>
+
+//=======================================================================
+//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_Tools.cdl b/src/HelixGeom/HelixGeom_Tools.cdl
new file mode 100644 (file)
index 0000000..6c0aed6
--- /dev/null
@@ -0,0 +1,42 @@
+-- File:       HelixGeom_Tools.cdl
+
+
+class Tools from HelixGeom 
+
+       ---Purpose: Approximation  algorithms  for  bulding  helix  curves
+
+uses 
+    HCurve  from  Adaptor3d,
+    BSplineCurve from  Geom,
+    Shape from GeomAbs
+--raises
+
+is  
+    ApprHelix(myclass; 
+           aT1        :Real from Standard;
+           aT2        :Real from Standard;
+           aPitch     :Real from Standard;
+           aRStart    :Real from Standard;
+           aTaperAngle:Real from Standard;
+           aIsCW      :Boolean from Standard;  
+           aTol       :Real from Standard;
+           theBSpl    :out BSplineCurve from Geom; 
+           theMaxError:out Real  from  Standard)   
+       ---Purpose: Bulding  helix  curves
+       returns Integer from Standard;
+     
+    ApprCurve3D(myclass;  
+           theHC      :out HCurve  from  Adaptor3d; 
+           theTol     : Real  from  Standard; 
+           theCont    : Shape  from  GeomAbs; 
+           theMaxSeg  : Integer  from  Standard;
+           theMaxDeg  : Integer  from  Standard; 
+           theBSpl    :out  BSplineCurve  from  Geom; 
+           theMaxError:out  Real  from  Standard) 
+       ---Purpose: Reaprroximation  of  adaptor  curve
+       returns Integer from Standard;
+--fields
+
+end Tools;
+
+
diff --git a/src/HelixGeom/HelixGeom_Tools.cxx b/src/HelixGeom/HelixGeom_Tools.cxx
new file mode 100644 (file)
index 0000000..c0d655c
--- /dev/null
@@ -0,0 +1,168 @@
+// File:       HelixGeom_Tools.cxx
+
+
+
+#include <HelixGeom_Tools.ixx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <AdvApprox_DichoCutting.hxx>
+#include <AdvApprox_EvaluatorFunction.hxx>
+#include <AdvApprox_ApproxAFunction.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.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/HelixTest/FILES b/src/HelixTest/FILES
new file mode 100644 (file)
index 0000000..855ee4b
--- /dev/null
@@ -0,0 +1,2 @@
+HelixTest.cxx
+HelixTest_HelixCommands.cxx
diff --git a/src/HelixTest/HelixTest.cdl b/src/HelixTest/HelixTest.cdl
new file mode 100644 (file)
index 0000000..667a855
--- /dev/null
@@ -0,0 +1,19 @@
+-- File:       HelixTest.cdl
+
+
+package HelixTest 
+
+       ---Purpose: 
+
+uses
+    Draw,
+    DBRep, 
+    TopoDS,
+    gp
+is 
+   AllCommands  (aDI:out Interpretor from Draw); 
+   HelixCommands  (aDI:out Interpretor from Draw); 
+   Factory      (aDI:out Interpretor from Draw);  
+
+end HelixTest;
+
diff --git a/src/HelixTest/HelixTest.cxx b/src/HelixTest/HelixTest.cxx
new file mode 100644 (file)
index 0000000..210149d
--- /dev/null
@@ -0,0 +1,35 @@
+// File:       HelixTest.cxx
+
+#include <HelixTest.ixx>
+#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_HelixCommands.cxx b/src/HelixTest/HelixTest_HelixCommands.cxx
new file mode 100644 (file)
index 0000000..0f151c8
--- /dev/null
@@ -0,0 +1,559 @@
+// File:       HelixTest_HelixCommands.cxx
+
+#include <HelixTest.ixx>
+#include <Draw_Interpretor.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <Draw.hxx>
+#include <Draw_Viewer.hxx>
+#include <Draw_Marker3D.hxx>
+#include <Draw_Segment3D.hxx>
+#include <Draw_Color.hxx>
+#include <HelixGeom_Tools.hxx>
+
+#include <DrawTrSurf.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Line.hxx>
+
+#include <gp_Pln.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+
+#include <HelixBRep_BuilderHelix.hxx>
+#include <DBRep.hxx>
+#include <TopoDS_Shape.hxx>
+#include <gp.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <TColGeom_HArray1OfCurve.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.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 5ad90edc613cbd8cd1465d94c9529b31e27f76b3..7d767e742640f3279d37b8163644da86f28d297a 100755 (executable)
@@ -6,3 +6,5 @@ srcinc:::ModelingData.tcl
 srcinc:::Visualization.tcl
 srcinc:::ApplicationFramework.tcl
 srcinc:::DataExchange.tcl
+srcinc:::Helix.tcl
+srcinc:::Unfolding.tcl
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]
+}
index 02f24518edf42dca880e4e4c220c315adfa4d1be..2d5d613eec367fd0f9f658af02b2af724799734c 100755 (executable)
@@ -3270,47 +3270,6 @@ struct OCC25545_Functor
   mutable volatile int myIsRaceDetected;
 };
 
-//=======================================================================
-//function : OCC25545
-//purpose  : Tests data race when concurrently accessing TopLoc_Location::Transformation()
-//=======================================================================
-#ifdef HAVE_TBB
-static Standard_Integer OCC25545 (Draw_Interpretor& di, 
-                                  Standard_Integer, 
-                                  const char **)
-{
-  // Place vertices in a vector, giving the i-th vertex the
-  // transformation that translates it on the vector (i,0,0) from the origin.
-  size_t n = 1000;
-  std::vector<TopoDS_Shape> aShapeVec (n);
-  std::vector<TopLoc_Location> aLocVec (n);
-  TopoDS_Shape aShape = BRepBuilderAPI_MakeVertex (gp::Origin ());
-  aShapeVec[0] = aShape;
-  for (size_t i = 1; i < n; ++i) {
-    gp_Trsf aT;
-    aT.SetTranslation (gp_Vec (1, 0, 0));
-    aLocVec[i] = aLocVec[i - 1] * aT;
-    aShapeVec[i] = aShape.Moved (aLocVec[i]);
-  }
-
-  // Evaluator function will access vertices geometry
-  // concurrently
-  OCC25545_Functor aFunc(aShapeVec);
-
-  //concurrently process
-  tbb::parallel_for (size_t (0), n, aFunc, tbb::simple_partitioner ());
-  QVERIFY (!aFunc.myIsRaceDetected);
-  return 0;
-}
-#else
-static Standard_Integer OCC25545 (Draw_Interpretor&, 
-                                  Standard_Integer, 
-                                  const char **argv)
-{
-  cout << "Test skipped: command " << argv[0] << " requires TBB library" << endl;
-  return 0;
-}
-#endif
 
 //=======================================================================
 //function : OCC25547
@@ -4368,10 +4327,6 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) {
   theCommands.Add ("OCC25348", "OCC25348", __FILE__, OCC25348, group);
   theCommands.Add ("OCC25413", "OCC25413 shape", __FILE__, OCC25413, group);
   theCommands.Add ("OCC25446", "OCC25446 res b1 b2 op", __FILE__, OCC25446, group);
-  theCommands.Add ("OCC25545", 
-                   "no args; tests data race when concurrently accessing \n"
-                   "\t\tTopLoc_Location::Transformation()",
-                   __FILE__, OCC25545, group);
   theCommands.Add ("OCC25547", "OCC25547", __FILE__, OCC25547, group);
   theCommands.Add ("OCC24881", "OCC24881 shape", __FILE__, OCC24881, group);
   theCommands.Add ("OCC26172", "OCC26172", __FILE__, OCC26172, group);
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/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/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/Unfolding.cdl b/src/Unfolding/Unfolding.cdl
new file mode 100644 (file)
index 0000000..aa130b1
--- /dev/null
@@ -0,0 +1,90 @@
+-- File:       Unfolding.cdl
+-- Created:    Tue Jul 22 12:48:05 2008
+-- Author:     Sergey KHROMOV
+--             <skv@dimox>
+---Copyright:  Open CASCADE 2008
+
+package Unfolding
+    ---Purpose: This package contains a tool for unfolding a surface on a plane.
+
+uses
+
+    TopoDS,
+    TopTools,
+    gp,
+    Standard,
+    TCollection,
+    TColgp,
+    math
+
+is
+
+    ---Purpose: Enumeration that defines an error status of an operation.
+    enumeration ErrorStatus
+    is
+       Done,
+       NotDone,
+       Failure,
+       InvalidSurface,
+       InvalidInput,
+       InvalidShape,
+       ComplexShape
+    end;
+
+    class Surface;
+
+    class Point;
+    
+    class FunctionWithDerivative;
+    
+    class Shell;
+
+    class FaceDataContainer;
+
+    class FaceDataMapHasher;
+
+    class Array2OfPoint
+          instantiates Array2 from TCollection (Point from Unfolding);
+
+    class HArray2OfPoint
+       instantiates HArray2 from TCollection (Point         from Unfolding,
+                                              Array2OfPoint from Unfolding);
+
+    class IndexedMapOfFaceDataContainer
+       instantiates IndexedMap from TCollection
+                                           (FaceDataContainer from Unfolding,
+                                            FaceDataMapHasher from Unfolding);
+
+    ToShell(theShape     :     Shape       from TopoDS;
+            theTolerance :     Real        from Standard;
+            theStatus    : out ErrorStatus from Unfolding)
+    ---Purpose: 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.
+    returns Shell from TopoDS;
+
+    NbSamples(theEdge     : Edge        from TopoDS;
+             theFaces    : ListOfShape from TopTools;
+             theTolerance: Real        from Standard)
+    ---Purpose: This method returns the number of sample points for theEdge.
+    --          theFaces is a list of faces that contain theEdge.
+    returns Integer from Standard;
+
+    GetMaxNbSamples
+    ---Purpose: This method returns the maximal number of points for sampling of
+    --          edges and/or faces.
+    ---C++: inline
+    returns Integer from Standard;
+
+end Unfolding;
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.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_FaceDataContainer.cdl b/src/Unfolding/Unfolding_FaceDataContainer.cdl
new file mode 100644 (file)
index 0000000..075705b
--- /dev/null
@@ -0,0 +1,89 @@
+-- File:       Unfolding_FaceDataContainer.cdl
+-- Created:    Fri Sep 19 16:52:05 2008
+-- Author:     Sergey KHROMOV
+--             <skv@kurox>
+---Copyright:   Matra Datavision 2008
+
+class FaceDataContainer from Unfolding inherits TShared from MMgt
+    ---Purpose: This class represents a data container for data constructed
+    --          during unfolding operation.
+
+uses
+
+    Face                      from TopoDS,
+    Edge                      from TopoDS,
+    Trsf                      from gp,
+    Real                      from Standard,
+    ListOfShape               from TopTools,
+    DataMapOfShapeListOfShape from TopTools
+
+is
+
+    Create
+       ---Purpose: Empty constructor
+       ---C++: inline
+    returns FaceDataContainer from Unfolding;
+
+    SetFace(me: mutable; theFace: Face from TopoDS);
+       ---Purpose: Sets the original face.
+
+    GetFace(me)
+       ---Purpose: Returns the original face.
+       ---C++: inline
+       ---C++: return const &
+    returns Face from TopoDS;
+
+    SetUnfoldedFace(me: mutable; theUnfoldedFace: Face from TopoDS);
+       ---Purpose: Sets the unfolded face for the original one.
+       ---C++: inline
+
+    GetUnfoldedFace(me)
+       ---Purpose: Returns the unfolded face for the original one.
+       ---C++: inline
+       ---C++: return const &
+    returns Face from TopoDS;
+
+    SetDistortionArea(me: mutable; theDistortionArea: Real from Standard);
+       ---Purpose: Sets the distortion area.
+       ---C++: inline
+
+    GetDistortionArea(me)
+       ---Purpose: Returns the distortion area.
+       ---C++: inline
+    returns Real from Standard;
+
+    SetMaxGaussCurvature(me: mutable; theCurvature: Real from Standard);
+       ---Purpose: Sets the maximal Gauss curvature.
+       ---C++: inline
+
+    GetMaxGaussCurvature(me)
+       ---Purpose: Returns the maximal Gauss curvature.
+       ---C++: inline
+    returns Real from Standard;
+
+    Reset(me: mutable);
+       ---Purpose: Resets the data container.
+       ---C++: inline
+
+    ApplyTrsf(me: mutable; theTrsf: Trsf from gp);
+       ---Purpose: Applies the transformation to all unfolded shapes.
+
+    SetEdgesForEdge(me: mutable;
+                   theEdge         : Edge        from TopoDS;
+                   theUnfoldedEdges: ListOfShape from TopTools);
+       ---Purpose: Associates unfolded edges with the source edge.
+
+    GetEdgesForEdge(me; theEdge: Edge from TopoDS)
+       ---Purpose: Returns unfolded edges associated to the source edge.
+       ---C++: return const &
+    returns ListOfShape from TopTools;
+
+fields
+
+    myFace           : Face                      from TopoDS;
+    myUnfoldedFace   : Face                      from TopoDS;
+    myEdgeMap        : DataMapOfShapeListOfShape from TopTools;
+    myDistortionArea : Real                      from Standard;
+    myCurvature      : Real                      from Standard;
+
+end;
diff --git a/src/Unfolding/Unfolding_FaceDataContainer.cxx b/src/Unfolding/Unfolding_FaceDataContainer.cxx
new file mode 100644 (file)
index 0000000..b1d147d
--- /dev/null
@@ -0,0 +1,111 @@
+// File:       Unfolding_FaceDataContainer.cxx
+// Created:    Tue Jul 22 13:12:24 2008
+// Author:     Sergey KHROMOV
+//             <skv@dimox>
+
+
+#include <Unfolding_FaceDataContainer.ixx>
+#include <BRepBuilderAPI_Transform.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+
+//=======================================================================
+//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.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.cdl b/src/Unfolding/Unfolding_FaceDataMapHasher.cdl
new file mode 100644 (file)
index 0000000..7ee72b4
--- /dev/null
@@ -0,0 +1,32 @@
+-- File:       Unfolding_FaceDataMapHasher.cdl
+-- Created:    Fri Sep 19 16:52:05 2008
+-- Author:     Sergey KHROMOV
+--             <skv@kurox>
+---Copyright:   Matra Datavision 2008
+
+class FaceDataMapHasher from Unfolding
+       ---Purpose: Hash tool, used for generating maps of face data containers.
+
+uses
+
+    FaceDataContainer from Unfolding,
+    Integer           from Standard,
+    Boolean           from Standard
+
+is
+
+    HashCode(myclass; theKey  : FaceDataContainer from Unfolding;
+                     theUpper: Integer           from Standard)
+       ---Purpose: Returns a HasCode value  for  the  Key <K>  in the
+       --          range 0..theUpper.
+       ---C++: inline
+    returns Integer from Standard;
+       
+    IsEqual(myclass; theKey1, theKey2 : FaceDataContainer from Unfolding)
+       ---Purpose: Returns True  when the two  keys are the same. Two
+       --          same  keys  must   have  the  same  hashcode,  the
+       --          contrary is not necessary.
+       ---C++: inline
+    returns Boolean from Standard;
+
+end;
diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.cxx b/src/Unfolding/Unfolding_FaceDataMapHasher.cxx
new file mode 100644 (file)
index 0000000..8357ff5
--- /dev/null
@@ -0,0 +1,7 @@
+// File:       Unfolding_FaceDataMapHasher.cxx
+// Created:    Mon Sep 22 09:01:04 2008
+// Author:     Sergey KHROMOV
+//             <skv@kurox>
+
+
+#include <Unfolding_FaceDataMapHasher.ixx>
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.cdl b/src/Unfolding/Unfolding_FunctionWithDerivative.cdl
new file mode 100644 (file)
index 0000000..6ca0c19
--- /dev/null
@@ -0,0 +1,60 @@
+-- File:       Unfolding_FunctionWithDerivative.cdl
+-- Created:    Fri Sep  5 17:44:29 2008
+-- Author:     Mikhail KLOKOV
+--             <mkk@kurox>
+---Copyright:  Open CASCADE 2008
+
+class FunctionWithDerivative from Unfolding inherits FunctionWithDerivative from math
+uses
+    Array1OfXY from TColgp,
+    Trsf2d from gp,
+    Dir2d from gp
+is
+
+    Create (theMaster, theSlave: Array1OfXY from TColgp; 
+           theDir: Dir2d from gp;
+           theTrsf: Trsf2d from gp) 
+       returns FunctionWithDerivative from Unfolding;
+       ---Purpose:
+
+    Value(me: in out; X: Real; F: out Real)
+        ---Purpose: Computes the value <F>of the function for the variable <X>.
+       --          Returns True if the calculation were successfully done, 
+       --          False otherwise.
+
+    returns Boolean
+    is redefined;
+    Derivative(me: in out; X: Real; D: out Real)
+        ---Purpose: Computes the derivative <D> of the function 
+        --          for the variable <X>.
+       --           Returns True if the calculation were successfully done, 
+       --           False otherwise.
+
+    returns Boolean
+    is redefined;    
+
+    Values(me: in out; X: Real; F, D: out Real)
+       ---Purpose: 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.
+
+    returns Boolean
+    is redefined;
+    
+    GetStateNumber (me: in out) returns Integer from Standard
+       is redefined;
+
+    Area(me)
+       returns Real from Standard;
+    
+fields
+    myMasterPolyLine: Array1OfXY from TColgp;
+    mySlavePolyLine: Array1OfXY from TColgp;
+    myTrsf: Trsf2d from gp;
+    myShiftDir: Dir2d from gp;
+    myShift: Real from Standard;
+    myArea: Real from Standard;
+
+end FunctionWithDerivative from Unfolding;
diff --git a/src/Unfolding/Unfolding_FunctionWithDerivative.cxx b/src/Unfolding/Unfolding_FunctionWithDerivative.cxx
new file mode 100644 (file)
index 0000000..fca468b
--- /dev/null
@@ -0,0 +1,247 @@
+// File:       Unfolding_FunctionWithDerivative.cxx
+// Created:    Fri Sep  5 17:51:58 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+
+
+#include <Unfolding_FunctionWithDerivative.ixx>
+
+
+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_Point.cdl b/src/Unfolding/Unfolding_Point.cdl
new file mode 100644 (file)
index 0000000..8c62588
--- /dev/null
@@ -0,0 +1,82 @@
+-- File:       Unfolding_Point.cdl
+-- Created:    Mon Jul 28 14:56:12 2008
+-- Author:     Sergey KHROMOV
+--             <skv@dimox>
+---Copyright:   Matra Datavision 2008
+
+
+class Point from Unfolding
+    ---Purpose: 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.
+
+uses
+
+    XY   from gp,
+    XYZ  from gp,
+    Real from Standard
+
+is
+
+    Create
+    ---Purpose: Empty constructor.
+    ---C++: inline
+    returns Point from Unfolding;
+
+    SetPointOnSurface(me: in out; thePOnSurface: XYZ from gp);
+    ---Purpose: Sets the point on a surface.
+    ---C++: inline
+
+    GetPointOnSurface(me)
+    ---Purpose: Returns the point on a surface.
+    ---C++: return const &
+    ---C++: inline
+    returns XYZ from gp;
+
+    SetParameters(me: in out; theU: Real from Standard;
+                              theV: Real from Standard);
+    ---Purpose: Sets the U and V parameters of the point on a surface.
+    ---C++: inline
+
+    GetParameters(me; theU: out Real from Standard;
+                      theV: out Real from Standard);
+    ---Purpose: Returns the U and V parameters of the point on a surface.
+    ---C++: inline
+
+    GetU(me)
+    ---Purpose: Returns the U parameter of the point on a surface.
+    ---C++: inline
+    returns Real from Standard;
+
+    GetV(me)
+    ---Purpose: Returns the V parameter of the point on a surface.
+    ---C++: inline
+    returns Real from Standard;
+
+    SetAngle(me:  in  out;  theAngle:  Real  from  Standard);
+    ---Purpose: Sets the angle between DU and DV directions.
+    ---C++: inline
+
+    GetAngle(me)
+    ---Purpose: Returns the angle between DU and DV directions.
+    ---C++: inline
+    returns Real from Standard;
+
+    SetPointOnPlane(me: in out; thePOnPlane: XY from gp);
+    ---Purpose: Sets the point on an unfolding plane.
+    ---C++: inline
+
+    GetPointOnPlane(me)
+    ---Purpose: Returns the point on an unfolding plane.
+    ---C++: return const &
+    ---C++: inline
+    returns XY from gp;
+
+fields
+
+    myPoint2d    : XY   from gp;
+    myPOnSurface : XYZ  from gp;
+    myPOnPlane   : XY   from gp;
+    myAngle      : Real from Standard;
+
+end;
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.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.cdl b/src/Unfolding/Unfolding_Shell.cdl
new file mode 100644 (file)
index 0000000..403ecf1
--- /dev/null
@@ -0,0 +1,167 @@
+-- File:       Unfolding_Shell.cdl
+-- Created:    Tue Sep  9 16:56:09 2008
+-- Author:     Mikhail KLOKOV
+--             <mkk@kurox>
+---Copyright:  Open CASCADE 2008
+
+class Shell from Unfolding
+
+    ---Purpose: 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.
+
+uses
+
+    ErrorStatus                   from Unfolding,
+    Shell                         from TopoDS,
+    Face                          from TopoDS,
+    ListOfShape                   from TopTools,
+    Pln                           from gp,
+    Real                          from Standard,
+    IndexedMapOfFaceDataContainer from Unfolding,
+    FaceDataContainer             from Unfolding
+
+is
+
+    Create
+    ---Purpose:  Empty constructor
+    returns Shell from Unfolding;
+
+    Create (theShell     : Shell from TopoDS;
+           thePlane    : Pln  from gp;
+           theContourTolerance: Real from Standard;
+           theCurvatureTolerance: Real from Standard = 0.001;
+           theDeflection: Real from Standard = 0.001)
+    ---Purpose: Constructor. Initializes the object with the shell, the plane and
+    --          the tolerances for operation.
+    returns Shell from Unfolding;
+
+    SetShell (me: in out; theShell: Shell from TopoDS);
+    ---Purpose: Sets the face.
+    ---C++: inline
+
+    GetShell (me)
+    ---Purpose: Returns the shell.
+    ---C++: inline
+    ---C++: return const &
+    returns Shell from TopoDS;
+
+    SetPlane (me: in out; thePlane: Pln from gp);
+    ---Purpose: Sets the plane.
+    ---C++: inline
+
+    GetPlane (me)
+    ---Purpose: Returns the plane.
+    ---C++: inline
+    ---C++: return const &
+    returns Pln from gp;
+
+    SetCurvatureTolerance (me: in out; theTolerance: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetCurvatureTolerance (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+    
+    SetContourTolerance (me: in out; theTolerance: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetContourTolerance (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+
+    SetDeflection (me: in out; theDeflection: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetDeflection (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+
+    Perform (me: in out)
+    ---Purpose: 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().
+    returns Boolean from Standard;
+
+    ErrorStatus (me)
+    ---Purpose: 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;
+    ---C++: inline
+    returns ErrorStatus from Unfolding;
+
+    GetResult (me)
+    ---Purpose: Returns the result of the operation. If the operation is failed,
+    --          it returns a null shape.
+    ---C++: inline
+    ---C++: return const &
+    returns Face from TopoDS;
+
+
+    GetAreaError(me)
+    ---Purpose: Returns the area cumulated during primitive patches mergin.
+    --          It shows computed distortion.
+    ---C++: inline
+    returns Real from Standard;
+    
+    GetMaxGaussCurvature(me)
+    ---Purpose: Returns the gauss curvature computed in the mesh points.
+    ---C++: inline
+    returns Real from Standard;
+
+
+
+    --protected
+    Reset(me: in out)
+    ---Purpose: Resets data to the initial state.
+    ---C++: inline
+    is protected;
+
+    --private
+    ComputeTransformed(me: in out; theResult: in out ListOfShape from TopTools)
+    returns Boolean from Standard
+    is private;
+
+    MoveFace2ToFace1(me: in out; theFaceData1  : FaceDataContainer from Unfolding;
+                                theFaceData2  : FaceDataContainer from Unfolding;
+                                theCommonEdges: ListOfShape       from TopTools;
+                                 theIsFixed    : Boolean           from Standard)
+    ---Purpose: 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.
+    returns Boolean from Standard
+    is private;
+
+fields
+
+    myShell          : Shell                         from TopoDS;
+    myPlane          : Pln                           from gp;
+    myTolContour     : Real                          from Standard;
+    myTolCurvature   : Real                          from Standard;
+    myDeflection     : Real                          from Standard;
+    myMapFaceData    : IndexedMapOfFaceDataContainer from Unfolding;
+    myResult         : Face                          from TopoDS;
+    myErrorStatus    : ErrorStatus                   from Unfolding;
+    myDistortionArea : Real                          from Standard;
+    myCurvature      : Real                          from Standard;
+
+end Shell from Unfolding;
diff --git a/src/Unfolding/Unfolding_Shell.cxx b/src/Unfolding/Unfolding_Shell.cxx
new file mode 100644 (file)
index 0000000..f6430e1
--- /dev/null
@@ -0,0 +1,777 @@
+// File:       Unfolding_Shell.cxx
+// Created:    Tue Sep  9 17:14:33 2008
+// Author:     Mikhail KLOKOV
+//             <mkk@kurox>
+
+
+#include <Unfolding_Shell.ixx>
+#include <Unfolding.hxx>
+#include <Unfolding_FunctionWithDerivative.hxx>
+#include <Unfolding_Surface.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom_Plane.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_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_MapOfShape.hxx>
+#include <BRepCheck_Analyzer.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.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.cdl b/src/Unfolding/Unfolding_Surface.cdl
new file mode 100644 (file)
index 0000000..dfc5a25
--- /dev/null
@@ -0,0 +1,200 @@
+-- File:       Unfolding_Surface.cdl
+-- Created:    Tue Jul 22 12:50:10 2008
+-- Author:     Sergey KHROMOV
+--             <skv@dimox>
+---Copyright:  Open CASCADE 2008
+
+
+class Surface from Unfolding
+    ---Purpose: 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.
+
+uses
+
+    ErrorStatus           from Unfolding,
+    HArray2OfPoint        from Unfolding,
+    FaceDataContainer     from Unfolding,
+    Face                  from TopoDS,
+    Wire                  from TopoDS,
+    Edge                  from TopoDS,
+    Vertex                from TopoDS,
+    ListOfShape           from TopTools,
+    Pln                   from gp,
+    XY                    from gp,
+    Real                  from Standard,
+    DataMapOfShapeInteger from TopTools
+
+is
+
+    Create
+    ---Purpose:  Empty constructor
+    ---C++: inline
+    returns Surface from Unfolding;
+
+    Create (theFace              : Face from TopoDS;
+           thePlane             : Pln  from gp;
+           theContourTolerance  : Real from Standard;
+           theCurvatureTolerance: Real from Standard = 0.001;
+           theDeflection        : Real from Standard = 0.001)
+    ---Purpose: Constructor. Initializes the object with the face, the plane and
+    --          the tolerance for operation.
+    returns Surface from Unfolding;
+
+    SetFace (me: in out; theFace: Face from TopoDS);
+    ---Purpose: Sets the face.
+    ---C++: inline
+
+    GetFace (me)
+    ---Purpose: Returns the face.
+    ---C++: inline
+    ---C++: return const &
+    returns Face from TopoDS;
+
+    SetPlane (me: in out; thePlane: Pln from gp);
+    ---Purpose: Sets the plane.
+    ---C++: inline
+
+    GetPlane (me)
+    ---Purpose: Returns the plane.
+    ---C++: inline
+    ---C++: return const &
+    returns Pln from gp;
+
+    SetCurvatureTolerance (me: in out; theTolerance: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetCurvatureTolerance (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+    
+    SetContourTolerance (me: in out; theTolerance: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetContourTolerance (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+
+    SetDeflection (me: in out; theDeflection: Real from Standard);
+    ---Purpose: Sets the tolerance for the operation.
+    ---C++: inline
+
+    GetDeflection (me)
+    ---Purpose: Returns the tolerance for the operation.
+    ---C++: inline
+    returns Real from Standard;
+
+    Perform (me: in out; theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools)
+    ---Purpose: 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.
+    returns Boolean from Standard;
+
+    ErrorStatus (me)
+    ---Purpose: 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.
+    ---C++: inline
+    returns ErrorStatus from Unfolding;
+
+    GetDataContainer(me)
+    ---Purpose: Returns data container. That stores all results of the operation.
+    ---C++: inline
+    returns FaceDataContainer from Unfolding;
+
+    --protected
+    Reset(me: in out)
+    ---Purpose: Resets data to the initial state.
+    ---C++: inline
+    is protected;
+
+    --private
+    InitGrid(me: in out)
+    ---Purpose: 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.
+    returns Boolean from Standard
+    is private;
+
+    NbPoints(me; theUMin     :     Real    from Standard;
+                 theUMax     :     Real    from Standard;
+                 theVMin     :     Real    from Standard;
+                 theVMax     :     Real    from Standard;
+                 theNbPointsU: out Integer from Standard;
+                 theNbPointsV: out Integer from Standard)
+    ---Purpose: Computes and returns the numbers of sampling points
+    --          for U and V directions.
+    is private;
+
+    Unfolding(me: in out)
+    ---Purpose: 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.
+    returns Boolean from Standard
+    is private;
+
+    BuildPlanarFace(me: in out;
+                   theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools)
+    ---Purpose: Constructs and returns a planar face.
+    returns Boolean from Standard
+    is private;
+
+    BuildPlanarWire(me: in out;
+                   theWire            :     Wire                  from TopoDS;
+                   theMapEdgeNbSamples:     DataMapOfShapeInteger from TopTools;
+                   thePlanarWire      : out Wire                  from TopoDS)
+    ---Purpose: Constructs and returns planar unfolded wire from original one.
+    returns Boolean from Standard
+    is private;
+
+    UnfoldEdge(me;
+              theEdge            :        Edge                  from TopoDS;
+              theStartVtx        :        Vertex                from TopoDS;
+              theEndVtx          :        Vertex                from TopoDS;
+              theMapEdgeNbSamples:        DataMapOfShapeInteger from TopTools;
+              theStartPnt        : in out XY                    from gp;
+              theEndPnt          :    out XY                    from gp;
+               thePlnEdges        :    out ListOfShape           from TopTools)
+    ---Purpose: Constructs and returns a set of planar unfolded edges
+    --          from theEdge.
+    returns Boolean from Standard
+    is private;
+
+    ComputePointOnPlane(me; thePoint       :     XY   from gp;
+                            theEdgeTol     :     Real from Standard;
+                            thePointOnPlane: out XY   from gp)
+    ---Purpose: Computes and returns a point on plane that corresponds
+    --          to a point on a surface.
+    returns Boolean from Standard
+    is private;
+
+fields
+
+    myDataContainer  : FaceDataContainer from Unfolding;
+    myPlane          : Pln               from gp;
+    myTolContour     : Real              from Standard;
+    myTolCurvature   : Real              from Standard;
+    myDeflection     : Real              from Standard;
+    myGrid           : HArray2OfPoint    from Unfolding;
+    myErrorStatus    : ErrorStatus       from Unfolding;
+
+end;
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.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/UnfoldingTest.cdl b/src/UnfoldingTest/UnfoldingTest.cdl
new file mode 100644 (file)
index 0000000..23d72fa
--- /dev/null
@@ -0,0 +1,24 @@
+-- File:       UnfoldingTest.cdl
+-- Created:    Tue Jul 22 18:15:41 2008
+-- Author:     Sergey KHROMOV
+--             <skv@dimox>
+---Copyright:   Matra Datavision 2008
+
+
+package UnfoldingTest
+    ---Purpose: This package defines a set of Draw commands for testing of
+    --          functionality of the package Unfolding.
+
+uses
+
+    Draw
+
+is
+
+    Commands(theDI: in out Interpretor from Draw);
+    ---Purpose: Adds Draw commands to the draw interpretor.
+
+    Factory(theDI: out Interpretor from Draw);
+    ---Purpose: Plugin entry point function.
+
+end UnfoldingTest;
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)
index 0db16ce60bd35ec62ab740e745a674a9efb9d37b..96ace7dac12cc3ded01205af049d430b0e4e3365 100644 (file)
@@ -13,7 +13,6 @@
 //
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
-
 #include <OpenGl_GlCore20.hxx>
 #include <AIS_Shape.hxx>
 #include <AIS_InteractiveObject.hxx>
@@ -2117,8 +2116,8 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
         }
       }
       break;
-
-    case WM_MOUSEWHEEL:
+#if _MSC_VER >= 1500
+       case WM_MOUSEWHEEL:
     {
       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
       if (wParam & MK_CONTROL)
@@ -2134,12 +2133,13 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
           }
         }
       }
-      else
+     else
       {
         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
       }
       break;
     }
+#endif
 
     case WM_MOUSEMOVE:
       {