0030686: Visualization, SelectMgr_ViewerSelector - sorting issues of transformation...
[occt.git] / src / SelectMgr / SelectMgr_ViewerSelector.cxx
index c8bb090..0099563 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-// Modified by  ...
-//              ROB JAN/07/98 : Improve Storage of detected entities
-//              AGV OCT/23/03 : Optimize the method SortResult() (OCC4201)
+#include <SelectMgr_ViewerSelector.hxx>
 
 #include <BVH_Tree.hxx>
+#include <gp_GTrsf.hxx>
 #include <gp_Pnt.hxx>
 #include <OSD_Environment.hxx>
 #include <Precision.hxx>
-#include <SelectMgr_ViewerSelector.hxx>
-#include <SelectMgr_CompareResults.hxx>
 #include <SelectBasics_EntityOwner.hxx>
 #include <SelectBasics_SensitiveEntity.hxx>
 #include <SelectBasics_PickResult.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_SortCriterion.hxx>
 #include <SelectMgr_SensitiveEntitySet.hxx>
-#include <SortTools_QuickSortOfInteger.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <TColStd_HArray1OfInteger.hxx>
 #include <TColStd_ListOfInteger.hxx>
 
+#include <algorithm>
 
-//=======================================================================
-// function: SelectMgr_ToleranceMap
-// purpose : Sets tolerance values to -1.0
-//=======================================================================
-SelectMgr_ToleranceMap::SelectMgr_ToleranceMap()
-{
-  myLargestKey = -1.0;
-  myCustomTolerance = -1.0;
-}
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
 
-//=======================================================================
-// function: ~SelectMgr_ToleranceMap
-// purpose :
-//=======================================================================
-SelectMgr_ToleranceMap::~SelectMgr_ToleranceMap()
-{
-  myTolerances.Clear();
-}
-
-//=======================================================================
-// function: Add
-// purpose : Adds the value given to map, checks if the current tolerance value
-//           should be replaced by theTolerance
-//=======================================================================
-void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
-{
-  if (myTolerances.IsBound (theTolerance))
+namespace {
+  // Comparison operator for sorting selection results
+  class CompareResults
   {
-    Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
-    aFreq++;
+  public:
+   
+    CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
+      : myMapOfCriterion (aMapOfCriterion)
+    {
+    }
 
-    if (aFreq == 1 && theTolerance != myLargestKey)
-      myLargestKey = Max (theTolerance, myLargestKey);
-  }
-  else
-  {
-    if (myTolerances.IsEmpty())
+    Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
     {
-      myTolerances.Bind (theTolerance, 1);
-      myLargestKey = theTolerance;
-      return;
+      return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
     }
 
-    myTolerances.Bind (theTolerance, 1);
-    myLargestKey = Max (theTolerance, myLargestKey);
-  }
+  private:
+    void operator = (const CompareResults&);
+
+  private:
+    const SelectMgr_IndexedDataMapOfOwnerCriterion&  myMapOfCriterion;
+  };
+
+  static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
 }
 
 //=======================================================================
-// function: Decrement
-// purpose : Decrements a counter of the tolerance given, checks if the current tolerance value
-//           should be recalculated
+// function : updatePoint3d
+// purpose  :
 //=======================================================================
-void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
+void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
+                                              const SelectBasics_PickResult& thePickResult,
+                                              const Handle(SelectBasics_SensitiveEntity)& theEntity,
+                                              const gp_GTrsf& theInversedTrsf,
+                                              const SelectMgr_SelectingVolumeManager& theMgr) const
 {
-  if (myTolerances.IsBound (theTolerance))
+  if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
   {
-    Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
-    aFreq--;
-
-    if (Abs (theTolerance - myLargestKey) < Precision::Confusion() && aFreq == 0)
-    {
-      myLargestKey = 0.0;
-      for (NCollection_DataMap<Standard_Real, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
-      {
-        if (anIter.Value() != 0)
-          myLargestKey = Max (myLargestKey, anIter.Key());
-      }
-    }
+    return;
   }
-}
 
-//=======================================================================
-// function: Tolerance
-// purpose : Returns a current tolerance that must be applied
-//=======================================================================
-Standard_Real SelectMgr_ToleranceMap::Tolerance()
-{
-  return myCustomTolerance < 0.0 ? myLargestKey : myCustomTolerance;
-}
+  if (thePickResult.HasPickedPoint())
+  {
+    theCriterion.Point = thePickResult.PickedPoint();
+  }
+  else if (!thePickResult.IsValid())
+  {
+    theCriterion.Point = thePickResult.PickedPoint();
+    return;
+  }
+  else
+  {
+    theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
+  }
 
-//=======================================================================
-// function: SetCustomTolerance
-// purpose : Sets tolerance to the given one and disables adaptive checks
-//=======================================================================
-void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theTolerance)
-{
-  myCustomTolerance = theTolerance;
-}
+  gp_GTrsf anInvTrsf = theInversedTrsf;
+  if (theCriterion.Entity->HasInitLocation())
+  {
+    anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
+  }
+  if (anInvTrsf.Form() != gp_Identity)
+  {
+    anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
+  }
 
