0023824: Bad results of sweep operation when a path curve has unpredictable torsion...
authorjgv <jgv@opencascade.com>
Fri, 22 Mar 2013 13:10:51 +0000 (17:10 +0400)
committerjgv <jgv@opencascade.com>
Fri, 22 Mar 2013 13:10:51 +0000 (17:10 +0400)
Adding test cases for this fix

26 files changed:
src/BRepFill/BRepFill_Draft.cxx
src/BRepFill/BRepFill_Pipe.cdl
src/BRepFill/BRepFill_Pipe.cxx
src/BRepFill/BRepFill_PipeShell.cdl
src/BRepFill/BRepFill_PipeShell.cxx
src/BRepFill/BRepFill_Sweep.cdl
src/BRepFill/BRepFill_Sweep.cxx
src/BRepOffsetAPI/BRepOffsetAPI.cdl
src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cdl
src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cxx
src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl
src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx
src/BRepTest/BRepTest_SweepCommands.cxx
src/GeomFill/GeomFill.cdl
src/GeomFill/GeomFill_CorrectedFrenet.cdl
src/GeomFill/GeomFill_CorrectedFrenet.cxx
src/GeomFill/GeomFill_DiscreteTrihedron.cdl [new file with mode: 0644]
src/GeomFill/GeomFill_DiscreteTrihedron.cxx [new file with mode: 0644]
src/GeomFill/GeomFill_Frenet.cdl
src/GeomFill/GeomFill_Frenet.cxx
src/GeomFill/GeomFill_Sweep.cdl
src/GeomFill/GeomFill_Sweep.cxx
tests/bugs/modalg_5/bug23824_1 [new file with mode: 0755]
tests/bugs/modalg_5/bug23824_2 [new file with mode: 0755]
tests/bugs/modalg_5/bug23824_3 [new file with mode: 0755]
tests/bugs/modalg_5/bug23824_4 [new file with mode: 0755]

index 75b704e..fb63cfd 100755 (executable)
@@ -525,7 +525,7 @@ static Standard_Boolean GoodOrientation(const Bnd_Box& B,
   BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
   Sweep.SetTolerance(myTol);
   Sweep.SetAngularControl(angmin, angmax);
-  Sweep.Build(myStyle, GeomFill_Location, myCont);
+  Sweep.Build(myStyle, myCont);
   if (Sweep.IsDone()) {
     myShape = Sweep.Shape();
     myShell = TopoDS::Shell(myShape);
index a8a6da8..46ee387 100755 (executable)
@@ -41,8 +41,8 @@ uses
     Edge   from TopoDS,
     Vertex from TopoDS,  
     Pnt    from  gp,
-    Trsf  from  gp 
-    
+    Trsf   from  gp,
+    Trihedron from GeomFill
 
 raises
     DomainError from Standard, 
@@ -57,6 +57,21 @@ is
              GeneratePartCase : Boolean from Standard = Standard_False) 
     returns Pipe from BRepFill;
     
+    SetMode(me : in out;
+           aMode : Trihedron from GeomFill);
+       ---Purpose: Set the mode of sweeping
+       --          It can be:
+       --          - Frenet
+       --          - Corrected Frenet
+       --          - Discrete Trihedron
+       --          By default the mode is Corrected Frenet
+    
+    SetForceApproxC1(me : in out;
+                    ForceApproxC1 : Boolean from Standard);
+       ---Purpose: Set the flag that indicates attempt to approximate
+       --          a C1-continuous surface if a swept surface proved
+       --          to be C0.
+
     Perform (me : in out;  Spine   : Wire from TopoDS; 
                           Profile : Shape from TopoDS;
                            GeneratePartCase : Boolean from Standard = Standard_False) 
@@ -175,4 +190,7 @@ fields
      
     myDegmax  : Integer from Standard;
     mySegmax  : Integer from Standard;
+    myMode    : Trihedron from GeomFill;
+    myForceApproxC1 : Boolean from Standard;
+    
 end Pipe;
index 2b4d5b9..c27ed8c 100755 (executable)
@@ -30,6 +30,8 @@
 #include <BRepTools_Substitution.hxx>
 
 #include <GeomFill_CorrectedFrenet.hxx>
+#include <GeomFill_Frenet.hxx>
+#include <GeomFill_DiscreteTrihedron.hxx>
 #include <GeomFill_CurveAndTrihedron.hxx>
 
 #include <BRepFill_SectionPlacement.hxx>
@@ -70,6 +72,8 @@ BRepFill_Pipe::BRepFill_Pipe()
 {
   myDegmax = 10;
   mySegmax = 100;
+  myMode = GeomFill_IsCorrectedFrenet;
+  myForceApproxC1 = Standard_False;
 }
 
 
@@ -84,9 +88,39 @@ BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
 {
   myDegmax = 10;
   mySegmax = 100;
+  myMode = GeomFill_IsCorrectedFrenet;
+  myForceApproxC1 = Standard_False;
   Perform(Spine, Profile, KPart);
 }
 
+//=======================================================================
+//function : SetMode
+//purpose  : Set the mode of sweeping
+//           It can be:
+//           - Frenet
+//           - Corrected Frenet
+//           - Discrete Trihedron
+//=======================================================================
+
+void BRepFill_Pipe::SetMode(const GeomFill_Trihedron aMode)
+{
+  if (aMode == GeomFill_IsFrenet ||
+      aMode == GeomFill_IsCorrectedFrenet ||
+      aMode == GeomFill_IsDiscreteTrihedron)
+    myMode = aMode;
+}
+
+//=======================================================================
+//function : SetForceApproxC1
+//purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+
+void BRepFill_Pipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myForceApproxC1 = ForceApproxC1;
+}
 
 
 //=======================================================================
@@ -111,9 +145,19 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
   BRepTools_WireExplorer wexp;
   TopoDS_Shape TheProf; 
 
-
- Handle(GeomFill_CorrectedFrenet) TLaw = 
-   new (GeomFill_CorrectedFrenet) ();
+  Handle(GeomFill_TrihedronLaw) TLaw;
+  switch (myMode)
+  {
+  case GeomFill_IsFrenet:
+    TLaw = new GeomFill_Frenet();
+    break;
+  case GeomFill_IsCorrectedFrenet:
+    TLaw = new GeomFill_CorrectedFrenet();
+    break;
+  case GeomFill_IsDiscreteTrihedron:
+    TLaw = new GeomFill_DiscreteTrihedron();
+    break;
+  }
   Handle(GeomFill_CurveAndTrihedron) Loc = 
     new (GeomFill_CurveAndTrihedron) (TLaw);
   myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
@@ -366,7 +410,8 @@ TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
 
  // Sweeping
  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
- MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+ MkSw.SetForceApproxC1(myForceApproxC1);
+ MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
  TopoDS_Shape aLocalShape = MkSw.Shape();
  return TopoDS::Wire(aLocalShape);
 // return TopoDS::Wire(MkSw.Shape());
@@ -491,7 +536,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
      Handle(BRepFill_ShapeLaw) Section = 
        new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
-      MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+      MkSw.SetForceApproxC1(myForceApproxC1);
+      MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
       result = MkSw.Shape();
     }
 
@@ -501,7 +547,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
                     TopoDS::Wire(TheLast));
-      MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
+      MkSw.SetForceApproxC1(myForceApproxC1);
+      MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
       result = MkSw.Shape();
 
       // Labeling of elements
index 6fd4184..5001810 100755 (executable)
@@ -66,6 +66,12 @@ is
        ---Level:  Public   
        ---See Also:GeomFill_IsCorrectedFrenet
     
+    SetDiscrete(me  :  mutable);
+       ---Purpose: Set a Discrete trihedron  
+        --          to  perform  the  sweeping
+       ---Level:  Public   
+       ---See Also:GeomFill_IsDiscreteTrihedron
+    
     Set(me  :  mutable;  Axe  :  Ax2  from  gp); 
        ---Purpose: Set  an  fixed  trihedron  to  perform  the  sweeping 
          --         all sections will be parallel.
@@ -106,6 +112,13 @@ is
 
         ---Level: Public
 
+    SetForceApproxC1(me  :  mutable;
+                    ForceApproxC1 : Boolean from Standard);
+       ---Purpose: Set the flag that indicates attempt to approximate
+       --          a C1-continuous surface if a swept surface proved
+       --          to be C0.
+
+
 -- =================================
 --  Methodes to define section(s)
 -- ================================= 
@@ -271,8 +284,9 @@ fields
 
   myTol3d       :  Real; 
   myBoundTol    :  Real;  
