0030046: Modeling Algorithms - Cannot find necessary projection of the curve
authorknosulko <knosulko@opencascade.com>
Fri, 20 Aug 2021 09:39:26 +0000 (12:39 +0300)
committersmoskvin <smoskvin@opencascade.com>
Tue, 26 Oct 2021 20:10:34 +0000 (23:10 +0300)
move algorithm of obtaining results from function gproject to method ProjLib_CompProjectedCurve::Perform;
fix tolerances in ProjLib_PrjResolve::ProjLib_PrjResolve;
new treatment of myMaxDist;
use extend bounds in approximation;
add test;
test case "bugs modalg_5 bug25980", "bugs modalg_7 bug24185" have been changed according to new behavior.

src/BRepAlgo/BRepAlgo_NormalProjection.cxx
src/GeometryTest/GeometryTest_CurveCommands.cxx
src/ProjLib/ProjLib_CompProjectedCurve.cxx
src/ProjLib/ProjLib_CompProjectedCurve.hxx
src/ProjLib/ProjLib_PrjResolve.cxx
tests/bugs/modalg_5/bug25980
tests/bugs/modalg_7/bug24185
tests/bugs/moddata_3/bug30046 [new file with mode: 0644]

index 2a289eb..f94dab3 100644 (file)
@@ -355,6 +355,10 @@ void BRepAlgo_NormalProjection::SetDefaultParams()
 #endif
            Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d);
             appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d);
+
+        if (appr.MaxError3d() > 1.e3 * myTol3d)
+          continue;
+
 #ifdef OCCT_DEBUG_CHRONO
            ResultChron(chr_approx,t_approx);
            approx_count++;
