0024964: ThruSections crashes the DRAW.exe
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_ThruSections.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 951c185..29e3711
@@ -1,55 +1,47 @@
-// File:       BRepOffsetAPI_ThruSections.cxx
-// Created:    Tue Jul 18 16:18:09 1995
-// Author:     Jing Cheng MEI
-//             <mei@junon>
+// Created on: 1995-07-18
+// Created by: Joelle CHAUVET
+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
 // Modified:   Mon Jan 12 10:50:10 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              gestion automatique de l'origine et de l'orientation
 //              avec la methode ArrangeWires
 // Modified:   Mon Jan 19 10:11:56 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              traitement des cas particuliers cylindre, cone, plan 
 //              (methodes DetectKPart et CreateKPart)
 // Modified:   Mon Feb 23 09:28:46 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              traitement des sections avec nombre d'elements different
 //              + quelques ameliorations pour les cas particuliers
 //              + cas de la derniere section ponctuelle
 // Modified:   Mon Apr  6 15:47:44 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              traitement des cas particuliers deplace dans BRepFill 
 // Modified:   Thu Apr 30 15:24:17 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              separation sections fermees / sections ouvertes + debug 
 // Modified:   Fri Jul 10 11:23:35 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              surface de CreateSmoothed par concatenation,approximation
 //              et segmentation (PRO13924, CTS21295)
 // Modified:   Tue Jul 21 16:48:35 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              pb de ratio (BUC60281) 
 // Modified:   Thu Jul 23 11:38:36 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              sections bouclantes
 // Modified:   Fri Aug 28 10:13:44 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              traitement des sections ponctuelles
 //              dans l'historique (cf. loft06 et loft09)
 //              et dans le cas des solides
 // Modified:   Tue Nov  3 10:06:15 1998
-// Author:     Joelle CHAUVET
-//             <jct@sgi64>
 //              utilisation de BRepFill_CompatibleWires
+
 
 #include <BRepOffsetAPI_ThruSections.ixx>
 
 #include <BRepBuilderAPI_FindPlane.hxx>
 
 
+//=======================================================================
+//function : PreciseUpar
+//purpose  : pins the u-parameter of surface close to U-knot
+//           to this U-knot
+//=======================================================================
+
+static Standard_Real PreciseUpar(const Standard_Real anUpar,
+  const Handle(Geom_BSplineSurface)& aSurface)
+{
+  Standard_Real Tol = Precision::PConfusion();
+  Standard_Integer i1, i2;
 
+  aSurface->LocateU(anUpar, Tol, i1, i2);
+  Standard_Real U1 = aSurface->UKnot(i1);
+  Standard_Real U2 = aSurface->UKnot(i2);
+
+  Standard_Real NewU = anUpar;
+
+  NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
+  return NewU;
+}
 
 //=======================================================================
 //function :  PerformPlan
-//purpose  : Construit s'il existe un plan de remplissage
+//purpose  : Construct a plane of filling if exists
 //=======================================================================
 
 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
-                                   const Standard_Real presPln,
-                                   TopoDS_Face& theFace)
+  const Standard_Real presPln,
+  TopoDS_Face& theFace)
 {
   Standard_Boolean isDegen = Standard_True;
   TopoDS_Iterator iter(W);
   for (; iter.More(); iter.Next())
-    {
-      const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
-      if (!BRep_Tool::Degenerated(anEdge))
-       isDegen = Standard_False;
-    }
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
+    if (!BRep_Tool::Degenerated(anEdge))
+      isDegen = Standard_False;
+  }
   if (isDegen)
     return Standard_True;
 