-  myTolAngular  :  Real;  
+  myTolAngular  :  Real;
   angmin,  angmax  :  Real; 
+  myForceApproxC1 : Boolean;
   
   myLaw         :  Function         from  Law;    
   myLocation    :  LocationLaw      from  BRepFill; 
index 208af33..e6aadaf 100755 (executable)
@@ -52,6 +52,7 @@
 #include <GeomFill_TrihedronLaw.hxx>
 #include <GeomFill_CorrectedFrenet.hxx>
 #include <GeomFill_Frenet.hxx>
+#include <GeomFill_DiscreteTrihedron.hxx>
 #include <GeomFill_Fixed.hxx>
 #include <GeomFill_ConstantBiNormal.hxx>
 #include <GeomFill_SectionLaw.hxx>
@@ -211,6 +212,7 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
                       :  mySpine(Spine), 
                         myTrihedron(GeomFill_IsCorrectedFrenet),
                         myTransition(BRepFill_Modified),
+                         myForceApproxC1(Standard_False),
                         myStatus(GeomFill_PipeOk)
 {
   myLocation.Nullify();
@@ -248,6 +250,23 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
 }
 
 //=======================================================================
+//function : SetDiscrete
+//purpose  : Define a law of Discrete Trihedron
+//=======================================================================
+ void BRepFill_PipeShell::SetDiscrete() 
+{
+  Handle(GeomFill_TrihedronLaw) TLaw;
+
+  myTrihedron = GeomFill_IsDiscreteTrihedron;
+  TLaw = new (GeomFill_DiscreteTrihedron) ();
+
+  Handle(GeomFill_CurveAndTrihedron) Loc = 
+    new (GeomFill_CurveAndTrihedron) (TLaw);
+  myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
+  mySection.Nullify(); //It is required to relocalize sections.
+}
+
+//=======================================================================
 //function : Set
 //purpose  : Define a law Constant
 //=======================================================================
@@ -385,6 +404,17 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
 }
 
 //=======================================================================
+//function : SetForceApproxC1
+//purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myForceApproxC1 = ForceApproxC1;
+}
+
+//=======================================================================
 //function : Add
 //purpose  : Add a Section
 //=======================================================================
@@ -629,9 +659,13 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
   BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
   MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
   MkSw.SetAngularControl(angmin, angmax);
+  MkSw.SetForceApproxC1(myForceApproxC1);
   MkSw.SetBounds(TopoDS::Wire(myFirst), 
                 TopoDS::Wire(myLast));
-  MkSw.Build(myTransition);
+  GeomAbs_Shape theContinuity = GeomAbs_C2;
+  if (myTrihedron == GeomFill_IsDiscreteTrihedron)
+    theContinuity = GeomAbs_C0;
+  MkSw.Build(myTransition, theContinuity);
 
   myStatus = myLocation->GetStatus();
   Ok =  (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
index 6b4356a..cf6a678 100755 (executable)
@@ -80,10 +80,17 @@ is
    --   Transition "Round" replace the Transition "Right"          
    is  static; 
                     
+   SetForceApproxC1(me:  in  out;
+                   ForceApproxC1 : Boolean from Standard);
+       ---Purpose: Set the flag that indicates attempt to approximate
+       --          a C1-continuous surface if a swept surface proved
+       --          to be C0.
+
+                    
    Build(me : in  out; 
          Transition : TransitionStyle  =  BRepFill_Modified;    
-         Approx     : ApproxStyle = GeomFill_Location; 
          Continuity : Shape  from  GeomAbs   = GeomAbs_C2;
+         Approx     : ApproxStyle = GeomFill_Location; 
         Degmax     : Integer = 11;
          Segmax     : Integer = 30); 
         
@@ -170,6 +177,7 @@ fields
   myContinuity     :  Shape from  GeomAbs; 
   myDegmax         :  Integer; 
   mySegmax         :  Integer;
+  myForceApproxC1  :  Boolean;
   myShape          :  Shape from  TopoDS; 
   myLoc            :  LocationLaw  from  BRepFill; 
   mySec            :  SectionLaw   from  BRepFill; 
index f9ceeca..7df0994 100755 (executable)
@@ -1685,6 +1685,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
  myContinuity  = GeomAbs_C2;
  myDegmax      = 11;
  mySegmax      = 30;
+ myForceApproxC1 = Standard_False;
 }
 
 //=======================================================================
@@ -1752,6 +1753,17 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
   myAngMax = Min (MaxAngle, 6.28);
 }
 
+//=======================================================================
+//function : SetForceApproxC1
+//purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+ void BRepFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myForceApproxC1 = ForceApproxC1;
+}
+
 ///=======================================================================
 //function : CorrectApproxParameters
 //purpose  : 
@@ -1820,6 +1832,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
     // Curve by iso value
     GeomFill_Sweep Sweep(myLoc->Law(ipath), KPart);
     Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular);
+    Sweep.SetForceApproxC1(myForceApproxC1);
     Sweep.Build(mySec->Law(isec), myApproxStyle, myContinuity, myDegmax, mySegmax);
     if (!Sweep.IsDone())  
       return Standard_False;
@@ -1985,6 +1998,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
 
     GeomFill_Sweep Sweep(myLoc->Law(IPath), KPart);
     Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular);
+    Sweep.SetForceApproxC1(myForceApproxC1);
 
     // Case of evolutionary section, definition of parametric correspondence
     if (!constSection) {
@@ -2491,13 +2505,13 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
 //purpose  : Construt the result of sweeping
 //======================================================================
  void BRepFill_Sweep::Build(const BRepFill_TransitionStyle Transition,
-                           const GeomFill_ApproxStyle Approx,
                            const GeomAbs_Shape Continuity,
+                           const GeomFill_ApproxStyle Approx,
                            const Standard_Integer Degmax,
                            const Standard_Integer Segmax) 
 {
-  myApproxStyle = Approx;
   myContinuity  = Continuity;
+  myApproxStyle = Approx;
   myDegmax = Degmax;
   mySegmax = Segmax;
 
index dbdadcd..47963d9 100755 (executable)
@@ -28,7 +28,8 @@ uses
     StdFail,
     gp, 
     GeomAbs,
-    Geom, 
+    Geom,
+    GeomFill,
     Approx,
     TopoDS,
     TopTools, 
index 1d1b603..a0f8b4e 100755 (executable)
@@ -35,6 +35,7 @@ class MakePipe from BRepOffsetAPI inherits MakeSweep from BRepPrimAPI
        -- with G1 continuous spines only.
 uses
     Pipe        from BRepFill,
+    Trihedron   from GeomFill,
     Wire        from TopoDS,
     Shape       from TopoDS,
     Edge        from TopoDS,
@@ -58,6 +59,21 @@ is
        -- composite solid.
     returns MakePipe from BRepOffsetAPI;
     
+    SetMode(me : in out;
+           aMode : Trihedron from GeomFill);
+       ---Purpose: Set the mode of sweeping
+       --          It can be:
+       --          - Frenet
+       --          - Corrected Frenet
+       --          - Discrete Trihedron
+       --          By default the mode is Corrected Frenet
+    
+    SetForceApproxC1(me : in out;
+                    ForceApproxC1 : Boolean from Standard);
+       ---Purpose: Set the flag that indicates attempt to approximate
+       --          a C1-continuous surface if a swept surface proved
+       --          to be C0.
+
 
     Pipe(me) returns Pipe from BRepFill
        ---C++: return const &
index f98ffe3..5b0374b 100755 (executable)
@@ -41,6 +41,32 @@ BRepOffsetAPI_MakePipe::BRepOffsetAPI_MakePipe(const TopoDS_Wire&  Spine ,
 }
 
 //=======================================================================
+//function : SetMode
+//purpose  : Set the mode of sweeping
+//           It can be:
+//           - Frenet
+//           - Corrected Frenet
+//           - Discrete Trihedron
+//=======================================================================
+
+void BRepOffsetAPI_MakePipe::SetMode(const GeomFill_Trihedron aMode)
+{
+  myPipe.SetMode(aMode);
+}
+
+//=======================================================================
+//function : SetForceApproxC1
+//purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+
+void BRepOffsetAPI_MakePipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myPipe.SetForceApproxC1(ForceApproxC1);
+}
+
+//=======================================================================
 //function : Pipe
 //purpose  : 
 //=======================================================================
index 1141a12..d53613f 100755 (executable)
@@ -73,6 +73,10 @@ is
         --          to  perform  the  sweeping 
        --       If IsFrenet is false, a corrected Frenet trihedron is used.
     
+    SetDiscreteMode(me  :  in  out);
+       ---Purpose: Sets a Discrete trihedron  
+        --          to  perform  the  sweeping 
+    
     SetMode(me  :  in  out;  Axe  :  Ax2  from  gp); 
        ---Purpose: Sets  a  fixed  trihedron  to  perform  the  sweeping 
         --         all sections will be parallel.
@@ -110,6 +114,7 @@ is
 
         ---Level: Public
 
+
 -- =================================
 --  Methodes to define section(s)
 -- ================================= 
@@ -212,6 +217,12 @@ is
        -- - boundary tolerance BoundTol
        -- - angular tolerance TolAngular.
         
+    SetForceApproxC1(me  :  in  out;
+                    ForceApproxC1 : Boolean from Standard);
+       ---Purpose: Set the flag that indicates attempt to approximate
+       --          a C1-continuous surface if a swept surface proved
+       --          to be C0.
+
     SetTransitionMode(me  :  in  out;  
                      Mode  :TransitionMode  from  BRepBuilderAPI  =  BRepBuilderAPI_Transformed)  
        ---Purpose: Sets the transition mode to manage discontinuities on
index f1189fa..551488c 100755 (executable)
@@ -50,6 +50,15 @@ BRepOffsetAPI_MakePipeShell::BRepOffsetAPI_MakePipeShell(const TopoDS_Wire& Spin
 }
 
 //=======================================================================
+//function : SetDiscreteMode
+//purpose  : 
+//=======================================================================
+ void BRepOffsetAPI_MakePipeShell::SetDiscreteMode() 
+{
+  myPipe->SetDiscrete();
+}
+
+//=======================================================================
 //function : SetMode
 //purpose  : 
 //=======================================================================
@@ -185,8 +194,9 @@ void BRepOffsetAPI_MakePipeShell::Delete( const TopoDS_Shape& Profile)
   }
   return Status;
 }
