]> OCCT Git - occt-copy.git/commitdiff
0031203: SENR-21-037 SenerAlgo_ProjectWire fails when projecting wire to face (691...
authorifv <ifv@opencascade.com>
Mon, 2 Dec 2019 09:11:41 +0000 (12:11 +0300)
committerifv <ifv@opencascade.com>
Tue, 3 Dec 2019 09:37:36 +0000 (12:37 +0300)
src/BRepClass/BRepClass_FaceExplorer.cxx

index 3fb9b5baf5dad3e4db03894187aac2d5abda9890..8f32e9c06785bcb079c662c67257402dea6f718c 100644 (file)
@@ -27,6 +27,7 @@
 #include <Precision.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Face.hxx>
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>
 
 static const Standard_Real Probing_Start = 0.123;
 static const Standard_Real Probing_End = 0.7;
@@ -41,27 +42,28 @@ BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
        myFace(F),
        myCurEdgeInd(1),
        myCurEdgePar(Probing_Start)
-{
+ {
   myFace.Orientation(TopAbs_FORWARD);
 }
 
+
 //=======================================================================
 //function : CheckPoint
 //purpose  : 
 //=======================================================================
 
-Standard_Boolean  BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
+Standard_Boolean BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
 {
   Standard_Real anUMin = 0.0, anUMax = 0.0, aVMin = 0.0, aVMax = 0.0;
   TopLoc_Location aLocation;
   const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(myFace, aLocation);
   aSurface->Bounds(anUMin, anUMax, aVMin, aVMax);
   if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
-      Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
+    Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
   {
     BRepTools::UVBounds(myFace, anUMin, anUMax, aVMin, aVMax);
     if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
-        Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
+      Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
     {
       return Standard_True;
     }
@@ -71,14 +73,14 @@ Standard_Boolean  BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
   Standard_Real aDistance = aCenterPnt.Distance(thePoint);
   if (Precision::IsInfinite(aDistance))
   {
-    thePoint.SetCoord(anUMin - ( anUMax - anUMin ),
-                       aVMin - ( aVMax - aVMin ));
+    thePoint.SetCoord (anUMin - (anUMax - anUMin ),
+                       aVMin - (aVMax - aVMin ));
     return Standard_False;
   }
   else
   {
     Standard_Real anEpsilon = Epsilon(aDistance);
-    if (anEpsilon > Max(anUMax - anUMin, aVMax - aVMin))
+    if (anEpsilon > Max (anUMax - anUMin, aVMax - aVMin))
     {
       gp_Vec2d aLinVec(aCenterPnt, thePoint);
       gp_Dir2d aLinDir(aLinVec);
@@ -124,7 +126,7 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
                                                      gp_Lin2d& L,
                                                      Standard_Real& Par)
 {
-  TopExp_Explorer      anExpF(myFace,TopAbs_EDGE);
+  TopExp_Explorer      anExpF(myFace, TopAbs_EDGE);
   Standard_Integer     i;
   Standard_Real        aFPar;
   Standard_Real        aLPar;
@@ -137,7 +139,7 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
     if (i != myCurEdgeInd)
       continue;
 
-    const TopoDS_Shape       &aLocalShape   = anExpF.Current();
+    const TopoDS_Shape       &aLocalShape = anExpF.Current();
     const TopAbs_Orientation  anOrientation = aLocalShape.Orientation();
 
     if (anOrientation == TopAbs_FORWARD || anOrientation == TopAbs_REVERSED) {
@@ -146,27 +148,29 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
       aC2d = BRep_Tool::CurveOnSurface(anEdge, myFace, aFPar, aLPar);
 
       if (!aC2d.IsNull()) {
-       // Treatment of infinite cases.
-       if (Precision::IsNegativeInfinite(aFPar)) {
-         if (Precision::IsPositiveInfinite(aLPar)) {
-           aFPar = -1.;
-           aLPar =  1.;
-         } else {
-           aFPar = aLPar - 1.;
-         }
-       } else if (Precision::IsPositiveInfinite(aLPar))
-         aLPar = aFPar + 1.;
-
-       for (; myCurEdgePar < Probing_End ;myCurEdgePar += Probing_Step) {
-         aParamIn = myCurEdgePar*aFPar + (1. - myCurEdgePar)*aLPar;
+        // Treatment of infinite cases.
+        if (Precision::IsNegativeInfinite(aFPar)) {
+          if (Precision::IsPositiveInfinite(aLPar)) {
+            aFPar = -1.;
+            aLPar = 1.;
+          }
+          else {
+            aFPar = aLPar - 1.;
+          }
+        }
+        else if (Precision::IsPositiveInfinite(aLPar))
+          aLPar = aFPar + 1.;
+
+        for (; myCurEdgePar < Probing_End; myCurEdgePar += Probing_Step) {
+          aParamIn = myCurEdgePar*aFPar + (1. - myCurEdgePar)*aLPar;
 
           gp_Vec2d aTanVec;
-         aC2d->D1(aParamIn, aPOnC, aTanVec);
-         Par = aPOnC.SquareDistance(P);
+          aC2d->D1(aParamIn, aPOnC, aTanVec);
+          Par = aPOnC.SquareDistance(P);
 
-         if (Par > aTolParConf2) {
-           gp_Vec2d aLinVec(P, aPOnC);
-           gp_Dir2d aLinDir(aLinVec);
+          if (Par > aTolParConf2) {
+            gp_Vec2d aLinVec(P, aPOnC);
+            gp_Dir2d aLinDir(aLinVec);
 
             Standard_Real aTanMod = aTanVec.SquareMagnitude();
             if (aTanMod < aTolParConf2)
@@ -174,8 +178,10 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
             aTanVec /= Sqrt(aTanMod);
             Standard_Real aSinA = aTanVec.Crossed(aLinDir.XY());
             const Standard_Real SmallAngle = 0.001;
+            Standard_Boolean isSmallAngle = Standard_False;
             if (Abs(aSinA) < SmallAngle)
             {
+              isSmallAngle = Standard_True;
               // The line from the input point P to the current point on edge
               // is tangent to the edge curve. This condition is bad for classification.
               // Therefore try to go to another point in the hope that there will be 
@@ -185,28 +191,62 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
                 continue;
             }
 
-           L = gp_Lin2d(P, aLinDir);
-
-           // Check if ends of a curve lie on a line.
-           aC2d->D0(aFPar, aPOnC);
-
-           if (L.SquareDistance(aPOnC) > aTolParConf2) {
-             aC2d->D0(aLPar, aPOnC);
-
-             if (L.SquareDistance(aPOnC) > aTolParConf2) {
-               myCurEdgePar += Probing_Step;
-
-               if (myCurEdgePar >= Probing_End) {
-                 myCurEdgeInd++;
-                 myCurEdgePar = Probing_Start;
-               }
-
-               Par = Sqrt(Par);
-               return Standard_True;
-             }
-           }
-         }
-       }
+            L = gp_Lin2d(P, aLinDir);
+
+            // Check if ends of a curve lie on a line.
+            aC2d->D0(aFPar, aPOnC);
+            Standard_Real aFDist = P.SquareDistance(aPOnC);
+            if (L.SquareDistance(aPOnC) > aTolParConf2) {
+              aC2d->D0(aLPar, aPOnC);
+              if (L.SquareDistance(aPOnC) > aTolParConf2) {
+                Standard_Real aLDist = P.SquareDistance(aPOnC);
+
+                if (isSmallAngle)
+                {
+                  //Try to find minimal distance between curve and line
+
+                  Geom2dAPI_ProjectPointOnCurve aProj;
+                  aProj.Init(P, aC2d, aFPar, aLPar);
+                  if (aProj.NbPoints() > 0)
+                  {
+                    Standard_Real aMinDist = aProj.LowerDistance();
+                    aMinDist *= aMinDist;
+                    Standard_Real aTMin = aProj.LowerDistanceParameter();
+                    if (aMinDist > aFDist)
+                    {
+                      aMinDist = aFDist;
+                      aTMin = aFPar;
+                    }
+                    if (aMinDist > aLDist)
+                    {
+                      aMinDist = aLDist;
+                      aTMin = aLPar;
+                    }
+                    if (aMinDist < Par)
+                    {
+                      Par = aMinDist;
+                      if (Par < aTolParConf2)
+                      {
+                        continue;
+                      }
+                      aC2d->D1(aTMin, aPOnC, aTanVec);
+                      aLinDir.SetXY(aTanVec.XY());
+                      L = gp_Lin2d(P, aLinDir);
+                    }
+                  }
+                }
+                myCurEdgePar += Probing_Step;
+                if (myCurEdgePar >= Probing_End) {
+                  myCurEdgeInd++;
+                  myCurEdgePar = Probing_Start;
+                }
+
+                Par = Sqrt(Par);
+                return Standard_True;
+              }
+            }
+          }
+        }
       } // if (!aC2d.IsNull()) {
     } // if (anOrientation == TopAbs_FORWARD ...
 
@@ -217,7 +257,7 @@ Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
 
   // nothing found, return an horizontal line
   Par = RealLast();
-  L   = gp_Lin2d(P,gp_Dir2d(1,0));
+  L = gp_Lin2d(P, gp_Dir2d(1, 0));
 
   return Standard_False;
 }