@@ -132,22 +144,22 @@ static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
   if (!W.IsNull()) {
     BRepBuilderAPI_FindPlane Searcher( W, presPln );
     if (Searcher.Found())
-      {
-       theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
-       Ok = Standard_True;
-      }
+    {
+      theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
+      Ok = Standard_True;
+    }
     else // try to find another surface
+    {
+      BRepBuilderAPI_MakeFace MF( W );
+      if (MF.IsDone())
       {
-       BRepBuilderAPI_MakeFace MF( W );
-       if (MF.IsDone())
-         {
-           theFace = MF.Face();
-           Ok = Standard_True;
-         }
+        theFace = MF.Face();
+        Ok = Standard_True;
       }
+    }
   }
 
- return Ok;
+  return Ok;
 }
 
 //=============================================================================
@@ -156,7 +168,7 @@ static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
 //=============================================================================
 
 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
-                                      const TopoDS_Shape& aShell)
+  const TopoDS_Shape& aShell)
 {
   TopExp_Explorer Explo(aFace, TopAbs_EDGE);
   TopoDS_Shape anEdge = Explo.Current();
@@ -168,11 +180,11 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
   const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
   TopoDS_Shape theEdge;
   for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
-    {
-      theEdge = Explo.Current();
-      if (theEdge.IsSame(anEdge))
-       break;
-    }
+  {
+    theEdge = Explo.Current();
+    if (theEdge.IsSame(anEdge))
+      break;
+  }
 
   TopAbs_Orientation Or2 = theEdge.Orientation();
   if (Or1 == Or2)
@@ -186,8 +198,8 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
 //=======================================================================
 
 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
-                             const TopoDS_Wire& wire2, const Standard_Real presPln,
-                             TopoDS_Face& face1, TopoDS_Face& face2)
+  const TopoDS_Wire& wire2, const Standard_Real presPln,
+  TopoDS_Face& face1, TopoDS_Face& face2)
 {
   if (shell.IsNull())
     StdFail_NotDone::Raise("Thrusections is not build");
@@ -195,31 +207,31 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
   BRep_Builder BB;
 
   if (!B)
-    {
-      // Il faut boucher les extremites 
-      B =  PerformPlan(wire1, presPln, face1);
+  {
+    // It is necessary to close the extremities 
+    B =  PerformPlan(wire1, presPln, face1);
+    if (B) {
+      B =  PerformPlan(wire2, presPln, face2);
       if (B) {
-       B =  PerformPlan(wire2, presPln, face2);
-       if (B) {
-         if (!face1.IsNull() && !IsSameOriented( face1, shell ))
-           face1.Reverse();
-         if (!face2.IsNull() && !IsSameOriented( face2, shell ))
-           face2.Reverse();
-         
-         if (!face1.IsNull())
-           BB.Add(shell, face1);
-         if (!face2.IsNull())
-           BB.Add(shell, face2);
-         
-         shell.Closed(Standard_True);
-       }
+        if (!face1.IsNull() && !IsSameOriented( face1, shell ))
+          face1.Reverse();
+        if (!face2.IsNull() && !IsSameOriented( face2, shell ))
+          face2.Reverse();
+
+        if (!face1.IsNull())
+          BB.Add(shell, face1);
+        if (!face2.IsNull())
+          BB.Add(shell, face2);
+
+        shell.Closed(Standard_True);
       }
     }
+  }
 
   TopoDS_Solid solid;
   BB.MakeSolid(solid); 
   BB.Add(solid, shell);
-  
+
   // verify the orientation the solid
   BRepClass3d_SolidClassifier clas3d(solid);
   clas3d.PerformInfinitePoint(Precision::Confusion());
@@ -227,7 +239,7 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
     BB.MakeSolid(solid); 
     TopoDS_Shape aLocalShape = shell.Reversed();
     BB.Add(solid, TopoDS::Shell(aLocalShape));
-//    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
+    //    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
   }
 
   solid.Closed(Standard_True);
@@ -241,11 +253,11 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
 //=======================================================================
 
 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled,
-                                            const Standard_Real pres3d):
-                                            myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
+  const Standard_Real pres3d):
+myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
 {
   myWCheck = Standard_True;
-//----------------------------
+  //----------------------------
   myParamType = Approx_ChordLength; 
   myDegMax    = 8; 
   myContinuity = GeomAbs_C2;
@@ -262,13 +274,13 @@ BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean is
 //=======================================================================
 
 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
-                                const Standard_Real pres3d)
+  const Standard_Real pres3d)
 {
   myIsSolid = isSolid;
   myIsRuled = ruled;
   myPres3d = pres3d;
   myWCheck = Standard_True;
-//----------------------------
+  //----------------------------
   myParamType = Approx_ChordLength; 
   myDegMax    = 6; 
   myContinuity = GeomAbs_C2;
@@ -336,40 +348,40 @@ void BRepOffsetAPI_ThruSections::Build()
   Standard_Integer i;
   TopExp_Explorer explo;
   for (i = 2; i <= myWires.Length()-1; i++)
+  {
+    Standard_Boolean wdeg = Standard_True;
+    for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
     {
-      Standard_Boolean wdeg = Standard_True;
-      for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
-       {
-         const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
-         wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
-       }
-      if (wdeg)
-       Standard_Failure::Raise("Wrong usage of punctual sections");
+      const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
+      wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
     }
+    if (wdeg)
+      Standard_Failure::Raise("Wrong usage of punctual sections");
+  }
   if (myWires.Length() <= 2)
-    {
-      Standard_Boolean wdeg = Standard_True;
-      for (i = 1; i <= myWires.Length(); i++)
-       for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
-         {
-           const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
-           wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
-         }
+  {
+    Standard_Boolean wdeg = Standard_True;
+    for (i = 1; i <= myWires.Length(); i++)
+      for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
+      {
+        const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
+        wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
+      }
       if (wdeg)
-       Standard_Failure::Raise("Wrong usage of punctual sections");
-    }
+        Standard_Failure::Raise("Wrong usage of punctual sections");
+  }
 
   if (myWCheck) {
     // compute origin and orientation on wires to avoid twisted results
     // and update wires to have same number of edges
-    
-    // on utilise BRepFill_CompatibleWires
+
+    // use BRepFill_CompatibleWires
     TopTools_SequenceOfShape WorkingSections;
     WorkingSections.Clear();
     TopTools_DataMapOfShapeListOfShape WorkingMap;
     WorkingMap.Clear();
-    
-    // Calcul des sections de travail
+
+    // Calculate the working sections
     BRepFill_CompatibleWires Georges(myWires);
     Georges.Perform();
     if (Georges.IsDone()) {
@@ -379,7 +391,7 @@ void BRepOffsetAPI_ThruSections::Build()
     myWires = WorkingSections;
   }
 
-  // Calcul de la shape resultat
+  // Calculate the resulting shape
   if (myWires.Length() == 2 || myIsRuled) {
     // create a ruled shell
     CreateRuled();
@@ -390,7 +402,7 @@ void BRepOffsetAPI_ThruSections::Build()
   }
   // Encode the Regularities
   BRepLib::EncodeRegularity(myShape);
-  
+
 }
 
 
@@ -403,7 +415,7 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
 {
   Standard_Integer nbSects = myWires.Length();
   BRepFill_Generator aGene;
-//  for (Standard_Integer i=1; i<=nbSects; i++) {
+  //  for (Standard_Integer i=1; i<=nbSects; i++) {
   Standard_Integer i;
   for (i=1; i<=nbSects; i++) {
     aGene.AddWire(TopoDS::Wire(myWires(i)));
@@ -413,7 +425,7 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
 
   if (myIsSolid) {
 
-    // on regarde si le premier wire est identique au dernier
+    // check if the first wire is the same as the last
     Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
 
     if (vClosed) {
@@ -422,15 +434,15 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
       BRep_Builder B;
       B.MakeSolid(solid); 
       B.Add(solid, shell);
-      
-      // verify the orientation the solid
+
+      // verify the orientation of the solid
       BRepClass3d_SolidClassifier clas3d(solid);
       clas3d.PerformInfinitePoint(Precision::Confusion());
       if (clas3d.State() == TopAbs_IN) {
-       B.MakeSolid(solid); 
-       TopoDS_Shape aLocalShape = shell.Reversed();
-       B.Add(solid, TopoDS::Shell(aLocalShape));
-//     B.Add(solid, TopoDS::Shell(shell.Reversed()));
+        B.MakeSolid(solid); 
+        TopoDS_Shape aLocalShape = shell.Reversed();
+        B.Add(solid, TopoDS::Shell(aLocalShape));
+        //     B.Add(solid, TopoDS::Shell(shell.Reversed()));
       }
       myShape = solid;
 
@@ -460,12 +472,12 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
 
   TopTools_IndexedDataMapOfShapeListOfShape MV;
   TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
-  
+
   for (i=1; i<=nbSects-1; i++) {
-    
+
     const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
     const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
-    
+
     anExp1.Init(wire1);
     anExp2.Init(wire2);
 
@@ -477,51 +489,51 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
       const TopoDS_Shape& edge2 = anExp2.Current();
       Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
       Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
-      
+
       TopTools_MapOfShape MapFaces;
       if (degen2){
-       TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
-       for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
-         MapFaces.Add(it.Value());
-       }
+        TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
+        for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
+          MapFaces.Add(it.Value());
+        }
       }
       else {
-       for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
-         MapFaces.Add(it.Value());
-       }
+        for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
+          MapFaces.Add(it.Value());
+        }
       }
-      
+
       if (degen1) {
-       TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
-       for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
-         const TopoDS_Shape& Face = it.Value();
-         if (MapFaces.Contains(Face)) {
-           myGenerated.Bind(edge1, Face);
-           break;
-         }
-       }
+        TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
+        for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
+          const TopoDS_Shape& Face = it.Value();
+          if (MapFaces.Contains(Face)) {
+            myGenerated.Bind(edge1, Face);
+            break;
+          }
+        }
       }
       else {
-       for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
-         const TopoDS_Shape& Face = it.Value();
-         if (MapFaces.Contains(Face)) {
-           myGenerated.Bind(edge1, Face);
-           break;
-         }
-       }
+        for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
+          const TopoDS_Shape& Face = it.Value();
+          if (MapFaces.Contains(Face)) {
+            myGenerated.Bind(edge1, Face);
+            break;
+          }
+        }
       }