+
 //=======================================================================
-//function : SetTransitionMode
+//function : SetTolerance
 //purpose  : 
 //=======================================================================
  void BRepOffsetAPI_MakePipeShell::SetTolerance(const Standard_Real Tol3d,
@@ -197,6 +207,17 @@ void BRepOffsetAPI_MakePipeShell::Delete( const TopoDS_Shape& Profile)
 }
 
 //=======================================================================
+//function : SetForceApproxC1
+//purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+ void BRepOffsetAPI_MakePipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myPipe->SetForceApproxC1(ForceApproxC1);
+}
+
+//=======================================================================
 //function : SetTransitionMode
 //purpose  : 
 //=======================================================================
index 631d9f1..f493fd7 100755 (executable)
@@ -431,6 +431,7 @@ static Standard_Integer setsweep(Draw_Interpretor& di,
     di << "   -FR : Tangent and Normal are given by Frenet trihedron" <<"\n";
     di << "   -CF : Tangente is given by Frenet," << "\n";
     di << "         the Normal is computed to minimize the torsion " << "\n";
+    di << "   -DT : discrete trihedron" << "\n";
     di << "   -DX Surf : Tangent and Normal are given by Darboux trihedron," <<"\n";     
     di << "       Surf have to be a shell or a face" <<"\n";
     di << "   -CN dx dy dz : BiNormal is given by dx dy dz" << "\n";
@@ -450,6 +451,9 @@ static Standard_Integer setsweep(Draw_Interpretor& di,
   else if (!strcmp(a[1],"-CF")) {
     Sweep->SetMode(Standard_False);
   }
+  else if (!strcmp(a[1],"-DT")) {
+    Sweep->SetDiscreteMode();
+  }
   else if (!strcmp(a[1],"-DX")) {
     if (n!=3) {
       //cout << "bad arguments !" << endl;
index a849f1d..12bc078 100755 (executable)
@@ -67,7 +67,7 @@ is
     enumeration Trihedron 
     is IsCorrectedFrenet, IsFixed, IsFrenet, IsConstantNormal, IsDarboux, 
      IsGuideAC,  IsGuidePlan, 
-      IsGuideACWithContact,  IsGuidePlanWithContact end;
+      IsGuideACWithContact,  IsGuidePlanWithContact, IsDiscreteTrihedron  end;
     
     class Filling;
        ---Purpose: Root class for Filling;
@@ -195,6 +195,13 @@ is
     class SequenceOfTrsf
        instantiates Sequence  from TCollection (Trsf from gp); 
 
+    class SequenceOfAx2
+       instantiates Sequence from TCollection (Ax2 from gp);
+
+    class HSequenceOfAx2
+       instantiates HSequence from TCollection (Ax2 from gp,
+                                                SequenceOfAx2 from GeomFill);
+
     --
     -- private classes
     -- 
@@ -226,6 +233,7 @@ is
        class Fixed;
         class Frenet; 
         class CorrectedFrenet;
+       class DiscreteTrihedron;
        class ConstantBiNormal; 
        class Darboux; 
        class DraftTrihedron; 
index 1fb4f7d..dfd809e 100755 (executable)
@@ -37,7 +37,8 @@ uses
  HArray1OfReal  from TColStd, 
  SequenceOfReal from TColStd, 
  HArray1OfVec   from TColgp, 
- SequenceOfVec  from TColgp
+ SequenceOfVec  from TColgp,
+ Trihedron      from GeomFill
  
 raises
  OutOfRange,  ConstructionError
@@ -45,11 +46,14 @@ is
 
    Create returns CorrectedFrenet from GeomFill;
 
+   Create (ForEvaluation: Boolean)
+   returns CorrectedFrenet from GeomFill;
+
    Copy(me)   
    returns  TrihedronLaw  from  GeomFill          
    is  redefined;
  
-   Init(me: mutable)   
+   Init(me: mutable)
    is  static  private; 
  
    InitInterval(me; First, Last, Step: Real;   
@@ -59,7 +63,7 @@ is
                 SeqPoles:   out SequenceOfReal from TColStd; 
                 SeqAngle:   out SequenceOfReal from TColStd; 
                 SeqTangent: out SequenceOfVec from TColgp; 
-                SeqNormal:  out SequenceOfVec from TColgp) 
+                SeqNormal:  out SequenceOfVec from TColgp)
    returns Boolean 
    --- Purpose:  Computes BSpline representation of Normal evolution at one  
    --- interval of continuity of Frenet. Returns True if FuncInt = 0
@@ -142,6 +146,20 @@ is
        OutOfRange from Standard 
     is redefined;  
      
+     
+--  ===================  To define the best trihedron mode  ===============
+     
+    EvaluateBestMode(me : mutable)
+    returns Trihedron from GeomFill;
+    ---Purpose: Tries to define the best trihedron mode
+    --          for the curve. It can be:
+    --          - Frenet
+    --          - CorrectedFrenet
+    --          - DiscreteTrihedron
+    --          Warning: the CorrectedFrenet must be constructed
+    --          with option ForEvaluation = True,
+    --          the curve must be set by method SetCurve.
+     
          
 --  ===================  To help   computation of  Tolerance   ===============  
     GetAverageLaw(me  :  mutable;
@@ -165,11 +183,13 @@ is
     is redefined;
 
 fields 
-   frenet         : Frenet           from  GeomFill; 
-   EvolAroundT    : Function         from  Law; 
-   TLaw           : Function         from  Law; 
-   AT,  AN        : Vec              from  gp;
-   isFrenet       : Boolean; 
+   frenet          : Frenet           from  GeomFill; 
+   EvolAroundT     : Function         from  Law; 
+   TLaw            : Function         from  Law; 
+   AT,  AN         : Vec              from  gp;
+   isFrenet        : Boolean; 
+   myForEvaluation : Boolean;
+   
    ---OCC78
    HArrPoles      : HArray1OfReal    from  TColStd;
    HArrAngle      : HArray1OfReal    from  TColStd;
index c670ea2..862bae8 100755 (executable)
@@ -44,6 +44,7 @@
 #include <Geom_BSplineCurve.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
 
+
 #ifdef DEB
 static Standard_Boolean Affich=0;
 #endif
@@ -90,6 +91,30 @@ static void draw(const Handle(Law_Function)& law)
 }
 #endif
 
+
+static Standard_Real ComputeTorsion(const Standard_Real Param,
+                                    const Handle(Adaptor3d_HCurve)& aCurve)
+{
+  Standard_Real Torsion;
+  
+  gp_Pnt aPoint;
+  gp_Vec DC1, DC2, DC3;
+  aCurve->D3(Param, aPoint, DC1, DC2, DC3);
+  gp_Vec DC1crossDC2 = DC1 ^ DC2;
+  Standard_Real Norm_DC1crossDC2 = DC1crossDC2.Magnitude();
+
+  Standard_Real DC1DC2DC3 = DC1crossDC2 * DC3 ; //mixed product
+
+  Standard_Real Tol = gp::Resolution();
+  Standard_Real SquareNorm_DC1crossDC2 = Norm_DC1crossDC2 * Norm_DC1crossDC2;
+  if (SquareNorm_DC1crossDC2 <= Tol)
+    Torsion = 0.;
+  else
+    Torsion = DC1DC2DC3 / SquareNorm_DC1crossDC2 ;
+
+  return Torsion;
+}
+
 //===============================================================
 // Function : smoothlaw
 // Purpose : to smooth a law : Reduce the number of knots
@@ -280,13 +305,25 @@ static Standard_Boolean FindPlane ( const Handle(Adaptor3d_HCurve)& c,
 }
 
 //===============================================================
-// Function : 
+// Function : Constructor
 // Purpose :
 //===============================================================
 GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet() 
  : isFrenet(Standard_False)
 {
   frenet = new GeomFill_Frenet();
+  myForEvaluation = Standard_False;
+}
+
+//===============================================================
+// Function : Constructor
+// Purpose :
+//===============================================================
+GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet(const Standard_Boolean ForEvaluation) 
+ : isFrenet(Standard_False)
+{
+  frenet = new GeomFill_Frenet();
+  myForEvaluation = ForEvaluation;
 }
 
 Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
@@ -314,6 +351,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
       {
        // No probleme isFrenet
        isFrenet = Standard_True;
+        break;
       }
      default :
        { 
@@ -382,8 +420,12 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
   for(i = 1; i <= NbI; i++) {
     NbStep = Max(Standard_Integer((T(i+1) - T(i))/AvStep), 3);
     Step = (T(i+1) - T(i))/NbStep;
-    if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func, SeqPoles, SeqAngle, SeqTangent, SeqNormal))
-      if(isFrenet) isFrenet = Standard_False;
+    if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func,
+                     SeqPoles, SeqAngle, SeqTangent, SeqNormal))
+    {
+      if(isFrenet)
+        isFrenet = Standard_False;
+    }
     Handle(Law_Composite)::DownCast(EvolAroundT)->ChangeLaws().Append(Func);
   }
   if(myTrimmed->IsPeriodic()) 