-//=======================================================================
-// function: ResetDefaults
-// purpose : Unsets a custom tolerance and enables adaptive checks
-//=======================================================================
-void SelectMgr_ToleranceMap::ResetDefaults()
-{
-  myCustomTolerance = -1.0;
+  if (mySelectingVolumeMgr.Camera().IsNull())
+  {
+    theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
+  }
+  else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
+  {
+    theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
+  }
+  else
+  {
+    const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
+    theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
+  }
 }
 
 //==================================================
@@ -142,51 +122,53 @@ void SelectMgr_ToleranceMap::ResetDefaults()
 //==================================================
 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
 preferclosest(Standard_True),
-mytolerance(2.0),
 myToUpdateTolerance (Standard_True),
+myCameraScale (1.0),
 myCurRank (0),
 myIsLeftChildQueuedFirst (Standard_False),
 myEntityIdx (0)
 {
-  mySelectableObjects = new SelectMgr_SelectableObjectSet();
+  myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
 }
 
-
 //==================================================
 // Function: Activate
 // Purpose :
 //==================================================
 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
 {
-  for (theSelection->Init(); theSelection->More(); theSelection->Next())
+  for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
   {
-    theSelection->Sensitive()->SetActiveForSelection();
+    aSelEntIter.Value()->SetActiveForSelection();
   }
 
-  theSelection->SetSelectionState (SelectMgr_SOS_Activated);
+  if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
+  {
+    theSelection->SetSelectionState (SelectMgr_SOS_Activated);
 
-  myTolerances.Add (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
-  myToUpdateTolerance = Standard_True;
+    myTolerances.Add (theSelection->Sensitivity());
+    myToUpdateTolerance = Standard_True;
+  }
 }
 
-
 //==================================================
 // Function: Deactivate
 // Purpose :
 //==================================================
 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
 {
-  for (theSelection->Init(); theSelection->More(); theSelection->Next())
+  for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
   {
-    theSelection->Sensitive()->ResetSelectionActiveStatus();
+    aSelEntIter.Value()->ResetSelectionActiveStatus();
   }
 
-  theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
+  if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
+  {
+    theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
 
-  myTolerances.Decrement (theSelection->Sensitivity());
-  mytolerance = myTolerances.Tolerance();
-  myToUpdateTolerance = Standard_True;
+    myTolerances.Decrement (theSelection->Sensitivity());
+    myToUpdateTolerance = Standard_True;
+  }
 }
 
 //==================================================
@@ -196,7 +178,6 @@ void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& th
 void SelectMgr_ViewerSelector::Clear()
 {
   mystored.Clear();
-  myMapOfDetected.Clear();
 }
 
 //=======================================================================
@@ -206,30 +187,18 @@ void SelectMgr_ViewerSelector::Clear()
 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
 {
   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
-    && theEntity->SensitivityFactor() < myTolerances.Tolerance();
+    && sensitivity (theEntity) < myTolerances.Tolerance();
 }
 
 //=======================================================================
-// function: scaleAndTransform
-// purpose : Applies given scale and transformation matrices to the default selecting volume manager
+// function: sensitivity
+// purpose : In case if custom tolerance is set, this method will return sum of entity
+//           sensitivity and custom tolerance.
 //=======================================================================
-SelectMgr_SelectingVolumeManager SelectMgr_ViewerSelector::scaleAndTransform (const Standard_Real theScale,
-                                                                              const gp_Trsf& theTrsf)
+Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
 {
-  SelectMgr_SelectingVolumeManager aMgr;
-
-  if (theScale > Precision::Angular())
-  {
-    aMgr = mySelectingVolumeMgr.Scale (theScale);
-  }
-
-  if (theTrsf.Form() != gp_Identity)
-  {
-    aMgr = aMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Unknown ?
-      mySelectingVolumeMgr.Transform (theTrsf) : aMgr.Transform (theTrsf);
-  }
-
-  return aMgr;
+  return myTolerances.IsCustomTolSet() ?
+    theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
 }
 
 //=======================================================================
@@ -238,47 +207,141 @@ SelectMgr_SelectingVolumeManager SelectMgr_ViewerSelector::scaleAndTransform (co
 //           entity theEntity overlaps current selecting volume precisely
 //=======================================================================
 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
-                                             const Standard_Integer theEntityIdx,
+                                             const gp_GTrsf& theInversedTrsf,
                                              SelectMgr_SelectingVolumeManager& theMgr)
 {
-  const Handle(SelectMgr_EntityOwner)& anOwner =
-    Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId());
-
-  SelectBasics_PickResult aPickResult;
-  if (theEntity->Matches (theMgr, aPickResult))
+  Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
+  Handle(SelectMgr_SelectableObject) aSelectable;
+  Standard_Boolean toRestoresViewClipEnabled = Standard_False;
+  if (!anOwner.IsNull())
   {
-    if (!anOwner.IsNull())
+    aSelectable = anOwner->Selectable();
+  }
+  if (!aSelectable.IsNull())
+  {
+    if (!aSelectable->ClipPlanes().IsNull()
+      && aSelectable->ClipPlanes()->ToOverrideGlobal())
     {
-      if (HasDepthClipping (anOwner) && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
-      {
-        Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
-                                                       aPickResult.Depth());
-        if (isClipped)
-          return;
-      }
-
-      Standard_Integer aPriority = anOwner->Priority();
-
-      SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33, preferclosest);
-      if (mystored.Contains (anOwner))
+      theMgr.SetViewClippingEnabled (Standard_False);
+      toRestoresViewClipEnabled = Standard_True;
+    }
+    else if (!aSelectable->TransformPersistence().IsNull())
+    {
+      if (aSelectable->TransformPersistence()->IsZoomOrRotate()
+      && !theMgr.ViewClipping().IsNull())
       {
-        if (theMgr.GetActiveSelectionType() != 1)
+        // Zoom/rotate persistence object lives in two worlds at the same time.
+        // Global clipping planes can not be trivially applied without being converted
+        // into local space of transformation persistence object.
+        // As more simple alternative - just clip entire object by its anchor point defined in the world space.
+        const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
+
+        const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
+        for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
         {
-          SelectMgr_SortCriterion& aPrevCriterion = mystored.ChangeFromKey (anOwner);
-          if (aCriterion > aPrevCriterion)
+          const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+          if (!aPlane->IsOn())
           {
-            aPrevCriterion = aCriterion;
-            myMapOfDetected.ChangeFind (anOwner) = theEntityIdx;
+            continue;
+          }
+
+          const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
+          if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
+          {
+            return;
           }
         }
       }
-      else
+
+      theMgr.SetViewClippingEnabled (Standard_False);
+      toRestoresViewClipEnabled = Standard_True;
+    }
+  }
+
+  SelectBasics_PickResult aPickResult;
+  const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
+  if (toRestoresViewClipEnabled)
+  {
+    theMgr.SetViewClippingEnabled (Standard_True);
+  }
+
+  if (!isMatched
+    || anOwner.IsNull())
+  {
+    return;
+  }
+
+  if (HasDepthClipping (anOwner)
+  && !aSelectable.IsNull()
+  &&  theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
+  {
+    Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
+                                                                  aPickResult.Depth());
+    if (isClipped)
+      return;
+  }
+
+  SelectMgr_SortCriterion aCriterion;
+  myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
+  aCriterion.Entity    = theEntity;
+  aCriterion.Priority  = anOwner->Priority();
+  aCriterion.Depth     = aPickResult.Depth();
+  aCriterion.MinDist   = aPickResult.DistToGeomCenter();
+  aCriterion.ToPreferClosest = preferclosest;
+
+  if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
+  {
+    ++aPrevCriterion->NbOwnerMatches;
+    aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
+    if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
+    {
+      if (aCriterion > *aPrevCriterion)
       {
-        mystored.Add (anOwner, aCriterion);
-        myMapOfDetected.Bind (anOwner, theEntityIdx);
+        updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
+        *aPrevCriterion = aCriterion;
       }
     }
   }
