]> OCCT Git - occt-copy.git/commitdiff
CEVT-06-001 : Projection algorithm improvement to ensure imprinting of a curve on... CR0-710-CEVT
authorifv <ifv@opencascade.com>
Tue, 26 Sep 2017 13:27:03 +0000 (16:27 +0300)
committerifv <ifv@opencascade.com>
Wed, 4 Oct 2017 14:26:37 +0000 (17:26 +0300)
Adaptation for OCCT7.1.0 of commit for CR28909

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..9e21aad47b2ad726fd3468523fb1f77a2256180c 100644 (file)
@@ -50,6 +50,7 @@ Approx_ComputeCLine::Approx_ComputeCLine
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
+  myMaxSegments = IntegerLast();
   alldone = Standard_False;
   Perform(Line);
 }
@@ -76,6 +77,7 @@ Approx_ComputeCLine::Approx_ComputeCLine
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
+  myMaxSegments = IntegerLast();
 }
 
 //=======================================================================
@@ -91,9 +93,11 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
   Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
   UFirst = Line.FirstParameter();
   ULast  = Line.LastParameter();
-  Standard_Real TolU = (ULast-UFirst)*1.e-05;
+  Standard_Real TolU = Max((ULast-UFirst)*1.e-05, Precision::PApproximation());
   Standard_Real myfirstU = UFirst; 
   Standard_Real mylastU = ULast;