-      
+
       if (!degen1) anExp1.Next();
       if (!degen2) anExp2.Next();
-      
+
       tantque = anExp1.More() && anExp2.More();
       if (degen1) tantque = anExp2.More();
       if (degen2) tantque = anExp1.More();
-      
+
     }
-      
+
   }
-      
+
 }
 
 //=======================================================================
@@ -536,19 +548,19 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
   BRepTools_WireExplorer anExp;
 
   Standard_Boolean w1Point = Standard_True;
-  // on regarde si le premier wire est ponctuel
+  // check if the first wire is punctual
   for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
     w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
   }
 
   Standard_Boolean w2Point = Standard_True;
-  // on regarde si le dernier wire est ponctuel
+  // check if the last wire is punctual
   for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
     w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
   }
 
   Standard_Boolean vClosed = Standard_False;
-  // on regarde si le premier wire est identique au dernier
+  // check if the first wire is the same as last
   if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
 
   // find the dimension
@@ -572,24 +584,24 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
   for (i=1; i<=nbSects; i++) {
     const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
     if (!wire.Closed()) {
-      // on regarde quand meme si les vertex sont les memes.
+      // check if the vertices are the same
       TopoDS_Vertex V1, V2;
       TopExp::Vertices(wire,V1,V2);
       if ( !V1.IsSame(V2)) uClosed = Standard_False;
     }
     if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
-      // si le wire est ponctuel
+      // if the wire is punctual
       anExp.Init(TopoDS::Wire(wire));
       for(j=1; j<=nbEdges; j++) {
-       nb++;
-       shapes(nb) = anExp.Current();
+        nb++;
+        shapes(nb) = anExp.Current();
       }
     }
     else {
-      // sinon
+      // otherwise
       for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
-       nb++;
-       shapes(nb) = anExp.Current();
+        nb++;
+        shapes(nb) = anExp.Current();
       }
     }
   }