@@ -402,7 +444,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
     HArrTangent->ChangeValue(i) = SeqTangent(i); 
     HArrNormal->ChangeValue(i) = SeqNormal(i); 
   };
-
+  
 #if DRAW
   if (Affich) {
     draw(EvolAroundT);
@@ -431,6 +473,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
   TColStd_SequenceOfReal EvolAT;
   Standard_Real Param = First, LengthMin, L, norm;
   Standard_Boolean isZero = Standard_True, isConst = Standard_True;
+  const Standard_Real minnorm = 1.e-16;
   Standard_Integer i;
   gp_Pnt PonC;
   gp_Vec D1;
@@ -446,7 +489,9 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
   Standard_Real angleAT, currParam, currStep = Step;
 
   Handle( Geom_Plane ) aPlane;
-  Standard_Boolean isPlanar = FindPlane( myCurve, aPlane );
+  Standard_Boolean isPlanar = Standard_False;
+  if (!myForEvaluation)
+    isPlanar = FindPlane( myCurve, aPlane );
 
   i = 1;
   currParam = Param;
@@ -493,13 +538,21 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
 
       //Evaluate the Next step
       CS.D1(Param, PonC, D1);
-      L = Max(PonC.XYZ().Modulus()/2, LengthMin);
+      
+      L = PonC.XYZ().Modulus()/2;
       norm = D1.Magnitude(); 
-      if (norm < Precision::Confusion()) {
-       norm = Precision::Confusion();
+      if (norm <= gp::Resolution())
+      {
+        //norm = 2.*gp::Resolution();
+        norm = minnorm;
       }
       currStep = L / norm;
-      if  (currStep > Step) currStep = Step;//default value
+      if (currStep <= gp::Resolution()) //L = 0 => curvature = 0, linear segment
+        currStep = Step;
+      if (currStep < Precision::Confusion()) //too small step
+        currStep = Precision::Confusion();
+      if  (currStep > Step) //too big step
+        currStep = Step;//default value
     }
     else 
       currStep /= 2; // Step too long !
@@ -888,6 +941,59 @@ Standard_Real GeomFill_CorrectedFrenet::GetAngleAT(const Standard_Real Param) co
 }
 
 //===============================================================
+// Function : EvaluateBestMode
+// Purpose :
+//===============================================================
+GeomFill_Trihedron GeomFill_CorrectedFrenet::EvaluateBestMode()
+{
+  if (EvolAroundT.IsNull())
+    return GeomFill_IsFrenet; //Frenet
+
+  const Standard_Real MaxAngle = 3.*M_PI/4.;
+  const Standard_Real MaxTorsion = 100.;
+  
+  Standard_Real Step, u, v, tmin, tmax;
+  Standard_Integer NbInt, i, j, k = 1;
+  NbInt = EvolAroundT->NbIntervals(GeomAbs_CN);
+  TColStd_Array1OfReal Int(1, NbInt+1);
+  EvolAroundT->Intervals(Int, GeomAbs_CN);
+  gp_Pnt2d old;
+  gp_Vec2d aVec, PrevVec;
+
+  Standard_Integer NbSamples = 10;
+  for(i = 1; i <= NbInt; i++){
+    tmin = Int(i);
+    tmax = Int(i+1);
+    Standard_Real Torsion = ComputeTorsion(tmin, myTrimmed);
+    if (Abs(Torsion) > MaxTorsion)
+      return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
+      
+    Handle(Law_Function) trimmedlaw = EvolAroundT->Trim(tmin, tmax, Precision::PConfusion()/2);
+    Step = (Int(i+1)-Int(i))/NbSamples;
+    for (j = 0; j <= NbSamples; j++) { 
+      u = tmin + j*Step;
+      v = trimmedlaw->Value(u);
+      gp_Pnt2d point2d(u,v);
+      if (j != 0)
+      {
+        aVec.SetXY(point2d.XY() - old.XY());
+        if (k > 2)
+        {
+          Standard_Real theAngle = PrevVec.Angle(aVec);
+          if (Abs(theAngle) > MaxAngle)
+            return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
+        }
+        PrevVec = aVec;
+      }
+      old = point2d;
+      k++;
+    }
+  }
+
+  return GeomFill_IsCorrectedFrenet; //CorrectedFrenet
+}
+
+//===============================================================
 // Function : GetAverageLaw
 // Purpose :
 //===============================================================
