]> OCCT Git - occt-copy.git/commitdiff
0030489: Modeling Algorithms - BRepBuilderAPI_GTransform hangs
authorifv <ifv@opencascade.com>
Tue, 11 Jul 2017 07:15:28 +0000 (10:15 +0300)
committerazv <azv@opencascade.com>
Thu, 11 Apr 2019 07:20:20 +0000 (10:20 +0300)
Approx_ComputeCLine.gxx - criterium to stop interval cutting is increased.
ProjLib_ProjectedCurve.cxx - fix regression for bugs modalg_5 bug25886
Other tests are modified according to current state of algorithm

0028909: Algorithm of BO is stuck while fusing shell and edges

Approximation parameters: degmin, degmax, max number of segments, boundary condition, maximal distance of projecting are added in interface of classes ProjLib_ProjectedCurve, ProjLib_ComputeApprox,
ProjLib_ComputeApproxOnPolarSurface
Algorithm of Approx/Approx_ComputeCLine is modified in order to treat maximal number of segments allowed for cutting.
Algorithm of method BOPTools_AlgoTools2D::MakePCurveOnFace(...) is modified in order to manage cases with big edge tolerances.
Test case added
Some test cases were modified according to new behavior of algorithms

13 files changed:
src/Approx/Approx_ComputeCLine.gxx
src/Approx/Approx_FitAndDivide.hxx
src/Approx/Approx_FitAndDivide2d.hxx
src/BOPTools/BOPTools_AlgoTools2D.cxx
src/BRepFill/BRepFill_ComputeCLine.hxx
src/ProjLib/ProjLib.cxx
src/ProjLib/ProjLib.hxx
src/ProjLib/ProjLib_ComputeApprox.cxx
src/ProjLib/ProjLib_ComputeApprox.hxx
src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx
src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx
src/ProjLib/ProjLib_ProjectedCurve.cxx
src/ProjLib/ProjLib_ProjectedCurve.hxx

index f2fc63c460a799a1790e214391f8d3ecb1485860..d13c01e6e31b523673a27cab2e77276f4202cc12 100644 (file)
 //=======================================================================
 
 Approx_ComputeCLine::Approx_ComputeCLine
-                    (const MultiLine& Line,
-                    const Standard_Integer degreemin,
-                    const Standard_Integer degreemax,
-                    const Standard_Real Tolerance3d,
-                    const Standard_Real Tolerance2d,
-                    const Standard_Boolean cutting,
-                    const AppParCurves_Constraint FirstC,
-                    const AppParCurves_Constraint LastC)
+(const MultiLine& Line,
+const Standard_Integer degreemin,
+const Standard_Integer degreemax,
+const Standard_Real Tolerance3d,
+const Standard_Real Tolerance2d,
+const Standard_Boolean cutting,
+const AppParCurves_Constraint FirstC,
+const AppParCurves_Constraint LastC)
 {
   mydegremin = degreemin;
   mydegremax = degreemax;
@@ -50,6 +50,7 @@ Approx_ComputeCLine::Approx_ComputeCLine
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
+  myMaxSegments = IntegerLast();
   alldone = Standard_False;
   Perform(Line);
 }
@@ -60,13 +61,13 @@ Approx_ComputeCLine::Approx_ComputeCLine
 //=======================================================================
 
 Approx_ComputeCLine::Approx_ComputeCLine
-                    (const Standard_Integer degreemin,
-                    const Standard_Integer degreemax,
-                    const Standard_Real Tolerance3d,
-                    const Standard_Real Tolerance2d,
-                    const Standard_Boolean cutting,
-                    const AppParCurves_Constraint FirstC,
-                    const AppParCurves_Constraint LastC)
+(const Standard_Integer degreemin,
+const Standard_Integer degreemax,
+const Standard_Real Tolerance3d,
+const Standard_Real Tolerance2d,
+const Standard_Boolean cutting,
+const AppParCurves_Constraint FirstC,
+const AppParCurves_Constraint LastC)
 {
   alldone = Standard_False;
   mydegremin = degreemin;
@@ -76,6 +77,7 @@ Approx_ComputeCLine::Approx_ComputeCLine
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
+  myMaxSegments = IntegerLast();
 }
 
 //=======================================================================
@@ -86,19 +88,22 @@ Approx_ComputeCLine::Approx_ComputeCLine
 void Approx_ComputeCLine::Perform(const MultiLine& Line)
 {
   Standard_Real UFirst, ULast;
-  Standard_Boolean Finish = Standard_False, 
-          begin = Standard_True, Ok = Standard_False;
+  Standard_Boolean Finish = Standard_False,
+    begin = Standard_True, Ok = Standard_False;
   Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
   UFirst = Line.FirstParameter();
-  ULast  = Line.LastParameter();
-  Standard_Real TolU = (ULast-UFirst)*1.e-05;
-  Standard_Real myfirstU = UFirst; 
+  ULast = Line.LastParameter();
+  Standard_Real TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion());
+  Standard_Real myfirstU = UFirst;
   Standard_Real mylastU = ULast;
+  Standard_Integer aMaxSegments = 0;
+  Standard_Integer aMaxSegments1 = myMaxSegments - 1;
+  Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 5;
 
   if (!mycut)
   {
     alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
-    if (!alldone) 
+    if (!alldone)
     {
       tolreached = Standard_False;
       myfirstparam.Append(UFirst);
@@ -108,25 +113,28 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
       Tolers2d.Append(currenttol2d);
     }
   }
-  else 
+  else
   {
 
     // previous decision to be taken if we get worse with next cut (eap)
     AppParCurves_MultiCurve KeptMultiCurve;
     Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
 
-    while (!Finish) 
+    while (!Finish)
     {
-      
+
       // Gestion du decoupage de la multiline pour approximer:
-      if (!begin) 
+      if (!begin)
       {
-        if (Ok) 
+        if (Ok)
         {
           // Calcul de la partie a approximer.
           myfirstU = mylastU;
-          mylastU  = ULast;
-          if (Abs(ULast-myfirstU) <= RealEpsilon())
+          mylastU = ULast;
+          aNbCut = 0;
+          aNbImp = 0;
+          if (Abs(ULast - myfirstU) <= RealEpsilon()
+              || aMaxSegments >= myMaxSegments)
           {
             Finish = Standard_True;
             alldone = Standard_True;
@@ -142,45 +150,59 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
           if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
           {
             KeptMultiCurve = TheMultiCurve;
-            KeptUfirst     = myfirstU;
-            KeptUlast      = mylastU;
-            KeptT3d        = thetol3d;
-            KeptT2d        = thetol2d;
+            KeptUfirst = myfirstU;
+            KeptUlast = mylastU;
+            KeptT3d = thetol3d;
+            KeptT2d = thetol2d;
+            aNbImp++;
           }
 
           // cut an interval
-          mylastU = (myfirstU + mylastU)/2;
+          mylastU = (myfirstU + mylastU) / 2;
+          aNbCut++;
         }
       }
 
       // Calcul des parametres sur ce nouvel intervalle.
       Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
+      if (Ok)
+      {
+        aMaxSegments++;
+      }
 
       //cout << myfirstU << " - " << mylastU << "  tol : " << thetol3d << " " << thetol2d << endl;
-
+      Standard_Boolean aStopCutting = Standard_False;
+      if (aNbCut >= aNbComp)
+      {
+        if (aNbCut > aNbImp)
+        {
+          aStopCutting = Standard_True;
+        }
+      }
       // is new decision better?
-      if (!Ok && Abs(myfirstU-mylastU) <= TolU)
+      if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting ))
       {
-          Ok = Standard_True; // stop interval cutting, approx the rest part
+        Ok = Standard_True; // stop interval cutting, approx the rest part
 
-          if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
-          {
-            KeptMultiCurve = TheMultiCurve;
-            KeptUfirst     = myfirstU;
-            KeptUlast      = mylastU;
-            KeptT3d        = thetol3d;
-            KeptT2d        = thetol2d;
-          }
+        if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
+        {
+          KeptMultiCurve = TheMultiCurve;
+          KeptUfirst = myfirstU;
+          KeptUlast = mylastU;
+          KeptT3d = thetol3d;
+          KeptT2d = thetol2d;
+        }
 
-          mylastU = KeptUlast;
+        mylastU = KeptUlast;
 
-          tolreached = Standard_False; // helas
-          myMultiCurves.Append(KeptMultiCurve);
-          Tolers3d.Append     (KeptT3d);
-          Tolers2d.Append     (KeptT2d);
-          myfirstparam.Append (KeptUfirst);
-          mylastparam.Append  (KeptUlast);
-        }
+        tolreached = Standard_False; // helas
+        myMultiCurves.Append(KeptMultiCurve);
+        aMaxSegments++;
+        Tolers3d.Append(KeptT3d);
+        Tolers2d.Append(KeptT2d);
+        myfirstparam.Append(KeptUfirst);
+        mylastparam.Append(KeptUlast);
+      }
 
       begin = Standard_False;
     } // while (!Finish)
@@ -215,10 +237,10 @@ const
 //=======================================================================
 
 Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
-                                            const Standard_Real Ufirst,
-                                            const Standard_Real Ulast,
-                                            Standard_Real&   TheTol3d,
-                                            Standard_Real&   TheTol2d)
+  const Standard_Real Ufirst,
+  const Standard_Real Ulast,
+  Standard_Real&   TheTol3d,
+  Standard_Real&   TheTol2d)
 {
 
 
@@ -233,14 +255,14 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
     if (mydone) {
       LSquare.Error(Fv, TheTol3d, TheTol2d);
       if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
-       // Stockage de la multicurve approximee.
-       tolreached = Standard_True;
+        // Stockage de la multicurve approximee.
+        tolreached = Standard_True;
         myMultiCurves.Append(LSquare.Value());
-       myfirstparam.Append(Ufirst);
-       mylastparam.Append(Ulast);
-       Tolers3d.Append(TheTol3d);
-       Tolers2d.Append(TheTol2d);
-       return Standard_True;
+        myfirstparam.Append(Ufirst);
+        mylastparam.Append(Ulast);
+        Tolers3d.Append(TheTol3d);
+        Tolers2d.Append(TheTol2d);
+        return Standard_True;
       }
     }
     if (deg == mydegremax) {
@@ -248,7 +270,7 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
       currenttol3d = TheTol3d;
       currenttol2d = TheTol2d;
     }