@@ -612,12 +624,10 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
   TopLoc_Location loc;
   TopoDS_Vertex v1f,v1l,v2f,v2l;
 
-  GeomFill_SectionGenerator section;
   Standard_Integer nbPnts = 21;
   TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
 
-  // on concatene chaque section pour obtenir une surface totale que
-  // l'on va segmenter
+  // concatenate each section to get a total surface that will be segmented
   Handle(Geom_BSplineSurface) TS;
   TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
 
@@ -628,17 +638,19 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
   TopoDS_Shape firstEdge;
   for (i=1; i<=nbEdges; i++) {  
 
-    // segmentation de TS
+    // segmentation of TS
     Handle(Geom_BSplineSurface) surface;
     surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
     Standard_Real Ui1,Ui2,V0,V1;
     Ui1 = i-1;
     Ui2 = i;
+    Ui1 = PreciseUpar(Ui1, surface);
+    Ui2 = PreciseUpar(Ui2, surface);
     V0  = surface->VKnot(surface->FirstVKnotIndex());
     V1  = surface->VKnot(surface->LastVKnotIndex());
     surface->Segment(Ui1,Ui2,V0,V1);
 
-    // recuperation des vertices
+    // return vertices
     edge =  TopoDS::Edge(shapes(i));
     TopExp::Vertices(edge,v1f,v1l);
     if (edge.Orientation() == TopAbs_REVERSED)
@@ -655,17 +667,17 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
 
     // make the wire
     B.MakeWire(W);
-    
+
     // make the missing edges
     Standard_Real f1, f2, l1, l2;
     surface->Bounds(f1,l1,f2,l2);
-  
+
     // --- edge 1
     if ( w1Point ) {
-      // copie de l'edge degeneree
+      // copy the degenerated edge
       TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
       edge1 =  TopoDS::Edge(aLocalShape);
-//      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
+      //      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
       edge1.Orientation(TopAbs_FORWARD);
     }
     else {
@@ -676,25 +688,25 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     v1l.Orientation(TopAbs_REVERSED);
     B.Add(edge1, v1l);
     B.Range(edge1, f1, l1);
-    // traitement des sections bouclantes
-    // on stocke les edges de la 1ere section
+    // processing of looping sections
+    // store edges of the 1st section
     if (vClosed)
       vcouture(i) = edge1;
-    
+
 
     // --- edge 2
     if (vClosed)
       edge2 = TopoDS::Edge(vcouture(i));
     else {
       if ( w2Point ) {
-       // copie de l'edge degeneree
-       TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
-       edge2 =  TopoDS::Edge(aLocalShape);
-//     edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
-       edge2.Orientation(TopAbs_FORWARD);
+        // copy of the degenerated edge
+        TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
+        edge2 =  TopoDS::Edge(aLocalShape);
+        //     edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
+        edge2.Orientation(TopAbs_FORWARD);
       }
       else {
-       B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
+        B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
       }
       v2f.Orientation(TopAbs_FORWARD);
       B.Add(edge2, v2f);
@@ -714,7 +726,7 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
       B.Add(edge3, v2f);
       B.Range(edge3, f2, l2);
       if (uClosed) {
-       couture = edge3;
+        couture = edge3;
       }
     }
     else {
@@ -743,34 +755,34 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     // set PCurve
     if (vClosed) {
       B.UpdateEdge(edge1,
-                  new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
-                  new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
+        new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
+        Precision::Confusion());
       B.Range(edge1,face,f1,l1);
     }
     else {
       B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge1,face,f1,l1);
       B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge2,face,f1,l1);
     }
 
     if ( uClosed && nbEdges ==1 )  {
       B.UpdateEdge(edge3,
-                  new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
-                  new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
+        new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
+        Precision::Confusion());
       B.Range(edge3,face,f2,l2);
 
     }
     else {
       B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge3,face,f2,l2);
       B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge4,face,f2,l2);
     }
     B.Add(face,W);