diff --git a/src/GeomFill/GeomFill_DiscreteTrihedron.cdl b/src/GeomFill/GeomFill_DiscreteTrihedron.cdl
new file mode 100644 (file)
index 0000000..0f55665
--- /dev/null
@@ -0,0 +1,154 @@
+-- Created on: 2013-02-05
+-- Created by: Julia GERASIMOVA
+-- Copyright (c) 2001-2013 OPEN CASCADE SAS
+--
+-- The content of this file is subject to the Open CASCADE Technology Public
+-- License Version 6.5 (the "License"). You may not use the content of this file
+-- except in compliance with the License. Please obtain a copy of the License
+-- at http://www.opencascade.org and read it completely before using this file.
+--
+-- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+-- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+--
+-- The Original Code and all software distributed under the License is
+-- distributed on an "AS IS" basis, without warranty of any kind, and the
+-- Initial Developer hereby disclaims all such warranties, including without
+-- limitation, any warranties of merchantability, fitness for a particular
+-- purpose or non-infringement. Please see the License for the specific terms
+-- and conditions governing the rights and limitations under the License.
+
+
+class DiscreteTrihedron from GeomFill
+    inherits TrihedronLaw  from  GeomFill 
+    
+               ---Purpose: Defined Discrete Trihedron Law.        
+               --          The requirement for path curve is only G1.
+               --          The result is C0-continuous surface
+               --          that can be later approximated to C1.
+
+uses
+    HCurve from  Adaptor3d, 
+    Shape  from  GeomAbs, 
+    Pnt    from  gp,
+    Vec    from  gp,
+    Array1OfReal from TColStd,
+    Frenet from GeomFill,
+    HSequenceOfAx2 from GeomFill,
+    HSequenceOfReal from TColStd
+
+raises
+ OutOfRange,  ConstructionError
+is  
+
+   Create  
+      returns DiscreteTrihedron from GeomFill 
+      raises  ConstructionError; 
+    
+   Copy(me)   
+   returns  TrihedronLaw  from  GeomFill          
+   is  redefined;
+   Init(me: mutable)   
+   is  static; 
+
+   SetCurve(me : mutable;  C  :  HCurve  from  Adaptor3d) 
+   is  redefined;
+
+-- 
+-- 
+--========== To compute Location and derivatives Location
+--              
+   D0(me : mutable; 
+      Param: Real; 
+      Tangent    : out  Vec  from  gp; 
+      Normal     : out  Vec  from  gp; 
+      BiNormal   : out  Vec  from  gp)
+      ---Purpose: compute Trihedron on curve at parameter <Param>         
+   returns Boolean  is  redefined;
+       
+   D1(me : mutable;
+      Param: Real;       
+      Tangent    : out  Vec  from  gp;  
+      DTangent   : out  Vec  from  gp; 
+      Normal     : out  Vec  from  gp; 
+      DNormal    : out  Vec  from  gp;                 
+      BiNormal   : out  Vec  from  gp; 
+      DBiNormal  : out  Vec  from  gp)
+      ---Purpose: compute Trihedron and  derivative Trihedron  on curve
+      --          at parameter <Param>                
+      --  Warning : It used only for C1 or C2 aproximation
+      --  For the moment it returns null values for DTangent, DNormal
+      --  and DBiNormal.
+   returns Boolean  
+   is  redefined; 
+   
+   D2(me : mutable;
+      Param: Real;       
+      Tangent    : out  Vec  from  gp;  
+      DTangent   : out  Vec  from  gp; 
+      D2Tangent  : out  Vec  from  gp; 
+      Normal     : out  Vec  from  gp; 
+      DNormal    : out  Vec  from  gp;                 
+      D2Normal   : out  Vec  from  gp; 
+      BiNormal   : out  Vec  from  gp; 
+      DBiNormal  : out  Vec  from  gp; 
+      D2BiNormal : out  Vec  from  gp)    
+      ---Purpose: compute  Trihedron on curve          
+      --          first and seconde  derivatives.
+      --  Warning : It used only for C2 aproximation
+      --  For the moment it returns null values for DTangent, DNormal
+      --  DBiNormal, D2Tangent, D2Normal, D2BiNormal.
+   returns Boolean
+   is  redefined; 
+--
+--  =================== Management  of  continuity  ===================
+--                 
+   NbIntervals(me; S : Shape from GeomAbs) 
+       ---Purpose: Returns  the number  of  intervals for  continuity
+       --          <S>. 
+        --          May be one if Continuity(me) >= <S>
+   returns Integer  is  redefined;
+
+   Intervals(me; T : in out Array1OfReal from TColStd; 
+                S : Shape from GeomAbs)
+       ---Purpose: Stores in <T> the  parameters bounding the intervals
+       --          of continuity <S>.
+       --          
+       --          The array must provide  enough room to  accomodate
+       --          for the parameters. i.e. T.Length() > NbIntervals()
+    raises
+       OutOfRange from Standard 
+    is redefined;  
+     
+         
+--  ===================  To help   computation of  Tolerance   ===============  
+    GetAverageLaw(me  :  mutable;
+      ATangent    : out  Vec  from  gp; 
+      ANormal     : out  Vec  from  gp; 
+      ABiNormal   : out  Vec  from  gp) 
+     ---Purpose: Get average value of Tangent(t) and Normal(t) it is usful to 
+     --          make fast approximation of rational  surfaces.        
+  is  redefined;
+
+--   =================== To help Particular case   ===============     
+   
+    IsConstant(me) 
+    ---Purpose: Say if the law is Constant.        
+    returns  Boolean   
+    is redefined;
+   IsOnlyBy3dCurve(me) 
+     ---Purpose: Return True.        
+    returns  Boolean   
+    is redefined;  
+    
+
+fields 
+
+   myPoint      : Pnt  from  gp;
+   myTrihedrons : HSequenceOfAx2  from GeomFill;
+   myKnots      : HSequenceOfReal from TColStd;
+   myFrenet     : Frenet  from GeomFill;
+   myUseFrenet  : Boolean from Standard;
+   
+end DiscreteTrihedron;
diff --git a/src/GeomFill/GeomFill_DiscreteTrihedron.cxx b/src/GeomFill/GeomFill_DiscreteTrihedron.cxx
new file mode 100644 (file)
index 0000000..6a74bfb
--- /dev/null
@@ -0,0 +1,392 @@
+// Created on: 2013-02-05
+// Created by: Julia GERASIMOVA
+// Copyright (c) 2001-2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+
+#include <GeomFill_DiscreteTrihedron.ixx>
+#include <GeomFill_DiscreteTrihedron.hxx>
+#include <GeomFill_Frenet.hxx>
+#include <GeomAbs_CurveType.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HSequenceOfReal.hxx>
+#include <GeomFill_HSequenceOfAx2.hxx>
+
+
+static const Standard_Real TolConf = Precision::Confusion();
+
+//=======================================================================
+//function : GeomFill_DiscreteTrihedron
+//purpose  : Constructor
+//=======================================================================
+
+GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron()
+{
+  myFrenet = new GeomFill_Frenet();
+  myKnots      = new TColStd_HSequenceOfReal();
+  myTrihedrons = new GeomFill_HSequenceOfAx2();
+}
+
+//=======================================================================
+//function : Copy
+//purpose  : 
+//=======================================================================
+
+Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const
+{
+  Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)();
+  if (!myCurve.IsNull()) copy->SetCurve(myCurve);
+  return copy;
+}
+
+//=======================================================================
+//function : SetCurve
+//purpose  : 
+//=======================================================================
+
+void GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_HCurve)& C) 
+{
+  GeomFill_TrihedronLaw::SetCurve(C);
+  if (! C.IsNull()) {
+    GeomAbs_CurveType type;
+    type = C->GetType();
+    switch  (type) {
+    case GeomAbs_Circle:
+    case GeomAbs_Ellipse:
+    case GeomAbs_Hyperbola:
+    case GeomAbs_Parabola:
+    case GeomAbs_Line:
+      {
+       // No probleme
+       myUseFrenet = Standard_True;
+        myFrenet->SetCurve(C);
+        break;
+      }
+    default :
+      {
+        myUseFrenet = Standard_False;
+        // We have to fill <myKnots> and <myTrihedrons>
+        Init();
+        break;
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : Init
+//purpose  : 
+//=======================================================================
+
+void GeomFill_DiscreteTrihedron::Init()
+{
+  Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN);
+  TColStd_Array1OfReal Knots(1, NbIntervals+1);
+  myTrimmed->Intervals(Knots, GeomAbs_CN);
+
+  //Standard_Real Tol = Precision::Confusion();
+  Standard_Integer NbSamples = 10;
+
+  Standard_Integer i, j;
+  for (i = 1; i <= NbIntervals; i++)
+  {
+    Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples;
+    for (j = 0; j < NbSamples; j++)
+    {
+      Standard_Real Param = Knots(i) + j*delta;
+      myKnots->Append(Param);
+    }
+  }
+  myKnots->Append(Knots(NbIntervals+1));
+  
+  
+  gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt;
+  gp_Vec Tangent;
+  gp_Dir TangDir;
+  Standard_Real norm;
+  for (i = 1; i <= myKnots->Length(); i++)
+  {
+    Standard_Real Param = myKnots->Value(i);
+    myTrimmed->D1(Param, Pnt, Tangent);
+    norm = Tangent.Magnitude();
+    if (norm < TolConf)
+    {
+      Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples;
+      if (subdelta < Precision::PConfusion())
+        subdelta = myKnots->Value(i+1) - myKnots->Value(i);
+      SubPnt = myTrimmed->Value(Param + subdelta);
+      Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ());
+    }
+    //Tangent.Normalize();
+    TangDir = Tangent; //normalize;
+    Tangent = TangDir;
+    if (i == 1) //first point
+    {
+      gp_Ax2 FirstAxis(Origin, TangDir);
+      myTrihedrons->Append(FirstAxis);
+    }
+    else
+    {
+      gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length());
+      gp_Vec LastTangent = LastAxis.Direction();
+      gp_Vec AxisOfRotation = LastTangent ^ Tangent;
+      if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite
+      {
+        Standard_Real ScalarProduct = LastTangent * Tangent;
+        if (ScalarProduct > 0.) //tangents are equal
+          myTrihedrons->Append(LastAxis);
+        else //tangents are opposite
+        {
+          Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.;
+          if (NewParam - myKnots->Value(i-1) < gp::Resolution())
+            Standard_ConstructionError::Raise("GeomFill_DiscreteTrihedron : impassable singularities on path curve");
+          myKnots->InsertBefore(i, NewParam);
+          i--;
+        }
+      }
+      else //good value of angle
+      {
+        Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation);
+        gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
+        gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle);
+        NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
+        myTrihedrons->Append(NewAxis);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : D0
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param,
+                                                gp_Vec& Tangent,
+                                                gp_Vec& Normal,
+                                                gp_Vec& BiNormal)
+{
+  if (myUseFrenet)
+  {
+    myFrenet->D0(Param, Tangent, Normal, BiNormal);
+  }
+  else
+  {
+    //Locate <Param> in the sequence <myKnots>
+    Standard_Integer Index = -1;
+    Standard_Real TolPar = Precision::PConfusion();
+    //Standard_Real TolConf = Precision::Confusion();
+    Standard_Integer NbSamples = 10;
+    gp_Pnt Origin(0.,0.,0.);
+    
+    Standard_Integer i;
+    //gp_Ax2 PrevAxis;
+    //Standard_Real PrevParam;
+
+    Standard_Integer I1, I2;
+    I1 = 1;
+    I2 = myKnots->Length();
+    for (;;)
+    {
+      i = (I1 + I2)/2;
+      if (Param <= myKnots->Value(i))
+        I2 = i;
+      else
+        I1 = i;
+      if (I2 - I1 <= 1)
+        break;
+    }
+    Index = I1;
+    if (Abs(Param - myKnots->Value(I2)) < TolPar)
+      Index = I2;
+
+    Standard_Real PrevParam = myKnots->Value(Index);
+    gp_Ax2        PrevAxis  = myTrihedrons->Value(Index);
+    gp_Ax2 theAxis;
+    if (Abs(Param - PrevParam) < TolPar)
+      theAxis = PrevAxis;
+    else //<Param> is between knots
+    {
+      myTrimmed->D1(Param, myPoint, Tangent);
+      Standard_Real norm = Tangent.Magnitude();
+      if (norm < TolConf)
+      {
+        Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples;
+        if (subdelta < Precision::PConfusion())
+          subdelta = myKnots->Value(Index+1) - Param;
+        gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta);
+        Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ());
+      }
+      //Tangent.Normalize();
+      gp_Dir TangDir(Tangent); //normalize;
+      Tangent = TangDir;
+      gp_Vec PrevTangent = PrevAxis.Direction();
+      gp_Vec AxisOfRotation = PrevTangent ^ Tangent;
+      if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal
+      {
+        //we assume that tangents can not be opposite
+        theAxis = PrevAxis;
+      }
+      else //good value of angle
+      {
+        Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation);
+        gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
+        theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle);
+      }
+      theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
+    } //end of else (Param is between knots)
+
+    Tangent  = theAxis.Direction();
+    Normal   = theAxis.XDirection();
+    BiNormal = theAxis.YDirection();
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : D1
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param,
+                                                gp_Vec& Tangent,
+                                                gp_Vec& DTangent,
+                                                gp_Vec& Normal,
+                                                gp_Vec& DNormal,
+                                                gp_Vec& BiNormal,
+                                                gp_Vec& DBiNormal) 
+{
+  if (myUseFrenet)
+  {
+    myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
+  }
+  else
+  {
+    D0(Param, Tangent, Normal, BiNormal);
+
+    DTangent.SetCoord(0.,0.,0.);
+    DNormal.SetCoord(0.,0.,0.);
+    DBiNormal.SetCoord(0.,0.,0.);
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : D2
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param,
+                                                gp_Vec& Tangent,
+                                                gp_Vec& DTangent,
+                                                gp_Vec& D2Tangent,
+                                                gp_Vec& Normal,
+                                                gp_Vec& DNormal,
+                                                gp_Vec& D2Normal,
+                                                gp_Vec& BiNormal,
+                                                gp_Vec& DBiNormal,
+                                                gp_Vec& D2BiNormal) 
+{
+  if (myUseFrenet)
+  {
+    myFrenet->D2(Param, Tangent, DTangent, D2Tangent,
+                 Normal, DNormal, D2Normal,
+                 BiNormal, DBiNormal, D2BiNormal);
+  }
+  else
+  {
+    D0(Param, Tangent, Normal, BiNormal);
+    
+    DTangent.SetCoord(0.,0.,0.);
+    DNormal.SetCoord(0.,0.,0.);
+    DBiNormal.SetCoord(0.,0.,0.);
+    D2Tangent.SetCoord(0.,0.,0.);
+    D2Normal.SetCoord(0.,0.,0.);
+    D2BiNormal.SetCoord(0.,0.,0.);
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : NbIntervals
+//purpose  : 
+//=======================================================================
+
+Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape S) const
+{
+  return (myTrimmed->NbIntervals(GeomAbs_CN));
+}
+
+//=======================================================================
+//function : Intervals
+//purpose  : 
+//=======================================================================
+
+void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T,
+                                           const GeomAbs_Shape S) const
+{
+  myTrimmed->Intervals(T, GeomAbs_CN);
+}
+
+ void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent,
+                                     gp_Vec& ANormal,
+                                     gp_Vec& ABiNormal) 
+{
+  Standard_Integer Num = 20; //order of digitalization
+  gp_Vec T, N, BN;
+  ATangent = gp_Vec(0, 0, 0);
+  ANormal = gp_Vec(0, 0, 0);
+  ABiNormal = gp_Vec(0, 0, 0);
+  Standard_Real Step = (myTrimmed->LastParameter() - 
+                        myTrimmed->FirstParameter()) / Num;
+  Standard_Real Param;
+  for (Standard_Integer i = 0; i <= Num; i++) {
+    Param = myTrimmed->FirstParameter() + i*Step;
+    if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
+    D0(Param, T, N, BN);
+    ATangent += T;
+    ANormal += N;
+    ABiNormal += BN;
+  }
+  ATangent /= Num + 1;
+  ANormal /= Num + 1;
+
+  ATangent.Normalize();
+  ABiNormal = ATangent.Crossed(ANormal).Normalized();
+  ANormal = ABiNormal.Crossed(ATangent);
+}
+
+//=======================================================================
+//function : IsConstant
+//purpose  : 
+//=======================================================================
+
+ Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const
+{
+  return (myCurve->GetType() == GeomAbs_Line);
+}
+
+//=======================================================================
+//function : IsOnlyBy3dCurve
+//purpose  : 
+//=======================================================================
+
+ Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const
+{
+  return Standard_True;
+}
index 16a95e4..2036593 100755 (executable)
@@ -141,7 +141,8 @@ is
 
    DoSingular(me: mutable; U: Real; Index: Integer;  
               Tangent, BiNormal: out Vec from gp; 
-              n, k, TFlag, BNFlag: out Integer) 
+              n, k, TFlag, BNFlag: out Integer;
+             Delta: out Real)
     returns Boolean
     is private; 
 