+  Standard_Integer aMaxSegments = 0;
+  Standard_Integer aMaxSegments1 = myMaxSegments - 1;
 
   if (!mycut)
   {
@@ -126,7 +130,8 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
           // Calcul de la partie a approximer.
           myfirstU = mylastU;
           mylastU  = ULast;
-          if (Abs(ULast-myfirstU) <= RealEpsilon())
+          if (Abs(ULast-myfirstU) <= RealEpsilon() 
+              || aMaxSegments >= myMaxSegments)
           {
             Finish = Standard_True;
             alldone = Standard_True;
@@ -155,11 +160,15 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
 
       // Calcul des parametres sur ce nouvel intervalle.
       Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
+      if(Ok)
+      {
+        aMaxSegments++;
+      }
 
       //cout << myfirstU << " - " << mylastU << "  tol : " << thetol3d << " " << thetol2d << endl;
 
       // is new decision better?
-      if (!Ok && Abs(myfirstU-mylastU) <= TolU)
+      if (!Ok && (Abs(myfirstU-mylastU) <= TolU || aMaxSegments >= aMaxSegments1))
       {
           Ok = Standard_True; // stop interval cutting, approx the rest part
 
@@ -176,6 +185,7 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line)
 
           tolreached = Standard_False; // helas
           myMultiCurves.Append(KeptMultiCurve);
+          aMaxSegments++;
           Tolers3d.Append     (KeptT3d);
           Tolers2d.Append     (KeptT2d);
           myfirstparam.Append (KeptUfirst);
@@ -303,6 +313,16 @@ void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
   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;
+}
+
 //=======================================================================
 //function : IsAllApproximated
 //purpose  : returns False if at a moment of the approximation,
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 bdef984b15c3b6eea4fbcb3262c0ee9d611cdd08..ada5cbcca82440aa7907d4ce92439e06601c2009 100644 (file)
@@ -57,6 +57,7 @@
 #include <IntTools_Tools.hxx>
 #include <Precision.hxx>
 #include <ProjLib_ProjectedCurve.hxx>
+#include <ProjLib.hxx>
 #include <Standard_ConstructionError.hxx>
 #include <Standard_NotImplemented.hxx>
 #include <TopExp.hxx>
@@ -64,6 +65,7 @@
 #include <TopLoc_Location.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
+#include <AppParCurves_Constraint.hxx>
 
 static 
   Standard_Boolean CheckEdgeLength (const TopoDS_Edge& );
@@ -626,6 +628,9 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
   aBAHS=new GeomAdaptor_HSurface(aGAS);
   aBAHC=new GeomAdaptor_HCurve(aC3D, aT1, aT2);
   //
+  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 (aGAS.GetType() == GeomAbs_SurfaceOfRevolution) {
     Standard_Real aTR;
@@ -640,27 +645,42 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
     aTolR = aProj1.GetTolerance();
   } 
   else {
-    Standard_Real aTR = Precision::Confusion();//1.e-7;
-    if (TolReached2d > aTR) {
-      aTR = Min(0.0001, Max(.01 * TolReached2d, aTR));
+    ProjLib_ProjectedCurve aProjCurv(aBAHS);
+    Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1;
+    Standard_Real aMaxDist = -1;
+    AppParCurves_Constraint aBndPnt = AppParCurves_NoConstraint;
+    if ((TolReached2d >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf))
+    {
+      aTR = Min(aMaxTol, 0.1*TolReached2d);
+      aMaxSegments = 100;
+      aMaxDist = 1.e3*TolReached2d;
+      if (!isAnaSurf)
+      {
+        aBndPnt = AppParCurves_PassPoint;
+      }
     }
-
-    ProjLib_ProjectedCurve aProjCurv(aBAHS, aBAHC, aTR);// 1
-    BOPTools_AlgoTools2D::MakePCurveOfType(aProjCurv, aC2D);
+    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
-    BOPTools_AlgoTools2D::MakePCurveOfType(aProjCurvAgain, aC2D);
+  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
-      BOPTools_AlgoTools2D::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 e536aacd8b4e3c907bcdf4863ddb3e5314fc6d38..36ee34ddbcf8c4f46d7e2e6d2c944145a797c0ed 100644 (file)
 #include <ProjLib_Plane.hxx>
 #include <ProjLib_Sphere.hxx>
 #include <ProjLib_Torus.hxx>
+#include <ProjLib_ProjectedCurve.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_Circle.hxx>
+#include <Geom2d_Ellipse.hxx>
+#include <Geom2d_Parabola.hxx>
+#include <Geom2d_Hyperbola.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_BezierCurve.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Adaptor3d_HSurface.hxx>
 
 //=======================================================================
 //function : Project
@@ -234,3 +244,63 @@ gp_Lin2d  ProjLib::Project(const gp_Torus& To, const gp_Circ& Ci)
   ProjLib_Torus Proj( To, Ci);
   return Proj.Line();
 }
+
+//=======================================================================
+//function : MakePCurveOfType
+//purpose  : 
+//=======================================================================
+void  ProjLib::MakePCurveOfType
+  (const ProjLib_ProjectedCurve& PC, 
+   Handle(Geom2d_Curve)& C2D)
+{
+  
+  switch (PC.GetType()) {
+
+  case GeomAbs_Line : 
+    C2D = new Geom2d_Line(PC.Line()); 
+    break;
+  case GeomAbs_Circle : 
+    C2D = new Geom2d_Circle(PC.Circle());
+    break;
+  case GeomAbs_Ellipse :
+    C2D = new Geom2d_Ellipse(PC.Ellipse());
+    break;
+  case GeomAbs_Parabola : 
+    C2D = new Geom2d_Parabola(PC.Parabola()); 
+    break;
+  case GeomAbs_Hyperbola : 
+    C2D = new Geom2d_Hyperbola(PC.Hyperbola()); 
+    break;
+  case GeomAbs_BSplineCurve :
+    C2D = PC.BSpline(); 
+    break;
+  case GeomAbs_BezierCurve : 
+  case GeomAbs_OtherCurve : 
+    default :
+    Standard_NotImplemented::Raise
+      ("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 a06c3dfde4b2530712095eed92ed8e757429a2ee..f5334796437efd58a109ef09d760285b5b6f6343 100644 (file)
@@ -20,6 +20,7 @@
 #include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
+#include <Geom2d_Curve.hxx>
 
 class gp_Pnt2d;
 class gp_Pln;
@@ -54,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
@@ -128,6 +129,15 @@ public:
   
   Standard_EXPORT static gp_Lin2d Project (const gp_Torus& To, const gp_Circ& Ci);
 
+  //! 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 b93d33784c999e5a6af58f093f2342645f20f979..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>
@@ -42,6 +43,7 @@
 #include <Geom_BezierCurve.hxx>
 #include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_BezierCurve.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
 
 //#define DRAW
 #ifdef DRAW
@@ -115,7 +117,7 @@ static gp_Pnt2d Function_Value(const Standard_Real U,
       break;
     }
   default:
-    Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value");
+    throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value");
   }
 
   if ( UCouture) {
@@ -195,7 +197,33 @@ static Standard_Boolean Function_D1( const Standard_Real U,
   
   return Standard_True;
 }
+//=======================================================================
+//function : Function_ComputeStep
+//purpose  : 
+//=======================================================================
+static Standard_Real Function_ComputeStep(
+  const Handle(Adaptor3d_HCurve)&   myCurve,
+  const Standard_Real R)
+{
+  Standard_Real Step0 = .1;
+  Standard_Real W1, W2;
+  W1 = myCurve->FirstParameter();
+  W2 = myCurve->LastParameter();
+  Standard_Real L = GCPnts_AbscissaPoint::Length(myCurve->Curve());
+  Standard_Integer nbp = RealToInt(L / (R*M_PI_4)) + 1;
+  nbp = Max(nbp, 3);
+  Standard_Real Step = (W2 - W1) / (nbp - 1);
+  if (Step > Step0)
+  {
+    Step = Step0;
+    nbp = RealToInt((W2 - W1) / Step) + 1;
+    nbp = Max(nbp, 3);
+    Step = (W2 - W1) / (nbp - 1);
+  }
 
+  return Step;
+
+}
 //=======================================================================
 //function : Function_SetUVBounds
 //purpose  : 
@@ -272,15 +300,21 @@ static void Function_SetUVBounds(Standard_Real& myU1,
         Standard_Real U1, V1, U , V, Delta = 0., d = 0., pmin = W1, pmax = W1, dmax = 0., Uf, Ul;
         ElSLib::Parameters( Cone, P1, U1, V1);
         ElSLib::Parameters( Cone, P2, Ul, V1);
-        myU1 = U1; myU2 = U1; Uf = U1; 
-        Standard_Real Step = .1;
-        Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
-        if(myCurve->GetType() == GeomAbs_Line)
+        const gp_Ax1& anAx1 = Cone.Axis();
+        gp_Lin aLin(anAx1);
+        Standard_Real R = (aLin.Distance(P1) + aLin.Distance(P2) + aLin.Distance(P)) / 3.;
+        Standard_Real Step;
+        myU1 = U1; myU2 = U1; Uf = U1;
+        if (myCurve->GetType() == GeomAbs_Line)
+        {
+          Standard_Integer nbp = 3;
+          Step = (W2 - W1) / (nbp - 1);
+        }
+        else
         {
-          nbp = 3;
+          Step = Function_ComputeStep(myCurve, R);
         }
-        nbp = Max(nbp, 3);
-        Step = (W2 - W1) / (nbp - 1);
+        //
         Standard_Boolean isclandper = (!(myCurve->IsClosed()) && !(myCurve->IsPeriodic()));
         Standard_Boolean isFirst = Standard_True;
         for(Standard_Real par = W1 + Step; par <= W2; par += Step)
@@ -402,11 +436,10 @@ static void Function_SetUVBounds(Standard_Real& myU1,
     else {
       Standard_Real U1, V1, U , V;
       ElSLib::Parameters( Cylinder, P1, U1, V1);
-      Standard_Real Step = .1, Delta = 0.;
+      Standard_Real R = Cylinder.Radius();
+      Standard_Real Delta = 0., Step;
       Standard_Real eps = M_PI, dmax = 0., d = 0.;
-      Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
-      nbp = Max(nbp, 3);
-      Step = (W2 - W1) / (nbp - 1);
+      Step = Function_ComputeStep(myCurve, R);
       myU1 = U1; myU2 = U1;
       Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
       for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
@@ -655,11 +688,10 @@ static void Function_SetUVBounds(Standard_Real& myU1,
     else {
       Standard_Real U1, V1, U , V;
       ElSLib::Parameters( SP, P1, U1, V1);
-      Standard_Real Step = .1, Delta = 0.;
+      Standard_Real R = SP.Radius();
+      Standard_Real Delta = 0., Step;
       Standard_Real eps = M_PI, dmax = 0., d = 0.;
-      Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
-      nbp = Max(nbp, 3);
-      Step = (W2 - W1) / (nbp - 1);
+      Step = Function_ComputeStep(myCurve, R);
       myU1 = U1; myU2 = U1;
       Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
       for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
@@ -710,13 +742,12 @@ static void Function_SetUVBounds(Standard_Real& myU1,
   //     
   case GeomAbs_Torus:{
     gp_Torus TR = mySurface->Torus();
-    Standard_Real U1, V1, U , V;
+    Standard_Real U1, V1, U , V, dU, dV;
     ElSLib::Parameters( TR, P1, U1, V1);
-    Standard_Real Step = .1, DeltaU = 0., DeltaV = 0.;
-    Standard_Real eps = M_PI, dmaxU = 0., dU = 0., dmaxV = 0., dV = 0.;
-    Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
-    nbp = Max(nbp, 3);
-    Step = (W2 - W1) / (nbp - 1);
+    Standard_Real R = TR.MinorRadius();
+    Standard_Real DeltaU = 0., DeltaV = 0., Step;
+    Standard_Real eps = M_PI, dmaxU = 0., dmaxV = 0.;
+    Step = Function_ComputeStep(myCurve, R);
     myU1 = U1; myU2 = U1;
     myV1 = V1; myV2 = V1;
     Standard_Real pminU = W1, pmaxU = W1, pminV = W1, pmaxV = W1,
@@ -926,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
@@ -935,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)  &&
@@ -1055,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()) {
@@ -1085,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);
       }
 
@@ -1111,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.)
@@ -1127,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();
@@ -1183,7 +1264,7 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
         break;
       }
     default:
-      Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value");
+      throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value");
     }
     Standard_Boolean ToMirror = Standard_False;
     Standard_Real du = 0., dv = 0.;
@@ -1224,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 4b410a518d1e48fbd2cc0bececddee5b7ac0ace2..14185a35045fa14ff9545afb60ae1c029313a0f8 100644 (file)
@@ -284,7 +284,7 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
         break;
       }
     default:
-      Standard_NoSuchObject::Raise("ProjLib_ComputeApproxOnPolarSurface::Value");
+      throw Standard_NoSuchObject("ProjLib_ComputeApproxOnPolarSurface::Value");
     }
     return gp_Pnt2d(S, T);
   }
@@ -363,7 +363,7 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
   }
   else
   {
-    Standard_NoSuchObject::Raise("");
+    throw Standard_NoSuchObject ("ProjLib_ComputeApproxOnPolarSurface::ProjectUsingInitialCurve2d() - unknown surface type");
   }
 
   // Try to run simple search with initial point (U0, V0).
@@ -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);
 
@@ -885,6 +926,7 @@ Handle(Adaptor2d_HCurve2d)
 
   Standard_Integer NbOfPnts = 61; 
   GCPnts_QuasiUniformAbscissa QUA(Curve->GetCurve(),NbOfPnts);
+  NbOfPnts = QUA.NbPoints();
   TColgp_Array1OfPnt Pts(1,NbOfPnts);
   TColStd_Array1OfReal Param(1,NbOfPnts);
   Standard_Integer i, j;
@@ -1031,7 +1073,7 @@ Handle(Adaptor2d_HCurve2d)
        break;
       }
     default:
