0026641: Visualization, TKOpenGl - handle correctly transformation persistence within...
[occt.git] / src / SelectMgr / SelectMgr_ViewerSelector.cxx
index 9190f3b..9bb2816 100644 (file)
 //              AGV OCT/23/03 : Optimize the method SortResult() (OCC4201)
 
 #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>
 
-IMPLEMENT_STANDARD_HANDLE (SelectMgr_ViewerSelector, MMgt_TShared)
-IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, MMgt_TShared)
+#include <algorithm>
 
-static Standard_Boolean SelectDebugModeOnVS()
-{
-  static Standard_Integer isDebugMode( -1 );
-  if ( isDebugMode < 0 ) {
-    isDebugMode = 1;
-    OSD_Environment selectdb("SELDEBUGMODE");
-    if ( selectdb.Value().IsEmpty() )
-      isDebugMode = 0;
-  }
-  return ( isDebugMode != 0 );
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector,MMgt_TShared)
+
+namespace {
+  // Comparison operator for sorting selection results
+  class CompareResults
+  {
+  public:
+   
+    CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
+      : myMapOfCriterion (aMapOfCriterion)
+    {
+    }
+
+    Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
+    {
+      return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
+    }
+
+  private:
+    void operator = (const CompareResults&);
+
+  private:
+    const SelectMgr_IndexedDataMapOfOwnerCriterion&  myMapOfCriterion;
+  };
 }
 
+//=======================================================================
+// function: SelectMgr_ToleranceMap
+// purpose : Sets tolerance values to -1.0
+//=======================================================================
 SelectMgr_ToleranceMap::SelectMgr_ToleranceMap()
 {
   myLargestKey = -1;
+  myCustomTolerance = -1;
 }
 
+//=======================================================================
+// function: ~SelectMgr_ToleranceMap
+// purpose :
+//=======================================================================
 SelectMgr_ToleranceMap::~SelectMgr_ToleranceMap()
 {
   myTolerances.Clear();
 }
 
-void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
+//=======================================================================
+// 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_Integer& theTolerance)
 {
   if (myTolerances.IsBound (theTolerance))
   {
     Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
     aFreq++;
 
-    if (theTolerance == myLargestKey)
-      return;
-
-    Standard_Integer aMaxFreq = myTolerances.Find (myLargestKey);
-    if (aFreq >= aMaxFreq)
-    {
-      myLargestKey = aFreq == aMaxFreq ? Max (myLargestKey, theTolerance) : theTolerance;
-    }
+    if (aFreq == 1 && theTolerance != myLargestKey)
+      myLargestKey = Max (theTolerance, myLargestKey);
   }
   else
   {
@@ -87,57 +107,47 @@ void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
     }
 
     myTolerances.Bind (theTolerance, 1);
-    Standard_Integer aMaxFreq = myTolerances.Find (myLargestKey);
-    if (aMaxFreq <= 1)
-    {
-      myLargestKey = aMaxFreq == 1 ? Max (myLargestKey, theTolerance) : theTolerance;
-    }
+    myLargestKey = Max (theTolerance, myLargestKey);
   }
 }
 
-void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
+//=======================================================================
+// function: Decrement
+// purpose : Decrements a counter of the tolerance given, checks if the current tolerance value
+//           should be recalculated
+//=======================================================================
+void SelectMgr_ToleranceMap::Decrement (const Standard_Integer& theTolerance)
 {
   if (myTolerances.IsBound (theTolerance))
   {
     Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
     aFreq--;
 
-    if (theTolerance == myLargestKey)
+    if (Abs (theTolerance - myLargestKey) < Precision::Confusion() && aFreq == 0)
     {
-      Standard_Integer aMaxFreq = aFreq;
-      for (NCollection_DataMap<Standard_Real, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
+      myLargestKey = 0;
+      for (NCollection_DataMap<Standard_Integer, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
       {
-        if (aMaxFreq <= anIter.Value() && myLargestKey != anIter.Key())
-        {
-          aMaxFreq = anIter.Value();
-          myLargestKey = anIter.Key();
-        }
+        if (anIter.Value() != 0)
+          myLargestKey = Max (myLargestKey, anIter.Key());
       }
     }
   }
 }
 
-const Standard_Real SelectMgr_ToleranceMap::Largest()
-{
-  return myLargestKey;
-}
-
 //==================================================
 // Function: Initialize
 // Purpose :
 //==================================================
 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
 preferclosest(Standard_True),
-mytolerance(2.0),
 myToUpdateTolerance (Standard_True),
 myCurRank (0),
 myIsLeftChildQueuedFirst (Standard_False),
 myEntityIdx (0)
 {
-  mySelectableObjects = new SelectMgr_SelectableObjectSet();
 }
 
-
 //==================================================
 // Function: Activate
 // Purpose :
@@ -152,11 +162,9 @@ void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theS
   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
 
   myTolerances.Add (theSelection->Sensitivity());
-  mytolerance = myTolerances.Largest();
   myToUpdateTolerance = Standard_True;
 }
 
-
 //==================================================
 // Function: Deactivate
 // Purpose :
@@ -171,7 +179,6 @@ void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& th
   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
 
   myTolerances.Decrement (theSelection->Sensitivity());
-  mytolerance = myTolerances.Largest();
   myToUpdateTolerance = Standard_True;
 }
 