index 1692201..fc26d2d 100644 (file)
@@ -261,134 +261,135 @@ static Standard_Integer to3d (Draw_Interpretor& , Standard_Integer n, const char
 
 static Standard_Integer gproject(Draw_Interpretor& di, Standard_Integer n, const char** a)
 {
-  
-  char newname[1024];
-  char* temp = newname;
-  char newname1[10];
-  char* temp1 = newname1;
-  char name[100];
-  Standard_Integer ONE = 1;
-
-  if (n == 3)
-    Sprintf(name,"p");
-  else if (n == 4) {
-    Sprintf(name,"%s",a[1]);
-    ONE = 2;
+  TCollection_AsciiString newname;
+  TCollection_AsciiString newname1;
+
+  if (n < 4)
+  {
+    di << "gproject waits 3 or more arguments\n";
+    return 1;
   }
-  else {
-   di << "gproject wait 2 or 3 arguments\n";
-   return 1;
-  } 
 
-  Handle(Geom_Curve) Cur = DrawTrSurf::GetCurve(a[ONE]);
-  Handle(Geom_Surface) Sur = DrawTrSurf::GetSurface(a[ONE+1]);
+  TCollection_AsciiString name = a[1];
+
+  Handle(Geom_Curve) Cur = DrawTrSurf::GetCurve(a[2]);
+  Handle(Geom_Surface) Sur = DrawTrSurf::GetSurface(a[3]);
   if (Cur.IsNull() || Sur.IsNull()) return 1;
 
   Handle(GeomAdaptor_Curve) hcur = new GeomAdaptor_Curve(Cur);
   Handle(GeomAdaptor_Surface) hsur = new GeomAdaptor_Surface(Sur);
 
+  Standard_Integer index = 4;
+  Standard_Real aTol3d = 1.e-6;
+  Standard_Real aMaxDist = -1.0;
 
-  Standard_Real myTol3d = 1.e-6;
-  GeomAbs_Shape myContinuity = GeomAbs_C2;
-  Standard_Integer myMaxDegree = 14, myMaxSeg = 16;
+  if (n > 4 && a[4][0] != '-')
+  {
+    aTol3d = Draw::Atof(a[4]);
+    index = 5;
 
+    if (n > 5 && a[5][0] != '-')
+    {
+      aMaxDist = Draw::Atof(a[5]);
+      index = 6;
+    }
+  }
 
-  Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (hsur, hcur, myTol3d/10, myTol3d/10);
+  Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve(aTol3d, hsur, hcur, aMaxDist);
   ProjLib_CompProjectedCurve& Projector = *HProjector;
 
-  Standard_Integer k;
-  Standard_Real Udeb, Ufin, UIso, VIso;
-  Standard_Boolean Only2d, Only3d;
-  gp_Pnt2d P2d, Pdeb, Pfin;
-  gp_Pnt P;
-  Handle(Adaptor2d_Curve2d) HPCur;
-  Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection
-
-  for(k = 1; k <= Projector.NbCurves(); k++){
-    Sprintf(newname,"%s_%d",name,k);
-    Sprintf(newname1,"%s2d_%d",name,k);
-    if(Projector.IsSinglePnt(k, P2d)){
-//      std::cout<<"Part "<<k<<" of the projection is punctual"<<std::endl;
-      Projector.GetSurface()->D0(P2d.X(), P2d.Y(), P);
-      DrawTrSurf::Set(temp, P);
-      DrawTrSurf::Set(temp1, P2d);
-      di<<temp<<" is 3d projected curve\n";
-      di<<temp1<<" is pcurve\n";
+  GeomAbs_Shape aContinuity = GeomAbs_C2;
+  Standard_Integer aMaxDegree, aMaxSeg;
+  Standard_Boolean aProj2d;
+  Standard_Boolean aProj3d;
+
+  while (index + 1 < n)
+  {
+    if (a[index][0] != '-') return 1;
+
+    if (a[index][1] == 'c')
+    {
+      Standard_CString aContinuityName = a[index + 1];
+      if (!strcmp(aContinuityName, "C0"))
+      {
+        aContinuity = GeomAbs_C0;
+      }
+      else if (!strcmp(aContinuityName, "C1"))
+      {
+        aContinuity = GeomAbs_C1;
+      }
+      else if (!strcmp(aContinuityName, "C2"))
+      {
+        aContinuity = GeomAbs_C2;
+      }
+
+      Projector.SetContinuity(aContinuity);
     }
-    else {
-      Only2d = Only3d = Standard_False;
-      Projector.Bounds(k, Udeb, Ufin);
-      gp_Dir2d Dir; // Only for isoparametric projection
-      
-      if (Projector.IsUIso(k, UIso)) {
-//      std::cout<<"Part "<<k<<" of the projection is U-isoparametric curve"<<std::endl;
-        Projector.D0(Udeb, Pdeb);
-        Projector.D0(Ufin, Pfin);
-        Udeb = Pdeb.Y();
-        Ufin = Pfin.Y();
-        if (Udeb > Ufin) {
-          Dir = gp_Dir2d(0, -1);
-          Udeb = - Udeb;
-          Ufin = - Ufin;
-        }
-        else Dir = gp_Dir2d(0, 1);
-        PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(UIso, 0), Dir), Udeb, Ufin);
-        HPCur = new Geom2dAdaptor_Curve(PCur2d);
-        Only3d = Standard_True;
+    else if (a[index][1] == 'd')
+    {
+      aMaxDegree = Draw::Atoi(a[index + 1]);
+      aMaxDegree = aMaxDegree > 25 ? 25 : aMaxDegree;
+      Projector.SetMaxDegree(aMaxDegree);
+    }
+    else if (a[index][1] == 's')
+    {
+      aMaxSeg = Draw::Atoi(a[index + 1]);
+      Projector.SetMaxSeg(aMaxSeg);
+    }
+    else if (!strcmp(a[index], "-2d"))
+    {
+      aProj2d = Draw::Atoi(a[index + 1]) > 0 ? Standard_True : Standard_False;
+      Projector.SetProj2d(aProj2d);
+    }
+    else if (!strcmp(a[index], "-3d"))
+    {
+      aProj3d = Draw::Atoi(a[index + 1]) > 0 ? Standard_True : Standard_False;
+      Projector.SetProj3d(aProj3d);
+    }
+
+    index += 2;
+  }
+
+  Projector.Perform();
+
+  for (Standard_Integer k = 1; k <= Projector.NbCurves(); k++) {
+    newname  = name +   "_" + TCollection_AsciiString(k);
+    newname1 = name + "2d_" + TCollection_AsciiString(k);
+
+    if (Projector.ResultIsPoint(k))
+    {
+      if (Projector.GetProj2d())
+      {
+        DrawTrSurf::Set(newname1.ToCString(), Projector.GetResult2dP(k));
+        di << newname1 << " is pcurve\n";
       }
-      else if(Projector.IsVIso(k, VIso)) {
-//      std::cout<<"Part "<<k<<" of the projection is V-isoparametric curve"<<std::endl;
-        Projector.D0(Udeb, Pdeb);
-        Projector.D0(Ufin, Pfin);
-        Udeb = Pdeb.X();
-        Ufin = Pfin.X();
-        if (Udeb > Ufin) {
-          Dir = gp_Dir2d(-1, 0);
-          Udeb = - Udeb;
-          Ufin = - Ufin;
-        }
-        else Dir = gp_Dir2d(1, 0);
-        PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(0, VIso), Dir), Udeb, Ufin);
-        HPCur = new Geom2dAdaptor_Curve(PCur2d);
-        Only3d = Standard_True;
+      if (Projector.GetProj3d())
+      {
+        DrawTrSurf::Set(newname.ToCString(), Projector.GetResult3dP(k));
+        di << newname << " is 3d projected curve\n";
       }
-      else HPCur = HProjector;
-      
-      if(Projector.MaxDistance(k) <= myTol3d)
-        Only2d = Standard_True;
-      
-      if(Only2d && Only3d) {
-        Handle(Geom_Curve) OutCur = new Geom_TrimmedCurve (GeomAdaptor::MakeCurve (*hcur), Ufin, Udeb);
-        DrawTrSurf::Set(temp, OutCur);
-        DrawTrSurf::Set(temp1, PCur2d);
-        di<<temp<<" is 3d projected curve\n";
-        di<<temp1<<" is pcurve\n";
-        return 0;
-        }
-      else {
-        Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d);
-        appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d);
-        if(!Only3d) {
-         PCur2d = appr.Curve2d();
-         di << " Error in 2d is " << appr.MaxError2dU()
-              << ";  "  << appr.MaxError2dV() << "\n"; 
-       }
-        if(Only2d) {
-          Handle(Geom_Curve) OutCur = new Geom_TrimmedCurve (GeomAdaptor::MakeCurve (*hcur), Ufin, Udeb);
-          DrawTrSurf::Set(temp, OutCur);
-          }
-        else {
-         di << " Error in 3d is " <<  appr.MaxError3d() << "\n";
-         DrawTrSurf::Set(temp, appr.Curve3d());
-       }
-        DrawTrSurf::Set(temp1, PCur2d);
-        di<<temp<<" is 3d projected curve\n";
-        di<<temp1<<" is pcurve\n";
+    }
+    else {
+      if (Projector.GetProj2d())
+      {
+        DrawTrSurf::Set(newname1.ToCString(), Projector.GetResult2dC(k));
+
+        di << newname1 << " is pcurve\n";
+        di << " Tolerance reached in 2d is " << Projector.GetResult2dUApproxError(k)
+            << ";  " << Projector.GetResult2dVApproxError(k) << "\n";
+      }
+      if (Projector.GetProj3d())
+      {
+        DrawTrSurf::Set(newname.ToCString(), Projector.GetResult3dC(k));
+
+        di << newname << " is 3d projected curve\n";
+        di << " Tolerance reached in 3d is " << Projector.GetResult3dApproxError(k) << "\n";
       }
     }
   }
-return 0;
+  return 0;
 }
+
 //=======================================================================
 //function : project
 //purpose  : 
@@ -1801,9 +1802,15 @@ void  GeometryTest::CurveCommands(Draw_Interpretor& theCommands)
                  to3d,g);
 
   theCommands.Add("gproject",
-                 "gproject : [projectname] curve surface",
-                 __FILE__,
-                 gproject,g);
+                  "gproject projectname curve surface [tolerance [maxdist]]\n"
+                  "\t\t[-c continuity][-d maxdegree][-s maxsegments][-2d proj2d][-3d proj3d]\n"
+                  "\t\t-c continuity  : set curve continuity (C0, C1, C2) for approximation\n"
+                  "\t\t-d maxdegree   : set max possible degree of result for approximation\n"
+                  "\t\t-s maxsegments : set max value of parametric intervals the projected curve for approximation\n"
+                  "\t\t-2d proj2d     : set necessity of 2d results (0 or 1)\n"
+                  "\t\t-3d proj3d     : set necessity of 3d results (0 or 1)",
+                  __FILE__,
+                  gproject,g);
   
   theCommands.Add("project",
                  "project : no args to have help",
index b13f5ac..7c9dede 100644 (file)
 #include <Adaptor2d_Curve2d.hxx>
 #include <Adaptor3d_Curve.hxx>
 #include <Adaptor3d_Surface.hxx>
+#include <Approx_CurveOnSurface.hxx>
 #include <Extrema_ExtCS.hxx>
 #include <Extrema_ExtPS.hxx>
 #include <Extrema_GenLocateExtPS.hxx>
 #include <Extrema_POnCurv.hxx>
 #include <Extrema_POnSurf.hxx>
 #include <GeomAbs_CurveType.hxx>
+#include <GeomAdaptor_Surface.hxx>
 #include <GeomLib.hxx>
 #include <gp_Mat2d.hxx>
 #include <gp_Pnt2d.hxx>
 #include <Standard_NoSuchObject.hxx>
 #include <Standard_NotImplemented.hxx>
 #include <Standard_OutOfRange.hxx>
+#include <Standard_TypeMismatch.hxx>
 #include <TColgp_HSequenceOfPnt.hxx>
 #include <Adaptor3d_CurveOnSurface.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_Line.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
 #include <Geom2dAdaptor_Curve.hxx>
+#include <GeomAdaptor.hxx>
 #include <Extrema_ExtCC.hxx>
 #include <NCollection_Vector.hxx>
 
+#include <typeinfo>
+
 #define FuncTol 1.e-10
 
 IMPLEMENT_STANDARD_RTTIEXT(ProjLib_CompProjectedCurve, Adaptor2d_Curve2d)
@@ -537,7 +547,8 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point,
   const Standard_Real TolU, 
   const Standard_Real TolV, 
   Standard_Real& U, 
-  Standard_Real& V)
+  Standard_Real& V,
+  Standard_Real theMaxDist)
 {
 
   ProjLib_PrjResolve aPrjPS (*C, *S, 1);
@@ -549,6 +560,11 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point,
 
   aExtPS.Perform(Point);
   Standard_Integer argmin = 0;
+  Standard_Real aMaxDist = theMaxDist;
+  if (aMaxDist > 0.)
+  {
+    aMaxDist *= aMaxDist;
+  }
   if (aExtPS.IsDone() && aExtPS.NbExt()) 
   {
     Standard_Integer i, Nend;
@@ -556,6 +572,10 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point,
     Nend = aExtPS.NbExt();
     for(i = 1; i <= Nend; i++)
     {
+      if (aMaxDist > 0. && aMaxDist < aExtPS.SquareDistance(i))
+      {
+        continue;
+      }
       Extrema_POnSurf POnS = aExtPS.Point(i);
       POnS.Parameter(ParU, ParV);
       aPrjPS.Perform(t, ParU, ParV, gp_Pnt2d(TolU, TolV), 
@@ -582,9 +602,9 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point,
 
 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve()
 : myNbCurves(0),
+  myMaxDist (0.0),
   myTolU    (0.0),
-  myTolV    (0.0),
-  myMaxDist (0.0)
+  myTolV    (0.0)
 {
 }
 
@@ -598,13 +618,19 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
                             const Handle(Adaptor3d_Curve)&   theCurve,
                             const Standard_Real               theTolU,
                             const Standard_Real               theTolV)
-: mySurface (theSurface),
-  myCurve   (theCurve),
-  myNbCurves(0),
-  mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
-  myTolU    (theTolU),
-  myTolV    (theTolV),
-  myMaxDist (-1.0)
+: mySurface   (theSurface),
+  myCurve     (theCurve),
+  myNbCurves  (0),
+  mySequence  (new ProjLib_HSequenceOfHSequenceOfPnt()),
+  myTol3d     (1.e-6),
+  myContinuity(GeomAbs_C2),
+  myMaxDegree (14),
+  myMaxSeg    (16),
+  myProj2d    (Standard_True),
+  myProj3d    (Standard_False),
+  myMaxDist   (-1.0),
+  myTolU      (theTolU),
+  myTolV      (theTolV)
 {
   Init();
 }
@@ -620,17 +646,51 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
                             const Standard_Real               theTolU,
                             const Standard_Real               theTolV,
                             const Standard_Real               theMaxDist)
-: mySurface (theSurface),
-  myCurve   (theCurve),
-  myNbCurves(0),
-  mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
-  myTolU    (theTolU),
-  myTolV    (theTolV),
-  myMaxDist (theMaxDist)
+: mySurface   (theSurface),
+  myCurve     (theCurve),
+  myNbCurves  (0),
+  mySequence  (new ProjLib_HSequenceOfHSequenceOfPnt()),
+  myTol3d     (1.e-6),
+  myContinuity(GeomAbs_C2),
+  myMaxDegree (14),
+  myMaxSeg    (16),
+  myProj2d    (Standard_True),
+  myProj3d    (Standard_False),
+  myMaxDist   (theMaxDist),
+  myTolU      (theTolU),
+  myTolV      (theTolV)
 {
   Init();
 }
 
+//=======================================================================
+//function : ProjLib_CompProjectedCurve
+//purpose  : 
+//=======================================================================
+
+ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
+                           (const Standard_Real              theTol3d,
+                            const Handle(Adaptor3d_Surface)& theSurface,
+                            const Handle(Adaptor3d_Curve)&   theCurve,
+                            const Standard_Real              theMaxDist)
+: mySurface   (theSurface),
+  myCurve     (theCurve),
+  myNbCurves  (0),
+  mySequence  (new ProjLib_HSequenceOfHSequenceOfPnt()),
+  myTol3d     (theTol3d),
+  myContinuity(GeomAbs_C2),
+  myMaxDegree (14),
+  myMaxSeg    (16),
+  myProj2d    (Standard_True),
+  myProj3d    (Standard_False),
+  myMaxDist   (theMaxDist)
+{
+  myTolU = Max(Precision::PConfusion(), mySurface->UResolution(theTol3d));
+  myTolV = Max(Precision::PConfusion(), mySurface->VResolution(theTol3d));
+
+  Init();
+}
+
 //=======================================================================
 //function : ShallowCopy
 //purpose  : 
@@ -774,7 +834,7 @@ void ProjLib_CompProjectedCurve::Init()
         InitChron(chr_init_point);
 #endif
         // PConfusion - use geometric tolerances in extrema / optimization.
-        initpoint=InitialPoint(CPoint, t,myCurve,mySurface, Precision::PConfusion(), Precision::PConfusion(), U, V);
+        initpoint=InitialPoint(CPoint, t, myCurve, mySurface, myTolU, myTolV, U, V, myMaxDist);
 #ifdef OCCT_DEBUG_CHRONO
         ResultChron(chr_init_point,t_init_point);
         init_point_count++;
@@ -1164,6 +1224,239 @@ void ProjLib_CompProjectedCurve::Init()
     }
   }
 }
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::Perform()
+{
+  if (myNbCurves == 0)
+    return;
+
+  Standard_Boolean approx2d = myProj2d;
+  Standard_Boolean approx3d = myProj3d;
+  Standard_Real Udeb, Ufin, UIso, VIso;
+  gp_Pnt2d P2d, Pdeb, Pfin;
+  gp_Pnt P;
+  Handle(Adaptor2d_Curve2d) HPCur;
+  Handle(Adaptor3d_Surface) HS = mySurface->ShallowCopy(); // For expand bounds of surface
+  Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection
+  Handle(Geom_Curve)   PCur3d;
+
+  if (myProj2d == Standard_True)
+  {
+    myResult2dPoint = new TColgp_HArray1OfPnt2d(1, myNbCurves);
+    myResult2dCurve = new TColGeom2d_HArray1OfCurve(1, myNbCurves);
+  }
+
+  if (myProj3d == Standard_True)
+  {
+    myResult3dPoint = new TColgp_HArray1OfPnt(1, myNbCurves);
+    myResult3dCurve = new TColGeom_HArray1OfCurve(1, myNbCurves);
+  }
+
+  myResultIsPoint = new TColStd_HArray1OfBoolean(1, myNbCurves);
+  myResultIsPoint->Init(Standard_False);
+
+  myResult3dApproxError = new TColStd_HArray1OfReal(1, myNbCurves);
+  myResult3dApproxError->Init(0.0);
+
+  myResult2dUApproxError = new TColStd_HArray1OfReal(1, myNbCurves);
+  myResult2dUApproxError->Init(0.0);
+
+  myResult2dVApproxError = new TColStd_HArray1OfReal(1, myNbCurves);
+  myResult2dVApproxError->Init(0.0);
+
+  for (Standard_Integer k = 1; k <= myNbCurves; k++)
+  {
+    if (IsSinglePnt(k, P2d)) // Part k of the projection is punctual
+    {
+      GetSurface()->D0(P2d.X(), P2d.Y(), P);
+      if (myProj2d == Standard_True)
+      {
+        myResult2dPoint->SetValue(k, P2d);
+      }
+      if (myProj3d == Standard_True)
+      {
+        myResult3dPoint->SetValue(k, P);
+      }
+      myResultIsPoint->SetValue(k, Standard_True);
+    }
+    else
+    {
+      Bounds(k, Udeb, Ufin);
+      gp_Dir2d Dir; // Only for isoparametric projection
+
+      if (IsUIso(k, UIso)) // Part k of the projection is U-isoparametric curve
+      {
+        approx2d = Standard_False;
+
+        D0(Udeb, Pdeb);
+        D0(Ufin, Pfin);
+        Udeb = Pdeb.Y();
+        Ufin = Pfin.Y();
+        if (Udeb > Ufin)
+        {
+          Dir = gp_Dir2d(0, -1);
+          Udeb = -Udeb;
+          Ufin = -Ufin;
+        }
+        else Dir = gp_Dir2d(0, 1);
+        PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(UIso, 0), Dir), Udeb, Ufin);
+        HPCur = new Geom2dAdaptor_Curve(PCur2d);
+      }
+      else if (IsVIso(k, VIso)) // Part k of the projection is V-isoparametric curve
+      {
+        approx2d = Standard_False;
+
+        D0(Udeb, Pdeb);
+        D0(Ufin, Pfin);
+        Udeb = Pdeb.X();
+        Ufin = Pfin.X();
+        if (Udeb > Ufin)
+        {
+          Dir = gp_Dir2d(-1, 0);
+          Udeb = -Udeb;
+          Ufin = -Ufin;
+        }
+        else Dir = gp_Dir2d(1, 0);
+        PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(0, VIso), Dir), Udeb, Ufin);
+        HPCur = new Geom2dAdaptor_Curve(PCur2d);
+      }
+      else
+      {
+        if (!mySurface->IsUPeriodic())
+        {
+          Standard_Real U1, U2;
+          Standard_Real dU = 10. * myTolU;
+
+          U1 = mySurface->FirstUParameter();
+          U2 = mySurface->LastUParameter();
+          U1 -= dU;
+          U2 += dU;
+
+          HS = HS->UTrim(U1, U2, 0.0);
+        }
+
+        if (!mySurface->IsVPeriodic())
+        {
+          Standard_Real V1, V2;
+          Standard_Real dV = 10. * myTolV;
+
+          V1 = mySurface->FirstVParameter();
+          V2 = mySurface->LastVParameter();
+          V1 -= dV;
+          V2 += dV;
+
+          HS = HS->VTrim(V1, V2, 0.0);
+        }
+
+        Handle(ProjLib_CompProjectedCurve) HP = Handle(ProjLib_CompProjectedCurve)::DownCast(this->ShallowCopy());
+        HP->Load(HS);
+        HPCur = HP;
+      }
+
+      if (approx2d || approx3d)
+      {
+        Standard_Boolean only2d, only3d;
+        if (approx2d && approx3d)
+        {
+          only2d = !approx2d;
+          only3d = !approx3d;
+        }
+        else
+        {
+          only2d = approx2d;
+          only3d = approx3d;
+        }
+
+        Approx_CurveOnSurface appr(HPCur, HS, Udeb, Ufin, myTol3d);
+        appr.Perform(myMaxSeg, myMaxDegree, myContinuity, only3d, only2d);
+
+        if (approx2d)
+        {
+          PCur2d = appr.Curve2d();
+          myResult2dUApproxError->SetValue(k, appr.MaxError2dU());
+          myResult2dVApproxError->SetValue(k, appr.MaxError2dV());
+        }
+
+        if (approx3d)
+        {
+          PCur3d = appr.Curve3d();
+          myResult3dApproxError->SetValue(k, appr.MaxError3d());
+        }
+      }
+
+      if (myProj2d == Standard_True)
+      {
+        myResult2dCurve->SetValue(k, PCur2d);
+      }
+
+      if (myProj3d == Standard_True)
+      {
+        myResult3dCurve->SetValue(k, PCur3d);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : SetTol3d
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetTol3d(const Standard_Real theTol3d)
+{
+  myTol3d = theTol3d;
+}
+
+//=======================================================================
+//function : SetContinuity
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetContinuity(const GeomAbs_Shape theContinuity)
+{
+  myContinuity = theContinuity;
+}
+
+//=======================================================================
+//function : SetMaxDegree
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetMaxDegree(const Standard_Integer theMaxDegree)
+{
+  if (theMaxDegree < 1) return;
+  myMaxDegree = theMaxDegree;
+}
+
+//=======================================================================
+//function : SetMaxSeg
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetMaxSeg(const Standard_Integer theMaxSeg)
+{
+  if (theMaxSeg < 1) return;
+  myMaxSeg = theMaxSeg;
+}
+
+//=======================================================================
+//function : SetProj3d
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetProj3d(const Standard_Boolean theProj3d)
+{
+  myProj3d = theProj3d;
+}
+
+//=======================================================================
+//function : SetProj2d
+//purpose  : 
+//=======================================================================
+void ProjLib_CompProjectedCurve::SetProj2d(const Standard_Boolean theProj2d)
+{
+  myProj2d = theProj2d;
+}
+
 //=======================================================================
 //function : Load
 //purpose  : 
@@ -1379,7 +1672,7 @@ void ProjLib_CompProjectedCurve::D0(const Standard_Real U,gp_Pnt2d& P) const
   ProjLib_PrjResolve aPrjPS (*myCurve, *mySurface, 1);
   aPrjPS.Perform(U, U0, V0, gp_Pnt2d(myTolU, myTolV), 
     gp_Pnt2d(mySurface->FirstUParameter(), mySurface->FirstVParameter()), 
-    gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()));
+    gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()), FuncTol);
   if (aPrjPS.IsDone())
     P = aPrjPS.Solution();
   else
