]> OCCT Git - occt.git/commitdiff
0031716: Visualization, Select3D_SensitiveSet::matches() - avoid building BVH in...
authorage <age@opencascade.com>
Tue, 18 Aug 2020 07:08:06 +0000 (10:08 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 22 Aug 2020 09:13:10 +0000 (12:13 +0300)
src/Select3D/Select3D_SensitiveSet.cxx
src/Select3D/Select3D_SensitiveSet.hxx

index dfffbbea1f83bebc37e35ccaca6df4a2bc5a12a5..3c2b460b1fb564272778608d744ec2d2e5f3fe29 100644 (file)
@@ -78,6 +78,51 @@ namespace
   };
 }
 
+//=======================================================================
+// function : processElements
+// purpose  :
+//=======================================================================
+Standard_Boolean Select3D_SensitiveSet::processElements (SelectBasics_SelectingVolumeManager& theMgr,
+                                                         Standard_Integer theFirstElem,
+                                                         Standard_Integer theLastElem,
+                                                         Standard_Boolean theIsFullInside,
+                                                         Standard_Boolean theToCheckAllInside,
+                                                         SelectBasics_PickResult& thePickResult,
+                                                         Standard_Integer& theMatchesNb)
+{
+  SelectBasics_PickResult aPickResult;
+  for (Standard_Integer anIdx = theFirstElem; anIdx <= theLastElem; anIdx++)
+  {
+    if (!theMgr.IsOverlapAllowed()) // inclusion test
+    {
+      if (!elementIsInside (theMgr, anIdx, theIsFullInside))
+      {
+        if (theToCheckAllInside)
+        {
+          continue;
+        }
+        return Standard_False;
+      }
+    }
+    else // overlap test
+    {
+      if (!overlapsElement (aPickResult, theMgr, anIdx, theIsFullInside))
+      {
+        continue;
+      }
+
+      if (thePickResult.Depth() > aPickResult.Depth())
+      {
+        thePickResult = aPickResult;
+        myDetectedIdx = anIdx;
+      }
+    }
+    ++theMatchesNb;
+  }
+
+  return Standard_True;
+}
+
 //=======================================================================
 // function : Matches
 // purpose  :
@@ -87,116 +132,113 @@ Standard_Boolean Select3D_SensitiveSet::matches (SelectBasics_SelectingVolumeMan
                                                  Standard_Boolean theToCheckAllInside)
 {
   myDetectedIdx = -1;
-  const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
-  if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
-                                                aBVH->MaxPoint (0)))
+  
+  if (myContent.Size() < 1)
   {
     return Standard_False;
   }
 
-  NodeInStack aStack[BVH_Constants_MaxTreeDepth];
-  NodeInStack aNode;
+  const Select3D_BndBox3d& aGlobalBox = myContent.Box();
+  Standard_Boolean isFullInside = Standard_True;
 
-  Standard_Integer aHead = -1;
+  if (!theMgr.Overlaps(aGlobalBox.CornerMin(),
+                       aGlobalBox.CornerMax(),
+                       &isFullInside))
+  {
+    return Standard_False;
+  }
 
   Standard_Integer aMatchesNb = -1;
-  SelectBasics_PickResult aPickResult;
+
   const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point);
-  for (;;)
+  if (toCheckFullInside && isFullInside)
   {
-    const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode.Id];
-
-    if (aData.x() == 0) // is inner node
+    Standard_Integer aSize = myContent.Size();
+    if (!processElements (theMgr, 0, aSize - 1, Standard_True, theToCheckAllInside, thePickResult, aMatchesNb))
     {
-      NodeInStack aLeft (aData.y(), toCheckFullInside), aRight(aData.z(), toCheckFullInside);
-      Standard_Boolean toCheckLft = Standard_True, toCheckRgh = Standard_True;
-      if (!aNode.IsFullInside)
-      {
-        toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLeft.Id), aBVH->MaxPoint (aLeft.Id), toCheckFullInside ? &aLeft.IsFullInside : NULL);
-        if (!toCheckLft)
-        {
-          aLeft.IsFullInside = Standard_False;
-        }
+      return Standard_False;
+    }
+  }
+  else
+  {
+    const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
+    NodeInStack aStack[BVH_Constants_MaxTreeDepth];
+    NodeInStack aNode;
 
-        toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRight.Id), aBVH->MaxPoint (aRight.Id), toCheckFullInside ? &aRight.IsFullInside : NULL);
-        if (!toCheckRgh)
-        {
-          aRight.IsFullInside = Standard_False;
-        }
-      }
+    Standard_Integer aHead = -1;
 
