0030058: Visualization, Select3D_SensitivePrimitiveArray - the selection is not fast...
[occt.git] / src / SelectMgr / SelectMgr_RectangularFrustum.cxx
index ac2291a..d972e19 100644 (file)
@@ -24,7 +24,7 @@
 // =======================================================================
 void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegPnt1,
                                                            const gp_Pnt& theSegPnt2,
-                                                           Standard_Real& theDepth)
+                                                           SelectBasics_PickResult& thePickResult) const
 {
   gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
   gp_XYZ aV = myViewRayDir.XYZ();
@@ -39,7 +39,7 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   Standard_Real aSn = aCoef;
   Standard_Real aTc, aTn, aTd = aCoef;
 
-  if (aCoef < Precision::Confusion())
+  if (aCoef < gp::Resolution())
   {
     aTn = anE;
     aTd = aC;
@@ -68,19 +68,34 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   {
     aTn = aTd;
   }
-  aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
+  aTc = (Abs (aTd) < gp::Resolution() ? 0.0 : aTn / aTd);
 
-  gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc;
-  theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale;
+  const gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc;
+  thePickResult.SetDepth (myNearPickedPnt.Distance (aClosestPnt) * myScale);
+
+  const gp_Vec aPickedVec = aClosestPnt.XYZ() - theSegPnt1.XYZ();
+  const gp_Vec aFigureVec = theSegPnt2.XYZ()  - theSegPnt1.XYZ();
+  const Standard_Real aPickedVecMod = aPickedVec.Magnitude();
+  const Standard_Real aFigureVecMod = aFigureVec.Magnitude();
+  if (aPickedVecMod <= gp::Resolution()
+   || aFigureVecMod <= gp::Resolution())
+  {
+    thePickResult.SetPickedPoint (aClosestPnt);
+    return;
+  }
+
+  const Standard_Real aCosOfAngle = aFigureVec.Dot (aPickedVec) / (aPickedVecMod * aFigureVecMod);
+  const Standard_Real aSegPntShift = Min(aFigureVecMod, Max(0.0, aCosOfAngle * aPickedVecMod));
+  thePickResult.SetPickedPoint (theSegPnt1.XYZ() + aFigureVec.XYZ() * (aSegPntShift / aFigureVecMod));
 }
 
 // =======================================================================
 // function : segmentPlaneIntersection
 // purpose  :
 // =======================================================================
-void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane,
+bool SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane,
                                                              const gp_Pnt& thePntOnPlane,
-                                                             Standard_Real& theDepth)
+                                                             SelectBasics_PickResult& thePickResult) const
 {
   gp_XYZ anU = myViewRayDir.XYZ();
   gp_XYZ aW = myNearPickedPnt.XYZ() - thePntOnPlane.XYZ();
@@ -91,25 +106,26 @@ void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePl
   {
     if (Abs (aN) < Precision::Angular())
     {
-      theDepth = DBL_MAX;
-      return;
+      thePickResult.Invalidate();
+      return false;
     }
     else
     {
-      theDepth = DBL_MAX;
-      return;
+      thePickResult.Invalidate();
+      return false;
     }
   }
 
   Standard_Real aParam = aN / aD;
   if (aParam < 0.0 || aParam > 1.0)
   {
-    theDepth = DBL_MAX;
-    return;
+    thePickResult.Invalidate();
+    return false;
   }
 
   gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + anU * aParam;
-  theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale;
+  thePickResult.SetDepth (myNearPickedPnt.Distance (aClosestPnt) * myScale);
+  return true;
 }
 
 namespace
@@ -276,7 +292,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
-  myViewClipRange.Clear();
+  myViewClipRange.SetVoid();
 
   myScale = 1.0;
 }
@@ -306,7 +322,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
-  myViewClipRange.Clear();
+  myViewClipRange.SetVoid();
 
   myScale = 1.0;
 }
@@ -413,7 +429,7 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
                                                          const SelectMgr_Vec3& theBoxMax,
-                                                         Standard_Boolean*     theInside)
+                                                         Standard_Boolean*     theInside) const
 {
   return hasOverlap (theBoxMin, theBoxMax, theInside);
 }
@@ -425,7 +441,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
                                                          const SelectMgr_Vec3& theBoxMax,
-                                                         Standard_Real& theDepth)
+                                                         SelectBasics_PickResult& thePickResult) const
 {
   if (!hasOverlap (theBoxMin, theBoxMax))
     return Standard_False;
@@ -435,9 +451,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
   aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y()));
   aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z()));
 
