0028661: BRepOffsetAPI_MakePipeShell throws an exception Standard_NoSuchObject: NColl...
[occt.git] / src / GeomFill / GeomFill_Sweep.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 4cc94cb..d37105d
@@ -1,66 +1,79 @@
-// File:       GeomFill_Sweep.cxx
-// Created:    Fri Nov 21 15:18:22 1997
-// Author:     Philippe MANGIN
-//             <pmn@sgi29>
+// Created on: 1997-11-21
+// Created by: Philippe MANGIN
+// Copyright (c) 1997-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 by skv - Fri Feb  6 11:44:48 2004 OCC5073
 
-#include <GeomFill_Sweep.ixx>
-#include <GeomFill_SweepFunction.hxx>
+#include <AdvApprox_ApproxAFunction.hxx>
+#include <AdvApprox_PrefAndRec.hxx>
+#include <Approx_SweepApproximation.hxx>
+#include <ElCLib.hxx>
+#include <ElSLib.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_ConicalSurface.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_SurfaceOfLinearExtrusion.hxx>
+#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_ToroidalSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAbs_CurveType.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomConvert_ApproxSurface.hxx>
+#include <GeomFill_LocationLaw.hxx>
 #include <GeomFill_LocFunction.hxx>
-
-#include <Standard_ErrorHandler.hxx>
-
-#include <gp_Pnt2d.hxx>
-#include <gp_Dir2d.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Dir.hxx>
-#include <gp_Lin.hxx>
+#include <GeomFill_SectionLaw.hxx>
+#include <GeomFill_Sweep.hxx>
+#include <GeomFill_SweepFunction.hxx>
+#include <GeomLib.hxx>
+#include <gp_Ax2.hxx>
 #include <gp_Circ.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Dir2d.hxx>
 #include <gp_GTrsf.hxx>
+#include <gp_Lin.hxx>
 #include <gp_Mat.hxx>
-#include <gp_Ax2.hxx>
-
+#include <gp_Pnt.hxx>
+#include <gp_Pnt2d.hxx>
+#include <gp_Sphere.hxx>
+#include <Precision.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <StdFail_NotDone.hxx>
 #include <TColgp_Array1OfPnt.hxx>
 #include <TColgp_Array2OfPnt.hxx>
 #include <TColgp_HArray2OfPnt.hxx>
-//#include <GeomLib_Array1OfMat.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TColStd_Array2OfReal.hxx>
 
-#include <GeomAbs_CurveType.hxx>
-#include <GeomAdaptor_Curve.hxx>
-#include <GeomLib.hxx>
-
-#include <Geom2d_Line.hxx>
-#include <Geom2d_BSplineCurve.hxx>
-#include <Geom2d_TrimmedCurve.hxx>
-
-#include <Geom_Circle.hxx>
-#include <Geom_Line.hxx>
-#include <Geom_BSplineSurface.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom_SurfaceOfLinearExtrusion.hxx>
-#include <Geom_CylindricalSurface.hxx>
-#include <Geom_ConicalSurface.hxx>
-#include <Geom_ToroidalSurface.hxx>
-#include <Geom_SphericalSurface.hxx>
-#include <Geom_SurfaceOfRevolution.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-
-#include <Approx_SweepApproximation.hxx>
-#include <AdvApprox_PrefAndRec.hxx>
-#include <AdvApprox_ApproxAFunction.hxx>
-
-#include <Precision.hxx>
-#include <ElCLib.hxx>
-
+//#include <GeomLib_Array1OfMat.hxx>
 //=======================================================================
 //class : GeomFill_Sweep_Eval
 //purpose: The evaluator for curve approximation
 //=======================================================================