@@ -149,7 +150,8 @@ is
       Param: Real; Index:  Integer;
       Tangent    : out  Vec  from  gp; 
       Normal     : out  Vec  from  gp; 
-      BiNormal   : out  Vec  from  gp)
+      BiNormal   : out  Vec  from  gp;
+      Delta      : out  Real)
       ---Purpose: computes Triedrhon on curve at parameter <Param>         
    returns Boolean   
    is private;
@@ -161,7 +163,8 @@ is
       Normal     : out  Vec  from  gp; 
       DNormal    : out  Vec  from  gp;                 
       BiNormal   : out  Vec  from  gp; 
-      DBiNormal  : out  Vec  from  gp) 
+      DBiNormal  : out  Vec  from  gp;
+      Delta      : out  Real)
     ---Purpose: computes Triedrhon and  derivative Trihedron  on curve
       --          at parameter <Param>                
       --  Warning : It used only for C1 or C2 aproximation     
@@ -178,7 +181,8 @@ is
       D2Normal   : out  Vec  from  gp; 
       BiNormal   : out  Vec  from  gp; 
       DBiNormal  : out  Vec  from  gp; 
-      D2BiNormal : out  Vec  from  gp)    
+      D2BiNormal : out  Vec  from  gp;
+      Delta      : out  Real)
       ---Purpose: computes  Trihedron on curve          
       --          first and seconde  derivatives.
       --  Warning : It used only for C2 aproximation