-  theDepth = aNearestPnt.Distance (myNearPickedPnt);
+  thePickResult.SetDepth (aNearestPnt.Distance (myNearPickedPnt));
 
-  return isViewClippingOk (theDepth);
+  return isViewClippingOk (thePickResult);
 }
 
 // =======================================================================
@@ -445,7 +461,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
 // purpose  : Intersection test between defined volume and given point
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
-                                                         Standard_Real& theDepth)
+                                                         SelectBasics_PickResult& thePickResult) const
 {
   if (!hasOverlap (thePnt))
     return Standard_False;
@@ -454,16 +470,17 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
   gp_Pnt aDetectedPnt =
     myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * (aV.Dot (myViewRayDir.XYZ()) / myViewRayDir.Dot (myViewRayDir));
 
-  theDepth = aDetectedPnt.Distance (myNearPickedPnt) * myScale;
+  thePickResult.SetDepth (aDetectedPnt.Distance (myNearPickedPnt) * myScale);
+  thePickResult.SetPickedPoint (thePnt);
 
-  return isViewClippingOk (theDepth);
+  return isViewClippingOk (thePickResult);
 }
 
 // =======================================================================
 // function : Overlaps
 // purpose  : Intersection test between defined volume and given point
 // =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt) const
 {
   return hasOverlap (thePnt);
 }
@@ -474,15 +491,14 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt)
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
                                                          const gp_Pnt& thePnt2,
-                                                         Standard_Real& theDepth)
+                                                         SelectBasics_PickResult& thePickResult) const
 {
-  theDepth = -DBL_MAX;
   if (!hasOverlap (thePnt1, thePnt2))
     return Standard_False;
 
-  segmentSegmentDistance (thePnt1, thePnt2, theDepth);
+  segmentSegmentDistance (thePnt1, thePnt2, thePickResult);
 
-  return isViewClippingOk (theDepth);
+  return isViewClippingOk (thePickResult);
 }
 
 // =======================================================================
@@ -494,12 +510,13 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts,
                                                          Select3D_TypeOfSensitivity theSensType,
-                                                         Standard_Real& theDepth)
+                                                         SelectBasics_PickResult& thePickResult) const
 {
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
     Standard_Integer aMatchingSegmentsNb = -1;
-    theDepth = DBL_MAX;
+    SelectBasics_PickResult aPickResult;
+    thePickResult.Invalidate();
     const Standard_Integer aLower  = theArrayOfPnts.Lower();
     const Standard_Integer anUpper = theArrayOfPnts.Upper();
     for (Standard_Integer aPntIter = aLower; aPntIter <= anUpper; ++aPntIter)
@@ -509,9 +526,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPn
       if (hasOverlap (aStartPnt, aEndPnt))
       {
         aMatchingSegmentsNb++;
-        Standard_Real aSegmentDepth = RealLast();
-        segmentSegmentDistance (aStartPnt, aEndPnt, aSegmentDepth);
-        theDepth = Min (theDepth, aSegmentDepth);
+        segmentSegmentDistance (aStartPnt, aEndPnt, aPickResult);
+        thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
       }
     }
 
@@ -521,15 +537,16 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPn
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
     gp_Vec aPolyNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
-    if (!hasOverlap (theArrayOfPnts, aPolyNorm))
+    if (!hasOverlap (theArrayOfPnts, aPolyNorm)
+     || !segmentPlaneIntersection (aPolyNorm,
+                                   theArrayOfPnts.First(),
+                                   thePickResult))
+    {
       return Standard_False;
-
-    segmentPlaneIntersection (aPolyNorm,
-                              theArrayOfPnts.Value (theArrayOfPnts.Lower()),
-                              theDepth);
+    }
   }
 
-  return isViewClippingOk (theDepth);
+  return isViewClippingOk (thePickResult);
 }
 
 // =======================================================================
@@ -543,13 +560,13 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
                                                          const gp_Pnt& thePnt2,
                                                          const gp_Pnt& thePnt3,
                                                          Select3D_TypeOfSensitivity theSensType,
-                                                         Standard_Real& theDepth)
+                                                         SelectBasics_PickResult& thePickResult) const
 {
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
     const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 };
     const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 4);