+  else
+  {
+    aCriterion.NbOwnerMatches = 1;
+    updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
+    mystored.Add (anOwner, aCriterion);
+  }
+}
+
+//=======================================================================
+// function: computeFrustum
+// purpose : Internal function that checks if a current selecting frustum
+//           needs to be scaled and transformed for the entity and performs
+//           necessary calculations
+//=======================================================================
+void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
+                                               const SelectMgr_SelectingVolumeManager&     theMgr,
+                                               const gp_GTrsf&                             theInvTrsf,
+                                               SelectMgr_FrustumCache&                     theCachedMgrs,
+                                               SelectMgr_SelectingVolumeManager&           theResMgr)
+{
+  Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
+  const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
+  const Standard_Boolean toScale = aScale != 1;
+  const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
+  if (toScale && toTransform)
+  {
+    theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
+  }
+  else if (toScale)
+  {
+    if (!theCachedMgrs.IsBound (aScale))
+    {
+      theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
+    }
+    theResMgr = theCachedMgrs.Find (aScale);
+  }
+  else if (toTransform)
+  {
+    theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
+  }
 }
 
 //=======================================================================
@@ -287,20 +350,53 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
 //           between some entity of selectable object theObject and
 //           current selecting volume
 //=======================================================================
-void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject)
+void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
+                                               const SelectMgr_SelectingVolumeManager& theMgr,
+                                               const Handle(Graphic3d_Camera)& theCamera,
+                                               const Graphic3d_Mat4d& theProjectionMat,
+                                               const Graphic3d_Mat4d& theWorldViewMat,
+                                               const Standard_Integer theViewportWidth,
+                                               const Standard_Integer theViewportHeight)
 {
-  NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
-    myMapOfObjectSensitives.ChangeFind (theObject);
-
+  Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
   if (anEntitySet->Size() == 0)
+  {
     return;
+  }
 
-  const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
+  const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
+  gp_GTrsf aInversedTrsf;
+  if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
+  {
+    if (theObject->TransformPersistence().IsNull())
+    {
+      aInversedTrsf = theObject->InversedTransformation();
+    }
+    else
+    {
+      gp_GTrsf aTPers;
+      Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
+
+      aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
+      aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
+      aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
+      aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
+      aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
+      aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
+      aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
+      aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
+      aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
+      aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
+
+      aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
+    }
+  }
 
-  SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ?
-    mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr;
+  SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
+                                        ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
+                                        : theMgr;
 
-  NCollection_DataMap<Handle(Standard_Type), SelectMgr_SelectingVolumeManager> aScaledTrnsfFrustums;
+  SelectMgr_FrustumCache aScaledTrnsfFrustums;
 
   Standard_Integer aNode = 0; // a root node
   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
@@ -308,14 +404,17 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   {
     return;
   }
-  Standard_Integer aStack[32];
+
+  const Standard_Integer aFirstStored = mystored.Extent() + 1;
+
+  Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
   Standard_Integer aHead = -1;
   for (;;)
   {
     if (!aSensitivesTree->IsOuter (aNode))
     {
-      const Standard_Integer aLeftChildIdx  = aSensitivesTree->LeftChild  (aNode);
-      const Standard_Integer aRightChildIdx = aSensitivesTree->RightChild (aNode);
+      const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
+      const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
       const Standard_Boolean isLeftChildIn  =  aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
       const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
@@ -349,23 +448,13 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
       Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
       {
-        const Handle(SelectMgr_SensitiveEntity)& aSensitive =
-          anEntitySet->GetSensitiveById (anIdx);
+        const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
         if (aSensitive->IsActiveForSelection())
         {
           const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
           SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
-          if (isToScaleFrustum (anEnt))
-          {
-            if (!aScaledTrnsfFrustums.IsBound (anEnt->DynamicType()))
-            {
-              aScaledTrnsfFrustums.Bind (anEnt->DynamicType(),
-                                         scaleAndTransform (anEnt->SensitivityFactor(), theObject->InversedTransformation()));
-            }
-
-            aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType());
-          }
-          checkOverlap (anEnt, anIdx, aTmpMgr);
+          computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
+          checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
         }
       }
       if (aHead < 0)
@@ -377,6 +466,35 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
       --aHead;
     }
   }