index 0008c74..964f004 100755 (executable)
@@ -326,11 +326,13 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
 {
   Standard_Real norm;
   Standard_Integer Index;
+  Standard_Real Delta = 0.;
   if(IsSingular(Param, Index)) 
-    if (SingularD0(Param, Index, Tangent, Normal, BiNormal))
+    if (SingularD0(Param, Index, Tangent, Normal, BiNormal, Delta))
       return Standard_True;
 
-  myTrimmed->D2(Param, P, Tangent, BiNormal);
+  Standard_Real theParam = Param + Delta;
+  myTrimmed->D2(theParam, P, Tangent, BiNormal);
   Tangent.Normalize();
   BiNormal = Tangent.Crossed(BiNormal);
   norm = BiNormal.Magnitude();
@@ -360,13 +362,15 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
                                       gp_Vec& DBiNormal) 
 {
   Standard_Integer Index;
+  Standard_Real Delta = 0.;
   if(IsSingular(Param, Index)) 
-    if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal))
+    if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal, Delta))
       return Standard_True;
 
 //  Standard_Real Norma;
+  Standard_Real theParam = Param + Delta;
   gp_Vec DC1, DC2, DC3;
-  myTrimmed->D3(Param, P, DC1, DC2, DC3);
+  myTrimmed->D3(theParam, P, DC1, DC2, DC3);
   Tangent = DC1.Normalized();
 
   //if (DC2.Magnitude() <= NullTol || Tangent.Crossed(DC2).Magnitude() <= NullTol) {
@@ -412,16 +416,19 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
                                       gp_Vec& D2BiNormal) 
 {
   Standard_Integer Index;
+  Standard_Real Delta = 0.;
   if(IsSingular(Param, Index)) 
     if(SingularD2(Param, Index, Tangent, DTangent, D2Tangent, 
                   Normal, DNormal, D2Normal, 
-                  BiNormal, DBiNormal, D2BiNormal))
+                  BiNormal, DBiNormal, D2BiNormal,
+                  Delta))
       return Standard_True;
 
 //  Standard_Real Norma;
+  Standard_Real theParam = Param + Delta;
   gp_Vec DC1, DC2, DC3, DC4;
-  myTrimmed->D3(Param, P, DC1, DC2, DC3);
-  DC4 = myTrimmed->DN(Param, 4);
+  myTrimmed->D3(theParam, P, DC1, DC2, DC3);
+  DC4 = myTrimmed->DN(theParam, 4);
 
   Tangent = DC1.Normalized();
 
@@ -604,9 +611,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
                                              Standard_Integer& n, 
                                              Standard_Integer& k, 
                                              Standard_Integer& TFlag,
-                                             Standard_Integer& BNFlag)
+                                             Standard_Integer& BNFlag,
+                                             Standard_Real& Delta)
 {
   Standard_Integer i, MaxN = 20;
+  Delta = 0.;
   Standard_Real h;
   h = 2*mySnglLen->Value(Index);
 
@@ -615,7 +624,8 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
   TFlag = 1;
   BNFlag = 1;
   GetInterval(A, B);
-  if (U >= (A + B)/2) h = -h;
+  if (U >= (A + B)/2)
+    h = -h;
   for(i = 1; i <= MaxN; i++) {
     Tangent = myTrimmed->DN(U, i);
     if(Tangent.Magnitude() > Precision::Confusion()) break;
@@ -641,7 +651,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
        break;
       }
   }
-  if (i > MaxN) return Standard_False;
+  if (i > MaxN)
+  {
+    Delta = h;
+    return Standard_False;
+  }
+  
   BiNormal.Normalize();
   k = i;
 
@@ -657,11 +672,14 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
                                               const Standard_Integer Index,
                                               gp_Vec& Tangent,
                                               gp_Vec& Normal,
-                                              gp_Vec& BiNormal) 
+                                              gp_Vec& BiNormal,
+                                              Standard_Real& Delta)
 {
   Standard_Integer n, k, TFlag, BNFlag;
   if(!DoSingular(Param, Index, Tangent, BiNormal, 
-                 n, k, TFlag, BNFlag)) return Standard_False;
+                 n, k, TFlag, BNFlag, Delta))
+    return Standard_False;
+  
   Tangent *= TFlag;
   BiNormal *= BNFlag;
   Normal = BiNormal;
@@ -674,10 +692,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
                                               const Standard_Integer Index,
                                               gp_Vec& Tangent,gp_Vec& DTangent,
                                               gp_Vec& Normal,gp_Vec& DNormal,
-                                              gp_Vec& BiNormal,gp_Vec& DBiNormal) 
+                                              gp_Vec& BiNormal,gp_Vec& DBiNormal,
+                                              Standard_Real& Delta) 
 {
   Standard_Integer n, k, TFlag, BNFlag;
-  if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag)) return Standard_False;
+  if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta))
+    return Standard_False;
 
   gp_Vec F, DF, Dtmp;
   F = myTrimmed->DN(Param, n);
@@ -715,10 +735,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
                                               gp_Vec& D2Normal,
                                               gp_Vec& BiNormal,
                                               gp_Vec& DBiNormal,
-                                              gp_Vec& D2BiNormal) 
+                                              gp_Vec& D2BiNormal,
+                                              Standard_Real& Delta)
 {
   Standard_Integer n, k, TFlag, BNFlag;
-  if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag)) 
+  if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta)) 
     return Standard_False;
 
   gp_Vec F, DF, D2F, Dtmp1, Dtmp2;
index 2ed676f..9cddc73 100755 (executable)
@@ -78,7 +78,12 @@ is
            --                 beetween tangents on the section law and
            --                 tangent of iso-v on approximed surface
 
-                     
+   SetForceApproxC1(me  :  in  out;
+                   ForceApproxC1 : Boolean from Standard);
+   ---Purpose: Set the flag that indicates attempt to approximate
+   --          a C1-continuous surface if a swept surface proved
+   --          to be C0.
+                                                
     ExchangeUV(me)
        ---Purpose: returns true if sections are U-Iso
          -- This can be produce in some cases when <WithKpart> is True.
@@ -184,8 +189,9 @@ fields
     First,  Last  :  Real;
     SFirst,  SLast:  Real;  
     Tol3d,  BoundTol,  Tol2d,  TolAngular  :  Real;     
-    SError        :  Real;      
-     
+    SError        :  Real;
+    myForceApproxC1  :  Boolean;
+         
     myLoc      :  LocationLaw  from GeomFill;
     mySec      :  SectionLaw   from GeomFill;
     mySurface  :  Surface from Geom;
index 317649b..431a30e 100755 (executable)
@@ -68,6 +68,7 @@
 #include <Approx_SweepApproximation.hxx>
 #include <AdvApprox_PrefAndRec.hxx>
 #include <AdvApprox_ApproxAFunction.hxx>
+#include <GeomConvert_ApproxSurface.hxx>
 
 #include <Precision.hxx>
 #include <ElCLib.hxx>
@@ -121,6 +122,7 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
   myLoc =  Location;
   myKPart =  WithKpart;
   SetTolerance(1.e-4);
+  myForceApproxC1 = Standard_False;
 
   myLoc->GetDomain(First, Last);
   SFirst = SLast = 30.081996;
@@ -157,6 +159,18 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
   TolAngular = ToleranceAngular;
 }
 
+//=======================================================================
+//Function : SetForceApproxC1
+//Purpose  : Set the flag that indicates attempt to approximate
+//           a C1-continuous surface if a swept surface proved
+//           to be C0.
+//=======================================================================
+ void GeomFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
+{
+  myForceApproxC1 = ForceApproxC1;
+}
+
+
 //===============================================================
 // Function : ExchangeUV
 // Purpose :
@@ -298,56 +312,101 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
                    Approx.UDegree(),  Approx.VDegree(),
                    mySec->IsUPeriodic());
     SError = Approx. MaxErrorOnSurf();
-    
-    // Les Courbes 2d
-    myCurve2d = new  (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
-    CError =  new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
-    Standard_Integer kk,ii, ifin = 1, ideb;
-
-    if (myLoc->HasFirstRestriction()) {
-      ideb = 1;
-    }
-     else {
-       ideb = 2;
-     }
-    ifin += myLoc->TraceNumber();
-    if (myLoc->HasLastRestriction()) ifin++;
-
-    for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
-      Handle(Geom2d_BSplineCurve) C 
-       = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
-                                    Approx.Curves2dKnots(),
-                                    Approx.Curves2dMults(),
-                                    Approx.Curves2dDegree());
-      myCurve2d->SetValue(ii, C);
-      CError->SetValue(1, ii,  Approx.Max2dError(kk));
-      CError->SetValue(2, ii,  Approx.Max2dError(kk));
-    }
 