-      Standard_NoSuchObject::Raise("ProjLib_ComputeApproxOnPolarSurface::BuildInitialCurve2d");
+      throw Standard_NoSuchObject("ProjLib_ComputeApproxOnPolarSurface::BuildInitialCurve2d");
     }
   }
   else {
@@ -1054,7 +1096,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 +1112,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 +1134,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 +1164,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 +1192,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 +1266,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 +1291,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 +1363,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 +1390,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 +1419,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 +1447,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 +1532,6 @@ Handle(Adaptor2d_HCurve2d)
 //  Modified by Sergey KHROMOV - Thu Apr 18 10:58:02 2002 End
 }
 
-
-
-
 //=======================================================================
 //function : ProjLib_ProjectUsingInitialCurve2d
 //purpose  : 
@@ -1501,24 +1540,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 +1582,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 +1615,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 +1631,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 +1660,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 +1671,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 +1713,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 +1731,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 +1760,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 +1771,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 +1803,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 +1842,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 +1880,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 +1937,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 +1960,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 +1989,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 8dd18170654825d797de48e3b712abd91b879d81..656e99be766c82cda6a3b9705a947c226ba5231d 100644 (file)
 #include <GeomLib.hxx>
 #include <Extrema_ExtPC.hxx>
 #include <NCollection_DataMap.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