@@ -799,15 +811,15 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
       BRep_Builder B;
       B.MakeSolid(solid); 
       B.Add(solid, shell);
-      
+
       // verify the orientation the solid
       BRepClass3d_SolidClassifier clas3d(solid);
       clas3d.PerformInfinitePoint(Precision::Confusion());
       if (clas3d.State() == TopAbs_IN) {
-       B.MakeSolid(solid); 
-       TopoDS_Shape aLocalShape = shell.Reversed();
-       B.Add(solid, TopoDS::Shell(aLocalShape));
-//     B.Add(solid, TopoDS::Shell(shell.Reversed()));
+        B.MakeSolid(solid); 
+        TopoDS_Shape aLocalShape = shell.Reversed();
+        B.Add(solid, TopoDS::Shell(aLocalShape));
+        //     B.Add(solid, TopoDS::Shell(shell.Reversed()));
       }
       myShape = solid;
 
@@ -824,7 +836,7 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     myShape = shell;
     Done();
   }
-  
+
   TopExp_Explorer ex(myShape,TopAbs_EDGE);
   while (ex.More()) {
     const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
@@ -837,22 +849,89 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
 }
 
 //=======================================================================
+//function : EdgeToBSpline
+//purpose  : auxiliary -- get curve from edge and convert it to bspline
+//           parameterized from 0 to 1
+//=======================================================================
+
+// NOTE: this code duplicates the same function in BRepFill_NSections.cxx
+static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
+{
+  Handle(Geom_BSplineCurve) aBSCurve;
+  if (BRep_Tool::Degenerated(theEdge)) {
+    // degenerated edge : construction of a point curve
+    TColStd_Array1OfReal aKnots (1,2);
+    aKnots(1) = 0.;
+    aKnots(2) = 1.;
+
+    TColStd_Array1OfInteger aMults (1,2);
+    aMults(1) = 2;
+    aMults(2) = 2;
+
+    TColgp_Array1OfPnt aPoles(1,2);
+    TopoDS_Vertex vf, vl;
+    TopExp::Vertices(theEdge,vl,vf);
+    aPoles(1) = BRep_Tool::Pnt(vf);
+    aPoles(2) = BRep_Tool::Pnt(vl);
+
+    aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
+  }
+  else
+  {
+    // get the curve of the edge
+    TopLoc_Location aLoc;
+    Standard_Real aFirst, aLast;
+    Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
+
+    // convert its part used by edge to bspline; note that if edge curve is bspline,
+    // conversion made via trimmed curve is still needed -- it will copy it, segment 
+    // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
+    Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
+
+    // special treatment of conic curve
+    if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
+    {
+      GeomConvert_ApproxCurve anAppr (aTrimCurve, Precision::Confusion(), GeomAbs_C1, 16, 14);
+      if (anAppr.HasResult())
+        aBSCurve = anAppr.Curve();
+    }
+
+    // general case
+    if (aBSCurve.IsNull())
+      aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
+
+    // apply transformation if needed
+    if (! aLoc.IsIdentity())
+      aBSCurve->Transform (aLoc.Transformation());
+
+    // reparameterize to [0,1]
+    TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
+    aBSCurve->Knots (aKnots);
+    BSplCLib::Reparametrize (0., 1., aKnots);
+    aBSCurve->SetKnots (aKnots);
+  }
+
+  // reverse curve if edge is reversed
+  if (theEdge.Orientation() == TopAbs_REVERSED)
+    aBSCurve->Reverse();
+
+  return aBSCurve;
+}
+
+//=======================================================================
 //function : TotalSurf
 //purpose  : 
 //=======================================================================
 
 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