@@ -185,6 +192,27 @@ void SelectMgr_ViewerSelector::Clear()
   myMapOfDetected.Clear();
 }
 
+//=======================================================================
+// function: isToScaleFrustum
+// purpose : Checks if the entity given requires to scale current selecting frustum
+//=======================================================================
+Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
+{
+  return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
+    && sensitivity (theEntity) < myTolerances.Tolerance();
+}
+
+//=======================================================================
+// function: sensitivity
+// purpose : In case if custom tolerance is set, this method will return sum of entity
+//           sensitivity and custom tolerance.
+//=======================================================================
+Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
+{
+  return myTolerances.IsCustomTolSet() ?
+    theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
+}
+
 //=======================================================================
 // function: checkOverlap
 // purpose : Internal function that checks if a particular sensitive
@@ -194,27 +222,24 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
                                              const Standard_Integer theEntityIdx,
                                              SelectMgr_SelectingVolumeManager& theMgr)
 {
-  const Handle(SelectMgr_EntityOwner)& anOwner =
-    Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId());
+  Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
 
   SelectBasics_PickResult aPickResult;
   if (theEntity->Matches (theMgr, aPickResult))
   {
     if (!anOwner.IsNull())
     {
-      Standard_Boolean isPointSelection =
-        theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point;
-      if (HasDepthClipping (anOwner) && isPointSelection)
+      if (HasDepthClipping (anOwner) && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
       {
-        Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
-                                                       aPickResult.Depth());
+        Standard_Boolean isClipped = mySelectingVolumeMgr.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);
+      SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33.0, preferclosest);
       if (mystored.Contains (anOwner))
       {
         if (theMgr.GetActiveSelectionType() != 1)
@@ -236,6 +261,39 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
   }
 }
 
+//=======================================================================
+// 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 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 = mySelectingVolumeMgr.ScaleAndTransform (aScale, aTrsfMtr);
+  }
+  else if (toScale)
+  {
+    if (!theCachedMgrs.IsBound (aScale))
+    {
+      theCachedMgrs.Bind (aScale, mySelectingVolumeMgr.ScaleAndTransform (aScale, gp_Trsf()));
+    }
+    theResMgr = theCachedMgrs.Find (aScale);
+  }
+  else if (toTransform)
+  {
+    theResMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTrsfMtr);
+  }
+}
+
 //=======================================================================
 // function: traverseObject
 // purpose : Internal function that checks if there is possible overlap
@@ -252,8 +310,45 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
 
   const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
 