@@ -250,7 +283,7 @@ static void Project(ProjLib_Projector& P, Handle(Adaptor3d_HCurve)& C)
     case GeomAbs_OtherCurve:    // try the approximation
       break;
     default:
-      Standard_NoSuchObject::Raise(" ");
+      throw Standard_NoSuchObject(" ");
   }
 }
 
@@ -259,10 +292,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 +308,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 +326,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 +346,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 +368,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;
@@ -431,12 +488,19 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4);
         }
 
-        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])
@@ -538,7 +602,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 +632,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 +655,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 +683,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,7 +705,12 @@ 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();
@@ -723,6 +827,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
@@ -786,8 +926,7 @@ Standard_Real ProjLib_ProjectedCurve::LastParameter() const
 
 GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const
 {
-  Standard_NotImplemented::Raise("");
-  return GeomAbs_C0;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Continuity() - method is not implemented");
 }
 
 
@@ -798,8 +937,7 @@ GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const
 
 Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const 
 {
-  Standard_NotImplemented::Raise("");
-  return 0;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::NbIntervals() - method is not implemented");
 }
 
 
@@ -812,7 +950,7 @@ Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const
 void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  ,
                                       const GeomAbs_Shape ) const 
 {
-  Standard_NotImplemented::Raise("");
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Intervals() - method is not implemented");
 }
 
 