+
+  // in case of Box/Polyline selection - keep only Owners having all Entities detected
+  if (mySelectingVolumeMgr.IsOverlapAllowed()
+  || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
+   && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
+  {
+    return;
+  }
+
+  for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
+  {
+    const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
+    const Handle(SelectBasics_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
+    Standard_Integer aNbOwnerEntities = 0;
+    for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
+    {
+      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;
+        }
+      }
+    }
+  }
 }
 
 //=======================================================================
@@ -387,47 +505,129 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
 void SelectMgr_ViewerSelector::TraverseSensitives()
 {
   mystored.Clear();
-  myMapOfDetected.Clear();
-
-  if (mySelectableObjects->Size() == 0)
-    return;
 
-  const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& anObjectsTree = mySelectableObjects->BVH();
-
-  Standard_Integer aNode = 0;
-  if (!mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (0),
-                                      anObjectsTree->MaxPoint (0)))
+  Standard_Integer aWidth;
+  Standard_Integer aHeight;
+  mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
+  mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
+                                 mySelectingVolumeMgr.ProjectionMatrix(),
+                                 mySelectingVolumeMgr.WorldViewMatrix(),
+                                 mySelectingVolumeMgr.WorldViewProjState(),
+                                 aWidth, aHeight);
+  const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
+  if (!aCamera.IsNull())
   {
-    return;
+    myCameraEye = aCamera->Eye().XYZ();
+    myCameraDir = aCamera->Direction().XYZ();
+    myCameraScale = aCamera->IsOrthographic()
+                  ? aCamera->Scale()
+                  : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
+    const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
+    myCameraScale *= aPixelSize;
   }