@@ -1627,7 +1920,7 @@ void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const
           Solver.Perform((Tl + Tr)/2, CutPntsU(k), V, 
             gp_Pnt2d(Tol, myTolV), 
             gp_Pnt2d(Tl, mySurface->FirstVParameter()), 
-            gp_Pnt2d(Tr, mySurface->LastVParameter()));
+            gp_Pnt2d(Tr, mySurface->LastVParameter()), FuncTol);
           //
           if(Solver.IsDone()) 
           {
@@ -1693,7 +1986,7 @@ void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const
           Solver.Perform((Tl + Tr)/2, U, CutPntsV(k), 
             gp_Pnt2d(Tol, myTolV), 
             gp_Pnt2d(Tl, mySurface->FirstUParameter()), 
-            gp_Pnt2d(Tr, mySurface->LastUParameter()));
+            gp_Pnt2d(Tr, mySurface->LastUParameter()), FuncTol);
           //
           if(Solver.IsDone()) 
           {
@@ -1795,6 +2088,91 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
   return GeomAbs_OtherCurve;
 }
 
+//=======================================================================
+//function : ResultIsPoint
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean ProjLib_CompProjectedCurve::ResultIsPoint(const Standard_Integer theIndex) const
+{
+  return myResultIsPoint->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult2dUApproxError
+//purpose  : 
+//=======================================================================
+
+Standard_Real ProjLib_CompProjectedCurve::GetResult2dUApproxError(const Standard_Integer theIndex) const
+{
+  return myResult2dUApproxError->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult2dVApproxError
+//purpose  : 
+//=======================================================================
+
+Standard_Real ProjLib_CompProjectedCurve::GetResult2dVApproxError(const Standard_Integer theIndex) const
+{
+  return myResult2dVApproxError->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult3dApproxError
+//purpose  : 
+//=======================================================================
+
+Standard_Real ProjLib_CompProjectedCurve::GetResult3dApproxError(const Standard_Integer theIndex) const
+{
+  return myResult3dApproxError->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult2dC
+//purpose  : 
+//=======================================================================
+
+Handle(Geom2d_Curve) ProjLib_CompProjectedCurve::GetResult2dC(const Standard_Integer theIndex) const
+{
+  return myResult2dCurve->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult3dC
+//purpose  : 
+//=======================================================================
+
+Handle(Geom_Curve) ProjLib_CompProjectedCurve::GetResult3dC(const Standard_Integer theIndex) const
+{
+  return myResult3dCurve->Value(theIndex);
+}
+
+
+//=======================================================================
+//function : GetResult2dP
+//purpose  : 
+//=======================================================================
+
+gp_Pnt2d ProjLib_CompProjectedCurve::GetResult2dP(const Standard_Integer theIndex) const
+{
+  Standard_TypeMismatch_Raise_if(!myResultIsPoint->Value(theIndex),
+                                 "ProjLib_CompProjectedCurve : result is not a point 2d");
+  return myResult2dPoint->Value(theIndex);
+}
+
+//=======================================================================
+//function : GetResult3dP
+//purpose  : 
+//=======================================================================
+
+gp_Pnt ProjLib_CompProjectedCurve::GetResult3dP(const Standard_Integer theIndex) const
+{
+  Standard_TypeMismatch_Raise_if(!myResultIsPoint->Value(theIndex),
+                                 "ProjLib_CompProjectedCurve : result is not a point 3d");
+  return myResult3dPoint->Value(theIndex);
+}
+
 //=======================================================================
 //function : UpdateTripleByTrapCriteria
 //purpose  :
@@ -1834,7 +2212,7 @@ void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) co
   Standard_Real U,V;
   Standard_Boolean isDone = 
     InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface, 
-                 Precision::PConfusion(), Precision::PConfusion(), U, V);
+                 Precision::PConfusion(), Precision::PConfusion(), U, V, myMaxDist);
 
   if (!isDone)
     return;
index 0838670..8c5fa21 100644 (file)
 #include <Adaptor2d_Curve2d.hxx>
 #include <Adaptor3d_Surface.hxx>
 #include <ProjLib_HSequenceOfHSequenceOfPnt.hxx>
+#include <ProjLib_Projector.hxx>
+#include <TColGeom_HArray1OfCurve.hxx>
+#include <TColGeom2d_HArray1OfCurve.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+#include <TColgp_HArray1OfPnt2d.hxx>
 #include <TColStd_HArray1OfBoolean.hxx>
 #include <TColStd_HArray1OfReal.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom2d_Curve.hxx>
 #include <GeomAbs_Shape.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <GeomAbs_CurveType.hxx>
@@ -44,6 +51,13 @@ public:
   //! equal then MaxDist.
   //! if MaxDist < 0 then algorithm works as above.
   Standard_EXPORT ProjLib_CompProjectedCurve(const Handle(Adaptor3d_Surface)& S, const Handle(Adaptor3d_Curve)& C, const Standard_Real TolU, const Standard_Real TolV, const Standard_Real MaxDist);
+
+  //! this constructor tries to optimize the search using the
+  //! assumption that maximum distance between surface and curve less or
+  //! equal then MaxDist.
+  //! if MaxDist < 0 then algorithm try to find all solutions
+  //! Tolerances of parameters are calculated automatically.
+  Standard_EXPORT ProjLib_CompProjectedCurve(const Standard_Real Tol3d, const Handle(Adaptor3d_Surface)& S, const Handle(Adaptor3d_Curve)& C, const Standard_Real MaxDist = -1.0);
   
   //! Shallow copy of adaptor
   Standard_EXPORT virtual Handle(Adaptor2d_Curve2d) ShallowCopy() const Standard_OVERRIDE;
@@ -54,6 +68,35 @@ public:
   //! included  in this set of points.
   Standard_EXPORT void Init();
   
+  //! Performs projecting for given curve.
+  //! If projecting uses approximation, 
+  //! approximation parameters can be set before by corresponding methods 
+  //! SetTol3d(...), SeContinuity(...), SetMaxDegree(...), SetMaxSeg(...)
+  Standard_EXPORT void Perform();
+
+  //! Set the parameter, which defines 3d tolerance of approximation.
+  Standard_EXPORT void SetTol3d(const Standard_Real theTol3d);
+
+  //! Set the parameter, which defines curve continuity.
+  //! Default value is GeomAbs_C2;
+  Standard_EXPORT void SetContinuity(const GeomAbs_Shape theContinuity);
+
+  //! Set max possible degree of result BSpline curve2d, which is got by approximation.
+  //! If MaxDegree < 0, algorithm uses values that are chosen depending of types curve 3d
+  //! and surface.
+  Standard_EXPORT void SetMaxDegree(const Standard_Integer theMaxDegree);
+
+  //! Set the parameter, which defines maximal value of parametric intervals the projected
+  //! curve can be cut for approximation. If MaxSeg < 0, algorithm uses default 
+  //! value = 16.
+  Standard_EXPORT void SetMaxSeg(const Standard_Integer theMaxSeg);
+
+  //! Set the parameter, which defines necessity of 2d results.
+  Standard_EXPORT void SetProj2d(const Standard_Boolean theProj2d);
+
+  //! Set the parameter, which defines necessity of 3d results.
+  Standard_EXPORT void SetProj3d(const Standard_Boolean theProj3d);
+
   //! Changes the surface.
   Standard_EXPORT void Load (const Handle(Adaptor3d_Surface)& S);
   
@@ -143,6 +186,44 @@ public:
   //! Parabola, BezierCurve, BSplineCurve, OtherCurve.
   Standard_EXPORT GeomAbs_CurveType GetType() const Standard_OVERRIDE;
 
+  //! Returns true if result of projecting of the curve interval
+  //! with number Index is point.
+  Standard_EXPORT Standard_Boolean ResultIsPoint(const Standard_Integer theIndex) const;
+
+  //! Returns the error of approximation of U parameter 2d-curve as a result
+  //! projecting of the curve interval with number Index.
+  Standard_EXPORT Standard_Real GetResult2dUApproxError(const Standard_Integer theIndex) const;
+
+  //! Returns the error of approximation of V parameter 2d-curve as a result
+  //! projecting of the curve interval with number Index.
+  Standard_EXPORT Standard_Real GetResult2dVApproxError(const Standard_Integer theIndex) const;
+
+  //! Returns the error of approximation of 3d-curve as a result
+  //! projecting of the curve interval with number Index.
+  Standard_EXPORT Standard_Real GetResult3dApproxError(const Standard_Integer theIndex) const;
+
+  //! Returns the resulting 2d-curve of projecting
+  //! of the curve interval with number Index.
+  Standard_EXPORT Handle(Geom2d_Curve) GetResult2dC(const Standard_Integer theIndex) const;
+
+  //! Returns the resulting 3d-curve of projecting
+  //! of the curve interval with number Index.
+  Standard_EXPORT Handle(Geom_Curve) GetResult3dC(const Standard_Integer theIndex) const;
+
+  //! Returns the resulting 2d-point of projecting
+  //! of the curve interval with number Index.
+  Standard_EXPORT gp_Pnt2d GetResult2dP(const Standard_Integer theIndex) const;
+
+  //! Returns the resulting 3d-point of projecting
+  //! of the curve interval with number Index.
+  Standard_EXPORT gp_Pnt GetResult3dP(const Standard_Integer theIndex) const;
+
+  //! Returns the parameter, which defines necessity of only 2d results.
+  Standard_Boolean GetProj2d() const { return myProj2d; }
+
+  //! Returns the parameter, which defines necessity of only 3d results.
+  Standard_Boolean GetProj3d() const { return myProj3d; }
+
 private:
 
   //! This method performs check possibility of optimization traps and tries to go out from them.
@@ -157,14 +238,29 @@ private:
   Handle(Adaptor3d_Curve) myCurve;
   Standard_Integer myNbCurves;
   Handle(ProjLib_HSequenceOfHSequenceOfPnt) mySequence;
-  Standard_Real myTolU;
-  Standard_Real myTolV;
-  Standard_Real myMaxDist;
   Handle(TColStd_HArray1OfBoolean) myUIso;
   Handle(TColStd_HArray1OfBoolean) myVIso;
   Handle(TColStd_HArray1OfBoolean) mySnglPnts;
   Handle(TColStd_HArray1OfReal) myMaxDistance;
   Handle(TColStd_HArray1OfReal) myTabInt;
+  Standard_Real    myTol3d;
+  GeomAbs_Shape    myContinuity;
+  Standard_Integer myMaxDegree;
+  Standard_Integer myMaxSeg;
+  Standard_Boolean myProj2d;
+  Standard_Boolean myProj3d;
+  Standard_Real myMaxDist;
+  Standard_Real myTolU;
+  Standard_Real myTolV;
+
+  Handle(TColStd_HArray1OfBoolean)  myResultIsPoint;
+  Handle(TColStd_HArray1OfReal)     myResult2dUApproxError;
+  Handle(TColStd_HArray1OfReal)     myResult2dVApproxError;
+  Handle(TColStd_HArray1OfReal)     myResult3dApproxError;
+  Handle(TColgp_HArray1OfPnt)       myResult3dPoint;
+  Handle(TColgp_HArray1OfPnt2d)     myResult2dPoint;
+  Handle(TColGeom_HArray1OfCurve)   myResult3dCurve;
+  Handle(TColGeom2d_HArray1OfCurve) myResult2dCurve;
 };
 
 DEFINE_STANDARD_HANDLE(ProjLib_CompProjectedCurve, Adaptor2d_Curve2d)
index abd0f3e..2ab6b58 100644 (file)
@@ -81,7 +81,7 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_
 //    if (!S1.IsDone()) { return; }
 //  }
 //  else {
-  math_NewtonFunctionSetRoot SR (F, Tol, 1.e-10);
+  math_NewtonFunctionSetRoot SR (F, Tol, FuncTol);
   SR.Perform(F, Start, BInf, BSup);
 //    if (!SR.IsDone()) { return; }
   if (!SR.IsDone())
@@ -100,8 +100,8 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_
 
   Standard_Real ExtraU , ExtraV;
 //  if(!StrictInside) {
-    ExtraU = Tol2d.X();
-    ExtraV = Tol2d.Y();
+    ExtraU = 2. * Tol2d.X();
+    ExtraV = 2. * Tol2d.Y();
 //  }
   if (mySolution.X() > Inf.X() - Tol2d.X() && mySolution.X() < Inf.X()) mySolution.SetX(Inf.X());
   if (mySolution.X() > Sup.X() && mySolution.X() < Sup.X() + Tol2d.X()) mySolution.SetX(Sup.X()); 
@@ -119,7 +119,9 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_
     
     F.Value(X, FVal);   
 
-    if ((FVal(1)*FVal(1) + FVal(2)*FVal(2)) > FuncTol) myDone = Standard_False;
+    if (!SR.IsDone()) {
+      if ((FVal(1)*FVal(1) + FVal(2)*FVal(2)) > FuncTol) myDone = Standard_False;
+    }
   }
 
 