-      if (!theMgr.IsOverlapAllowed()) // inclusion test
+    for (;;)
+    {
+      const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode.Id];
+
+      if (aData.x() == 0) // is inner node
       {
-        if (!theToCheckAllInside)
+        NodeInStack aLeft (aData.y(), toCheckFullInside), aRight(aData.z(), toCheckFullInside);
+        Standard_Boolean toCheckLft = Standard_True, toCheckRgh = Standard_True;
+        if (!aNode.IsFullInside)
         {
-          if (!toCheckLft || !toCheckRgh)
+          toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLeft.Id), aBVH->MaxPoint (aLeft.Id), toCheckFullInside ? &aLeft.IsFullInside : NULL);
+          if (!toCheckLft)
           {
-            return Standard_False; // no inclusion
+            aLeft.IsFullInside = Standard_False;
           }
 
-          // skip extra checks
-          toCheckLft &= !aLeft.IsFullInside;
-          toCheckRgh &= !aRight.IsFullInside;
-        }
-      }
-
-      if (toCheckLft || toCheckRgh)
-      {
-        aNode = toCheckLft ? aLeft : aRight;
-        if (toCheckLft && toCheckRgh)
-        {
-          aStack[++aHead] = aRight;
+          toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRight.Id), aBVH->MaxPoint (aRight.Id), toCheckFullInside ? &aRight.IsFullInside : NULL);
+          if (!toCheckRgh)
+          {
+            aRight.IsFullInside = Standard_False;
+          }
         }
-      }
-      else
-      {
-        if (aHead < 0)
-          break;
 
-        aNode = aStack[aHead--];
-      }
-    }
-    else
-    {
-      for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
-      {
         if (!theMgr.IsOverlapAllowed()) // inclusion test
         {
-          if (!elementIsInside (theMgr, anElemIdx, aNode.IsFullInside))
+          if (!theToCheckAllInside)
           {
-            if (theToCheckAllInside)
+            if (!toCheckLft || !toCheckRgh)
             {
-              continue;
+              return Standard_False; // no inclusion
             }
-            return Standard_False;
+
+            // skip extra checks
+            toCheckLft &= !aLeft.IsFullInside;
+            toCheckRgh &= !aRight.IsFullInside;
           }
         }
-        else // overlap test
+
+        if (toCheckLft || toCheckRgh)
         {
-          if (!overlapsElement (aPickResult, theMgr, anElemIdx, aNode.IsFullInside))
+          aNode = toCheckLft ? aLeft : aRight;
+          if (toCheckLft && toCheckRgh)
           {
-            continue;
+            aStack[++aHead] = aRight;
           }
+        }
+        else
+        {
+          if (aHead < 0)
+            break;
 
-          if (thePickResult.Depth() > aPickResult.Depth())
-          {
-            thePickResult = aPickResult;
-            myDetectedIdx = anElemIdx;
-          }
+          aNode = aStack[aHead--];
         }
-        ++aMatchesNb;
       }
+      else
+      {
+        if (!processElements (theMgr, aData.y(), aData.z(), aNode.IsFullInside, theToCheckAllInside, thePickResult, aMatchesNb))
+        {
+          return Standard_False;
+        }
 
-      if (aHead < 0)
-        break;
+        if (aHead < 0)
+          break;
 
-      aNode = aStack[aHead--];
+        aNode = aStack[aHead--];
+      }
     }
   }
 
   if (aMatchesNb != -1)
   {
-    thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
+    thePickResult.SetDistToGeomCenter (distanceToCOG (theMgr));
   }
 
   return aMatchesNb != -1
index ba94866853c57f13369236ca95bcbde81f6fe113..be3ef600cfc15126af616e69406fe8dccb8cd6ec 100644 (file)
@@ -135,6 +135,22 @@ protected:
   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
   virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) = 0;
 
+  //! Process elements overlapped by the selection volume
+  //! @param theMgr selection manager
+  //! @param theFirstElem index of the first element
+  //! @param theLastElem index of the last element
+  //! @param theIsFullInside when TRUE indicates that entire BVH node is already inside selection volume
+  //! @param thePickResult [OUT] picking result (for picking by ray)
+  //! @param theMatchesNb [OUT] number of processed elements
+  //! @return FALSE if some element is outside the selection volume (if IsOverlapAllowed is FALSE); TRUE otherwise
+  Standard_EXPORT Standard_Boolean processElements (SelectBasics_SelectingVolumeManager& theMgr,
+                                                    Standard_Integer theFirstElem,
+                                                    Standard_Integer theLastElem,
+                                                    Standard_Boolean theIsFullInside,
+                                                    Standard_Boolean theToCheckAllInside,
+                                                    SelectBasics_PickResult& thePickResult,
+                                                    Standard_Integer& theMatchesNb);
+
 protected:
 
   //! The purpose of this class is to provide a link between BVH_PrimitiveSet