-  Standard_Integer aStack[32];
-  Standard_Integer aHead = -1;
-  for (;;)
+
+  for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
   {
-    if (!anObjectsTree->IsOuter (aNode))
+    SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
+      static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
+
+    if (mySelectableObjects.IsEmpty (aBVHSubset))
     {
-      const Standard_Integer aLeftChildIdx  = anObjectsTree->LeftChild  (aNode);
-      const Standard_Integer aRightChildIdx = anObjectsTree->RightChild (aNode);
-      const Standard_Boolean isLeftChildIn  =
-        mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aLeftChildIdx),
-                                       anObjectsTree->MaxPoint (aLeftChildIdx));
-      const Standard_Boolean isRightChildIn =
-        mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aRightChildIdx),
-                                       anObjectsTree->MaxPoint (aRightChildIdx));
-      if (isLeftChildIn
-        && isRightChildIn)
-      {
-        aNode = aLeftChildIdx;
-        ++aHead;
-        aStack[aHead] = aRightChildIdx;
-      }
-      else if (isLeftChildIn
-        || isRightChildIn)
+      continue;
+    }
+
+    gp_GTrsf aTFrustum;
+
+    SelectMgr_SelectingVolumeManager aMgr (Standard_False);
+
+    // for 2D space selection transform selecting volumes to perform overap testing
+    // directly in camera's eye space omitting the camera position, which is not
+    // needed there at all
+    if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
+    {
+      const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
+      aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
+      aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
+      aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
+      aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
+      aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
+      aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
+      aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
+      aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
+      aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
+      aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
+
+      // define corresponding frustum builder parameters
+      Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
+      aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
+      aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
+      aBuilder->SetWindowSize (aWidth, aHeight);
+      aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
+    }
+    else
+    {
+      aMgr = mySelectingVolumeMgr;
+    }
+
+    const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
+    const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
+                                            ? mySelectingVolumeMgr.WorldViewMatrix()
+                                            : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
+
+    const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
+
+    Standard_Integer aNode = 0;
+    if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
+    {
+      continue;
+    }
+
+    Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
+    Standard_Integer aHead = -1;
+    for (;;)
+    {
+      if (!aBVHTree->IsOuter (aNode))
       {
-        aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+        const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
+        const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
+        const Standard_Boolean isLeftChildIn  =
+          aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
+        const Standard_Boolean isRightChildIn =
+          aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
+        if (isLeftChildIn
+          && isRightChildIn)
+        {
+          aNode = aLeftChildIdx;
+          ++aHead;
+          aStack[aHead] = aRightChildIdx;
+        }
+        else if (isLeftChildIn
+          || isRightChildIn)
+        {
+          aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+        }
+        else
+        {
+          if (aHead < 0)
+          {
+            break;
+          }
+
+          aNode = aStack[aHead];
+          --aHead;
+        }
       }
       else
       {
+        Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
+        Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
+        for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
+        {
+          const Handle(SelectMgr_SelectableObject)& aSelectableObject =
+            mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
+
+          traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
+        }
         if (aHead < 0)
         {
           break;
@@ -437,27 +637,20 @@ void SelectMgr_ViewerSelector::TraverseSensitives()
         --aHead;
       }
     }
-    else
-    {
-      Standard_Integer aStartIdx = anObjectsTree->BegPrimitive (aNode);
-      Standard_Integer anEndIdx = anObjectsTree->EndPrimitive (aNode);
-      for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
-      {
-        traverseObject (mySelectableObjects->GetObjectById (anIdx));
-      }
-      if (aHead < 0)
-      {
-        break;
-      }
-
-      aNode = aStack[aHead];
-      --aHead;
-    }
   }
 
   SortResult();
 }
 