-
 class GeomFill_Sweep_Eval : public AdvApprox_EvaluatorFunction
 {
  public:
@@ -105,6 +118,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;
@@ -141,6 +155,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 :
@@ -241,8 +267,6 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
                                           const Standard_Integer Segmax) 
 {
   Standard_Boolean Ok = Standard_False;
-  Standard_Integer nbsegmax = Segmax, nbspan = myLoc->NbIntervals(GeomAbs_C1);
-  if (Segmax < nbspan)  nbsegmax = nbspan;
 
   Handle(GeomFill_SweepFunction) Func 
     = new (GeomFill_SweepFunction) (mySec, myLoc, First, SFirst,
@@ -256,7 +280,7 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
   if (Approx.IsDone()) {
     Ok = Standard_True;
 
-#if DEB
+#ifdef OCCT_DEBUG
     Approx.Dump(cout);
 #endif
     
@@ -282,56 +306,100 @@ 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);
+
+        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;
 }
@@ -381,7 +449,7 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
                                   Segmax, 
                                   eval,
                                   Preferentiel);
-#if DEB
+#ifdef OCCT_DEBUG
   Approx.Dump(cout);
 #endif
 
@@ -456,8 +524,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
 
   TfBegin.SetValues(GTfBegin(1,1), GTfBegin(1,2), GTfBegin(1,3), GTfBegin(1,4),
                    GTfBegin(2,1), GTfBegin(2,2), GTfBegin(2,3), GTfBegin(2,4),
-                   GTfBegin(3,1), GTfBegin(3,2), GTfBegin(3,3), GTfBegin(3,4),
-                   1.e-12, 1.e-14);
+                   GTfBegin(3,1), GTfBegin(3,2), GTfBegin(3,3), GTfBegin(3,4));
 
 // Get the last transformation
   theLoc->D0(aLast, M, VEnd);
@@ -467,8 +534,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
 
   TfEnd.SetValues(GTfEnd(1,1), GTfEnd(1,2), GTfEnd(1,3), GTfEnd(1,4),
                  GTfEnd(2,1), GTfEnd(2,2), GTfEnd(2,3), GTfEnd(2,4),
-                 GTfEnd(3,1), GTfEnd(3,2), GTfEnd(3,3), GTfEnd(3,4),
-                 1.e-12, 1.e-14);
+                 GTfEnd(3,1), GTfEnd(3,2), GTfEnd(3,3), GTfEnd(3,4));
 
   Handle(Geom_Surface) aSurf = theSec->BSplineSurface();
   Standard_Real Umin;
@@ -540,8 +606,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
       OCC_CATCH_SIGNALS
       Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
                    Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