-    
+
   }
   return Standard_False;
 }
@@ -260,11 +282,11 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
 //=======================================================================
 
 void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
-                                    Standard_Real& firstpar,
-                                    Standard_Real& lastpar) const
+  Standard_Real& firstpar,
+  Standard_Real& lastpar) const
 {
   firstpar = myfirstparam.Value(Index);
-  lastpar  = mylastparam.Value(Index);
+  lastpar = mylastparam.Value(Index);
 }
 
 //=======================================================================
@@ -273,7 +295,7 @@ void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
 //=======================================================================
 
 void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
-                                    const Standard_Integer degreemax)
+  const Standard_Integer degreemax)
 {
   mydegremin = degreemin;
   mydegremax = degreemax;
@@ -285,7 +307,7 @@ void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
 //=======================================================================
 
 void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
-                                      const Standard_Real Tolerance2d)
+  const Standard_Real Tolerance2d)
 {
   mytol3d = Tolerance3d;
   mytol2d = Tolerance2d;
@@ -297,10 +319,20 @@ void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
 //=======================================================================
 
 void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
-                                        const AppParCurves_Constraint LastC)
+  const AppParCurves_Constraint LastC)
 {
   myfirstC = FirstC;
-  mylastC  = LastC;
+  mylastC = LastC;
+}
+
+//=======================================================================
+//function : SetMaxSegments
+//purpose  : Changes the max number of segments, which is allowed for cutting.
+//=======================================================================
+
+void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
+{
+  myMaxSegments = theMaxSegments;
 }
 
 //=======================================================================
@@ -331,8 +363,8 @@ const {
 //=======================================================================
 
 void Approx_ComputeCLine::Error(const Standard_Integer Index,
-                              Standard_Real& tol3d,
-                              Standard_Real& tol2d) const
+  Standard_Real& tol3d,
+  Standard_Real& tol2d) const
 {
   tol3d = Tolers3d.Value(Index);
   tol2d = Tolers2d.Value(Index);
index 81a55658b7669db2a46fefcf9e7260fe67d6b8ae..f33f83e243b710d6374a3f2827428dc4196333bc 100644 (file)
@@ -60,6 +60,9 @@ public:
   
   //! Changes the constraints of the approximation.
   Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC);
+
+  //! Changes the max number of segments, which is allowed for cutting.
+  Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
   
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
@@ -114,6 +117,7 @@ private:
   Standard_Boolean mycut;
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
+  Standard_Integer myMaxSegments;
 
 
 };
index 646f45aba3b6fd7bee065259bacabdbebfee7272..829bd82fcbeb6213f7df5e5171e13f0bee75927b 100644 (file)
@@ -60,6 +60,9 @@ public:
   
   //! Changes the constraints of the approximation.
   Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC);
+
+  //! Changes the max number of segments, which is allowed for cutting.
+  Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
   
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
@@ -114,6 +117,7 @@ private:
   Standard_Boolean mycut;
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
+  Standard_Integer myMaxSegments;
 
 
 };
index 9697b92f561c0d37a9d62568ee3731cef13d58ad..20efb35b5ced653f5f513c7be2b8a24436f91981 100644 (file)
@@ -629,11 +629,13 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
   Handle(GeomAdaptor_HCurve) aBAHC = new GeomAdaptor_HCurve(aC3D, aT1, aT2);
   //
   Standard_Real aTolR;
+  Standard_Real aTR = Precision::Confusion();//1.e-7;
+  Standard_Real aMaxTol = 1.e3 * aTR; //0.0001
+  Standard_Boolean isAnaSurf =  ProjLib::IsAnaSurf(aBAHS);
+
   //when the type of surface is GeomAbs_SurfaceOfRevolution
-  if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution) {
-    Standard_Real aTR;
-    //
-    aTR=Precision::Confusion();//1.e-7;
+  if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution) 
+  {
     if (TolReached2d > aTR) {
       aTR=TolReached2d;
     }
@@ -642,23 +644,44 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
     ProjLib::MakePCurveOfType(aProj1, aC2D);
     aTolR = aProj1.GetTolerance();
   } 
-  else {
-    ProjLib_ProjectedCurve aProjCurv(aBAHS, aBAHC);// 1
+  else 
+  {
+    ProjLib_ProjectedCurve aProjCurv(aBAHS);
+    Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1;
+    Standard_Real aMaxDist = -1;
+    AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint;
+    if ((TolReached2d  >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf))
+    {
+      aTR = Min(aMaxTol, 0.1*TolReached2d);
+      aMaxSegments = 100;
+      aMaxDist = 1.e3*TolReached2d;
+      if(!isAnaSurf)
+      {
+        aBndPnt = AppParCurves_PassPoint;
+      }
+    }
+    else if(TolReached2d > aMaxTol)
+    {
+      aTR = Min(TolReached2d, 1.e3 * aMaxTol);
+      aMaxDist = 1.e2 * aTR;
+      aMaxSegments = 100;
+    }
+    aProjCurv.Load(aTR);
+    aProjCurv.SetDegree(aDegMin, aDegMax);
+    aProjCurv.SetMaxSegments(aMaxSegments);
+    aProjCurv.SetBndPnt(aBndPnt);
+    aProjCurv.SetMaxDist(aMaxDist);
+    aProjCurv.Perform(aBAHC);
     ProjLib::MakePCurveOfType(aProjCurv, aC2D);
     aTolR=aProjCurv.GetTolerance();
   }
   //
-  if (aC2D.IsNull()) { 
-    ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, TolReached2d);// 2
+  if (aC2D.IsNull() && (aTR < aMaxTol || aTR < TolReached2d))
+  { 
+    aTR = Max(TolReached2d, aMaxTol);
+    ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, aTR);// 2
     ProjLib::MakePCurveOfType(aProjCurvAgain, aC2D);
     aTolR = aProjCurvAgain.GetTolerance();
-    //
-    if (aC2D.IsNull()) { 
-      Standard_Real aTR=0.0001;
-      ProjLib_ProjectedCurve aProj3(aBAHS, aBAHC, aTR);// 3
-      ProjLib::MakePCurveOfType(aProj3, aC2D);
-      aTolR = aProj3.GetTolerance();
-    }
   }
   //
   if(aC2D.IsNull())
index 2b438001d5df5eba50a2bf6740b649a9e5986f5d..5391c41aae696357dee9cf7d06f70675cc75affb 100644 (file)
@@ -61,6 +61,9 @@ public:
   //! Changes the constraints of the approximation.
   Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC);
   
+  //! Changes the max number of segments, which is allowed for cutting.
+  Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
+
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
   //! when more points were needed.
@@ -114,7 +117,7 @@ private:
   Standard_Boolean mycut;
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
-
+  Standard_Integer myMaxSegments;
 
 };
 
index c9f380bcc824b36d5084300756cc92e1a20e1ed5..36ee34ddbcf8c4f46d7e2e6d2c944145a797c0ed 100644 (file)
@@ -48,6 +48,7 @@
 #include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_BezierCurve.hxx>
 #include <Standard_NotImplemented.hxx>
+#include <Adaptor3d_HSurface.hxx>
 
 //=======================================================================
 //function : Project
@@ -281,3 +282,25 @@ void  ProjLib::MakePCurveOfType
     break;
   }
 }
+//=======================================================================
+//function : IsAnaSurf
+//purpose  : 
+//=======================================================================
+Standard_Boolean  ProjLib::IsAnaSurf
+  (const Handle(Adaptor3d_HSurface)& theAS) 
+{ 
+  switch (theAS->GetType()) 
+  {
+
+  case GeomAbs_Plane:
+  case GeomAbs_Cylinder:
+  case GeomAbs_Cone:
+  case GeomAbs_Sphere:
+  case GeomAbs_Torus:
+    return Standard_True;
+    break;
+  default :
+    return Standard_False;
+    break;
+  }
+}
index b5fa7ac0970fe178e354491de5c6dd0325db6582..f5334796437efd58a109ef09d760285b5b6f6343 100644 (file)
@@ -55,7 +55,7 @@ class ProjLib_Cylinder;
 class ProjLib_Cone;
 class ProjLib_Sphere;
 class ProjLib_Torus;
-
+class Adaptor3d_HSurface;
 
 //! The  projLib package  first provides projection of
 //! curves on a   plane along a  given Direction.  The
@@ -132,6 +132,12 @@ public:
   //! Make empty  P-Curve <aC> of relevant to <PC> type
   Standard_EXPORT static void MakePCurveOfType (const ProjLib_ProjectedCurve& PC,
                                                 Handle(Geom2d_Curve)& aC);
+  //! Returns "true" if surface is analytical, that is it can be
+  //! Plane, Cylinder, Cone, Sphere, Torus.
+  //! For all other types of surface method returns "false".
+  Standard_EXPORT static Standard_Boolean IsAnaSurf
+                                           (const Handle(Adaptor3d_HSurface)& theAS);
+
 
 
 
index 9fc50d35fd1f250c5d1ea275e4be15c7ad32ec51..50909981873c6f32c768086771e627261b4d8612 100644 (file)
@@ -17,6 +17,7 @@
 // modified by NIZHNY-OFV  Thu Jan 20 11:04:19 2005
 
 #include <ProjLib_ComputeApprox.hxx>
+#include <ProjLib.hxx>
 
 #include <GeomAbs_SurfaceType.hxx>
 #include <GeomAbs_CurveType.hxx>
@@ -956,6 +957,18 @@ static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf,
 
   return aTolV;
 }