@@ -823,8 +961,7 @@ void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  ,
 
 Standard_Boolean ProjLib_ProjectedCurve::IsClosed() const
 {
-  Standard_NotImplemented::Raise("");
-  return Standard_True;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::IsClosed() - method is not implemented");
 }
 
 
@@ -846,8 +983,7 @@ Standard_Boolean ProjLib_ProjectedCurve::IsPeriodic() const
 
 Standard_Real ProjLib_ProjectedCurve::Period() const
 {
-  Standard_NotImplemented::Raise("");
-  return 0.;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Period() - method is not implemented");
 }
 
 
@@ -858,8 +994,7 @@ Standard_Real ProjLib_ProjectedCurve::Period() const
 
 gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const 
 {
-  Standard_NotImplemented::Raise("");
-  return gp_Pnt2d(0.,0.);
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Value() - method is not implemented");
 }
 
 
@@ -870,7 +1005,7 @@ gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const
 
 void ProjLib_ProjectedCurve::D0(const Standard_Real , gp_Pnt2d& ) const
 {
-  Standard_NotImplemented::Raise("");
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D0() - method is not implemented");
 }
 
 
@@ -883,7 +1018,7 @@ void ProjLib_ProjectedCurve::D1(const Standard_Real ,
                                      gp_Pnt2d&     , 
                                       gp_Vec2d&     ) const 
 {
-  Standard_NotImplemented::Raise("");
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D1() - method is not implemented");
 }
 
 
@@ -897,7 +1032,7 @@ void ProjLib_ProjectedCurve::D2(const Standard_Real ,
                                       gp_Vec2d&     , 
                                       gp_Vec2d&     ) const 
 {
-  Standard_NotImplemented::Raise("");
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D2() - method is not implemented");
 }
 
 
@@ -912,7 +1047,7 @@ void ProjLib_ProjectedCurve::D3(const Standard_Real,
                                      gp_Vec2d&, 
                                      gp_Vec2d&) const 
 {
-  Standard_NotImplemented::Raise("");
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D3() - method is not implemented");
 }
 
 
@@ -924,8 +1059,7 @@ void ProjLib_ProjectedCurve::D3(const Standard_Real,
 gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real, 
                                    const Standard_Integer) const 
 {
-  Standard_NotImplemented::Raise("");
-  return gp_Vec2d(0.,0.);
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::DN() - method is not implemented");
 }
 
 
@@ -936,8 +1070,7 @@ gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real,
 
 Standard_Real ProjLib_ProjectedCurve::Resolution(const Standard_Real) const 
 {
-  Standard_NotImplemented::Raise("");
-  return 0.;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Resolution() - method is not implemented");
 }
     
 
@@ -1117,7 +1250,5 @@ Handle(Adaptor2d_HCurve2d) ProjLib_ProjectedCurve::Trim
  const Standard_Real ,
  const Standard_Real ) const 
 {
-  Standard_NotImplemented::Raise("");
-  return NULL ;
+  throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Trim() - method is not implemented");
 }
-
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;
 };