-    return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theDepth);
+    return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, thePickResult);
   }
   else if (theSensType == Select3D_TOS_INTERIOR)
   {
@@ -568,16 +585,15 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
       // handle degenerated triangles: in this case, there is no possible way to detect overlap correctly.
       if (aTriangleNormal.SquareMagnitude() < 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 gp_XYZ aDiff = myNearPickedPnt.XYZ() - thePnt1.XYZ();
-      theDepth = aTriangleNormal.Dot (aDiff) * myScale;
-
-      return isViewClippingOk (theDepth);
+      thePickResult.SetDepth (aTriangleNormal.Dot (aDiff) * myScale);
+      thePickResult.SetPickedPoint (thePnt1);
+      return isViewClippingOk (thePickResult);
     }
 
     gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / anAlpha);
@@ -589,20 +605,18 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
     Standard_Real anU = aVec.Dot (aTrEdges[2]);
     Standard_Real aV  = aVec.Dot (aTrEdges[0]);
 
-    Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
-
+    const Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
+    const gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
     if (isInterior)
     {
-      gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
-      theDepth = myNearPickedPnt.Distance (aDetectedPnt) * myScale;
-
-      return isViewClippingOk (theDepth);
+      thePickResult.SetDepth (myNearPickedPnt.Distance (aPtOnPlane) * myScale);
+      thePickResult.SetPickedPoint (aPtOnPlane);
+      return isViewClippingOk (thePickResult);
     }
 
     gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
     Standard_Real aMinDist = RealLast();
     Standard_Integer aNearestEdgeIdx = -1;
-    gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
     for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx)
     {
       gp_XYZ aW = aPtOnPlane.XYZ() - aPnts[anEdgeIdx].XYZ();
@@ -614,10 +628,10 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
         aNearestEdgeIdx = anEdgeIdx;
       }
     }
-    segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], theDepth);
+    segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], thePickResult);
   }
 
-  return isViewClippingOk (theDepth);
+  return isViewClippingOk (thePickResult);
 }
 
 // =======================================================================
@@ -625,7 +639,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
 // purpose  : Measures distance between 3d projection of user-picked
 //            screen point and given point theCOG
 // =======================================================================
-Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
+Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) const
 {
   return theCOG.Distance (myNearPickedPnt) * myScale;
 }
@@ -637,7 +651,7 @@ Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt&
 // =======================================================================
 gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
 {
-  return myNearPickedPnt.XYZ() + myViewRayDir.Normalized().XYZ() * theDepth;
+  return myNearPickedPnt.XYZ() + myViewRayDir.Normalized().XYZ() * theDepth / myScale;
 }
 
 // =======================================================================
@@ -645,56 +659,81 @@ gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth
 // purpose  :
 // =======================================================================
 void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
-                                                         Standard_Real& theDepthMin,
-                                                         Standard_Real& theDepthMax)
+                                                         SelectMgr_ViewClipRange& theRange) const
 {
-  theDepthMax = DBL_MAX;
-  theDepthMin = -DBL_MAX;
   Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
   for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
     if (!aClipPlane->IsOn())
-      continue;
-
-    gp_Pln aGeomPlane = aClipPlane->ToPlane();
-
-    aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
-
-    const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
-
-    Standard_Real aDotProduct = myViewRayDir.XYZ ().Dot (aPlaneDirXYZ);
-    Standard_Real aDistance = - myNearPickedPnt.XYZ ().Dot (aPlaneDirXYZ)
-                              - aPlaneD;
-
-    // check whether the pick line is parallel to clip plane
-    if (Abs (aDotProduct) < Precision::Angular())
     {
-      // line lies below the plane and is not clipped, skip
       continue;
     }
 
-    // compute distance to point of pick line intersection with the plane
-    Standard_Real aParam = aDistance / aDotProduct;
-
-    // check if ray intersects the plane, in case aIntDist < 0
-    // the plane is "behind" the ray
-    if (aParam < 0.0)
+    Bnd_Range aSubRange (RealFirst(), RealLast());
+    for (const Graphic3d_ClipPlane* aSubPlaneIter = aClipPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
     {
-      continue;
-    }
+      const gp_Pln aGeomPlane = aSubPlaneIter->ToPlane();
+      aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
 
-    const gp_Pnt anIntersectionPt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
-    const Standard_Real aDistToPln = anIntersectionPt.Distance (myNearPickedPnt);
+      const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
+      Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ);
+      Standard_Real aDistance   = -myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) - aPlaneD;
+      Standard_Real aDistToPln  = 0.0;
 