+//=======================================================================
+//function : ProjLib_ComputeApprox
+//purpose  : 
+//=======================================================================
+
+ProjLib_ComputeApprox::ProjLib_ComputeApprox():
+  myTolerance(Precision::PApproximation()),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myBndPnt(AppParCurves_TangencyPoint)
+{
+}
 
 //=======================================================================
 //function : ProjLib_ComputeApprox
@@ -965,19 +978,32 @@ static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf,
 ProjLib_ComputeApprox::ProjLib_ComputeApprox
   (const Handle(Adaptor3d_HCurve)   & C,
    const Handle(Adaptor3d_HSurface) & S,
-   const Standard_Real              Tol )
+   const Standard_Real              Tol):
+  myTolerance(Max(Tol, Precision::PApproximation())),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myBndPnt(AppParCurves_TangencyPoint)
+{
+  Perform(C,  S);
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+void ProjLib_ComputeApprox::Perform
+  (const Handle(Adaptor3d_HCurve)   & C,
+   const Handle(Adaptor3d_HSurface) & S )
 {
   // if the surface is a plane and the curve a BSpline or a BezierCurve,
   // don`t make an Approx but only the projection of the poles.
 
-  myTolerance = Max(Precision::PApproximation(),Tol);
   Standard_Integer NbKnots, NbPoles ;
   GeomAbs_CurveType   CType = C->GetType();
   GeomAbs_SurfaceType SType = S->GetType();
 
-  Standard_Boolean SurfIsAnal = (SType != GeomAbs_BSplineSurface) &&
-                                (SType != GeomAbs_BezierSurface)  &&
-                                (SType != GeomAbs_OtherSurface)     ;
+  Standard_Boolean SurfIsAnal = ProjLib::IsAnaSurf(S);
 
   Standard_Boolean CurvIsAnal = (CType != GeomAbs_BSplineCurve) &&
                                 (CType != GeomAbs_BezierCurve)  &&
@@ -1085,21 +1111,43 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
 #endif    
 
 //-----------
-    Standard_Integer Deg1, Deg2;
+    Standard_Integer Deg1 = 8, Deg2;
     if(simplecase) {
-      Deg1 = 8; 
       Deg2 = 10; 
     }
     else {
-      Deg1 = 8; 
       Deg2 = 12; 
     }
+    if(myDegMin > 0)
+    {
+      Deg1 = myDegMin; 
+    }
+    //
+    if(myDegMax > 0)
+    {
+      Deg2 = myDegMax; 
+    }
+    //
+    Standard_Integer aMaxSegments = 1000;
+    if(myMaxSegments > 0)
+    {
+      aMaxSegments = myMaxSegments;
+    }
+    AppParCurves_Constraint aFistC = AppParCurves_TangencyPoint, aLastC = AppParCurves_TangencyPoint;
+    if(myBndPnt != AppParCurves_TangencyPoint)
+    {
+      aFistC = myBndPnt; 
+      aLastC = myBndPnt;
+    }
+  
 //-------------
     const Standard_Real aTolU = ComputeTolU(S, myTolerance);
     const Standard_Real aTolV = ComputeTolV(S, myTolerance);
     const Standard_Real aTol2d = Max(Sqrt(aTolU*aTolU + aTolV*aTolV), Precision::PConfusion());
 
-    Approx_FitAndDivide2d Fit(F, Deg1, Deg2, myTolerance, aTol2d, Standard_True);
+    Approx_FitAndDivide2d Fit(Deg1, Deg2, myTolerance, aTol2d, Standard_True, aFistC, aLastC);
+    Fit.SetMaxSegments(aMaxSegments);
+    Fit.Perform(F);
 
     Standard_Real aNewTol2d = 0;
     if(Fit.IsAllApproximated()) {
@@ -1115,8 +1163,7 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
               aNewTol2d = Max(aNewTol2d, Tol2d);
              AppParCurves_MultiCurve MC = Fit.Value( i);       //Charge la Ieme Curve
              TColgp_Array1OfPnt2d Poles2d( 1, MC.Degree() + 1);//Recupere les poles
-             MC.Curve(1, Poles2d);
-            
+             MC.Curve(1, Poles2d);        
              Conv.AddCurve(Poles2d);
       }
 
@@ -1141,13 +1188,6 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
                               C->LastParameter(),
                               NewKnots);
 
-      /*cout << endl;
-      for (int i = 1; i <= NbPoles; i++)
-      {
-        cout << NewPoles.Value(i).X() << " " << NewPoles.Value(i).Y() << endl;
-      }
-      cout << endl; */
-
       // il faut recadrer les poles de debut et de fin:
       // ( Car pour les problemes de couture, on a du ouvrir l`intervalle
       // de definition de la courbe.)
@@ -1157,6 +1197,17 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
                                            NewKnots,
                                            NewMults,
                                            Conv.Degree());
+
+      if(aFistC == AppParCurves_PassPoint || aLastC == AppParCurves_PassPoint)
+      {
+        // try to smoother the Curve GeomAbs_C1.
+        Standard_Integer aDeg = myBSpline->Degree();
+        Standard_Boolean OK = Standard_True;
+        Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d);
+        for (Standard_Integer ij = 2; ij < NbKnots; ij++) {
+          OK = OK && myBSpline->RemoveKnot(ij, aDeg-1, aSmoothTol);  
+        }
+      }
     }
     else {
       Standard_Integer NbCurves = Fit.NbMultiCurves();
@@ -1254,6 +1305,42 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
     }
   }
 }
+//=======================================================================
+//function : SetTolerance
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApprox::SetTolerance(const Standard_Real theTolerance)
+{
+  myTolerance = theTolerance;
+}
+
+//=======================================================================
+//function : SetDegree
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApprox::SetDegree(const Standard_Integer theDegMin, 
+                                       const Standard_Integer theDegMax)
+{
+  myDegMin = theDegMin;
+  myDegMax = theDegMax;
+}
+//=======================================================================
+//function : SetMaxSegments
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApprox::SetMaxSegments(const Standard_Integer theMaxSegments)
+{
+  myMaxSegments = theMaxSegments;
+}
+
+//=======================================================================
+//function : SetBndPnt
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApprox::SetBndPnt(const AppParCurves_Constraint theBndPnt)
+{
+  myBndPnt = theBndPnt;
+}
 
 //=======================================================================
 //function : BSpline
index 6bb6d54a36f146247e39093e597e387473f9578a..c1aeda678bc2933d61c9a1bc05d9788e2b9ae37c 100644 (file)
@@ -22,6 +22,8 @@
 #include <Standard_Handle.hxx>
 
 #include <Standard_Real.hxx>
+#include <AppParCurves_Constraint.hxx>
+
 class Geom2d_BSplineCurve;
 class Geom2d_BezierCurve;
 class Adaptor3d_HCurve;
@@ -31,17 +33,51 @@ class Adaptor3d_HSurface;
 //! Approximate the  projection of  a 3d curve   on an
 //! analytic surface and stores the result in Approx.
 //! The result is a 2d curve.
+//! For approximation some parameters are used, including 
+//! required tolerance of approximation.
+//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from
+//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed
+//! from 3d tolerance with help of U,V resolutions of surface.
+//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation
+//! and have nothing to do with distance between the projected curve and the surface.
 class ProjLib_ComputeApprox 
 {
 public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+  //! Empty constructor, it only sets some initial values for class fields.
+  Standard_EXPORT ProjLib_ComputeApprox();
+   
   //! <Tol>    is   the   tolerance   with  which    the
   //! approximation is performed.
+  //! Other parameters for approximation have default values.
   Standard_EXPORT ProjLib_ComputeApprox(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol);
   
+  //! Performs projecting.
+  //! In case of approximation current values of parameters are used:
+  //! default values or set by corresponding methods Set...
+  Standard_EXPORT void Perform(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S);
+
+  //! Set tolerance of approximation.
+  //! Default value is Precision::Confusion().
+  Standard_EXPORT void SetTolerance(const Standard_Real theTolerance);
+
+  //! Set min and max possible degree of result BSpline curve2d, which is got by approximation.
+  //! If theDegMin/Max < 0, algorithm uses values that are chosen depending of types curve 3d
+  //! and surface.
+  Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax);
+
+  //! Set the parameter, which defines maximal value of parametric intervals the projected
+  //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default 
+  //! value = 1000.
+  Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments);
+
+  //! Set the parameter, which defines type of boundary condition between segments during approximation.
+  //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint.
+  //! Default value is AppParCurves_TangencyPoint;
+  Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt);
+
   Standard_EXPORT Handle(Geom2d_BSplineCurve) BSpline() const;
   
   Standard_EXPORT Handle(Geom2d_BezierCurve) Bezier() const;
@@ -60,12 +96,13 @@ protected:
 
 private:
 
-
-
   Standard_Real myTolerance;
   Handle(Geom2d_BSplineCurve) myBSpline;
   Handle(Geom2d_BezierCurve) myBezier;
-
+  Standard_Integer myDegMin;
+  Standard_Integer myDegMax;
+  Standard_Integer myMaxSegments;
+  AppParCurves_Constraint myBndPnt;
 
 };
 
index 16e1255320b0b687aa4b65be0ca37be95a485042..c639c819f6899eb782f7e1486a840ce3cebefa57 100644 (file)
@@ -477,11 +477,15 @@ class ProjLib_PolarFunction : public AppCont_Function
 
 ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface()
 : myProjIsDone(Standard_False),
-  myTolerance (-1.0)
+  myTolerance(Precision::Approximation()),
+  myTolReached(-1.0),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
 }
 
-
 //=======================================================================
 //function : ProjLib_ComputeApproxOnPolarSurface
 //purpose  : 
@@ -493,10 +497,37 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
                      const Handle(Adaptor3d_HSurface)& theSurface,
                      const Standard_Real               theTolerance3D)
 : myProjIsDone(Standard_False),
-  myTolerance (theTolerance3D)
+  myTolerance(theTolerance3D),
+  myTolReached(-1.0),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
   myBSpline = Perform(theInitialCurve2d, theCurve, theSurface);
 }