-  SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ?
-    mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr;
+  gp_GTrsf aInversedTrsf;
+
+  if (theObject->HasTransformation() || theObject->TransformPersistence().Flags)
+  {
+    if (!theObject->TransformPersistence().Flags)
+    {
+      aInversedTrsf = theObject->InversedTransformation();
+    }
+    else
+    {
+      const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix();
+      const Graphic3d_Mat4d& aWorldView  = mySelectingVolumeMgr.WorldViewMatrix();
+
+      Standard_Integer aViewportWidth;
+      Standard_Integer aViewportHeight;
+      mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
+
+      gp_GTrsf aTPers;
+      Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (aProjection, aWorldView, aViewportWidth, aViewportHeight);
+      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 = aInversedTrsf.Form() != gp_Identity
+                                        ? mySelectingVolumeMgr.ScaleAndTransform (1, aInversedTrsf)
+                                        : mySelectingVolumeMgr;
+
+  SelectMgr_FrustumCache aScaledTrnsfFrustums;
 
   Standard_Integer aNode = 0; // a root node
   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
@@ -267,8 +362,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   {
     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),
@@ -302,11 +397,14 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
       Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
       {
-        const SelectMgr_HSensitiveEntity& aSensitive =
+        const Handle(SelectMgr_SensitiveEntity)& aSensitive =
           anEntitySet->GetSensitiveById (anIdx);
         if (aSensitive->IsActiveForSelection())
         {
-          checkOverlap (aSensitive->BaseSensitive(), anIdx, aMgr);
+          const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
+          SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
+          computeFrustum (anEnt, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
+          checkOverlap (anEnt, anIdx, aTmpMgr);
         }
       }
       if (aHead < 0)
@@ -330,45 +428,89 @@ 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)))
+  NCollection_Handle<BVH_Tree<Standard_Real, 3> > aBVHTree;
+  for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
   {
-    return;
-  }
-  Standard_Integer aStack[32];
-  Standard_Integer aHead = -1;
-  for (;;)
-  {
-    if (!anObjectsTree->IsOuter (aNode))
+    const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
+    if (isTrsfPers)
     {
-      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)
+      if (mySelectableObjectsTrsfPers.Size() == 0)
       {
-        aNode = aLeftChildIdx;
-        ++aHead;
-        aStack[aHead] = aRightChildIdx;
+        continue;
       }
-      else if (isLeftChildIn
-        || isRightChildIn)
+      const Graphic3d_Mat4d& aProjection            = mySelectingVolumeMgr.ProjectionMatrix();
+      const Graphic3d_Mat4d& aWorldView             = mySelectingVolumeMgr.WorldViewMatrix();
+      const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState();
+      Standard_Integer aViewportWidth;
+      Standard_Integer aViewportHeight;
+      mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
+      aBVHTree = mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState);
+    }
+    else
+    {
+      if (mySelectableObjects.Size() == 0)
       {
-        aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+        continue;
+      }
+      aBVHTree = mySelectableObjects.BVH();
+    }
+
+    Standard_Integer aNode = 0;
+    if (!mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (0),
+                                        aBVHTree->MaxPoint (0)))
+    {
+      continue;
+    }
+
+    Standard_Integer aStack[32];
+    Standard_Integer aHead = -1;
+    for (;;)
+    {
+      if (!aBVHTree->IsOuter (aNode))
+      {
+        const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
+        const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
+        const Standard_Boolean isLeftChildIn  =
+          mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
+                                         aBVHTree->MaxPoint (aLeftChildIdx));
+        const Standard_Boolean isRightChildIn =
+          mySelectingVolumeMgr.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)
+        {
+          Handle(SelectMgr_SelectableObject) aSelectableObject =
+            isTrsfPers ? mySelectableObjectsTrsfPers.GetObjectById (anIdx)
+                       : mySelectableObjects.GetObjectById (anIdx);
+
+          traverseObject (aSelectableObject);
+        }
         if (aHead < 0)
         {
           break;
@@ -378,39 +520,9 @@ 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();
-
-  if (SelectDebugModeOnVS())
-  {
-    cout<<"\tSelectMgr_VS:: Resultat du move"<<endl;
-    cout<<"\tNb Detectes :"<<mystored.Extent()<<endl;
-
-    for(Standard_Integer i=1; i<=mystored.Extent(); i++)
-    {
-      const SelectMgr_SortCriterion& Crit = mystored (myIndexes->Value(i));
-      cout << "\t" << i << " - Prior" << Crit.Priority()
-           << " - prof :" << Crit.Depth()
-           << "  - Dist. :" << Crit.MinDist() << endl;
-    }
-  }
 }
 
 //==================================================
@@ -422,7 +534,7 @@ 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;
 }
 
@@ -453,7 +565,7 @@ Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
   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);
+    Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
     return Ownr;
   }
 
@@ -501,7 +613,8 @@ Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_In
 //==================================================
 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
 {
-  return mySelectableObjects->Contains (theObject);
+  return mySelectableObjects.Contains (theObject)
+      || mySelectableObjectsTrsfPers.Contains (theObject);
 }
 
 //==================================================