index 30ea956..1d711a8 100644 (file)
@@ -1,5 +1,3 @@
-puts "REQUIRED All: Projection Failed"
-
 puts "========"
 puts "OCC25980"
 puts "========"
@@ -13,7 +11,6 @@ restore [locate_data_file s1t.draw] s
 
 set bug_info [catch {project x c s}]
 
-# Projection should fail due to big distance of projection at curve beginning
-if {$bug_info == 0} {
+if {$bug_info == 1} {
   puts "ERROR: OCC25980 is reproduced."
 }
index 671537e..6868c32 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC24185 ALL: Error : The length of result shape is"
-
 puts "========"
 puts "OCC24185"
 puts "========"
@@ -11,7 +9,7 @@ puts ""
 restore [locate_data_file bug24185_face.brep] f
 restore [locate_data_file bug24185_wire.brep] w
 
-nproject result w f
+nproject result w f 1.e-4 1
 
 checkshape result
 checkprops result -l 11.06
diff --git a/tests/bugs/moddata_3/bug30046 b/tests/bugs/moddata_3/bug30046
new file mode 100644 (file)
index 0000000..3e422bb
--- /dev/null
@@ -0,0 +1,65 @@
+puts "================"
+puts "0030046: Modeling Data - Cannot find necessary projection of the curve"
+puts "================"
+puts ""
+
+set BugNumber OCC30046
+
+restore [locate_data_file bug30046_cur.brep] c
+restore [locate_data_file bug30046_sur.brep] s
+
+gproject result c s 1.e-3 -2d 1 -3d 1
+gproject result_maxdist c s 1.e-7 2. -2d 1 -3d 1
+
+regexp {is ([-0-9.+eE]+)} [length result2d_1] full ll
+set len_result2d $ll
+
+regexp {is ([-0-9.+eE]+)} [length result_maxdist2d_1] full ll
+set len_result_maxdist2d $ll
+
+if {$len_result2d < $len_result_maxdist2d} {
+  puts "Faulty ${BugNumber}: length of a 2d projection, built with a smaller tolerance, must be less";
+}
+
+regexp {is ([-0-9.+eE]+)} [length result_1] full ll
+set len_result $ll
+
+regexp {is ([-0-9.+eE]+)} [length result_maxdist_1] full ll
+set len_result_maxdist $ll
+
+if {$len_result < $len_result_maxdist} {
+  puts "Faulty ${BugNumber}: length of a 3d projection, built with a smaller tolerance, must be less";
+}
+
+set tol_abs 1.0e-4
+set tol_rel 0.0001
+
+set bounds_result2d_1 [gbounding result2d_1]
+regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $bounds_result2d_1 full v1_x v1_y v2_x v2_y
+
+set expected_v1_x 0.050141663706179646
+checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel}
+
+set expected_v1_y 0.00039517687539122789
+checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel}
+
+set expected_v2_x 0.24709337491832356
+checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel}
+
+set expected_v2_y 0.00044697332650299172
+checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel}
+  
+set bounds_result_maxdist_1 [gbounding result_maxdist2d_1]
+regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $bounds_result_maxdist_1 full v1_x v1_y v2_x v2_y 
+
+set expected_v1_x 0.050141663706179958
+checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel}
+
+set expected_v1_y 0.00039517687539122805
+checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel}
+
+set expected_v2_x 0.24708119728076677
+checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel}
+
+set expected_v2_y 0.00044696841766235214
+checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel}
\ No newline at end of file