0031987: Visualization - Slow rectangular selection on models with big number of...
authorage <age@opencascade.com>
Tue, 8 Dec 2020 10:32:07 +0000 (13:32 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 10 Dec 2020 16:03:12 +0000 (19:03 +0300)
SelectMgr_SensitiveEntitySet now stores a map of registered owners with a counter of registered entities.
SelectMgr_ViewerSelector::traverseObject() now reads the number of sensitive entities for specific owner
from SelectMgr_SensitiveEntitySet instead of re-computing it every time.

src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx
src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx

index 35c433b..bad281a 100644 (file)
@@ -41,7 +41,12 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_SensitiveEntit
     theEntity->ResetSelectionActiveStatus();
     return;
   }
-  mySensitives.Add (theEntity);
+
+  const Standard_Integer anExtent = mySensitives.Extent();
+  if (mySensitives.Add (theEntity) > anExtent)
+  {
+    addOwner (theEntity->BaseSensitive()->OwnerId());
+  }
   MarkDirty();
 }
 
@@ -59,7 +64,12 @@ void SelectMgr_SensitiveEntitySet::Append (const Handle(SelectMgr_Selection)& th
       aSelEntIter.Value()->ResetSelectionActiveStatus();
       continue;
     }
-    mySensitives.Add (aSelEntIter.Value());
+
+    const Standard_Integer anExtent = mySensitives.Extent();
+    if (mySensitives.Add (aSelEntIter.Value()) > anExtent)
+    {
+      addOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId());
+    }
   }
   MarkDirty();
 }
@@ -85,6 +95,7 @@ void SelectMgr_SensitiveEntitySet::Remove (const Handle(SelectMgr_Selection)& th
     }
 
     mySensitives.RemoveLast();
+    removeOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId());
   }
 
   MarkDirty();
@@ -144,3 +155,37 @@ const Handle(SelectMgr_SensitiveEntity)& SelectMgr_SensitiveEntitySet::GetSensit
 {
   return mySensitives.FindKey (theIndex + 1);
 }
+
+//=======================================================================
+// function : addOwner
+// purpose  :
+//=======================================================================
+void SelectMgr_SensitiveEntitySet::addOwner (const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+  if (!theOwner.IsNull())
+  {
+    if (Standard_Integer* aNumber = myOwnersMap.ChangeSeek (theOwner))
+    {
+      ++(*aNumber);
+    }
+    else
+    {
+      myOwnersMap.Bind (theOwner, 1);
+    }
+  }
+}
+
+//=======================================================================
+// function : removeOwner
+// purpose  :
+//=======================================================================
+void SelectMgr_SensitiveEntitySet::removeOwner (const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+  if (Standard_Integer* aNumber = !theOwner.IsNull() ? myOwnersMap.ChangeSeek (theOwner) : NULL)
+  {
+    if (--(*aNumber) == 0)
+    {
+      myOwnersMap.UnBind (theOwner);
+    }
+  }
+}
index d65577f..61f8d84 100644 (file)
 #define _SelectMgr_SensitiveEntitySet_HeaderFile
 
 #include <BVH_PrimitiveSet3d.hxx>
+#include <NCollection_DataMap.hxx>
 #include <NCollection_IndexedMap.hxx>
 #include <Select3D_BndBox3d.hxx>
 #include <Select3D_BVHBuilder3d.hxx>
+#include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_SensitiveEntity.hxx>
 #include <SelectMgr_Selection.hxx>
 
 typedef NCollection_IndexedMap<Handle(SelectMgr_SensitiveEntity)> SelectMgr_IndexedMapOfHSensitive;
+typedef NCollection_DataMap<Handle(SelectMgr_EntityOwner), Standard_Integer> SelectMgr_MapOfOwners;
 
 //! This class is used to store all calculated sensitive entites of one selectable
 //! object. It provides an interface for building BVH tree which is used to speed-up
@@ -73,9 +76,21 @@ public:
   //! Returns map of entities.
   const SelectMgr_IndexedMapOfHSensitive& Sensitives() const { return mySensitives; }
 
+  //! Returns map of owners.
+  const SelectMgr_MapOfOwners& Owners() const { return myOwnersMap; }
+
+protected:
+
+  //! Adds entity owner to the map of owners (or increases its counter if it is already there).
+  Standard_EXPORT void addOwner (const Handle(SelectMgr_EntityOwner)& theOwner);
+
+  //! Decreases counter of owner in the map of owners (or removes it from the map if counter == 0).
+  Standard_EXPORT void removeOwner (const Handle(SelectMgr_EntityOwner)& theOwner);
+
 private:
 
   SelectMgr_IndexedMapOfHSensitive mySensitives;     //!< Map of entities and its corresponding index in BVH
+  SelectMgr_MapOfOwners myOwnersMap;                 //!< Map of entity owners and its corresponding number of sensitives
 };
 
 #endif // _SelectMgr_SensitiveEntitySet_HeaderFile
index c1102fb..f29494f 100644 (file)
@@ -581,19 +581,10 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
     const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
     Standard_Integer aNbOwnerEntities = 0;
-    for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
+    anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
+    if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
     {
-      if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
-      {
-        if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
-        {
-          // Remove from index map.
-          // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
-          // Hence, just keep iterating in backward direction.
-          mystored.RemoveFromIndex (aStoredIter);
-          break;
-        }
-      }
+      mystored.RemoveFromIndex (aStoredIter);
     }
   }
 }