+
+//=======================================================================
+//function : ProjLib_ComputeApproxOnPolarSurface
+//purpose  : case without curve of initialization
+//=======================================================================
+
+ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
+                      (const Handle(Adaptor3d_HCurve)&   theCurve,
+                       const Handle(Adaptor3d_HSurface)& theSurface,
+                       const Standard_Real               theTolerance3D)
+: myProjIsDone(Standard_False),
+  myTolerance(theTolerance3D),
+  myTolReached(-1.0),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
+{
+  const Handle(Adaptor2d_HCurve2d) anInitCurve2d;
+  myBSpline = Perform(anInitCurve2d, theCurve, theSurface);  
+} 
+
 //=======================================================================
 //function : ProjLib_ComputeApproxOnPolarSurface
 //purpose  : Process the case of sewing
@@ -509,7 +540,12 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
                  const Handle(Adaptor3d_HSurface)& theSurface,
                  const Standard_Real               theTolerance3D)
 : myProjIsDone(Standard_False),
-  myTolerance (theTolerance3D)
+  myTolerance(theTolerance3D),
+  myTolReached(-1.0),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
   // InitialCurve2d and InitialCurve2dBis are two pcurves of the sewing 
   Handle(Geom2d_BSplineCurve) bsc =
@@ -538,21 +574,6 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
   }
 }
 
-//=======================================================================
-//function : ProjLib_ComputeApproxOnPolarSurface
-//purpose  : case without curve of initialization
-//=======================================================================
-
-ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
-                      (const Handle(Adaptor3d_HCurve)&   theCurve,
-                       const Handle(Adaptor3d_HSurface)& theSurface,
-                       const Standard_Real               theTolerance3D)
-: myProjIsDone(Standard_False),
-  myTolerance (theTolerance3D)
-{
-  const Handle(Adaptor2d_HCurve2d) anInitCurve2d;
-  myBSpline = Perform(anInitCurve2d, theCurve, theSurface);  
-} 
 
 //=======================================================================
 //function : Concat
@@ -628,15 +649,27 @@ static Handle(Geom2d_BSplineCurve) Concat(Handle(Geom2d_BSplineCurve) C1,
   return BS;
 }
 
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+void ProjLib_ComputeApproxOnPolarSurface::Perform
+(const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S)
+{
+  const Handle(Adaptor2d_HCurve2d) anInitCurve2d;
+  myBSpline = Perform(anInitCurve2d, Curve, S);  
+}
 
 //=======================================================================
 //function : Perform
 //purpose  : 
 //=======================================================================
+
 Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
 (const Handle(Adaptor2d_HCurve2d)& InitialCurve2d,
  const Handle(Adaptor3d_HCurve)& Curve,
- const Handle(Adaptor3d_HSurface)& S) 
+ const Handle(Adaptor3d_HSurface)& S)
 {
   //OCC217
   Standard_Real Tol3d = myTolerance; 
@@ -752,8 +785,11 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
       }
        
       if(myProjIsDone) {
-       BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d);  
-       if(BSC2d.IsNull()) return Handle(Geom2d_BSplineCurve)(); //IFV
+       BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d);
+       if(BSC2d.IsNull()) 
+        {
+            return Handle(Geom2d_BSplineCurve)();
+        }
        LOfBSpline2d.Append(BSC2d);
       }
       else {
@@ -799,7 +835,7 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
          }
        }
        if(myProjIsDone) {
-         BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d);  
+         BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d);
          if(BSC2d.IsNull()) {
            return Handle(Geom2d_BSplineCurve)();
          }
@@ -854,9 +890,10 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
     if(!myProjIsDone) 
       return Handle(Geom2d_BSplineCurve)(); 
   }
-  return ProjectUsingInitialCurve2d(AHC, S, AHC2d);    
+  return ProjectUsingInitialCurve2d(AHC, S, AHC2d);     
 }
 
+
 //=======================================================================
 //function : ProjLib_BuildInitialCurve2d
 //purpose  : 
@@ -875,7 +912,11 @@ Handle(Adaptor2d_HCurve2d)
   Standard_Real Tol3d = myTolerance; 
   Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d);
   Standard_Real DistTol3d = 100.0*Tol3d;
-
+  if(myMaxDist > 0.)
+  {
+    DistTol3d = myMaxDist;
+  }
+  Standard_Real DistTol3d2 = DistTol3d * DistTol3d;
   Standard_Real uperiod = 0.0, vperiod = 0.0;
   computePeriodicity(Surf, uperiod, vperiod);
 
@@ -1054,7 +1095,7 @@ Handle(Adaptor2d_HCurve2d)
           aMinSqDist = aSqDist;
       }
     }