+//==================================================
+// Function: ClearPicked
+// Purpose :
+//==================================================
+void SelectMgr_ViewerSelector::ClearPicked()
+{
+  mystored.Clear();
+}
+
 //==================================================
 // Function: Picked
 // Purpose :
@@ -467,71 +660,37 @@ Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
 {
   Standard_Integer RankInMap = myIndexes->Value (myCurRank);
   const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
-  Handle(SelectMgr_EntityOwner) Ownr = *((Handle(SelectMgr_EntityOwner)*) &toto);
+  Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
   return Ownr;
 }
 
-
-
 //=======================================================================
-//function : More
+//function : Picked
 //purpose  :
 //=======================================================================
-Standard_Boolean SelectMgr_ViewerSelector::More()
-{
-  if(mystored.Extent()==0) return Standard_False;
-  if(myCurRank==0) return Standard_False;
-  return myCurRank <= myIndexes->Length();
-}
-
-//==================================================
-// Function: OnePicked
-// Purpose : only the best one is chosen
-//           depend on priority and mindist...
-//==================================================
-
-Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
-::OnePicked()
+Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
 {
-
-  Init();
-  if(More()){
-    Standard_Integer RankInMap = myIndexes->Value (myIndexes->Lower());
-    const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
-    Handle(SelectMgr_EntityOwner) Ownr = *((Handle(SelectMgr_EntityOwner)*) &toto);
-    return Ownr;
+  Handle(SelectMgr_EntityOwner) anOwner;
+  if (theRank < 1 || theRank > NbPicked())
+  {
+    return anOwner;
   }
 
-  Handle (SelectMgr_EntityOwner) NullObj; //returns a null Handle if there was not successfull pick...
-  return NullObj;
+  const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
+  const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
+  anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
+  return anOwner;
 }
 
-
 //=======================================================================
-//function : NbPicked
+//function : PickedData
 //purpose  :
 //=======================================================================
-
-Standard_Integer SelectMgr_ViewerSelector::NbPicked() const
+const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
 {
-  return mystored.Extent();
-}
-//=======================================================================
-//function : Picked
-//purpose  :
-//=======================================================================
-Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_Integer aRank) const
-{
-
-  Handle(SelectMgr_EntityOwner) anOwner;
-  if (aRank < 1 || aRank > NbPicked())
-    return anOwner;
-  Standard_Integer anOwnerIdx = myIndexes->Value (aRank);
-
-
-  const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
-  anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
-  return anOwner;
+  Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
+  const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
+  return mystored.FindFromIndex (anOwnerIdx);
 }
 
 //===================================================
@@ -540,13 +699,26 @@ Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_In
 //
 //==================================================
 
