From 266877a7c3963b4ac02bb1d015e74b405244d80e Mon Sep 17 00:00:00 2001 From: age Date: Tue, 8 Dec 2020 13:32:07 +0300 Subject: [PATCH] 0031987: Visualization - Slow rectangular selection on models with big number of sensitives 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. --- .../SelectMgr_SensitiveEntitySet.cxx | 49 ++++++++++++++++++- .../SelectMgr_SensitiveEntitySet.hxx | 15 ++++++ src/SelectMgr/SelectMgr_ViewerSelector.cxx | 15 ++---- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx index 35c433b9a0..bad281a5e1 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.cxx @@ -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); + } + } +} diff --git a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx index d65577f40c..61f8d84f92 100644 --- a/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx +++ b/src/SelectMgr/SelectMgr_SensitiveEntitySet.hxx @@ -17,13 +17,16 @@ #define _SelectMgr_SensitiveEntitySet_HeaderFile #include +#include #include #include #include +#include #include #include typedef NCollection_IndexedMap SelectMgr_IndexedMapOfHSensitive; +typedef NCollection_DataMap 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 diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index c1102fba7f..f29494f3fd 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -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); } } }