-    if (aMinSqDist > DistTol3d * DistTol3d) //try to project with less tolerance
+    if (aMinSqDist > DistTol3d2) //try to project with less tolerance
     {
       TolU = Min(TolU, Precision::PConfusion());
       TolV = Min(TolV, Precision::PConfusion());
@@ -1070,7 +1111,7 @@ Handle(Adaptor2d_HCurve2d)
       Standard_Integer GoodValue = 1;
 
       for ( i = 1 ; i <= aExtPS.NbExt() ; i++ ) {
-       if( aExtPS.SquareDistance(i) < DistTol3d * DistTol3d ) {
+       if( aExtPS.SquareDistance(i) < DistTol3d2 ) {
          if( aExtPS.SquareDistance(i) <= 1.e-18 ) {
            aExtPS.Point(i).Parameter(u,v);
            gp_Pnt2d p2d(u,v);
@@ -1092,7 +1133,7 @@ Handle(Adaptor2d_HCurve2d)
 
       if( Sols.Length() > 1 ) areManyZeros = Standard_True;
 
-      if( Dist2Min <= DistTol3d * DistTol3d) {
+      if( Dist2Min <= DistTol3d2) {
        if( !areManyZeros ) {
          aExtPS.Point(GoodValue).Parameter(u,v);
          Pts2d(1).SetCoord(u,v);
@@ -1122,7 +1163,7 @@ Handle(Adaptor2d_HCurve2d)
              Dist2Min = 1.e+200;
              if( aTPS.IsDone() && aTPS.NbExt() >= 1 ) {
                for( j = 1 ; j <= aTPS.NbExt() ; j++ ) {
-                 if( aTPS.SquareDistance(j) < DistTol3d * DistTol3d ) {
+                 if( aTPS.SquareDistance(j) < DistTol3d2 ) {
                    nbExtOk++;
                    if( aTPS.SquareDistance(j) < Dist2Min ) {
                      Dist2Min = aTPS.SquareDistance(j);
@@ -1150,7 +1191,7 @@ Handle(Adaptor2d_HCurve2d)
                Standard_Integer indExt = 0;
                if( aTPS.IsDone() && aTPS.NbExt() >= 1 ) {
                  for( i = 1 ; i <= aTPS.NbExt() ; i++ ) {
-                   if( aTPS.SquareDistance(i) < DistTol3d * DistTol3d && aTPS.SquareDistance(i) < Dist2Min ) {
+                   if( aTPS.SquareDistance(i) < DistTol3d2 && aTPS.SquareDistance(i) < Dist2Min ) {
                      Dist2Min = aTPS.SquareDistance(i);
                      indExt = i;
                      isFound = Standard_True;
@@ -1224,7 +1265,7 @@ Handle(Adaptor2d_HCurve2d)
 
          if (aLocateExtPS.IsDone())
           {
-           if (aLocateExtPS.SquareDistance() < DistTol3d * DistTol3d)
+           if (aLocateExtPS.SquareDistance() < DistTol3d2)
             {  //OCC217
               //if (aLocateExtPS.SquareDistance() < Tol3d * Tol3d) {
              (aLocateExtPS.Point()).Parameter(U0,V0);
@@ -1249,7 +1290,7 @@ Handle(Adaptor2d_HCurve2d)
                     imin = isol;
                   }
                 }
-                if (LocalMinSqDist < DistTol3d * DistTol3d)
+                if (LocalMinSqDist < DistTol3d2)
                 {
                   Standard_Real LocalU, LocalV;
                   aGlobalExtr.Point(imin).Parameter(LocalU, LocalV);
@@ -1321,7 +1362,7 @@ Handle(Adaptor2d_HCurve2d)
             locext.Perform(pntproj, Uaux, V0);
 
            if (locext.IsDone())
-             if (locext.SquareDistance() < DistTol3d * DistTol3d) {  //OCC217
+             if (locext.SquareDistance() < DistTol3d2) {  //OCC217
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
                (locext.Point()).Parameter(u,v);
                if((aUsup - U0) > (U0 - aUinf)) 
@@ -1348,7 +1389,7 @@ Handle(Adaptor2d_HCurve2d)
             locext.Perform(pntproj, U0, Vaux);
 
            if (locext.IsDone())
-             if (locext.SquareDistance() < DistTol3d * DistTol3d) {  //OCC217
+             if (locext.SquareDistance() < DistTol3d2) {  //OCC217
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
                (locext.Point()).Parameter(u,v);
                if((aVsup - V0) > (V0 - aVinf)) 
@@ -1377,7 +1418,7 @@ Handle(Adaptor2d_HCurve2d)
             locext.Perform(pntproj, Uaux, Vaux);
 
            if (locext.IsDone())
-             if (locext.SquareDistance() < DistTol3d * DistTol3d) {
+             if (locext.SquareDistance() < DistTol3d2) {
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
                (locext.Point()).Parameter(u,v);
                if((Usup - U0) > (U0 - Uinf)) 
@@ -1405,7 +1446,7 @@ Handle(Adaptor2d_HCurve2d)
                  Dist2Min = ext.SquareDistance(j);
                  aGoodValue = j;
                }
-             if (Dist2Min < DistTol3d * DistTol3d) {
+             if (Dist2Min < DistTol3d2) {
              //if (Dist2Min < Tol3d * Tol3d) {
                (ext.Point(aGoodValue)).Parameter(u,v);
                if(uperiod) {
@@ -1490,9 +1531,6 @@ Handle(Adaptor2d_HCurve2d)
 //  Modified by Sergey KHROMOV - Thu Apr 18 10:58:02 2002 End
 }
 
-
-
-
 //=======================================================================
 //function : ProjLib_ProjectUsingInitialCurve2d
 //purpose  : 
@@ -1501,24 +1539,27 @@ Handle(Geom2d_BSplineCurve)
      ProjLib_ComputeApproxOnPolarSurface::
      ProjectUsingInitialCurve2d(const Handle(Adaptor3d_HCurve)& Curve,
                                const Handle(Adaptor3d_HSurface)& Surf,
-                               const Handle(Adaptor2d_HCurve2d)& InitCurve2d) 
+                               const Handle(Adaptor2d_HCurve2d)& InitCurve2d)
 {  
   //OCC217
   Standard_Real Tol3d = myTolerance;
-  Standard_Real DistTol3d = 1.0*Tol3d;
+  Standard_Real DistTol3d = 100.0*Tol3d;
+  if(myMaxDist > 0.)
+  {
+    DistTol3d = myMaxDist;
+  }
+  Standard_Real DistTol3d2 = DistTol3d * DistTol3d;
   Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d);
   Standard_Real Tol2d = Max(Sqrt(TolU*TolU + TolV*TolV), Precision::PConfusion());
 
   Standard_Integer i;
   GeomAbs_SurfaceType TheTypeS = Surf->GetType();
   GeomAbs_CurveType TheTypeC = Curve->GetType();
-//  Handle(Standard_Type) TheTypeS = Surf->DynamicType();
-//  Handle(Standard_Type) TheTypeC = Curve->DynamicType();   // si on a :
-//  if(TheTypeS == STANDARD_TYPE(Geom_BSplineSurface)) {
   if(TheTypeS == GeomAbs_Plane) {
     Standard_Real S, T;
     gp_Pln Plane = Surf->Plane();
     if(TheTypeC == GeomAbs_BSplineCurve) {
+      myTolReached = Precision::Confusion();
       Handle(Geom_BSplineCurve) BSC = Curve->BSpline();
       TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
       for(i = 1;i <= Curve->NbPoles();i++) {
@@ -1540,6 +1581,7 @@ Handle(Geom2d_BSplineCurve)
       
     }
     if(TheTypeC == GeomAbs_BezierCurve) {
+      myTolReached = Precision::Confusion();
       Handle(Geom_BezierCurve) BC = Curve->Bezier();
       TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
       for(i = 1;i <= Curve->NbPoles();i++) {
@@ -1572,17 +1614,11 @@ Handle(Geom2d_BSplineCurve)
       gp_Pnt p22 = BSS->Pole(2,2);
       gp_Vec V1(p11,p12);
       gp_Vec V2(p21,p22);
-      if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){  //OCC217
-      //if(V1.IsEqual(V2,myTolerance,myTolerance/(p11.Distance(p12)*180/M_PI))){
-       //  so the polar surface is plane
-       //  and if it is enough to projet the  poles of Curve
+      if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){  
        Standard_Integer Dist2Min = IntegerLast();
        Standard_Real u,v;
-       //OCC217
-       //Standard_Real TolU = Surf->UResolution(myTolerance)
-       //  , TolV = Surf->VResolution(myTolerance);
-//     gp_Pnt pntproj;
        if(TheTypeC == GeomAbs_BSplineCurve) {
+          myTolReached = Tol3d;
          Handle(Geom_BSplineCurve) BSC = Curve->BSpline();
          TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
          for(i = 1;i <= Curve->NbPoles();i++) {
@@ -1594,8 +1630,7 @@ Handle(Geom2d_BSplineCurve)
 
            if (extrloc.IsDone()) {
              Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
-             if (Dist2Min < DistTol3d * DistTol3d) {  //OCC217
-             //if (Dist2Min < myTolerance * myTolerance) {
+             if (Dist2Min < DistTol3d2) {  
                (extrloc.Point()).Parameter(u,v);
                Poles2d(i).SetCoord(u,v);
                myProjIsDone = Standard_True;
@@ -1624,6 +1659,7 @@ Handle(Geom2d_BSplineCurve)
          }
        } 
        if(TheTypeC == GeomAbs_BezierCurve) {
+          myTolReached = Tol3d;
          Handle(Geom_BezierCurve) BC = Curve->Bezier();
          TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
          for(i = 1;i <= Curve->NbPoles();i++) {
@@ -1634,8 +1670,7 @@ Handle(Geom2d_BSplineCurve)
 
            if (extrloc.IsDone()) {
              Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
-             if (Dist2Min < DistTol3d * DistTol3d) {  //OCC217
-             //if (Dist2Min < myTolerance * myTolerance) {
+             if (Dist2Min < DistTol3d2) {  
                (extrloc.Point()).Parameter(u,v);
                Poles2d(i).SetCoord(u,v);
                myProjIsDone = Standard_True;
@@ -1677,19 +1712,15 @@ Handle(Geom2d_BSplineCurve)
       gp_Pnt p22 = BS->Pole(2,2);
       gp_Vec V1(p11,p12);
       gp_Vec V2(p21,p22);
-      if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ //OCC217
-      //if (V1.IsEqual(V2,myTolerance,myTolerance/(p11.Distance(p12)*180/M_PI))){ 
-       //    and if it is enough to project the poles of Curve
+      if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ 
        Standard_Integer Dist2Min = IntegerLast();
        Standard_Real u,v;
-        //OCC217
-       //Standard_Real TolU = Surf->UResolution(myTolerance)
-       //  , TolV = Surf->VResolution(myTolerance);
-
 //     gp_Pnt pntproj;
        if(TheTypeC == GeomAbs_BSplineCurve) {
+          myTolReached = Tol3d;
          Handle(Geom_BSplineCurve) BSC = Curve->BSpline();
-         TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
+         TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
          for(i = 1;i <= Curve->NbPoles();i++) {
            myProjIsDone = Standard_False;
            Dist2Min = IntegerLast();
@@ -1699,8 +1730,7 @@ Handle(Geom2d_BSplineCurve)
 
            if (extrloc.IsDone()) {
              Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
-             if (Dist2Min < DistTol3d * DistTol3d) {  //OCC217
-             //if (Dist2Min < myTolerance * myTolerance) {
+             if (Dist2Min < DistTol3d2) {  
                (extrloc.Point()).Parameter(u,v);
                Poles2d(i).SetCoord(u,v);
                myProjIsDone = Standard_True;
@@ -1729,6 +1759,7 @@ Handle(Geom2d_BSplineCurve)
          }
        } 
        if(TheTypeC == GeomAbs_BezierCurve) {
+          myTolReached = Tol3d;
          Handle(Geom_BezierCurve) BC = Curve->Bezier();
          TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles());
          for(i = 1;i <= Curve->NbPoles();i++) {
@@ -1739,8 +1770,7 @@ Handle(Geom2d_BSplineCurve)
 
            if (extrloc.IsDone()) {
              Dist2Min = (Standard_Integer ) extrloc.SquareDistance();
-             if (Dist2Min < DistTol3d * DistTol3d) {  //OCC217
-             //if (Dist2Min < myTolerance * myTolerance) {
+             if (Dist2Min < DistTol3d2) {  
                (extrloc.Point()).Parameter(u,v);
                Poles2d(i).SetCoord(u,v);
                myProjIsDone = Standard_True;
@@ -1772,8 +1802,7 @@ Handle(Geom2d_BSplineCurve)
     }
   }
 
-  ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, Tol3d) ;  //OCC217
-  //ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, myTolerance) ;
+  ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, Tol3d) ;  
 
 #ifdef OCCT_DEBUG
   Standard_Integer Nb = 50;
@@ -1812,15 +1841,34 @@ Handle(Geom2d_BSplineCurve)
 #endif
 
   Standard_Integer Deg1,Deg2;
-//  Deg1 = 8;
-//  Deg2 = 8;
-  Deg1 = 2; //IFV
-  Deg2 = 8; //IFV 
+  Deg1 = 2; 
+  Deg2 = 8;  
+  if(myDegMin > 0)
+  {
+    Deg1 = myDegMin;
+  }
+  if(myDegMax > 0)
+  {
+    Deg2 = myDegMax;
+  }
+  Standard_Integer aMaxSegments = 1000;
+  if(myMaxSegments > 0)
+  {
+    aMaxSegments = myMaxSegments;
+  }
+  AppParCurves_Constraint aFistC = AppParCurves_TangencyPoint, aLastC = AppParCurves_TangencyPoint;
+  if(myBndPnt != AppParCurves_TangencyPoint)
+  {
+    aFistC = myBndPnt; 
+    aLastC = myBndPnt;
+  }
 
-  Approx_FitAndDivide2d Fit(F,Deg1,Deg2,Tol3d,Tol2d, //OCC217
-  //Approx_FitAndDivide2d Fit(F,Deg1,Deg2,myTolerance,myTolerance,
-                           Standard_True);
+  Approx_FitAndDivide2d Fit(Deg1, Deg2, Tol3d, Tol2d, Standard_True, aFistC, aLastC);
+  Fit.SetMaxSegments(aMaxSegments);
+  Fit.Perform(F);
 
+  Standard_Real anOldTol2d = Tol2d;
+  Standard_Real aNewTol2d = 0;
   if(Fit.IsAllApproximated()) {
     Standard_Integer j;
     Standard_Integer NbCurves = Fit.NbMultiCurves();
@@ -1831,8 +1879,12 @@ Handle(Geom2d_BSplineCurve)
     for (j = 1; j <= NbCurves; j++) {
       Standard_Integer Deg = Fit.Value(j).Degree();
       MaxDeg = Max ( MaxDeg, Deg);
+      Fit.Error(j,Tol3d, Tol2d);
+      aNewTol2d = Max(aNewTol2d, Tol2d);
     }
-
+    //
+    myTolReached = Max(myTolReached, myTolerance * (aNewTol2d / anOldTol2d));
+    //
     NbPoles = MaxDeg * NbCurves + 1;               //Tops on the BSpline
     TColgp_Array1OfPnt2d  Poles( 1, NbPoles);
       
@@ -1884,10 +1936,9 @@ Handle(Geom2d_BSplineCurve)
     // try to smoother the Curve GeomAbs_C1.
 
     Standard_Boolean OK = Standard_True;
-
+    Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d);
     for (Standard_Integer ij = 2; ij < NbKnots; ij++) {
-      OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1,Tol3d);  //OCC217
-      //OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1,myTolerance);
+      OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1, aSmoothTol);  
     }
 #ifdef OCCT_DEBUG
     if (!OK) {
@@ -1908,11 +1959,6 @@ Handle(Geom2d_BSplineCurve)
      ProjLib_ComputeApproxOnPolarSurface::BSpline() const 
      
 {
-//  Modified by Sergey KHROMOV - Thu Apr 18 11:16:46 2002 End
-//   Standard_NoSuchObject_Raise_if
-//     (!myProjIsDone,
-//      "ProjLib_ComputeApproxOnPolarSurface:BSpline");
-//  Modified by Sergey KHROMOV - Thu Apr 18 11:16:47 2002 End
   return myBSpline ;
 }
 
@@ -1942,3 +1988,65 @@ Standard_Boolean ProjLib_ComputeApproxOnPolarSurface::IsDone() const
 {
   return myProjIsDone;
 }
+//=======================================================================
+//function : SetTolerance
+//purpose  : 
+//=======================================================================
+
+void ProjLib_ComputeApproxOnPolarSurface::SetTolerance(const Standard_Real theTol) 
+     
+{
+  myTolerance = theTol;
+}
+//=======================================================================
+//function : SetDegree
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApproxOnPolarSurface::SetDegree(
+                                       const Standard_Integer theDegMin, 
+                                       const Standard_Integer theDegMax)
+{
+  myDegMin = theDegMin;
+  myDegMax = theDegMax;
+}
+//=======================================================================
+//function : SetMaxSegments
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApproxOnPolarSurface::SetMaxSegments(
+                                   const Standard_Integer theMaxSegments)
+{
+  myMaxSegments = theMaxSegments;
+}
+
+//=======================================================================
+//function : SetBndPnt
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApproxOnPolarSurface::SetBndPnt(
+                                 const AppParCurves_Constraint theBndPnt)
+{
+  myBndPnt = theBndPnt;
+}
+
+//=======================================================================
+//function : SetMaxDist
+//purpose  : 
+//=======================================================================
+void ProjLib_ComputeApproxOnPolarSurface::SetMaxDist(
+                                          const Standard_Real theMaxDist)
+{
+  myMaxDist = theMaxDist;
+}
+
+//=======================================================================
+//function : Tolerance
+//purpose  : 
+//=======================================================================
+
+Standard_Real ProjLib_ComputeApproxOnPolarSurface::Tolerance() const 
+     
+{
+  return myTolReached;
+}
+
index 4e116eba9c44dcfa3ea1f65ca231f1b2eab03bed..3927f2759c55896e54bbfaf5d1f2fb1a1b71fac3 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <Standard_Boolean.hxx>
 #include <Standard_Real.hxx>
+#include <AppParCurves_Constraint.hxx>
 class Geom2d_BSplineCurve;
 class Geom2d_Curve;
 class Adaptor3d_HCurve;
@@ -35,33 +36,89 @@ class Adaptor2d_HCurve2d;
 //! The result is a  2d curve.  The evaluation of  the
 //! current  point of the  2d  curve is done with  the
 //! evaluation of the extrema  P3d - Surface.
+//! For approximation some parameters are used, including 
+//! required tolerance of approximation.
+//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from
+//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed
+//! from 3d tolerance with help of U,V resolutions of surface.
+//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation
+//! and have nothing to do with distance between the projected curve and the surface.
 class ProjLib_ComputeApproxOnPolarSurface 
 {
 public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+  //! Empty constructor, it only sets some initial values for class fields.
   Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface();
-  
+
+  //! Constructor, which performs projecting.
   Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol = 1.0e-4);
-  
+
+
+  //! Constructor, which performs projecting, using initial curve 2d InitCurve2d, which is any rough approximation of result curve. 
+  //! Parameter Tol is 3d tolerance of approximation.
   Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol);
+  //! Constructor, which performs projecting, using two initial curves 2d: InitCurve2d and InitCurve2dBis that are any rough approximations of result curves.
+  //! This constructor is used to get two pcurves for seem edge.
+  //! Parameter Tol is 3d tolerance of approximation.
+  Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor2d_HCurve2d)& InitCurve2dBis, const Handle(Adaptor3d_HCurve)& C, 
+                                                      const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol);
+
   
-  Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor2d_HCurve2d)& InitCurve2dBis, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol);
-  
+  //! Set min and max possible degree of result BSpline curve2d, which is got by approximation.
+  //! If theDegMin/Max < 0, algorithm uses values min = 2, max = 8.
+  Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax);
+
+  //! Set the parameter, which defines maximal value of parametric intervals the projected
+  //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default 
+  //! value = 1000.
+  Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments);
+
+  //! Set the parameter, which defines type of boundary condition between segments during approximation.
+  //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint.
+  //! Default value is AppParCurves_TangencyPoint.
+  Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt);
+
+  //! Set the parameter, which defines maximal possible distance between projected curve and surface.
+  //! It is used only for projecting on not analytical surfaces.
+  //! If theMaxDist < 0, algoritm uses default value 100.*Tolerance. 
+  //! If real distance between curve and surface more then theMaxDist, algorithm stops working.
+  Standard_EXPORT void SetMaxDist(const Standard_Real theMaxDist);
+
+  //! Set the tolerance used to project
+  //! the curve on the surface.
+  //! Default value is Precision::Approximation().
+  Standard_EXPORT void SetTolerance (const Standard_Real theTolerance);
+
+  //! Method, which performs projecting, using default values of parameters or
+  //! they must be set by corresponding methods before using.
+  Standard_EXPORT void Perform (const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S);
+
+  //! Method, which performs projecting, using default values of parameters or
+  //! they must be set by corresponding methods before using.
+  //! Parameter InitCurve2d is any rough estimation of 2d result curve.
   Standard_EXPORT Handle(Geom2d_BSplineCurve) Perform (const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S);
-  
+
+  //! Builds initial 2d curve as BSpline with degree = 1 using Extrema algoritm.
+  //! Method is used in method Perform(...).
   Standard_EXPORT Handle(Adaptor2d_HCurve2d) BuildInitialCurve2d (const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S);
-  
+
+
+  //! Method, which performs projecting.
+  //! Method is used in method Perform(...).
   Standard_EXPORT Handle(Geom2d_BSplineCurve) ProjectUsingInitialCurve2d (const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor2d_HCurve2d)& InitCurve2d);
-  
+
+  //! Returns result curve 2d.
   Standard_EXPORT Handle(Geom2d_BSplineCurve) BSpline() const;
-  
+  //! Returns second 2d curve.
   Standard_EXPORT Handle(Geom2d_Curve) Curve2d() const;
   
   Standard_EXPORT Standard_Boolean IsDone() const;
 
+  //! returns the reached Tolerance.
+  Standard_EXPORT Standard_Real Tolerance() const;
 
 
 
@@ -79,6 +136,12 @@ private:
   Standard_Real myTolerance;
   Handle(Geom2d_BSplineCurve) myBSpline;
   Handle(Geom2d_Curve) my2ndCurve;
+  Standard_Real myTolReached;
+  Standard_Integer myDegMin;
+  Standard_Integer myDegMax;
+  Standard_Integer myMaxSegments;
+  Standard_Real myMaxDist;
+  AppParCurves_Constraint myBndPnt;
 
 
 };
index 03ac507ca6ca2b9a6ac65b600f73b2374eda0fc3..136c1cf94f3b6dd3c6501580559bc09e49ab9451 100644 (file)
@@ -42,6 +42,7 @@
 #include <TColgp_HArray1OfPnt2d.hxx>
 #include <TColStd_HArray1OfReal.hxx>
 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
+#include <Geom2dConvert.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
 #include <GeomLib.hxx>
 #include <Extrema_ExtPC.hxx>
 #include <NCollection_DataMap.hxx>
+#include <ElSLib.hxx>
+#include <ElCLib.hxx>
+//=======================================================================
+//function : ComputeTolU
+//purpose  : 
+//=======================================================================
+
+static Standard_Real ComputeTolU(const Handle(Adaptor3d_HSurface)& theSurf,
+                                 const Standard_Real theTolerance)
+{
+  Standard_Real aTolU = theSurf->UResolution(theTolerance);
+  if (theSurf->IsUPeriodic())
+  {
+    aTolU = Min(aTolU, 0.01*theSurf->UPeriod());
+  }
+
+  return aTolU;
+}
+
+//=======================================================================
+//function : ComputeTolV
+//purpose  : 
+//=======================================================================
+
+static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf,
+                                 const Standard_Real theTolerance)
+{
+  Standard_Real aTolV = theSurf->VResolution(theTolerance);
+  if (theSurf->IsVPeriodic())
+  {
+    aTolV = Min(aTolV, 0.01*theSurf->VPeriod());
+  }
+
+  return aTolV;
+}
 
 //=======================================================================
 //function : IsoIsDeg
@@ -113,18 +149,19 @@ static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
 //=======================================================================
 
 static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve,
-                   Standard_Boolean* IsTrimmed,
-                   const Standard_Real dt,
-                   const gp_Pnt& Pole,
+                    Standard_Boolean* IsTrimmed,
+                    const Standard_Real dt,
+                    const gp_Pnt& Pole,
                     Standard_Integer* SingularCase,
-                    const Standard_Integer NumberOfSingularCase)
+                    const Standard_Integer NumberOfSingularCase,
+                    const Standard_Real TolConf)
 {
   Standard_Real f = myCurve->FirstParameter();
   Standard_Real l = myCurve->LastParameter();
 
   gp_Pnt P = myCurve->Value(f);
 
-  if(P.Distance(Pole) < Precision::Confusion()) {
+  if(P.Distance(Pole) <= TolConf) {
     IsTrimmed[0] = Standard_True;
     f = f+dt;
     myCurve = myCurve->Trim(f, l, Precision::Confusion());
@@ -132,7 +169,7 @@ static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve,
   }
   
   P = myCurve->Value(l);
-  if(P.Distance(Pole) < Precision::Confusion()) {
+  if(P.Distance(Pole) <= TolConf) {
     IsTrimmed[1] = Standard_True;
     l = l-dt;
     myCurve = myCurve->Trim(f, l, Precision::Confusion());
@@ -199,17 +236,24 @@ static void ExtendC2d (Handle(Geom2d_BSplineCurve)& aRes,
     }
   }
   gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle
+  Standard_Real ParOnLin = 0.;
+  if (theBoundDir.IsParallel(aDBnd, 100.*Precision::Angular()))
+  {
+    ParOnLin = ElCLib::Parameter(aLin, thePole);
+  }
+  else
+  {
+    Standard_Real U1x = BoundLin.Direction().X();
+    Standard_Real U1y = BoundLin.Direction().Y();
+    Standard_Real U2x = aLin.Direction().X();
+    Standard_Real U2y = aLin.Direction().Y();
+    Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
+    Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
 
-  Standard_Real U1x = BoundLin.Direction().X();
-  Standard_Real U1y = BoundLin.Direction().Y();
-  Standard_Real U2x = aLin.Direction().X();
-  Standard_Real U2y = aLin.Direction().Y();
-  Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
-  Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
-  
-  Standard_Real D = U1y*U2x-U1x*U2y;
-  
-  Standard_Real ParOnLin = (Uo21y * U1x - Uo21x * U1y)/D; //parameter of intersection point
+    Standard_Real D = U1y*U2x - U1x*U2y;
+
+    ParOnLin = (Uo21y * U1x - Uo21x * U1y) / D; //parameter of intersection point
+  }
   
   Handle(Geom2d_Line) aSegLine = new Geom2d_Line(aLin);
   aSegment = (FirstOrLast == 0)?
@@ -259,10 +303,13 @@ static void Project(ProjLib_Projector& P, Handle(Adaptor3d_HCurve)& C)
 //purpose  : 
 //=======================================================================
 
-ProjLib_ProjectedCurve::ProjLib_ProjectedCurve()
-
+ProjLib_ProjectedCurve::ProjLib_ProjectedCurve() :
+  myTolerance(Precision::Confusion()),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
-  myTolerance = Precision::Confusion();
 }
 
 
@@ -272,9 +319,13 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve()
 //=======================================================================
 
 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
-(const Handle(Adaptor3d_HSurface)& S)
+(const Handle(Adaptor3d_HSurface)& S) :
+  myTolerance(Precision::Confusion()),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
-  myTolerance = Precision::Confusion();
   Load(S);
 }
 
@@ -286,11 +337,15 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
 
 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
 (const Handle(Adaptor3d_HSurface)& S,
- const Handle(Adaptor3d_HCurve)& C)
+ const Handle(Adaptor3d_HCurve)& C) :
+  myTolerance(Precision::Confusion()),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
-  myTolerance = Precision::Confusion();
   Load(S);
-  Load(C);
+  Perform(C);
 }
 
 
@@ -302,11 +357,15 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
 (const Handle(Adaptor3d_HSurface)& S,
  const Handle(Adaptor3d_HCurve)&   C,
- const Standard_Real             Tol)
+ const Standard_Real             Tol) :
+  myTolerance(Max(Tol, Precision::Confusion())),
+  myDegMin(-1), myDegMax(-1),
+  myMaxSegments(-1),
+  myMaxDist(-1.),
+  myBndPnt(AppParCurves_TangencyPoint)
 {
-  myTolerance = Max(Tol, Precision::Confusion());
   Load(S);
-  Load(C);
+  Perform(C);
 }
 
 
@@ -320,13 +379,22 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HSurface)& S)
   mySurface = S ;
 }
 
-
 //=======================================================================
 //function : Load
 //purpose  : 
 //=======================================================================
 
-void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
+void ProjLib_ProjectedCurve::Load(const Standard_Real theTol)
+{
+  myTolerance = theTol;
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+void ProjLib_ProjectedCurve::Perform(const Handle(Adaptor3d_HCurve)& C)
 {
   myTolerance = Max(myTolerance, Precision::Confusion());
   myCurve = C;
@@ -335,6 +403,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
   GeomAbs_SurfaceType SType = mySurface->GetType();
   GeomAbs_CurveType   CType = myCurve->GetType();
   Standard_Boolean isAnalyticalSurf = Standard_True;
+  Standard_Boolean IsTrimmed[2] = { Standard_False, Standard_False };
+  Standard_Integer SingularCase[2];
+  const Standard_Real eps = 0.01;
+  Standard_Real TolConf = Precision::Confusion();
+  Standard_Real dt = (LastPar - FirstPar) * eps;
+  Standard_Real U1 = 0.0, U2 = 0.0, V1 = 0.0, V2 = 0.0;
+  U1 = mySurface->FirstUParameter();
+  U2 = mySurface->LastUParameter();
+  V1 = mySurface->FirstVParameter();
+  V2 = mySurface->LastVParameter();
 
   switch (SType)
   {
@@ -372,6 +450,28 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
           // periodique en V !)
           P.SetInBounds(myCurve->FirstParameter());
         }
+        else
+        {
+          const Standard_Real Vmax = M_PI / 2.;
+          const Standard_Real Vmin = -Vmax;
+          const Standard_Real minang = 1.e-5 * M_PI;
+          gp_Sphere aSph = mySurface->Sphere();
+          Standard_Real anR = aSph.Radius();
+          Standard_Real f = myCurve->FirstParameter();
+          Standard_Real l = myCurve->LastParameter();
+
+          gp_Pnt Pf = myCurve->Value(f);
+          gp_Pnt Pl = myCurve->Value(l);
+          gp_Pnt aLoc = aSph.Position().Location();
+          Standard_Real maxdist = Max(Pf.Distance(aLoc), Pl.Distance(aLoc));
+          TolConf = Max(anR * minang, Abs(anR - maxdist));
+
+          //Surface has pole at V = Vmin and Vmax
+          gp_Pnt Pole = mySurface->Value(U1, Vmin);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
+          Pole = mySurface->Value(U1, Vmax);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
+        }
         myResult = P;
       }
       break;
@@ -388,15 +488,11 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
     case GeomAbs_BSplineSurface:
       {
         isAnalyticalSurf = Standard_False;
-        Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
-        Standard_Integer SingularCase[2];
-        Standard_Real f, l, dt;
-        const Standard_Real eps = 0.01;
+        Standard_Real f, l;
         f = myCurve->FirstParameter();
         l = myCurve->LastParameter();
         dt = (l - f) * eps;
 
-        Standard_Real U1 = 0.0, U2=0.0, V1=0.0, V2=0.0;
         const Adaptor3d_Surface& S = mySurface->Surface();
         U1 = S.FirstUParameter();
         U2 = S.LastUParameter();
@@ -407,36 +503,43 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
         {
           //Surface has pole at U = Umin
           gp_Pnt Pole = mySurface->Value(U1, V1);
-          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1, TolConf);
         }
 
         if(IsoIsDeg(S, U2, GeomAbs_IsoU, 0., myTolerance))
         {
           //Surface has pole at U = Umax
           gp_Pnt Pole = mySurface->Value(U2, V1);
-          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2, TolConf);
         }
 
         if(IsoIsDeg(S, V1, GeomAbs_IsoV, 0., myTolerance))
         {
           //Surface has pole at V = Vmin
           gp_Pnt Pole = mySurface->Value(U1, V1);
-          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
         }
 
         if(IsoIsDeg(S, V2, GeomAbs_IsoV, 0., myTolerance))
         {
           //Surface has pole at V = Vmax
           gp_Pnt Pole = mySurface->Value(U1, V2);
-          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4);
+          TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
         }
 
-        ProjLib_ComputeApproxOnPolarSurface polar(myCurve, mySurface, myTolerance);
+        ProjLib_ComputeApproxOnPolarSurface polar;
+        polar.SetTolerance(myTolerance);
+        polar.SetDegree(myDegMin, myDegMax);
+        polar.SetMaxSegments(myMaxSegments);
+        polar.SetBndPnt(myBndPnt);
+        polar.SetMaxDist(myMaxDist);
+        polar.Perform(myCurve, mySurface); 
 
         Handle(Geom2d_BSplineCurve) aRes = polar.BSpline();
 
         if (!aRes.IsNull())
         {
+          myTolerance = polar.Tolerance();
           if( (IsTrimmed[0] || IsTrimmed[1]))
           {
             if(IsTrimmed[0])
@@ -467,10 +570,9 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
     default:
       {
         isAnalyticalSurf = Standard_False;
-        Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
         Standard_Real Vsingular[2] = {0.0 , 0.0}; //for surfaces of revolution
-        Standard_Real f = 0.0, l = 0.0, dt = 0.0;
-        const Standard_Real eps = 0.01;
+        Standard_Real f = 0.0, l = 0.0;
+        dt = 0.0;
 
         if(mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
         {
@@ -538,7 +640,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
           }
         }
 
-        ProjLib_CompProjectedCurve Projector(mySurface,myCurve, myTolerance, myTolerance, 100 * myTolerance);
+        Standard_Real aTolU = Max(ComputeTolU(mySurface, myTolerance), Precision::Confusion());
+        Standard_Real aTolV = Max(ComputeTolV(mySurface, myTolerance), Precision::Confusion());
+        Standard_Real aTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV);
+
+        Standard_Real aMaxDist = 100. * myTolerance;
+        if(myMaxDist > 0.)
+        {
+          aMaxDist = myMaxDist;
+        }
+        ProjLib_CompProjectedCurve Projector(mySurface,myCurve, aTolU, aTolV, aMaxDist);
         Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve();
         HProjector->Set(Projector);
 
@@ -559,8 +670,20 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
         Standard_Boolean Only3d = Standard_False;
         Standard_Boolean Only2d = Standard_True;
         GeomAbs_Shape Continuity = GeomAbs_C1;
+        if(myBndPnt == AppParCurves_PassPoint)
+        {
+          Continuity = GeomAbs_C0;
+        }
         Standard_Integer MaxDegree = 14;
+        if(myDegMax > 0)
+        {
+          MaxDegree = myDegMax;
+        }
         Standard_Integer MaxSeg    = 16;
+        if(myMaxSegments > 0)
+        {
+          MaxSeg = myMaxSegments;
+        }
 
         Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, 
                                    myTolerance, Continuity, MaxDegree, MaxSeg, 
@@ -570,6 +693,10 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
 
         if (!aRes.IsNull())
         {
+          aTolU = appr.MaxError2dU();
+          aTolV = appr.MaxError2dV();
+          Standard_Real aNewTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV);
+          myTolerance *= (aNewTol2d / aTol2d);
           if(IsTrimmed[0] || IsTrimmed[1])
           {
             // Treatment only for surface of revolution
@@ -594,6 +721,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
               aRes->FirstParameter(), aRes->LastParameter(),
               FirstPar, LastPar, NewCurve2d);
             aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
+            if(Continuity == GeomAbs_C0)
+            {
+              // try to smoother the Curve GeomAbs_C1.
+              Standard_Integer aDeg = aRes->Degree();
+              Standard_Boolean OK = Standard_True;
+              Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d);
+              for (Standard_Integer ij = 2; ij < aRes->NbKnots(); ij++) {
+                OK = OK && aRes->RemoveKnot(ij, aDeg-1, aSmoothTol);  
+              }
+            }
           }
 
           myResult.SetBSpline(aRes);
@@ -606,26 +743,64 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
   if ( !myResult.IsDone() && isAnalyticalSurf)
   {
     // Use advanced analytical projector if base analytical projection failed.
-    ProjLib_ComputeApprox Comp( myCurve, mySurface, myTolerance);
+    ProjLib_ComputeApprox Comp;
+    Comp.SetTolerance(myTolerance);
+    Comp.SetDegree(myDegMin, myDegMax);
+    Comp.SetMaxSegments(myMaxSegments);
+    Comp.SetBndPnt(myBndPnt);
+    Comp.Perform(myCurve, mySurface);
     if (Comp.Bezier().IsNull() && Comp.BSpline().IsNull())
       return; // advanced projector has been failed too
     myResult.Done();
-
-    // set the type
-    if ( SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
+    Handle(Geom2d_BSplineCurve) aRes;
+    if (Comp.BSpline().IsNull())
     {
-      myResult.SetType(GeomAbs_BezierCurve);
-      myResult.SetBezier(Comp.Bezier()) ;
+      aRes = Geom2dConvert::CurveToBSplineCurve(Comp.Bezier());
     }
     else
     {
+      aRes = Comp.BSpline();
+    }
+    if ((IsTrimmed[0] || IsTrimmed[1]))
+    {
+      if (IsTrimmed[0])
+      {
+        //Add segment before start of curve
+        Standard_Real f = myCurve->FirstParameter();
+        ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]);
+      }
+      if (IsTrimmed[1])
+      {
+        //Add segment after end of curve
+        Standard_Real l = myCurve->LastParameter();
+        ExtendC2d(aRes, l, dt, U1, U2, V1, V2, 1, SingularCase[1]);
+      }
+      Handle(Geom2d_Curve) NewCurve2d;
+      GeomLib::SameRange(Precision::PConfusion(), aRes,
+        aRes->FirstParameter(), aRes->LastParameter(),
+        FirstPar, LastPar, NewCurve2d);
+      aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
+      myResult.SetBSpline(aRes);
       myResult.SetType(GeomAbs_BSplineCurve);
-      myResult.SetBSpline(Comp.BSpline()) ;
+    }
+    else
+    {
+      // set the type
+      if (SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
+      {
+        myResult.SetType(GeomAbs_BezierCurve);
+        myResult.SetBezier(Comp.Bezier());
+      }
+      else
+      {
+        myResult.SetType(GeomAbs_BSplineCurve);
+        myResult.SetBSpline(Comp.BSpline());
+      }
     }
     // set the periodicity flag
     if (SType == GeomAbs_Plane        &&
-        CType == GeomAbs_BSplineCurve &&
-        myCurve->IsPeriodic()   )
+      CType == GeomAbs_BSplineCurve &&
+      myCurve->IsPeriodic())
     {
       myResult.SetPeriodic();
     }
@@ -723,6 +898,42 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
   }
 }
 
+//=======================================================================
+//function : SetDegree
+//purpose  : 
+//=======================================================================
+void ProjLib_ProjectedCurve::SetDegree(const Standard_Integer theDegMin, 
+                                       const Standard_Integer theDegMax)
+{
+  myDegMin = theDegMin;
+  myDegMax = theDegMax;
+}
+//=======================================================================
+//function : SetMaxSegments
+//purpose  : 
+//=======================================================================
+void ProjLib_ProjectedCurve::SetMaxSegments(const Standard_Integer theMaxSegments)
+{
+  myMaxSegments = theMaxSegments;
+}
+
+//=======================================================================
+//function : SetBndPnt
+//purpose  : 
+//=======================================================================
+void ProjLib_ProjectedCurve::SetBndPnt(const AppParCurves_Constraint theBndPnt)
+{
+  myBndPnt = theBndPnt;
+}
+
+//=======================================================================
+//function : SetMaxDist
+//purpose  : 
+//=======================================================================
+void ProjLib_ProjectedCurve::SetMaxDist(const Standard_Real theMaxDist)
+{
+  myMaxDist = theMaxDist;
+}
 
 //=======================================================================
 //function : GetSurface
index 0e3196d430acf04c8b6ab4635fd1b336c765daa3..c788587cd3cfefb2c9ddc93dff1fd0f3682102b8 100644 (file)
@@ -29,6 +29,7 @@
 #include <TColStd_Array1OfReal.hxx>
 #include <Standard_Boolean.hxx>
 #include <GeomAbs_CurveType.hxx>
+#include <AppParCurves_Constraint.hxx>
 class Adaptor3d_HSurface;
 class Adaptor3d_HCurve;
 class Standard_OutOfRange;
@@ -49,20 +50,32 @@ class Geom2d_BSplineCurve;
 
 //! Compute the 2d-curve.  Try to solve the particular
 //! case if possible.  Otherwize, an approximation  is
-//! done.
+//! done. For approximation some parameters are used, including 
+//! required tolerance of approximation.
+//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from
+//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed
+//! from 3d tolerance with help of U,V resolutions of surface.
+//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation
+//! and have nothing to do with distance between the projected curve and the surface.
 class ProjLib_ProjectedCurve  : public Adaptor2d_Curve2d
 {
 public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+  //! Empty constructor, it only sets some initial values for class fields.
   Standard_EXPORT ProjLib_ProjectedCurve();
   
+  //! Constructor with initialisation field mySurface
   Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S);
-  
+
+  //! Constructor, which performs projecting.
+  //! If projecting uses approximation, default parameters are used, in particular, 3d tolerance of approximation
+  //! is Precision::Confusion()
   Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C);
   
+  //! Constructor, which performs projecting.
+  //! If projecting uses approximation, 3d tolerance is Tol, default parameters are used, 
   Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C, const Standard_Real Tol);
   
   //! Changes the tolerance used to project
@@ -72,9 +85,33 @@ public:
   //! Changes the Surface.
   Standard_EXPORT void Load (const Handle(Adaptor3d_HSurface)& S);
   
-  //! Changes the Curve.
-  Standard_EXPORT void Load (const Handle(Adaptor3d_HCurve)& C);
+  //! Performs projecting for given curve.
+  //! If projecting uses approximation, 
+  //! approximation parameters can be set before by corresponding methods 
+  //! SetDegree(...), SetMaxSegmets(...), SetBndPnt(...), SetMaxDist(...)
+  Standard_EXPORT void Perform (const Handle(Adaptor3d_HCurve)& C);
   
+  //! Set min and max possible degree of result BSpline curve2d, which is got by approximation.
+  //! If theDegMin/Max < 0, algorithm uses values that are chosen depending of types curve 3d
+  //! and surface.
+  Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax);
+
+  //! Set the parameter, which defines maximal value of parametric intervals the projected
+  //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default 
+  //! value = 1000.
+  Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments);
+
+  //! Set the parameter, which defines type of boundary condition between segments during approximation.
+  //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint.
+  //! Default value is AppParCurves_TangencyPoint;
+  Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt);
+
+  //! Set the parameter, which degines maximal possible distance between projected curve and surface.
+  //! It uses only for projecting on not analytical surfaces.
+  //! If theMaxDist < 0, algoritm uses default value 100.*Tolerance. 
+  //! If real distance between curve and surface more then theMaxDist, algorithm stops working.
+  Standard_EXPORT void SetMaxDist(const Standard_Real theMaxDist);
+
   Standard_EXPORT const Handle(Adaptor3d_HSurface)& GetSurface() const;
   
   Standard_EXPORT const Handle(Adaptor3d_HCurve)& GetCurve() const;
@@ -203,8 +240,11 @@ private:
   Handle(Adaptor3d_HSurface) mySurface;
   Handle(Adaptor3d_HCurve) myCurve;
   ProjLib_Projector myResult;
-
-
+  Standard_Integer myDegMin;
+  Standard_Integer myDegMax;
+  Standard_Integer myMaxSegments;
+  Standard_Real myMaxDist;
+  AppParCurves_Constraint myBndPnt;
 };