+//==================================================
+// Function: SetEntitySetBuilder
+// Purpose :
+//==================================================
+void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
+{
+  myEntitySetBuilder = theBuilder;
+  for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
+  {
+    aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
+  }
+}
+
 //==================================================
 // Function: Contains
 // Purpose :
 //==================================================
 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
 {
-  return mySelectableObjects->Contains (theObject);
+  return mySelectableObjects.Contains (theObject);
 }
 
 //==================================================
@@ -557,17 +729,17 @@ Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_Selecta
                                                   TColStd_ListOfInteger& theModeList,
                                                   const SelectMgr_StateOfSelection theWantedState) const
 {
-  Standard_Boolean hasActivatedStates = mySelectableObjects->Contains (theSelectableObject);
-  for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
+  Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
+  for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
   {
-      if (theWantedState == SelectMgr_SOS_Any)
-      {
-        theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
-      }
-      else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
-      {
-        theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
-      }
+    if (theWantedState == SelectMgr_SOS_Any)
+    {
+      theModeList.Append (aSelIter.Value()->Mode());
+    }
+    else if (theWantedState == aSelIter.Value()->GetSelectionState())
+    {
+      theModeList.Append (aSelIter.Value()->Mode());
+    }
   }
 
   return hasActivatedStates;
@@ -580,18 +752,12 @@ Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_Selecta
 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
                                                      const Standard_Integer theMode) const
 {
-  if (!mySelectableObjects->Contains (theSelectableObject))
+  if (!Contains (theSelectableObject))
     return Standard_False;
 
-  for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
-  {
-    if (theMode == theSelectableObject->CurrentSelection()->Mode())
-    {
-      return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated;
-    }
-  }
-
-  return Standard_False;
+  const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
+  return !aSel.IsNull()
+       && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
 }
 
 //==================================================
@@ -601,18 +767,12 @@ Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_Sele
 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
                                                      const Standard_Integer theMode) const
 {
-  if (!mySelectableObjects->Contains (theSelectableObject))
+  if (!Contains (theSelectableObject))
     return Standard_False;
 
-  for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
-  {
-    if (theMode == theSelectableObject->CurrentSelection()->Mode())
-    {
-      return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
-    }
-  }
-
-  return Standard_False;
+  const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
+  return !aSel.IsNull()
+       && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
 }
 
 
@@ -634,26 +794,16 @@ SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(Select
 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
 {
   TCollection_AsciiString aStatus ("Status Object :\n\t");
-
-  for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
+  for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
   {
-    if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
+    if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
     {
-      aStatus = aStatus + "Mode " +
-        TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
-        " present - ";
-      if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
-      {
-        aStatus = aStatus + " Active \n\t";
-      }
-      else
-      {
-        aStatus = aStatus + " Inactive \n\t";
-      }
+      aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
+              + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
     }
   }
 
-  if (mySelectableObjects->Contains (theSelectableObject))
+  if (!Contains (theSelectableObject))
   {
     aStatus = aStatus + "Not Present in the selector\n\n";
   }
@@ -679,16 +829,12 @@ void SelectMgr_ViewerSelector::SortResult()
   if(myIndexes.IsNull() || anExtent != myIndexes->Length())
     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
 
-  // to work faster...
-  TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
-
-  // indices from 1 to N are loaded
-  Standard_Integer I ;
-  for (I=1; I <= anExtent; I++)
-    thearr(I)=I;
-
-  SortTools_QuickSortOfInteger::Sort (thearr,
-    SelectMgr_CompareResults(mystored));
+  TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
+  for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
+  {
+    anIndexArray.SetValue (anIndexIter, anIndexIter);
+  }
+  std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
 }
 
 //=======================================================================
@@ -708,8 +854,8 @@ void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_Selec
 {
   if (!myMapOfObjectSensitives.IsBound (theObject))
   {
-    mySelectableObjects->Append (theObject);
-    NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
+    mySelectableObjects.Append (theObject);
+    Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
   }
 }
@@ -721,12 +867,10 @@ void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_Selec
 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
                                                      const Handle(SelectMgr_Selection)& theSelection)
 {
-  if (myMapOfObjectSensitives.IsBound (theObject))
+  if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
   {
-    NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
-      myMapOfObjectSensitives.ChangeFind (theObject);
-    anEntitySet->Append (theSelection);
-    anEntitySet->BVH();
+    (*anEntitySet)->Append (theSelection);
+    (*anEntitySet)->BVH();
   }
   else
   {
@@ -735,16 +879,25 @@ void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_Sele
   }
 }
 