@@ -512,7 +625,7 @@ Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_Selecta
                                                   TColStd_ListOfInteger& theModeList,
                                                   const SelectMgr_StateOfSelection theWantedState) const
 {
-  Standard_Boolean hasActivatedStates = mySelectableObjects->Contains (theSelectableObject);
+  Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
   {
       if (theWantedState == SelectMgr_SOS_Any)
@@ -535,7 +648,7 @@ 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())
@@ -556,7 +669,7 @@ 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())
@@ -608,7 +721,7 @@ TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr
     }
   }
 
-  if (mySelectableObjects->Contains (theSelectableObject))
+  if (!Contains (theSelectableObject))
   {
     aStatus = aStatus + "Not Present in the selector\n\n";
   }
@@ -642,8 +755,8 @@ void SelectMgr_ViewerSelector::SortResult()
   for (I=1; I <= anExtent; I++)
     thearr(I)=I;
 
-  SortTools_QuickSortOfInteger::Sort (thearr,
-    SelectMgr_CompareResults(mystored));
+  std::sort (thearr.begin(), thearr.end(), CompareResults (mystored));
+
 }
 
 //=======================================================================
@@ -663,7 +776,15 @@ void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_Selec
 {
   if (!myMapOfObjectSensitives.IsBound (theObject))
   {
-    mySelectableObjects->Append (theObject);
+    if (!theObject->TransformPersistence().Flags)
+    {
+      mySelectableObjects.Append (theObject);
+    }
+    else
+    {
+      mySelectableObjectsTrsfPers.Append (theObject);
+    }
+
     NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
   }
@@ -690,6 +811,27 @@ void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_Sele
   }
 }
 
+//=======================================================================
+// function : MoveSelectableObject
+// purpose  :
+//=======================================================================
+void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
+{
+  if (!mySelectableObjects.Remove (theObject))
+  {
+    mySelectableObjectsTrsfPers.Remove (theObject);
+  }
+
+  if (!theObject->TransformPersistence().Flags)
+  {
+    mySelectableObjects.Append (theObject);
+  }
+  else
+  {
+    mySelectableObjectsTrsfPers.Append (theObject);
+  }
+}
+
 //=======================================================================
 // function : RemoveSelectableObject
 // purpose  : Removes selectable object from map of selectable ones
@@ -698,8 +840,11 @@ void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_Se
 {
   if (myMapOfObjectSensitives.IsBound (theObject))
   {
+    if (!mySelectableObjects.Remove (theObject))
+    {
+      mySelectableObjectsTrsfPers.Remove (theObject);
+    }
     myMapOfObjectSensitives.UnBind (theObject);
-    mySelectableObjects->Remove (theObject);
   }
 }
 
@@ -725,11 +870,20 @@ void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_S
 //=======================================================================
 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
 {
-  mySelectableObjects->MarkDirty();
+  mySelectableObjects.MarkDirty();
+  mySelectableObjectsTrsfPers.MarkDirty();
 
   if (theIsForce)
   {
-    mySelectableObjects->BVH();
+    const Graphic3d_Mat4d& aProjection            = mySelectingVolumeMgr.ProjectionMatrix();
+    const Graphic3d_Mat4d& aWorldView             = mySelectingVolumeMgr.WorldViewMatrix();
+    const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState();
+    Standard_Integer aViewportWidth;
+    Standard_Integer aViewportHeight;
+    mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
+
+    mySelectableObjects.BVH();
+    mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState);
   }
 }
 
@@ -741,7 +895,7 @@ 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);
@@ -758,7 +912,7 @@ 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())
@@ -792,9 +946,8 @@ const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEn
 // function : ActiveOwners
 // purpose  : Returns the list of active entity owners
 //=======================================================================
-NCollection_List<Handle(SelectBasics_EntityOwner)> SelectMgr_ViewerSelector::ActiveOwners() const
+void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
 {
-  NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
   {
     const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
@@ -803,10 +956,20 @@ NCollection_List<Handle(SelectBasics_EntityOwner)> SelectMgr_ViewerSelector::Act
     {
       if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
       {
-        anActiveOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
+        theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
       }
     }
   }
+}
 
-  return anActiveOwners;
+//=======================================================================
+//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);
 }