0026249: Visualization, TKV3d - fix possible division by zero in SelectMgr_Rectangula...
[occt.git] / src / SelectMgr / SelectMgr_RectangularFrustum.cxx
index b0867e2..b98d41d 100644 (file)
@@ -44,13 +44,11 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   Standard_Real aD = DOT (anU, aW);
   Standard_Real anE = DOT (aV, aW);
   Standard_Real aCoef = anA * aC - aB * aB;
-  Standard_Real aSc, aSn, aSd = aCoef;
+  Standard_Real aSn = aCoef;
   Standard_Real aTc, aTn, aTd = aCoef;
 
   if (aCoef < Precision::Confusion())
   {
-    aSn = 0.0;
-    aSd = 1.0;
     aTn = anE;
     aTd = aC;
   }
@@ -60,13 +58,11 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
     aTn = (anA * anE - aB * aD);
     if (aSn < 0.0)
     {
-      aSn = 0.0;
       aTn = anE;
       aTd = aC;
     }
-    else if (aSn > aSd)
+    else if (aSn > aCoef)
     {
-      aSn = aSd;
       aTn = anE + aB;
       aTd = aC;
     }
@@ -75,28 +71,11 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   if (aTn < 0.0)
   {
     aTn = 0.0;
-    if (-aD < 0.0)
-      aSn = 0.0;
-    else if (-aD > anA)
-      aSn = aSd;
-    else {
-      aSn = -aD;
-      aSd = anA;
-    }
   }
   else if (aTn > aTd)
   {
     aTn = aTd;
-    if ((-aD + aB) < 0.0)
-      aSn = 0;
-    else if ((-aD + aB) > anA)
-      aSn = aSd;
-    else {
-      aSn = (-aD +  aB);
-      aSd = anA;
-    }
   }
-  aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd);
   aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
 
   SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc;
@@ -713,7 +692,25 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
     SelectMgr_Vec3 aTrEdges[3] = { SelectMgr_Vec3 (thePnt2.X() - thePnt1.X(), thePnt2.Y() - thePnt1.Y(), thePnt2.Z() - thePnt1.Z()),
                                    SelectMgr_Vec3 (thePnt3.X() - thePnt2.X(), thePnt3.Y() - thePnt2.Y(), thePnt3.Z() - thePnt2.Z()),
                                    SelectMgr_Vec3 (thePnt1.X() - thePnt3.X(), thePnt1.Y() - thePnt3.Y(), thePnt1.Z() - thePnt3.Z()) };
-    SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / DOT (aTriangleNormal, myViewRayDir));
+
+    Standard_Real anAlpha = DOT (aTriangleNormal, myViewRayDir);
+    if (Abs (anAlpha) < gp::Resolution())
+    {
+      // handle degenerated triangles: in this case, there is no possible way to detect overlap correctly.
+      if (aTriangleNormal.SquareModulus() < gp::Resolution())
+      {
+        theDepth = std::numeric_limits<Standard_Real>::max();
+        return Standard_False;
+      }
+
+      // handle the case when triangle normal and selecting frustum direction are orthogonal: for this case, overlap
+      // is detected correctly, and distance to triangle's plane can be measured as distance to its arbitrary vertex.
+      const SelectMgr_Vec3 aDiff = myNearPickedPnt - aPnt1;
+      theDepth = DOT (aTriangleNormal, aDiff);
+      return Standard_True;
+    }
+
+    SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / anAlpha);
 
     Standard_Real aTime = DOT (aTriangleNormal, anEdge);