+//=======================================================================
+// function : MoveSelectableObject
+// purpose  :
+//=======================================================================
+void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
+{
+  mySelectableObjects.ChangeSubset (theObject);
+}
+
 //=======================================================================
 // function : RemoveSelectableObject
 // purpose  : Removes selectable object from map of selectable ones
 //=======================================================================
 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
 {
-  if (myMapOfObjectSensitives.IsBound (theObject))
+  Handle(SelectMgr_SelectableObject) anObj = theObject;
+  if (myMapOfObjectSensitives.UnBind (theObject))
   {
-    myMapOfObjectSensitives.UnBind (theObject);
-    mySelectableObjects->Remove (theObject);
+    mySelectableObjects.Remove (theObject);
   }
 }
 
@@ -756,11 +909,9 @@ void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_Se
 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
                                                         const Handle(SelectMgr_Selection)& theSelection)
 {
-  if (myMapOfObjectSensitives.IsBound (theObject))
+  if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
   {
-    NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
-      myMapOfObjectSensitives.ChangeFind (theObject);
-    anEntitySet->Remove (theSelection);
+    (*anEntitySet)->Remove (theSelection);
   }
 }
 
@@ -770,11 +921,21 @@ void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_S
 //=======================================================================
 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
 {
-  mySelectableObjects->MarkDirty();
+  mySelectableObjects.MarkDirty();
 
   if (theIsForce)
   {
-    mySelectableObjects->BVH();
+    Standard_Integer aViewportWidth, aViewportHeight;
+    mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
+
+    Standard_Integer aWidth;
+    Standard_Integer aHeight;
+    mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
+    mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
+                                   mySelectingVolumeMgr.ProjectionMatrix(),
+                                   mySelectingVolumeMgr.WorldViewMatrix(),
+                                   mySelectingVolumeMgr.WorldViewProjState(),
+                                   aWidth, aHeight);
   }
 }
 
@@ -786,10 +947,10 @@ void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsF
 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
                                                       const Standard_Boolean theIsForce)
 {
-  if (!mySelectableObjects->Contains (theObject))
+  if (!Contains (theObject))
     return;
 
-  NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
+  Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
   anEntitySet->MarkDirty();
 
   if (theIsForce)
@@ -803,14 +964,12 @@ void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_Sel
 // purpose  : Marks all added sensitive entities of all objects as
 //            non-selectable
 //=======================================================================
-void SelectMgr_ViewerSelector::resetSelectionActivationStatus()
+void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
 {
-  SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
-  for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
+  for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
   {
-    NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
-      aSensitivesIter.ChangeValue();
-    Standard_Integer anEntitiesNb = anEntitySet->Size();
+    Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
+    const Standard_Integer anEntitiesNb = anEntitySet->Size();
     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
     {
       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
@@ -825,12 +984,8 @@ void SelectMgr_ViewerSelector::resetSelectionActivationStatus()
 //=======================================================================
 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
 {
-  const Handle(SelectMgr_EntityOwner)& anOwner = myDetectedIter.Key();
-  const Handle(SelectMgr_SelectableObject)& anObject = anOwner->Selectable();
-  const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
-    myMapOfObjectSensitives.Find (anObject);
-
-  return anEntitySet->GetSensitiveById (myDetectedIter.Value())->BaseSensitive();
+  const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
+  return mystored.FindFromIndex (aRankInMap).Entity;
 }
 
 //=======================================================================
@@ -841,14 +996,27 @@ void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasic
 {
   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
   {
-    const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
-    Standard_Integer anEntitiesNb = anEntitySet->Size();
+    const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
+    const Standard_Integer anEntitiesNb = anEntitySet->Size();
     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
     {
-      if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
+      const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
+      if (aSensitive->IsActiveForSelection())
       {
-        theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
+        theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
       }
     }
   }
 }
+
+//=======================================================================
+//function : AllowOverlapDetection
+//purpose  : Sets the detection type: if theIsToAllow is false,
+//           only fully included sensitives will be detected, otherwise
+//           the algorithm will mark both included and overlapped entities
+//           as matched
+//=======================================================================
+void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
+{
+  mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
+}