-                                   TotalSurf(const TopTools_Array1OfShape& shapes,
-                                            const Standard_Integer NbSects,
-                                            const Standard_Integer NbEdges,
-                                            const Standard_Boolean w1Point,
-                                            const Standard_Boolean w2Point,
-                                            const Standard_Boolean vClosed) const
+                          TotalSurf(const TopTools_Array1OfShape& shapes,
+                                    const Standard_Integer NbSects,
+                                    const Standard_Integer NbEdges,
+                                    const Standard_Boolean w1Point,
+                                    const Standard_Boolean w2Point,
+                                    const Standard_Boolean vClosed) const
 {
   Standard_Integer i,j,jdeb=1,jfin=NbSects;
-  TopoDS_Edge edge;
-  TopLoc_Location loc;
-  Standard_Real first, last;
   TopoDS_Vertex vf,vl;
 
   GeomFill_SectionGenerator section;
@@ -863,7 +942,7 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
 
   if (w1Point) {
     jdeb++;
-    edge =  TopoDS::Edge(shapes(1));
+    TopoDS_Edge edge =  TopoDS::Edge(shapes(1));
     TopExp::Vertices(edge,vl,vf);
     TColgp_Array1OfPnt Extremities(1,2);
     Extremities(1) = BRep_Tool::Pnt(vf);
@@ -871,12 +950,11 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
     TColStd_Array1OfReal Bounds(1,2);
     Bounds(1) = 0.;
     Bounds(2) = 1.;
-    Standard_Integer Deg = 1;
     TColStd_Array1OfInteger Mult(1,2);
-    Mult(1) = Deg+1;
-    Mult(2) = Deg+1;
+    Mult(1) = 2;
+    Mult(2) = 2;
     Handle(Geom_BSplineCurve) BSPoint
-      = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
+      = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
     section.AddCurve(BSPoint);
   }
 
@@ -886,120 +964,47 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
 
   for (j=jdeb; j<=jfin; j++) {
 
-    // cas des sections bouclantes
+    // case of looping sections 
     if (j==jfin && vClosed) {
       section.AddCurve(BS1);
     }
 
     else {
       // read the first edge to initialise CompBS;
-      edge =  TopoDS::Edge(shapes((j-1)*NbEdges+1));
-      if (BRep_Tool::Degenerated(edge)) {
-       // edge degeneree : construction d'une courbe ponctuelle
-       TopExp::Vertices(edge,vl,vf);
-       TColgp_Array1OfPnt Extremities(1,2);
-       Extremities(1) = BRep_Tool::Pnt(vf);
-       Extremities(2) = BRep_Tool::Pnt(vl);
-       Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
-       curvTrim = new Geom_TrimmedCurve(curv,
-                                        curv->FirstParameter(),
-                                        curv->LastParameter());
-      }
-      else {
-       // recuperation de la courbe sur l'edge
-       Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
-       curvTrim = new Geom_TrimmedCurve(curv, first, last);
-       curvTrim->Transform(loc.Transformation());
-      }
-      if (edge.Orientation() == TopAbs_REVERSED) {
-       curvTrim->Reverse();
-      }
+      TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1));
+      Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
 
-      // transformation en BSpline reparametree sur [i-1,i]
-      curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
-      if (curvBS.IsNull()) { 
-       Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
-       if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
-         {
-           GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
-           if (appr.HasResult())
-             curvBS = appr.Curve();
-         }
-       if (curvBS.IsNull())
-         curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
-      }
-      TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
-      curvBS->Knots(BSK);
-      BSplCLib::Reparametrize(0.,1.,BSK);
-      curvBS->SetKnots(BSK);
-      
-      // initialisation
+      // initialization
       GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
 
       for (i=2; i<=NbEdges; i++) {  
-       // read the edge
-       edge =  TopoDS::Edge(shapes((j-1)*NbEdges+i));
-       if (BRep_Tool::Degenerated(edge)) {
-         // edge degeneree : construction d'une courbe ponctuelle
-         TopExp::Vertices(edge,vl,vf);
-         TColgp_Array1OfPnt Extremities(1,2);
-         Extremities(1) = BRep_Tool::Pnt(vf);
-         Extremities(2) = BRep_Tool::Pnt(vl);
-         Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
-         curvTrim = new Geom_TrimmedCurve(curv,
-                                          curv->FirstParameter(),
-                                          curv->LastParameter());
-       }
-       else {
-         // recuperation de la courbe sur l'edge
-         Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
-         curvTrim = new Geom_TrimmedCurve(curv, first, last);
-         curvTrim->Transform(loc.Transformation());
-       }
-       if (edge.Orientation() == TopAbs_REVERSED) {
-         curvTrim->Reverse();
-       }
-
-       // transformation en BSpline reparametree sur [i-1,i]
-       curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
-       if (curvBS.IsNull()) { 
-         Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
-         if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
-           {
-             GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
-             if (appr.HasResult())
-               curvBS = appr.Curve();
-           }
-         if (curvBS.IsNull())
-           curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
-       }
-       TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
-       curvBS->Knots(BSK);
-       BSplCLib::Reparametrize(i-1,i,BSK);
-       curvBS->SetKnots(BSK);
-
-       // concatenation
-       CompBS.Add(curvBS, 
-                  Precision::Confusion(),
-                  Standard_True,
-                  Standard_False,
-                  1);
+        // read the edge
+        TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i));
+        Standard_Real aTolV = Precision::Confusion();  
+        TopExp::Vertices(aNextEdge,vf,vl);
+        aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
+        aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
+        aTolV = Min(aTolV, 1.e-3);
+        curvBS = EdgeToBSpline (aNextEdge);
+
+        // concatenation
+        CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
       }
 