-                   Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4),
-                   1.e-12, 1.e-14);
+                   Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4));
     }
     catch (Standard_ConstructionError) {
       IsTrsf = Standard_False;
@@ -580,6 +645,8 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
     
   // (1.1.b) Cas Cylindrique
       if ( (SectionType == GeomAbs_Circle) && IsTrsf) {
+        const Standard_Real TolProd = 1.e-6;
+        
        gp_Circ C = AC.Circle();
        C.Transform(Tf2);
        
@@ -587,7 +654,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
        DS.Normalize();
         levier = Abs(DS.CrossMagnitude(DP)) * C.Radius();
         SError = levier * Abs(Last - First);
-       if (SError <= Tol) {
+       if (SError <= TolProd) {
          Ok = Standard_True;
           gp_Ax3 axe (C.Location(), DP, C.Position().XDirection());
          S = new (Geom_CylindricalSurface) 
@@ -728,8 +795,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
 //        OCC_CATCH_SIGNALS
        Tf2.SetValues(Tf(1,1), Tf(1,2), Tf(1,3), Tf(1,4),
                      Tf(2,1), Tf(2,2), Tf(2,3), Tf(2,4),
-                     Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4),
-                     1.e-14, 1.e-15);
+                     Tf(3,1), Tf(3,2), Tf(3,3), Tf(3,4));
 //      }
 //      catch (Standard_ConstructionError) {
 //     IsTrsf = Standard_False;
@@ -769,31 +835,40 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
         error *= C.Radius();
        if (error <= Tol) {
          SError = error;
-         error += Radius + Abs(RotRadius - C.Radius())/2;
-         if (error <= Tol) {
+         error += Radius;
+          if (Radius <= Tol) {
            // (2.1.a) Sphere
-           Standard_Real f = UFirst , l =  ULast;
+           Standard_Real f = UFirst , l =  ULast, aRadius = 0.0;
            SError = error;
            Centre.BaryCenter(1.0, C.Location(), 1.0); 
-           gp_Ax3 AxisOfSphere(Centre, DN, DS);  
-           S = new (Geom_SphericalSurface) 
-             (AxisOfSphere, (RotRadius + C.Radius())/2 );
+           gp_Ax3 AxisOfSphere(Centre, DN, DS);
+            aRadius = C.Radius();
+            gp_Sphere theSphere( AxisOfSphere, aRadius );
+           S = new Geom_SphericalSurface(theSphere);
            // Pour les spheres on ne peut pas controler le parametre
             // V (donc U car  myExchUV = Standard_True)
             // Il faut donc modifier UFirst, ULast...
-           if (C.Position().Direction().
-               IsOpposite(AxisOfSphere.YDirection(), 0.1) ) {
+            Standard_Real fpar = AC.FirstParameter();
+            Standard_Real lpar = AC.LastParameter();
+            Handle(Geom_Curve) theSection = new Geom_TrimmedCurve(Section, fpar, lpar);
+            theSection->Transform(Tf2);
+            gp_Pnt FirstPoint = theSection->Value(theSection->FirstParameter());
+            gp_Pnt LastPoint  = theSection->Value(theSection->LastParameter());
+            Standard_Real UfirstOnSec, VfirstOnSec, UlastOnSec, VlastOnSec;
+            ElSLib::Parameters(theSphere, FirstPoint, UfirstOnSec, VfirstOnSec);
+            ElSLib::Parameters(theSphere, LastPoint, UlastOnSec, VlastOnSec);
+            if (VfirstOnSec < VlastOnSec)
+            {
+              f = VfirstOnSec;
+              l = VlastOnSec;
+            }
+            else
+            {
              // L'orientation parametrique est inversee
-             l = 2*M_PI - UFirst;
-             f = 2*M_PI - ULast;
+              f = VlastOnSec;
+              l = VfirstOnSec;
              isUReversed = Standard_True;
            }
-           // On calcul le "glissement" parametrique.
-           Standard_Real rot; 
-           rot = C.Position().XDirection().AngleWithRef
-             (AxisOfSphere.XDirection(), AxisOfSphere.YDirection());
-           f -= rot;
-           l  -= rot;
 
            if ( (f >= -M_PI/2) && (l <= M_PI/2)) {
              Ok = Standard_True;
@@ -959,7 +1034,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
       mySurface = new (Geom_RectangularTrimmedSurface)
        (S,UFirst, ULast, Standard_True);
 
-#if DEB
+#ifdef OCCT_DEBUG
   if (isUPeriodic && !mySurface->IsUPeriodic()) 
     cout<<"Pb de periodicite en U" << endl;
   if (isUPeriodic && !mySurface->IsUClosed())
@@ -1019,7 +1094,7 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
 {
   Standard_Integer ind = IndexOfTrace+1;
   if (IndexOfTrace > myLoc->TraceNumber())
-    Standard_OutOfRange::Raise(" GeomFill_Sweep::ErrorOnTrace");
+    throw Standard_OutOfRange(" GeomFill_Sweep::ErrorOnTrace");
 
   UError =  CError->Value(1, ind);
   VError =  CError->Value(2, ind);
@@ -1064,6 +1139,6 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
 {
   Standard_Integer ind = IndexOfTrace+1;
   if (IndexOfTrace > myLoc->TraceNumber())
-    Standard_OutOfRange::Raise(" GeomFill_Sweep::Trace");
+    throw Standard_OutOfRange(" GeomFill_Sweep::Trace");
   return  myCurve2d->Value(ind);  
 }