-    // change depth limits for case of opposite and directed planes
-    if (aDotProduct < 0.0)
-    {
-      theDepthMax = Min (aDistToPln, theDepthMax);
+      // check whether the pick line is parallel to clip plane
+      if (Abs (aDotProduct) < Precision::Angular())
+      {
+        if (aDistance < 0.0)
+        {
+          continue;
+        }
+        aDistToPln  = RealLast();
+        aDotProduct = 1.0;
+      }
+      else
+      {
+        // compute distance to point of pick line intersection with the plane
+        const Standard_Real aParam = aDistance / aDotProduct;
+
+        const gp_Pnt anIntersectionPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
+        aDistToPln = anIntersectionPnt.Distance (myNearPickedPnt);
+        if (aParam < 0.0)
+        {
+          // the plane is "behind" the ray
+          aDistToPln = -aDistToPln;
+        }
+      }
+
+      // change depth limits for case of opposite and directed planes
+      if (!aClipPlane->IsChain())
+      {
+        if (aDotProduct < 0.0)
+        {
+          theRange.ChangeUnclipRange().TrimTo (aDistToPln);
+        }
+        else
+        {
+          theRange.ChangeUnclipRange().TrimFrom (aDistToPln);
+        }
+      }
+      else
+      {
+        if (aDotProduct < 0.0)
+        {
+          aSubRange.TrimFrom (aDistToPln);
+        }
+        else
+        {
+          aSubRange.TrimTo (aDistToPln);
+        }
+      }
     }
-    else if (aDistToPln > theDepthMin)
+
+    if (!aSubRange.IsVoid()
+      && aClipPlane->IsChain())
     {
-      theDepthMin = Max (aDistToPln, theDepthMin);
+      theRange.AddClipSubRange (aSubRange);
     }
   }
 }
@@ -705,12 +744,11 @@ void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_Sequenc
 //            detected belongs to the region defined by clipping planes
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
-                                                          const Standard_Real theDepth)
+                                                          const Standard_Real theDepth) const
 {
-  Standard_Real aMaxDepth, aMinDepth;
-  computeClippingRange (thePlanes, aMinDepth, aMaxDepth);
-
-  return (theDepth <= aMinDepth || theDepth >= aMaxDepth);
+  SelectMgr_ViewClipRange aRange;
+  computeClippingRange (thePlanes, aRange);
+  return aRange.IsClipped (theDepth);
 }
 
 // =======================================================================
@@ -722,27 +760,40 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
   if (thePlanes.IsNull()
    || thePlanes->IsEmpty())
   {
-    myViewClipRange.Clear();
+    myViewClipRange.SetVoid();
     return;
   }
 
-  Standard_Real aMaxDepth, aMinDepth;
-  computeClippingRange (*thePlanes, aMinDepth, aMaxDepth);
-  myViewClipRange.Set (aMinDepth, aMaxDepth);
+  computeClippingRange (*thePlanes, myViewClipRange);
 }
 
 // =======================================================================
 // function : isViewClippingOk
 // purpose  :
 // =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const
+Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const SelectBasics_PickResult& thePickResult) const
+{
+  return !myIsViewClipEnabled
+      || !myViewClipRange.IsClipped (thePickResult.Depth());
+}
+
+// =======================================================================
+// function : GetPlanes
+// purpose  :
+// =======================================================================
+void SelectMgr_RectangularFrustum::GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const
 {
-  if (!myViewClipRange.IsValid()
-   || !myIsViewClipEnabled)
+  thePlaneEquations.Clear();
+
+  SelectMgr_Vec4 anEquation;
+  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
   {
-    return Standard_True;
+    const gp_Vec& aPlaneNorm = myIsOrthographic && aPlaneIdx % 2 == 1 ?
+      myPlanes[aPlaneIdx - 1].Reversed() : myPlanes[aPlaneIdx];
+    anEquation.x() = aPlaneNorm.X();
+    anEquation.y() = aPlaneNorm.Y();
+    anEquation.z() = aPlaneNorm.Z();
+    anEquation.w() = - (aPlaneNorm.XYZ().Dot (myVertices[aPlaneIdx % 2 == 0 ? aPlaneIdx : aPlaneIdx + 2].XYZ()));
+    thePlaneEquations.Append (anEquation);
   }
-
-  return myViewClipRange.MaxDepth() > theDepth
-    && myViewClipRange.MinDepth() < theDepth;
 }