-      // recuperation de la section finale
+      // return the final section
       BS = CompBS.BSplineCurve();
       section.AddCurve(BS);
 
-      // cas des sections bouclantes
+      // case of looping sections
       if (j==jdeb && vClosed) {
-       BS1 = BS;
+        BS1 = BS;
       }
 
     }
   }
 
   if (w2Point) {
-    edge =  TopoDS::Edge(shapes(NbSects*NbEdges));
+    TopoDS_Edge edge =  TopoDS::Edge(shapes(NbSects*NbEdges));
     TopExp::Vertices(edge,vl,vf);
     TColgp_Array1OfPnt Extremities(1,2);
     Extremities(1) = BRep_Tool::Pnt(vf);
@@ -1007,12 +1012,11 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
     TColStd_Array1OfReal Bounds(1,2);
     Bounds(1) = 0.;
     Bounds(2) = 1.;
-    Standard_Integer Deg = 1;
     TColStd_Array1OfInteger Mult(1,2);
-    Mult(1) = Deg+1;
-    Mult(2) = Deg+1;
+    Mult(1) = 2;
+    Mult(2) = 2;
     Handle(Geom_BSplineCurve) BSPoint
-      = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
+      = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
     section.AddCurve(BSPoint);
   }
 
@@ -1040,13 +1044,13 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
   if(anApprox.IsDone()) {
     surface = 
       new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
-                           anApprox.SurfUKnots(), anApprox.SurfVKnots(),
-                           anApprox.SurfUMults(), anApprox.SurfVMults(),
-                           anApprox.UDegree(), anApprox.VDegree());
+      anApprox.SurfUKnots(), anApprox.SurfVKnots(),
+      anApprox.SurfUMults(), anApprox.SurfVMults(),
+      anApprox.UDegree(), anApprox.VDegree());
   }
 
   return surface;
-  
+
 }
 
 //=======================================================================
@@ -1088,7 +1092,7 @@ TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge)
 
 //=======================================================================
 //function : CriteriumWeight
-//purpose  : returns the Weights associed  to the criterium used in
+//purpose  : returns the Weights associated  to the criterium used in
 //           the  optimization.
 //=======================================================================
 //