-    // Si les courbes de restriction, ne sont pas calcules, on prend
-    // les iso Bords.
-    if (! myLoc->HasFirstRestriction()) {
-      gp_Dir2d D(0., 1.);
-      gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
-      Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
-      Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
-       (LC, First, Last);
-
-      myCurve2d->SetValue(1, TC);
-      CError->SetValue(1, 1, 0.);
-      CError->SetValue(2, 1, 0.);
-    }
+    if (myForceApproxC1 && !mySurface->IsCNv(1))
+    {
+      Standard_Real theTol = 1.e-4;
+      GeomAbs_Shape theUCont = GeomAbs_C1, theVCont = GeomAbs_C1;
+      Standard_Integer degU = 14, degV = 14;
+      Standard_Integer nmax = 16;
+      Standard_Integer thePrec = 1;  
+      
+      GeomConvert_ApproxSurface ConvertApprox(mySurface,theTol,theUCont,theVCont,
+                                              degU,degV,nmax,thePrec);
+      if (ConvertApprox.HasResult())
+      {
+        mySurface = ConvertApprox.Surface();
+        myCurve2d = new  (TColGeom2d_HArray1OfCurve) (1, 2);
+        CError =  new (TColStd_HArray2OfReal) (1,2, 1,2);
+
+        const Handle(Geom_BSplineSurface)& BSplSurf =
+          Handle(Geom_BSplineSurface)::DownCast(mySurface);
+        
+        gp_Dir2d D(0., 1.);
+        gp_Pnt2d P(BSplSurf->UKnot(1), 0);
+        Handle(Geom2d_Line) LC1 = new (Geom2d_Line) (P, D);
+        Handle(Geom2d_TrimmedCurve) TC1 =
+          new (Geom2d_TrimmedCurve) (LC1, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
+        
+        myCurve2d->SetValue(1, TC1);
+        CError->SetValue(1, 1, 0.);
+        CError->SetValue(2, 1, 0.);
  
-    if (! myLoc->HasLastRestriction()) {
-      gp_Dir2d D(0., 1.);
-      gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
-      Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
-      Handle(Geom2d_TrimmedCurve) TC = 
-       new (Geom2d_TrimmedCurve) (LC, First, Last);
-      myCurve2d->SetValue(myCurve2d->Length(), TC);
-      CError->SetValue(1, myCurve2d->Length(), 0.);
-      CError->SetValue(2, myCurve2d->Length(), 0.);
-    }
+        P.SetCoord(BSplSurf->UKnot(BSplSurf->NbUKnots()), 0);
+        Handle(Geom2d_Line) LC2 = new (Geom2d_Line) (P, D);
+        Handle(Geom2d_TrimmedCurve) TC2 = 
+          new (Geom2d_TrimmedCurve) (LC2, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
+        
+        myCurve2d->SetValue(myCurve2d->Length(), TC2);
+        CError->SetValue(1, myCurve2d->Length(), 0.);
+        CError->SetValue(2, myCurve2d->Length(), 0.);
+        
+        SError = theTol;
+      }
+    } //if (!mySurface->IsCNv(1))
+    
+    // Les Courbes 2d
+    if (myCurve2d.IsNull())
+    {
+      myCurve2d = new  (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
+      CError =  new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
+      Standard_Integer kk,ii, ifin = 1, ideb;
+      
+      if (myLoc->HasFirstRestriction()) {
+        ideb = 1;
+      }
+      else {
+        ideb = 2;
+      }
+      ifin += myLoc->TraceNumber();
+      if (myLoc->HasLastRestriction()) ifin++;
+      
+      for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
+        Handle(Geom2d_BSplineCurve) C 
+          = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
+                                       Approx.Curves2dKnots(),
+                                       Approx.Curves2dMults(),
+                                       Approx.Curves2dDegree());
+        myCurve2d->SetValue(ii, C);
+        CError->SetValue(1, ii,  Approx.Max2dError(kk));
+        CError->SetValue(2, ii,  Approx.Max2dError(kk));
+      }
+      
+      // Si les courbes de restriction, ne sont pas calcules, on prend
+      // les iso Bords.
+      if (! myLoc->HasFirstRestriction()) {
+        gp_Dir2d D(0., 1.);
+        gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
+        Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
+        Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
+          (LC, First, Last);
+        
+        myCurve2d->SetValue(1, TC);
+        CError->SetValue(1, 1, 0.);
+        CError->SetValue(2, 1, 0.);
+      }
+      
+      if (! myLoc->HasLastRestriction()) {
+        gp_Dir2d D(0., 1.);
+        gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
+        Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
+        Handle(Geom2d_TrimmedCurve) TC = 
+          new (Geom2d_TrimmedCurve) (LC, First, Last);
+        myCurve2d->SetValue(myCurve2d->Length(), TC);
+        CError->SetValue(1, myCurve2d->Length(), 0.);
+        CError->SetValue(2, myCurve2d->Length(), 0.);
+      }
+    } //if (myCurve2d.IsNull())
   } 
   return Ok;
 }
diff --git a/tests/bugs/modalg_5/bug23824_1 b/tests/bugs/modalg_5/bug23824_1
new file mode 100755 (executable)
index 0000000..08189cb
--- /dev/null
@@ -0,0 +1,33 @@
+puts "============"
+puts "OCC23824"
+puts "============"
+puts ""
+#######################################################################
+# Bad results of sweep operation when a path curve has unpredictable torsion along its way.
+#######################################################################
+
+set BugNumber OCC23824
+
+restore [locate_data_file bug23824_AXE.brep] spine 
+restore [locate_data_file bug23824_profil.brep] profile 
+
+wire spine spine
+
+mksweep spine
+setsweep -DT
+addsweep profile
+buildsweep result
+
+set square 516.633
+
+set nb_v_good 8
+set nb_e_good 10
+set nb_w_good 3
+set nb_f_good 3
+set nb_sh_good 1
+set nb_sol_good 0
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 25
+
+set 2dviewer 1
diff --git a/tests/bugs/modalg_5/bug23824_2 b/tests/bugs/modalg_5/bug23824_2
new file mode 100755 (executable)
index 0000000..2bf29b7
--- /dev/null
@@ -0,0 +1,34 @@
+puts "============"
+puts "OCC23824"
+puts "============"
+puts ""
+#######################################################################
+# Bad results of sweep operation when a path curve has unpredictable torsion along its way.
+#######################################################################
+
+set BugNumber OCC23824
+
+restore [locate_data_file bug23824_Case1_Path.brep] spine 
+restore [locate_data_file bug23824_Case1_Profile.brep] profile 
+
+wire spine spine
+wire profile profile
+
+mksweep spine
+setsweep -DT
+addsweep profile
+buildsweep result
+
+set square 8997.97
+
+set nb_v_good 2
+set nb_e_good 3
+set nb_w_good 1
+set nb_f_good 1
+set nb_sh_good 1
+set nb_sol_good 0
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 8
+
+set 2dviewer 1
diff --git a/tests/bugs/modalg_5/bug23824_3 b/tests/bugs/modalg_5/bug23824_3
new file mode 100755 (executable)
index 0000000..81f9803
--- /dev/null
@@ -0,0 +1,35 @@
+puts "============"
+puts "OCC23824"
+puts "============"
+puts ""
+#######################################################################
+# Bad results of sweep operation when a path curve has unpredictable torsion along its way.
+#######################################################################
+
+set BugNumber OCC23824
+
+restore [locate_data_file bug23824_Case2_Path.brep] spine 
+restore [locate_data_file bug23824_Case2_Profile.brep] profile 
+
+wire spine spine
+wire profile profile
+
+mksweep spine
+setsweep -DT
+addsweep profile
+
+buildsweep result
+
+set square 848.989
+
+set nb_v_good 2
+set nb_e_good 3
+set nb_w_good 1
+set nb_f_good 1
+set nb_sh_good 1
+set nb_sol_good 0
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 8
+
+set 2dviewer 1
diff --git a/tests/bugs/modalg_5/bug23824_4 b/tests/bugs/modalg_5/bug23824_4
new file mode 100755 (executable)
index 0000000..baa5da5
--- /dev/null
@@ -0,0 +1,35 @@
+puts "============"
+puts "OCC23824"
+puts "============"
+puts ""
+#######################################################################
+# Bad results of sweep operation when a path curve has unpredictable torsion along its way.
+#######################################################################
+
+set BugNumber OCC23824
+
+restore [locate_data_file bug23824_Case3_Path.brep] spine 
+restore [locate_data_file bug23824_Case3_Profile.brep] profile 
+
+wire profile profile
+explode spine
+wire spine spine_1
+
+mksweep spine
+setsweep -DT
+addsweep profile
+buildsweep result
+
+set square 38260.5
+
+set nb_v_good 2
+set nb_e_good 3
+set nb_w_good 1
+set nb_f_good 1
+set nb_sh_good 1
+set nb_sol_good 0
+set nb_compsol_good 0
+set nb_compound_good 0
+set nb_shape_good 8
+
+set 2dviewer 1