diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx
index ba42fb6f8a..35aada5f86 100644
--- a/src/AIS/AIS_InteractiveContext.cxx
+++ b/src/AIS/AIS_InteractiveContext.cxx
@@ -2983,10 +2983,11 @@ AIS_StatusOfPick AIS_InteractiveContext::SelectDetected (const AIS_SelectionSche
   if (theSelScheme == AIS_SelectionScheme_Replace && !myLastPicked.IsNull())
   {
     Graphic3d_Vec2i aMousePos (-1, -1);
-    if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
+    gp_Pnt2d aMouseRealPos = myMainSel->GetManager().GetMousePosition();
+    if (!Precision::IsInfinite (aMouseRealPos.X()) &&
+        !Precision::IsInfinite (aMouseRealPos.Y()))
     {
-      aMousePos.SetValues ((Standard_Integer )myMainSel->GetManager().GetMousePosition().X(),
-                           (Standard_Integer )myMainSel->GetManager().GetMousePosition().Y());
+      aMousePos.SetValues ((Standard_Integer )aMouseRealPos.X(), (Standard_Integer )aMouseRealPos.Y());
     }
     if (myLastPicked->HandleMouseClick (aMousePos, Aspect_VKeyMouse_LeftButton, Aspect_VKeyFlags_NONE, false))
     {
diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx
index 7ff3327b1a..99a003e93b 100644
--- a/src/AIS/AIS_Manipulator.cxx
+++ b/src/AIS/AIS_Manipulator.cxx
@@ -64,12 +64,12 @@ namespace
     //! Checks if picking ray can be used for detection.
     Standard_Boolean isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
     {
-      if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+      if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
       {
         return Standard_False;
       }
 
-      const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt());
+      const gp_Dir aRay = theMgr.GetViewRayDirection();
       return !aRay.IsNormal (myPlaneNormal, myAngleTol);
     }
   private:
diff --git a/src/AIS/AIS_ViewCube.cxx b/src/AIS/AIS_ViewCube.cxx
index a1719c6d61..756f6226a3 100644
--- a/src/AIS/AIS_ViewCube.cxx
+++ b/src/AIS/AIS_ViewCube.cxx
@@ -80,7 +80,7 @@ public:
   //! Checks if picking ray can be used for detection.
   bool isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
   {
-    if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+    if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
     {
       // disallow rectangular selection
       return false;
@@ -89,7 +89,7 @@ public:
     if (AIS_ViewCubeOwner* anOwner = dynamic_cast<AIS_ViewCubeOwner* >(myOwnerId.get()))
     {
       const Standard_Real anAngleToler = 10.0 * M_PI / 180.0;
-      const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt());
+      const gp_Dir aRay = theMgr.GetViewRayDirection();
       const gp_Dir aDir = V3d::GetProjAxis (anOwner->MainOrientation());
       return !aRay.IsNormal (aDir, anAngleToler);
     }
diff --git a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
index cecbca2a78..982a12ddc1 100644
--- a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
+++ b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
@@ -48,6 +48,10 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix,
                                    const Standard_Integer theYPix,
                                    const IVtk_IView::Handle&    theView)
 {
+  gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
+                      static_cast<Standard_Real> (theYPix));
+  mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos);
+
   if (myToUpdateTol)
   {
     // Compute and set a sensitivity tolerance according to the renderer (viewport).
@@ -65,7 +69,6 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix,
   Standard_Real aX = RealLast(), aY = RealLast();
   Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast();
 
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point);
   theView->GetCamera (aProj, anOrient, isOrthographic);
   mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic);
 
@@ -75,9 +78,7 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix,
   theView->GetViewport (aX, aY, aVpWidth, aVpHeight);
   mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight);
 
-  gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
-                      static_cast<Standard_Real> (theYPix));
-  mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
+  mySelectingVolumeMgr.BuildSelectingVolume();
 
   TraverseSensitives();
 }
@@ -92,6 +93,13 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer    theXMin,
                                    const Standard_Integer    theYMax,
                                    const IVtk_IView::Handle& theView)
 {
+  gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXMin),
+                         static_cast<Standard_Real> (theYMin));
+  gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXMax),
+                         static_cast<Standard_Real> (theYMax));
+  mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos,
+                                               aMaxMousePos);
+
   if (myToUpdateTol)
   {
     // Compute and set a sensitivity tolerance according to the renderer (viewport).
@@ -109,7 +117,6 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer    theXMin,
   Standard_Real aX = RealLast(), aY = RealLast();
   Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast();
 
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box);
   theView->GetCamera (aProj, anOrient, isOrthographic);
   mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic);
 
@@ -119,13 +126,7 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer    theXMin,
   theView->GetViewport (aX, aY, aVpWidth, aVpHeight);
   mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight);
 
-  gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXMin),
-                         static_cast<Standard_Real> (theYMin));
-  gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXMax),
-                         static_cast<Standard_Real> (theYMax));
-
-  mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos,
-                                             aMaxMousePos);
+  mySelectingVolumeMgr.BuildSelectingVolume();
 
   TraverseSensitives();
 }
@@ -138,7 +139,15 @@ void IVtkOCC_ViewerSelector::Pick (double**                  thePoly,
                                    const int                 theNbPoints,
                                    const IVtk_IView::Handle& theView)
 {
+  // Build TColgp_Array1OfPnt2d from input array of doubles
   TColgp_Array1OfPnt2d aPolyline (1, theNbPoints);
+  for (Standard_Integer anIt = 0; anIt < theNbPoints; anIt++)
+  {
+    gp_XY aDispPnt = thePoly[anIt][2] != 0 ? gp_XY (thePoly[anIt][0] / thePoly[anIt][2], thePoly[anIt][1] / thePoly[anIt][2])
+                                           : gp_XY (thePoly[anIt][0], thePoly[anIt][1]);
+    aPolyline.SetValue (anIt + 1, aDispPnt);
+  }
+  mySelectingVolumeMgr.InitPolylineSelectingVolume (aPolyline);
 
   if (myToUpdateTol)
   {
@@ -151,23 +160,12 @@ void IVtkOCC_ViewerSelector::Pick (double**                  thePoly,
     myToUpdateTol = Standard_False;
   }
 
-  // Build TColgp_Array1OfPnt2d from input array of doubles
-  gp_XYZ aWorldPnt;
-
-  for (Standard_Integer anIt = 0; anIt < theNbPoints; anIt++)
-  {
-    gp_XY aDispPnt = thePoly[anIt][2] != 0 ? gp_XY (thePoly[anIt][0] / thePoly[anIt][2], thePoly[anIt][1] / thePoly[anIt][2])
-                                           : gp_XY (thePoly[anIt][0], thePoly[anIt][1]);
-    aPolyline.SetValue (anIt + 1, aDispPnt);
-  }
-
   Standard_Integer aWidth = 0, aHeight = 0;
   Graphic3d_Mat4d aProj, anOrient;
   Standard_Boolean isOrthographic = Standard_False;
   Standard_Real aX = RealLast(), aY = RealLast();
   Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast();
 
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline);
   theView->GetCamera (aProj, anOrient, isOrthographic);
   mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic);
 
@@ -177,7 +175,7 @@ void IVtkOCC_ViewerSelector::Pick (double**                  thePoly,
   theView->GetViewport (aX, aY, aVpWidth, aVpHeight);
   mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight);
 
-  mySelectingVolumeMgr.BuildSelectingVolume (aPolyline);
+  mySelectingVolumeMgr.BuildSelectingVolume();
 
   TraverseSensitives();
 }
diff --git a/src/MeshVS/MeshVS_SensitiveQuad.cxx b/src/MeshVS/MeshVS_SensitiveQuad.cxx
index e12f3f70ce..860e50986d 100644
--- a/src/MeshVS/MeshVS_SensitiveQuad.cxx
+++ b/src/MeshVS/MeshVS_SensitiveQuad.cxx
@@ -67,7 +67,7 @@ Standard_Boolean MeshVS_SensitiveQuad::Matches (SelectBasics_SelectingVolumeMana
 {
   if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
-    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
     {
       SelectBasics_PickResult aDummy;
       return theMgr.Overlaps (myVertices[0], myVertices[1], myVertices[2], Select3D_TOS_INTERIOR, aDummy)
diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx
index 5376508176..cf168485bd 100644
--- a/src/QABugs/QABugs_19.cxx
+++ b/src/QABugs/QABugs_19.cxx
@@ -4145,24 +4145,22 @@ static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theA
   }
 
   SelectMgr_SelectingVolumeManager* aMgr = new SelectMgr_SelectingVolumeManager();
-  aMgr->SetActiveSelectionType (theArgNb > 4 ?
-    SelectMgr_SelectingVolumeManager::Box : SelectMgr_SelectingVolumeManager::Point);
+  if (theArgNb > 4)
+  {
+    aMgr->InitBoxSelectingVolume (aPxPnt1, aPxPnt2);
+  }
+  else
+  {
+    aMgr->InitPointSelectingVolume (aPxPnt1);
+  }
   aMgr->SetCamera (ViewerTest::CurrentView()->Camera());
   aMgr->SetPixelTolerance (ViewerTest::GetAISContext()->PixelTolerance());
   Standard_Integer aWidth, aHeight;
   ViewerTest::CurrentView()->View()->Window()->Size (aWidth, aHeight);
   aMgr->SetWindowSize (aWidth, aHeight);
-  if (theArgNb > 4)
-  {
-    aMgr->BuildSelectingVolume (aPxPnt1, aPxPnt2);
-  }
-  else
-  {
-    aMgr->BuildSelectingVolume (aPxPnt1);
-  }
+  aMgr->BuildSelectingVolume();
+
   const gp_Pnt* aVerts = aMgr->GetVertices();
-  gp_Pnt aNearPnt = aMgr->GetNearPickedPnt();
-  gp_Pnt aFarPnt  = aMgr->GetFarPickedPnt();
   BRepBuilderAPI_MakePolygon aWireBldrs[4];
 
   aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z()));
@@ -4202,6 +4200,17 @@ static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theA
   aCmp->SetColor (Quantity_NOC_GREEN);
   ViewerTest::Display ("c", aCmp, Standard_True, Standard_True);
 
+  gp_Pnt aNearPnt = aMgr->GetNearPickedPnt();
+  gp_Pnt aFarPnt = aMgr->GetFarPickedPnt();
+  if (Precision::IsInfinite (aFarPnt.X()) ||
+      Precision::IsInfinite (aFarPnt.Y()) ||
+      Precision::IsInfinite (aFarPnt.Z()))
+  {
+    theDI << "Near: " << aNearPnt.X() << " " << aNearPnt.Y() << " " << aNearPnt.Z() << "\n";
+    theDI << "Far: infinite point " << "\n";
+    return 0;
+  }
+
   Handle(Geom_CartesianPoint) aPnt1 = new Geom_CartesianPoint (aNearPnt);
   Handle(Geom_CartesianPoint) aPnt2 = new Geom_CartesianPoint (aFarPnt);
 
diff --git a/src/Select3D/Select3D_SensitiveCircle.cxx b/src/Select3D/Select3D_SensitiveCircle.cxx
index df02327e56..fca5dfbfd0 100644
--- a/src/Select3D/Select3D_SensitiveCircle.cxx
+++ b/src/Select3D/Select3D_SensitiveCircle.cxx
@@ -225,7 +225,7 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
     Points3D (anArrayOfPnt);
     if (!theMgr.IsOverlapAllowed())
     {
-      if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+      if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
       {
         SelectBasics_PickResult aDummy;
         return theMgr.Overlaps (anArrayOfPnt, mySensType, aDummy);
diff --git a/src/Select3D/Select3D_SensitiveGroup.cxx b/src/Select3D/Select3D_SensitiveGroup.cxx
index a89fd931bf..e35ffac63f 100644
--- a/src/Select3D/Select3D_SensitiveGroup.cxx
+++ b/src/Select3D/Select3D_SensitiveGroup.cxx
@@ -193,9 +193,9 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
 Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                    SelectBasics_PickResult& thePickResult)
 {
-  const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+  const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point
                                    && myMustMatchAll;
-  const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+  const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point
                                    && myToCheckOverlapAll;
   if (!toMatchAll && !toCheckAll)
   {
diff --git a/src/Select3D/Select3D_SensitivePoly.cxx b/src/Select3D/Select3D_SensitivePoly.cxx
index d582fef161..ebce929629 100644
--- a/src/Select3D/Select3D_SensitivePoly.cxx
+++ b/src/Select3D/Select3D_SensitivePoly.cxx
@@ -254,7 +254,7 @@ Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_Selecting
   }
 
   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
-  if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+  if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
   {
     SelectBasics_PickResult aDummy;
     return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), myPolyg.Pnt3d (aSegmentIdx + 1), aDummy);
diff --git a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx
index 00939c5c07..7da9ba350e 100644
--- a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx
+++ b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx
@@ -891,7 +891,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_Selecti
   myDetectedEdgeNode2 = -1;
   const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull();
   if (myGroups.IsNull()
-   || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point
+   || theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Point
    || !toDetectRange)
   {
     if (!matches (theMgr, thePickResult, toDetectRange))
@@ -995,7 +995,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
               myDetectedElem = myDetectedNode = aPointIndex;
               myMinDepthElem = myMinDepthNode = aPickResult.Depth();
             }
-            if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+            if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
             {
               if (!myDetectedElemMap.IsNull())
               {
@@ -1046,7 +1046,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
             }
             aResult = Standard_True;
             if (!myDetectedElemMap.IsNull()
-              && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+              && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
             {
               myDetectedElemMap->ChangeMap().Add(aTriIndex);
             }
@@ -1064,7 +1064,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
                 myMinDepthNode = aPickResult.Depth();
               }
               if (!myDetectedNodeMap.IsNull()
-                && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+                && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
               {
                 myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
               }
@@ -1152,7 +1152,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
           return Standard_False;
         }
 
-        if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+        if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
         {
           if (!myDetectedElemMap.IsNull())
           {
@@ -1195,7 +1195,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
           return Standard_False;
         }
 
-        if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+        if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
         {
           if (!myDetectedElemMap.IsNull())
           {
diff --git a/src/Select3D/Select3D_SensitiveSegment.cxx b/src/Select3D/Select3D_SensitiveSegment.cxx
index c402199ce9..8726d9d943 100644
--- a/src/Select3D/Select3D_SensitiveSegment.cxx
+++ b/src/Select3D/Select3D_SensitiveSegment.cxx
@@ -45,7 +45,7 @@ Standard_Boolean Select3D_SensitiveSegment::Matches (SelectBasics_SelectingVolum
 {
   if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
-    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
     {
       return theMgr.Overlaps (myStart, myEnd, thePickResult);
     }
diff --git a/src/Select3D/Select3D_SensitiveSet.cxx b/src/Select3D/Select3D_SensitiveSet.cxx
index 3c2b460b1f..d19b216dfd 100644
--- a/src/Select3D/Select3D_SensitiveSet.cxx
+++ b/src/Select3D/Select3D_SensitiveSet.cxx
@@ -150,7 +150,7 @@ Standard_Boolean Select3D_SensitiveSet::matches (SelectBasics_SelectingVolumeMan
 
   Standard_Integer aMatchesNb = -1;
 
-  const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point);
+  const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point);
   if (toCheckFullInside && isFullInside)
   {
     Standard_Integer aSize = myContent.Size();
diff --git a/src/Select3D/Select3D_SensitiveTriangle.cxx b/src/Select3D/Select3D_SensitiveTriangle.cxx
index 47291ad68a..f16c2dfb99 100644
--- a/src/Select3D/Select3D_SensitiveTriangle.cxx
+++ b/src/Select3D/Select3D_SensitiveTriangle.cxx
@@ -50,7 +50,7 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
 {
   if (!theMgr.IsOverlapAllowed())
   {
-    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
     {
       SelectBasics_PickResult aDummy;
       return theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDummy);
diff --git a/src/Select3D/Select3D_SensitiveTriangulation.cxx b/src/Select3D/Select3D_SensitiveTriangulation.cxx
index 7e2ddfb4f5..f7bbfa61a2 100644
--- a/src/Select3D/Select3D_SensitiveTriangulation.cxx
+++ b/src/Select3D/Select3D_SensitiveTriangulation.cxx
@@ -388,7 +388,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
   {
     const gp_Pnt aSegmPnt1 = myTriangul->Node (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
     const gp_Pnt aSegmPnt2 = myTriangul->Node (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
-    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
     {
       SelectBasics_PickResult aDummy;
       return theMgr.Overlaps (aSegmPnt1, aSegmPnt2, aDummy);
@@ -403,7 +403,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
     const gp_Pnt aPnt1 = myTriangul->Node (aNode1);
     const gp_Pnt aPnt2 = myTriangul->Node (aNode2);
     const gp_Pnt aPnt3 = myTriangul->Node (aNode3);
-    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
     {
       SelectBasics_PickResult aDummy;
       return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDummy);
diff --git a/src/Select3D/Select3D_SensitiveTriangulation.hxx b/src/Select3D/Select3D_SensitiveTriangulation.hxx
index dbc8871396..17f5bab650 100644
--- a/src/Select3D/Select3D_SensitiveTriangulation.hxx
+++ b/src/Select3D/Select3D_SensitiveTriangulation.hxx
@@ -25,6 +25,7 @@
 #include <SelectMgr_SelectingVolumeManager.hxx>
 #include <Select3D_SensitiveSet.hxx>
 
+class Poly_Triangle;
 class Poly_Triangulation;
 
 //! A framework to define selection of a sensitive entity made of a set of triangles.
diff --git a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
index c846147082..4e065def7b 100644
--- a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
+++ b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
@@ -33,15 +33,7 @@ class SelectBasics_SelectingVolumeManager
 {
 public:
 
-  //! Available selection types
-  enum SelectionType { Point, Box, Polyline, Unknown };
-
-public:
-
-  SelectBasics_SelectingVolumeManager()
-  : myActiveSelectionType(Unknown)
-  {
-  }
+  SelectBasics_SelectingVolumeManager() {}
 
   virtual ~SelectBasics_SelectingVolumeManager() {}
 
@@ -113,7 +105,15 @@ public:
   //! correspondingly) onto far view frustum plane
   virtual gp_Pnt GetFarPickedPnt() const = 0;
 
-  //! Return mouse coordinates for Point selection mode.
+  //! Valid only for point and rectangular selection.
+  //! Returns view ray direction
+  virtual gp_Dir GetViewRayDirection() const = 0;
+
+  //! Checks if it is possible to scale current active selecting volume
+  virtual Standard_Boolean IsScalableActiveVolume() const = 0;
+
+  //! Returns mouse coordinates for Point selection mode.
+  //! @return infinite point in case of unsupport of mouse position for this active selection volume.
   virtual gp_Pnt2d GetMousePosition() const = 0;
 
   //! Stores plane equation coefficients (in the following form:
@@ -122,10 +122,10 @@ public:
 
   //! Dumps the content of me into the stream
   virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const
-  { (void)theDepth; OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myActiveSelectionType) }
-
-protected:
-  SelectionType myActiveSelectionType;      //!< Active selection type: point, box or polyline
+  {
+    (void )theOStream;
+    (void )theDepth;
+  }
 };
 
 #endif // _SelectBasics_SelectingVolumeManager_HeaderFile
diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES
index 315af35eef..8b457da1d6 100755
--- a/src/SelectMgr/FILES
+++ b/src/SelectMgr/FILES
@@ -4,6 +4,8 @@ SelectMgr_AndFilter.cxx
 SelectMgr_AndFilter.hxx
 SelectMgr_AndOrFilter.cxx
 SelectMgr_AndOrFilter.hxx
+SelectMgr_BaseIntersector.cxx
+SelectMgr_BaseIntersector.hxx
 SelectMgr_BaseFrustum.cxx
 SelectMgr_BaseFrustum.hxx
 SelectMgr_BVHThreadPool.cxx
@@ -40,6 +42,7 @@ SelectMgr_SelectionImageFiller.cxx
 SelectMgr_SelectionImageFiller.hxx
 SelectMgr_SelectionManager.cxx
 SelectMgr_SelectionManager.hxx
+SelectMgr_SelectionType.hxx
 SelectMgr_SensitiveEntity.cxx
 SelectMgr_SensitiveEntity.hxx
 SelectMgr_SensitiveEntitySet.cxx
diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx
index a373ad0224..d90fba5278 100644
--- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx
+++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx
@@ -16,13 +16,13 @@
 #include <SelectMgr_BaseFrustum.hxx>
 
 #include <Message.hxx>
-
+#include <SelectMgr_FrustumBuilder.hxx>
 #include <Standard_Dump.hxx>
 
-IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum, SelectMgr_BaseIntersector)
 
 //=======================================================================
-// function : SelectMgr_SelectingVolume
+// function : SelectMgr_BaseFrustum
 // purpose  : Creates new selecting volume with pixel toletance set to 2,
 //            orthographic camera and empty frustum builder
 //=======================================================================
@@ -231,32 +231,14 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt1*/,
   return Standard_False;
 }
 
-//=======================================================================
-// function : DistToGeometryCenter
-// purpose  : Measures distance between 3d projection of user-picked
-//            screen point and given point theCOG
-//=======================================================================
-Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCOG*/) const
-{
-  return DBL_MAX;
-}
-
-//=======================================================================
-// function : DetectedPoint
-// purpose  :
-//=======================================================================
-gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const
-{
-  return gp_Pnt (RealLast(), RealLast(), RealLast());
-}
-
 //=======================================================================
 //function : DumpJson
 //purpose  : 
 //=======================================================================
-void SelectMgr_BaseFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
+void SelectMgr_BaseFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
 {
-  OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+  OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_BaseFrustum)
+  OCCT_DUMP_BASE_CLASS (theOStream, theDepth, SelectMgr_BaseIntersector)
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPixelTolerance)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsOrthographic)
diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx
index 05e82ebad9..bfb7107f98 100644
--- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx
+++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx
@@ -16,26 +16,14 @@
 #ifndef _SelectMgr_BaseFrustum_HeaderFile
 #define _SelectMgr_BaseFrustum_HeaderFile
 
-#include <gp_GTrsf.hxx>
-#include <Graphic3d_Camera.hxx>
-#include <Graphic3d_WorldViewProjState.hxx>
-#include <Select3D_BndBox3d.hxx>
-#include <Select3D_TypeOfSensitivity.hxx>
-#include <SelectMgr_FrustumBuilder.hxx>
-#include <SelectMgr_VectorTypes.hxx>
-#include <SelectMgr_ViewClipRange.hxx>
-#include <SelectBasics_PickResult.hxx>
-#include <TColgp_Array1OfPnt.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-
-#include <Standard_OStream.hxx>
+#include <SelectMgr_BaseIntersector.hxx>
 
 //! This class is an interface for different types of selecting frustums,
 //! defining different selection types, like point, box or polyline
 //! selection. It contains signatures of functions for detection of
 //! overlap by sensitive entity and initializes some data for building
 //! the selecting frustum
-class SelectMgr_BaseFrustum : public Standard_Transient
+class SelectMgr_BaseFrustum : public SelectMgr_BaseIntersector
 {
 public:
 
@@ -43,97 +31,71 @@ public:
   //! orthographic camera and empty frustum builder
   Standard_EXPORT SelectMgr_BaseFrustum();
 
+  //! Destructor
   virtual ~SelectMgr_BaseFrustum() {}
 
-  //! Return camera definition.
-  const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
-
-  //! Passes camera projection and orientation matrices to builder
-  Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera)& theCamera);
-
-  //! Passes camera projection and orientation matrices to builder
-  Standard_EXPORT void SetCamera (const Graphic3d_Mat4d& theProjection,
-                                  const Graphic3d_Mat4d& theWorldView,
-                                  const Standard_Boolean theIsOrthographic,
-                                  const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState());
-
-  //! @return current camera projection transformation common for all selecting volumes
-  Standard_EXPORT const Graphic3d_Mat4d& ProjectionMatrix() const;
-
-  //! @return current camera world view transformation common for all selecting volumes
-  Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const;
-
-  //! @return current camera world view projection transformation state
-  Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const;
-
-  Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTol);
-
-  Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, 
-                                      const Standard_Integer theHeight);
-
-  Standard_EXPORT void WindowSize (Standard_Integer& theWidth,
-                                   Standard_Integer& theHeight) const;
-
-  //! Passes viewport parameters to builder
-  Standard_EXPORT void SetViewport (const Standard_Real theX,
-                                    const Standard_Real theY,
-                                    const Standard_Real theWidth,
-                                    const Standard_Real theHeight);
-
   //! Nullifies the builder created in the constructor and copies the pointer given
   Standard_EXPORT void SetBuilder (const Handle(SelectMgr_FrustumBuilder)& theBuilder);
 
+  //! Return camera definition.
+  virtual const Handle(Graphic3d_Camera)& Camera() const Standard_OVERRIDE { return myCamera; }
 
-  //! Builds volume according to the point and given pixel tolerance
-  virtual void Build (const gp_Pnt2d& /*thePoint*/) {}
+  //! Passes camera projection and orientation matrices to builder
+  Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE;
 
-  //! Builds volume according to the selected rectangle
-  virtual void Build (const gp_Pnt2d& /*theMinPt*/,
-                      const gp_Pnt2d& /*theMaxPt*/) {}
+  //! Passes camera projection and orientation matrices to builder
+  Standard_EXPORT virtual void SetCamera (const Graphic3d_Mat4d& theProjection,
+                                          const Graphic3d_Mat4d& theWorldView,
+                                          const Standard_Boolean theIsOrthographic,
+                                          const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()) Standard_OVERRIDE;
 
-  //! Builds volume according to the triangle given
-  virtual void Build (const gp_Pnt2d& /*theP1*/,
-                      const gp_Pnt2d& /*theP2*/,
-                      const gp_Pnt2d& /*theP3*/) {}
+  //! @return current camera projection transformation common for all selecting volumes
+  Standard_EXPORT virtual const Graphic3d_Mat4d& ProjectionMatrix() const Standard_OVERRIDE;
+
+  //! @return current camera world view transformation common for all selecting volumes
+  Standard_EXPORT virtual const Graphic3d_Mat4d& WorldViewMatrix() const Standard_OVERRIDE;
+
+  //! @return current camera world view projection transformation state
+  Standard_EXPORT virtual const Graphic3d_WorldViewProjState& WorldViewProjState() const Standard_OVERRIDE;
+
+  Standard_EXPORT virtual void SetPixelTolerance (const Standard_Integer theTol) Standard_OVERRIDE;
+
+  Standard_EXPORT virtual void SetWindowSize (const Standard_Integer theWidth,
+                                              const Standard_Integer theHeight) Standard_OVERRIDE;
+
+  Standard_EXPORT virtual void WindowSize (Standard_Integer& theWidth,
+                                           Standard_Integer& theHeight) const Standard_OVERRIDE;
+
+  //! Passes viewport parameters to builder
+  Standard_EXPORT virtual void SetViewport (const Standard_Real theX,
+                                            const Standard_Real theY,
+                                            const Standard_Real theWidth,
+                                            const Standard_Real theHeight) Standard_OVERRIDE;
 
-  //! Builds selecting volumes set according to polyline points
-  virtual void Build (const TColgp_Array1OfPnt2d& /*thePoints*/) {}
 
-  //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
-  //!            Note that this method does not perform any checks on type of the frustum.
-  //! Returns a copy of the frustum resized according to the scale factor given
-  //! and transforms it using the matrix given.
-  //! There are no default parameters, but in case if:
-  //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
-  //!    - scale only is needed: @theTrsf must be set to gp_Identity.
-  virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer /*theScaleFactor*/,
-                                                           const gp_GTrsf& /*theTrsf*/) const
-  { 
-    return NULL; 
-  }
 
   //! SAT intersection test between defined volume and given axis-aligned box
   Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
                                                      const SelectMgr_Vec3& theBoxMax,
                                                      const SelectMgr_ViewClipRange& theClipRange,
-                                                     SelectBasics_PickResult& thePickResult) const;
+                                                     SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
   //! with minimum corner at point theMinPt and maximum at point theMaxPt
   Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
                                                      const SelectMgr_Vec3& theBoxMax,
-                                                     Standard_Boolean*     theInside = NULL) const;
+                                                     Standard_Boolean*     theInside = NULL) const Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
   Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
                                                      const SelectMgr_ViewClipRange& theClipRange,
-                                                     SelectBasics_PickResult& thePickResult) const;
+                                                     SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
   //! Does not perform depth calculation, so this method is defined as
   //! helper function for inclusion test. Therefore, its implementation
   //! makes sense only for rectangular frustum with box selection mode activated.
-  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const;
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const Standard_OVERRIDE;
 
   //! SAT intersection test between defined volume and given ordered set of points,
   //! representing line segments. The test may be considered of interior part or
@@ -141,13 +103,13 @@ public:
   Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts,
                                                      Select3D_TypeOfSensitivity theSensType,
                                                      const SelectMgr_ViewClipRange& theClipRange,
-                                                     SelectBasics_PickResult& thePickResult) const;
+                                                     SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Checks if line segment overlaps selecting frustum
   Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
                                                      const gp_Pnt& thePnt2,
                                                      const SelectMgr_ViewClipRange& theClipRange,
-                                                     SelectBasics_PickResult& thePickResult) const;
+                                                     SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! SAT intersection test between defined volume and given triangle. The test may
   //! be considered of interior part or boundary line defined by triangle vertices
@@ -157,26 +119,12 @@ public:
                                                      const gp_Pnt& thePt3,
                                                      Select3D_TypeOfSensitivity theSensType,
                                                      const SelectMgr_ViewClipRange& theClipRange,
-                                                     SelectBasics_PickResult& thePickResult) const;
-
-  //! Measures distance between 3d projection of user-picked
-  //! screen point and given point theCOG
-  Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const;
-
-  Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const;
-
-  //! Stores plane equation coefficients (in the following form:
-  //! Ax + By + Cz + D = 0) to the given vector
-  virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const
-  {
-    thePlaneEquations.Clear();
-    return;
-  }
+                                                     SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Dumps the content of me into the stream
-  Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+  Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
 
-  DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient)
+  DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum, SelectMgr_BaseIntersector)
 
 protected:
   Standard_Integer    myPixelTolerance;      //!< Pixel tolerance
diff --git a/src/SelectMgr/SelectMgr_BaseIntersector.cxx b/src/SelectMgr/SelectMgr_BaseIntersector.cxx
new file mode 100644
index 0000000000..4552ca1752
--- /dev/null
+++ b/src/SelectMgr/SelectMgr_BaseIntersector.cxx
@@ -0,0 +1,276 @@
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <SelectMgr_BaseIntersector.hxx>
+
+#include <Graphic3d_Camera.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseIntersector, Standard_Transient)
+
+//=======================================================================
+// function : ScaleAndTransform
+// purpose  :
+//=======================================================================
+Handle(SelectMgr_BaseIntersector) SelectMgr_BaseIntersector::ScaleAndTransform (const Standard_Integer,
+                                                                                const gp_GTrsf&,
+                                                                                const Handle(SelectMgr_FrustumBuilder)&) const
+{
+  return NULL;
+}
+
+//=======================================================================
+// function : Camera
+// purpose  :
+//=======================================================================
+const Handle(Graphic3d_Camera)& SelectMgr_BaseIntersector::Camera() const
+{
+  static const Handle(Graphic3d_Camera) anEmptyCamera;
+  return anEmptyCamera;
+}
+
+//=======================================================================
+// function : SetCamera
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::SetCamera (const Handle(Graphic3d_Camera)&)
+{
+}
+
+//=======================================================================
+// function : SetCamera
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::SetCamera (const Graphic3d_Mat4d&,
+                                           const Graphic3d_Mat4d&,
+                                           const Standard_Boolean,
+                                           const Graphic3d_WorldViewProjState&)
+{
+}
+
+//=======================================================================
+// function : ProjectionMatrix
+// purpose  :
+//=======================================================================
+const Graphic3d_Mat4d& SelectMgr_BaseIntersector::ProjectionMatrix() const
+{
+  static const Graphic3d_Mat4d anEmptyMatrix;
+  return anEmptyMatrix;
+}
+
+//=======================================================================
+// function : WorldViewMatrix
+// purpose  :
+//=======================================================================
+const Graphic3d_Mat4d& SelectMgr_BaseIntersector::WorldViewMatrix() const
+{
+  static const Graphic3d_Mat4d anEmptyMatrix;
+  return anEmptyMatrix;
+}
+
+//=======================================================================
+// function : WorldViewProjState
+// purpose  :
+//=======================================================================
+const Graphic3d_WorldViewProjState& SelectMgr_BaseIntersector::WorldViewProjState() const
+{
+  static const Graphic3d_WorldViewProjState anEmptyState;
+  return anEmptyState;
+}
+
+//=======================================================================
+// function : SetPixelTolerance
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::SetPixelTolerance (const Standard_Integer)
+{
+}
+
+//=======================================================================
+// function : WindowSize
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::WindowSize (Standard_Integer&,
+                                            Standard_Integer&) const
+{
+}
+
+//=======================================================================
+// function : SetWindowSize
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::SetWindowSize (const Standard_Integer,
+                                               const Standard_Integer)
+{
+}
+
+//=======================================================================
+// function : SetViewport
+// purpose  :
+//=======================================================================
+void SelectMgr_BaseIntersector::SetViewport (const Standard_Real,
+                                             const Standard_Real,
+                                             const Standard_Real,
+                                             const Standard_Real)
+{
+}
+
+//=======================================================================
+// function : GetNearPnt
+// purpose  :
+//=======================================================================
+const gp_Pnt& SelectMgr_BaseIntersector::GetNearPnt() const
+{
+  static const gp_Pnt anEmptyPnt;
+  return anEmptyPnt;
+}
+
+//=======================================================================
+// function : GetFarPnt
+// purpose  :
+//=======================================================================
+const gp_Pnt& SelectMgr_BaseIntersector::GetFarPnt() const
+{
+  static const gp_Pnt anEmptyPnt(RealLast(), RealLast(), RealLast());
+  return anEmptyPnt;
+}
+
+//=======================================================================
+// function : GetViewRayDirection
+// purpose  :
+//=======================================================================
+const gp_Dir& SelectMgr_BaseIntersector::GetViewRayDirection() const
+{
+  static const gp_Dir anEmptyDir;
+  return anEmptyDir;
+}
+
+//=======================================================================
+// function : GetMousePosition
+// purpose  :
+//=======================================================================
+const gp_Pnt2d& SelectMgr_BaseIntersector::GetMousePosition() const
+{
+  static const gp_Pnt2d aPnt(RealLast(), RealLast());
+  return aPnt;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const SelectMgr_Vec3&,
+                                                      const SelectMgr_Vec3&,
+                                                      const SelectMgr_ViewClipRange&,
+                                                      SelectBasics_PickResult&) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const SelectMgr_Vec3&,
+                                                      const SelectMgr_Vec3&,
+                                                      Standard_Boolean*) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&,
+                                                      const SelectMgr_ViewClipRange&,
+                                                      SelectBasics_PickResult&) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt& thePnt) const
+{
+  (void )thePnt;
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const TColgp_Array1OfPnt&,
+                                                      Select3D_TypeOfSensitivity,
+                                                      const SelectMgr_ViewClipRange&,
+                                                      SelectBasics_PickResult&) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&,
+                                                      const gp_Pnt&,
+                                                      const gp_Pnt&,
+                                                      Select3D_TypeOfSensitivity,
+                                                      const SelectMgr_ViewClipRange&,
+                                                      SelectBasics_PickResult&) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : Overlaps
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&,
+                                                      const gp_Pnt&,
+                                                      const SelectMgr_ViewClipRange&,
+                                                      SelectBasics_PickResult&) const
+{
+  return Standard_False;
+}
+
+//=======================================================================
+// function : DistToGeometryCenter
+// purpose  :
+//=======================================================================
+Standard_Real SelectMgr_BaseIntersector::DistToGeometryCenter (const gp_Pnt&) const
+{
+  return RealLast();
+}
+
+//=======================================================================
+// function : DetectedPoint
+// purpose  :
+//=======================================================================
+gp_Pnt SelectMgr_BaseIntersector::DetectedPoint (const Standard_Real) const
+{
+  return gp_Pnt(RealLast(), RealLast(), RealLast());
+}
+
+//=======================================================================
+//function : DumpJson
+//purpose  : 
+//=======================================================================
+void SelectMgr_BaseIntersector::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
+{
+  OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySelectionType)
+}
diff --git a/src/SelectMgr/SelectMgr_BaseIntersector.hxx b/src/SelectMgr/SelectMgr_BaseIntersector.hxx
new file mode 100644
index 0000000000..ef6e238c36
--- /dev/null
+++ b/src/SelectMgr/SelectMgr_BaseIntersector.hxx
@@ -0,0 +1,222 @@
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _SelectMgr_BaseIntersector_HeaderFile
+#define _SelectMgr_BaseIntersector_HeaderFile
+
+#include <gp_GTrsf.hxx>
+#include <Graphic3d_Mat4d.hxx>
+#include <Graphic3d_WorldViewProjState.hxx>
+#include <NCollection_Vector.hxx>
+#include <Select3D_TypeOfSensitivity.hxx>
+#include <SelectBasics_PickResult.hxx>
+#include <SelectMgr_SelectionType.hxx>
+#include <SelectMgr_VectorTypes.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+
+class Graphic3d_Camera;
+class SelectMgr_FrustumBuilder;
+class SelectMgr_ViewClipRange;
+
+//! This class is an interface for different types of selecting intersector,
+//! defining different selection types, like point, box or polyline
+//! selection. It contains signatures of functions for detection of
+//! overlap by sensitive entity and initializes some data for building
+//! the selecting intersector
+class SelectMgr_BaseIntersector : public Standard_Transient
+{
+public:
+
+  //! Creates new empty selecting volume
+  SelectMgr_BaseIntersector()
+  : mySelectionType (SelectMgr_SelectionType_Unknown)
+  {}
+
+  //! Destructor
+  virtual ~SelectMgr_BaseIntersector() {}
+
+  //! Builds intersector according to internal parameters
+  virtual void Build() {}
+
+  //! Returns selection type of this intersector
+  SelectMgr_SelectionType GetSelectionType() const { return mySelectionType; }
+
+public:
+
+  //! Checks if it is possible to scale this intersector.
+  //! @return false for the base class.
+  virtual Standard_Boolean IsScalable() const { return Standard_False; }
+
+  //! Sets pixel tolerance.
+  //! It makes sense only for scalable intersectors (built on a single point).
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual void SetPixelTolerance (const Standard_Integer theTol);
+
+  //! IMPORTANT: Scaling makes sense only for scalable intersectors (built on a single point)!
+  //!            Note that this method does not perform any checks on type of the frustum.
+  //! Returns a copy of the frustum resized according to the scale factor given
+  //! and transforms it using the matrix given.
+  //! There are no default parameters, but in case if:
+  //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
+  //!    - scale only is needed: @theTrsf must be set to gp_Identity.
+  //! Builder is an optional argument that represents corresponding settings for re-constructing transformed
+  //! frustum from scratch. Can be null if reconstruction is not expected furthermore.
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                               const gp_GTrsf& theTrsf,
+                                                                               const Handle(SelectMgr_FrustumBuilder)& theBuilder) const;
+
+public:
+
+  //! Returns camera definition.
+  //! This method returns empty camera for the base class.
+  Standard_EXPORT virtual const Handle(Graphic3d_Camera)& Camera() const;
+
+  //! Sets camera projection and orientation matrices.
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera);
+
+  //! Sets camera projection and orientation matrices.
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual void SetCamera (const Graphic3d_Mat4d& theProjection,
+                                          const Graphic3d_Mat4d& theWorldView,
+                                          const Standard_Boolean theIsOrthographic,
+                                          const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState());
+
+  //! Returns current camera projection transformation.
+  //! This method returns empty matrix for the base class.
+  Standard_EXPORT virtual const Graphic3d_Mat4d& ProjectionMatrix() const;
+
+  //! Returns current camera world view transformation.
+  //! This method returns empty matrix for the base class.
+  Standard_EXPORT virtual const Graphic3d_Mat4d& WorldViewMatrix() const;
+
+  //! Returns current camera world view projection transformation state.
+  //! This method returns empty matrix for the base class.
+  Standard_EXPORT virtual const Graphic3d_WorldViewProjState& WorldViewProjState() const;
+
+  //! Returns current window size.
+  //! This method doesn't set any output values for the base class.
+  Standard_EXPORT virtual void WindowSize (Standard_Integer& theWidth,
+                                           Standard_Integer& theHeight) const;
+
+  //! Sets current window size.
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual void SetWindowSize (const Standard_Integer theWidth,
+                                              const Standard_Integer theHeight);
+
+  //! Sets viewport parameters.
+  //! This method does nothing for the base class.
+  Standard_EXPORT virtual void SetViewport (const Standard_Real theX,
+                                            const Standard_Real theY,
+                                            const Standard_Real theWidth,
+                                            const Standard_Real theHeight);
+
+  //! Returns near point of intersector.
+  //! This method returns zero point for the base class.
+  Standard_EXPORT virtual const gp_Pnt& GetNearPnt() const;
+
+  //! Returns far point of intersector.
+  //! This method returns zero point for the base class.
+  Standard_EXPORT virtual const gp_Pnt& GetFarPnt() const;
+
+  //! Returns direction ray of intersector.
+  //! This method returns zero direction for the base class.
+  Standard_EXPORT virtual const gp_Dir& GetViewRayDirection() const;
+
+  //! Returns current mouse coordinates.
+  //! This method returns infinite point for the base class.
+  Standard_EXPORT virtual const gp_Pnt2d& GetMousePosition() const;
+
+  //! Stores plane equation coefficients (in the following form:
+  //! Ax + By + Cz + D = 0) to the given vector.
+  //! This method only clears input vector for the base class.
+  virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const
+  {
+    thePlaneEquations.Clear();
+  }
+
+public:
+
+  //! SAT intersection test between defined volume and given axis-aligned box
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                     const SelectMgr_Vec3& theBoxMax,
+                                                     const SelectMgr_ViewClipRange& theClipRange,
+                                                     SelectBasics_PickResult& thePickResult) const;
+
+  //! Returns true if selecting volume is overlapped by axis-aligned bounding box
+  //! with minimum corner at point theMinPt and maximum at point theMaxPt
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                     const SelectMgr_Vec3& theBoxMax,
+                                                     Standard_Boolean*     theInside = NULL) const;
+
+  //! Intersection test between defined volume and given point
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
+                                                     const SelectMgr_ViewClipRange& theClipRange,
+                                                     SelectBasics_PickResult& thePickResult) const;
+
+  //! Intersection test between defined volume and given point
+  //! Does not perform depth calculation, so this method is defined as
+  //! helper function for inclusion test. Therefore, its implementation
+  //! makes sense only for rectangular frustum with box selection mode activated.
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const;
+
+  //! SAT intersection test between defined volume and given ordered set of points,
+  //! representing line segments. The test may be considered of interior part or
+  //! boundary line defined by segments depending on given sensitivity type
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts,
+                                                     Select3D_TypeOfSensitivity theSensType,
+                                                     const SelectMgr_ViewClipRange& theClipRange,
+                                                     SelectBasics_PickResult& thePickResult) const;
+
+  //! Checks if line segment overlaps selecting frustum
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1,
+                                                     const gp_Pnt& thePnt2,
+                                                     const SelectMgr_ViewClipRange& theClipRange,
+                                                     SelectBasics_PickResult& thePickResult) const;
+
+  //! SAT intersection test between defined volume and given triangle. The test may
+  //! be considered of interior part or boundary line defined by triangle vertices
+  //! depending on given sensitivity type
+  Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1,
+                                                     const gp_Pnt& thePt2,
+                                                     const gp_Pnt& thePt3,
+                                                     Select3D_TypeOfSensitivity theSensType,
+                                                     const SelectMgr_ViewClipRange& theClipRange,
+                                                     SelectBasics_PickResult& thePickResult) const;
+
+public:
+
+  //! Measures distance between 3d projection of user-picked
+  //! screen point and given point theCOG.
+  //! It makes sense only for intersectors built on a single point.
+  //! This method returns infinite value for the base class.
+  Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const;
+
+  //! Calculates the point on a view ray that was detected during the run of selection algo by given depth.
+  //! It makes sense only for intersectors built on a single point.
+  //! This method returns infinite point for the base class.
+  Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const;
+
+  //! Dumps the content of me into the stream
+  Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
+
+  DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient)
+
+protected:
+
+  SelectMgr_SelectionType mySelectionType;
+};
+
+#endif // _SelectMgr_BaseIntersector_HeaderFile
diff --git a/src/SelectMgr/SelectMgr_Frustum.hxx b/src/SelectMgr/SelectMgr_Frustum.hxx
index b2bcdecf83..52a97c5e9d 100644
--- a/src/SelectMgr/SelectMgr_Frustum.hxx
+++ b/src/SelectMgr/SelectMgr_Frustum.hxx
@@ -16,13 +16,7 @@
 #ifndef _SelectMgr_Frustum_HeaderFile
 #define _SelectMgr_Frustum_HeaderFile
 
-#include <BVH_Box.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Vec.hxx>
-#include <gp_XYZ.hxx>
 #include <SelectMgr_BaseFrustum.hxx>
-#include <TColgp_HArray1OfPnt.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
 
 //! This is an internal class containing representation of rectangular selecting frustum, created in case
 //! of point and box selection, and algorithms for overlap detection between selecting
diff --git a/src/SelectMgr/SelectMgr_Frustum.lxx b/src/SelectMgr/SelectMgr_Frustum.lxx
index 248a9c258c..fabfd004e9 100644
--- a/src/SelectMgr/SelectMgr_Frustum.lxx
+++ b/src/SelectMgr/SelectMgr_Frustum.lxx
@@ -16,6 +16,7 @@
 #include <NCollection_Vector.hxx>
 #include <Poly_Array1OfTriangle.hxx>
 #include <Standard_Assert.hxx>
+#include <SelectMgr_FrustumBuilder.hxx>
 
 // =======================================================================
 // function : isSeparated
diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx
index 61a0743b85..27ee456421 100644
--- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx
+++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx
@@ -13,10 +13,22 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <SelectMgr_RectangularFrustum.hxx>
+
+#include <BVH_Tools.hxx>
 #include <NCollection_Vector.hxx>
 #include <Poly_Array1OfTriangle.hxx>
+#include <SelectMgr_FrustumBuilder.hxx>
+#include <SelectMgr_ViewClipRange.hxx>
 
-#include <SelectMgr_RectangularFrustum.hxx>
+// =======================================================================
+// function : Constructor
+// purpose  :
+// =======================================================================
+SelectMgr_RectangularFrustum::SelectMgr_RectangularFrustum()
+  : myScale(1.0)
+{
+}
 
 // =======================================================================
 // function : segmentSegmentDistance
@@ -204,56 +216,6 @@ namespace
     // Far
     theNormals[5] = -theNormals[4];
   }
-  
-  // =======================================================================
-  // function : rayBoxIntersection
-  // purpose  : Computes an intersection of ray with box
-  //            Returns distances to the first (or 0.0 if the ray origin is inside the box) and second intersection
-  //            If the ray has no intersection with the box returns DBL_MAX
-  // =======================================================================
-  Bnd_Range rayBoxIntersection (const gp_Ax1& theRay, const gp_Pnt& theBoxMin, const gp_Pnt& theBoxMax)
-  {
-    Standard_Real aTimeMinX = -DBL_MAX;
-    Standard_Real aTimeMinY = -DBL_MAX;
-    Standard_Real aTimeMinZ = -DBL_MAX;
-    Standard_Real aTimeMaxX = DBL_MAX;
-    Standard_Real aTimeMaxY = DBL_MAX;
-    Standard_Real aTimeMaxZ = DBL_MAX;
-
-    Standard_Real aTime1;
-    Standard_Real aTime2;
-
-    if (Abs (theRay.Direction().X()) > DBL_EPSILON)
-    {
-      aTime1 = (theBoxMin.X() - theRay.Location().X()) / theRay.Direction().X();
-      aTime2 = (theBoxMax.X() - theRay.Location().X()) / theRay.Direction().X();
-
-      aTimeMinX = Min (aTime1, aTime2);
-      aTimeMaxX = Max (aTime1, aTime2);
-    }
-    if (Abs (theRay.Direction().Y()) > DBL_EPSILON)
-    {
-      aTime1 = (theBoxMin.Y() - theRay.Location().Y()) / theRay.Direction().Y();
-      aTime2 = (theBoxMax.Y() - theRay.Location().Y()) / theRay.Direction().Y();
-
-      aTimeMinY = Min (aTime1, aTime2);
-      aTimeMaxY = Max (aTime1, aTime2);
-    }
-    if (Abs (theRay.Direction().Z()) > DBL_EPSILON)
-    {
-      aTime1 = (theBoxMin.Z() - theRay.Location().Z()) / theRay.Direction().Z();
-      aTime2 = (theBoxMax.Z() - theRay.Location().Z()) / theRay.Direction().Z();
-
-      aTimeMinZ = Min (aTime1, aTime2);
-      aTimeMaxZ = Max (aTime1, aTime2);
-    }
-
-    Standard_Real aTimeMin = Max (aTimeMinX, Max (aTimeMinY, aTimeMinZ));
-    Standard_Real aTimeMax = Min (aTimeMaxX, Min (aTimeMaxY, aTimeMaxZ));
-
-    return aTimeMin > aTimeMax || aTimeMax < 0.0 ? Bnd_Range (DBL_MAX, DBL_MAX)
-      : Bnd_Range (Max (aTimeMin, 0.0), aTimeMax);
-  }
 }
 
 // =======================================================================
@@ -316,52 +278,63 @@ void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_Rectangular
 }
 
 // =======================================================================
-// function : Build
-// purpose  : Build volume according to the point and given pixel
-//            tolerance
+// function : Init
+// purpose  :
 // =======================================================================
-void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
+void SelectMgr_RectangularFrustum::Init (const gp_Pnt2d &thePoint)
 {
-  myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0);
-  myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0);
-  myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ();
-  myMousePos = thePoint;
+  mySelectionType = SelectMgr_SelectionType_Point;
+  mySelRectangle.SetMousePos (thePoint);
+}
 
-  gp_Pnt2d aMinPnt (thePoint.X() - myPixelTolerance * 0.5,
-                    thePoint.Y() - myPixelTolerance * 0.5);
-  gp_Pnt2d aMaxPnt (thePoint.X() + myPixelTolerance * 0.5,
-                    thePoint.Y() + myPixelTolerance * 0.5);
-
-  // calculate base frustum characteristics: vertices and edge directions
-  computeFrustum (aMinPnt, aMaxPnt, myBuilder, myVertices, myEdgeDirs);
-
-  // compute frustum normals
-  computeNormals (myEdgeDirs, myPlanes);
-
-  // compute vertices projections onto frustum normals and
-  // {i, j, k} vectors and store them to corresponding class fields
-  cacheVertexProjections (this);
-
-  myScale = 1.0;
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+void SelectMgr_RectangularFrustum::Init (const gp_Pnt2d& theMinPnt,
+                                         const gp_Pnt2d& theMaxPnt)
+{
+  mySelectionType = SelectMgr_SelectionType_Box;
+  mySelRectangle.SetMinPnt (theMinPnt);
+  mySelRectangle.SetMaxPnt (theMaxPnt);
 }
 
 // =======================================================================
 // function : Build
-// purpose  : Build volume according to the selected rectangle
+// purpose  :
 // =======================================================================
-void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
-                                          const gp_Pnt2d& theMaxPnt)
+void SelectMgr_RectangularFrustum::Build()
 {
-  myNearPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5,
-                                                      (theMinPnt.Y() + theMaxPnt.Y()) * 0.5,
-                                                      0.0);
-  myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5,
-                                                     (theMinPnt.Y() + theMaxPnt.Y()) * 0.5,
-                                                     1.0);
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Build() should be called after selection frustum initialization");
+  gp_Pnt2d aMinPnt, aMaxPnt;
+  if (mySelectionType == SelectMgr_SelectionType_Point)
+  {
+    const gp_Pnt2d& aMousePos = mySelRectangle.MousePos();
+    myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (aMousePos.X(), aMousePos.Y(), 0.0);
+    myFarPickedPnt  = myBuilder->ProjectPntOnViewPlane (aMousePos.X(), aMousePos.Y(), 1.0);
+
+    aMinPnt.SetCoord (aMousePos.X() - myPixelTolerance * 0.5,
+                      aMousePos.Y() - myPixelTolerance * 0.5);
+    aMaxPnt.SetCoord (aMousePos.X() + myPixelTolerance * 0.5,
+                      aMousePos.Y() + myPixelTolerance * 0.5);
+  }
+  else
+  {
+    aMinPnt = mySelRectangle.MinPnt();
+    aMaxPnt = mySelRectangle.MaxPnt();
+    myNearPickedPnt = myBuilder->ProjectPntOnViewPlane ((aMinPnt.X() + aMaxPnt.X()) * 0.5,
+                                                        (aMinPnt.Y() + aMaxPnt.Y()) * 0.5,
+                                                        0.0);
+    myFarPickedPnt  = myBuilder->ProjectPntOnViewPlane ((aMinPnt.X() + aMaxPnt.X()) * 0.5,
+                                                        (aMinPnt.Y() + aMaxPnt.Y()) * 0.5,
+                                                        1.0);
+  }
+
   myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ();
 
   // calculate base frustum characteristics: vertices and edge directions
-  computeFrustum (theMinPnt, theMaxPnt, myBuilder, myVertices, myEdgeDirs);
+  computeFrustum (aMinPnt, aMaxPnt, myBuilder, myVertices, myEdgeDirs);
 
   // compute frustum normals
   computeNormals (myEdgeDirs, myPlanes);
@@ -384,9 +357,13 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
 //                  as any negative value;
 //                - scale only is needed: @theTrsf must be set to gp_Identity.
 // =======================================================================
-Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor,
-                                                                               const gp_GTrsf& theTrsf) const
+Handle(SelectMgr_BaseIntersector) SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                                   const gp_GTrsf& theTrsf,
+                                                                                   const Handle(SelectMgr_FrustumBuilder)& theBuilder) const
 {
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::ScaleAndTransform() should be called after selection frustum initialization");
+
   Standard_ASSERT_RAISE (theScaleFactor > 0,
     "Error! Pixel tolerance for selection should be greater than zero");
 
@@ -395,7 +372,10 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c
   const Standard_Boolean isToTrsf  = theTrsf.Form() != gp_Identity;
 
   if (!isToScale && !isToTrsf)
+  {
+    aRes->SetBuilder (theBuilder);
     return aRes;
+  }
 
   aRes->myIsOrthographic = myIsOrthographic;
   const SelectMgr_RectangularFrustum* aRef = this;
@@ -406,10 +386,11 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c
     aRes->myFarPickedPnt  = myFarPickedPnt;
     aRes->myViewRayDir    = myViewRayDir;
 
-    const gp_Pnt2d aMinPnt (myMousePos.X() - theScaleFactor * 0.5,
-                            myMousePos.Y() - theScaleFactor * 0.5);
-    const gp_Pnt2d aMaxPnt (myMousePos.X() + theScaleFactor * 0.5,
-                            myMousePos.Y() + theScaleFactor * 0.5);
+    const gp_Pnt2d& aMousePos = mySelRectangle.MousePos();
+    const gp_Pnt2d aMinPnt (aMousePos.X() - theScaleFactor * 0.5,
+                            aMousePos.Y() - theScaleFactor * 0.5);
+    const gp_Pnt2d aMaxPnt (aMousePos.X() + theScaleFactor * 0.5,
+                            aMousePos.Y() + theScaleFactor * 0.5);
 
     // recompute base frustum characteristics from scratch
     computeFrustum (aMinPnt, aMaxPnt, myBuilder, aRes->myVertices, aRes->myEdgeDirs);
@@ -460,11 +441,21 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c
 
   cacheVertexProjections (aRes.get());
 
-  aRes->myMousePos = myMousePos;
-
+  aRes->mySelectionType = mySelectionType;
+  aRes->mySelRectangle = mySelRectangle;
+  aRes->SetBuilder (theBuilder);
   return aRes;
 }
 
+// =======================================================================
+// function : IsScalable
+// purpose  :
+// =======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::IsScalable() const
+{
+  return mySelectionType == SelectMgr_SelectionType_Point;
+}
+
 // =======================================================================
 // function : Overlaps
 // purpose  : Returns true if selecting volume is overlapped by
@@ -475,6 +466,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
                                                          const SelectMgr_Vec3& theBoxMax,
                                                          Standard_Boolean*     theInside) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   return hasOverlap (theBoxMin, theBoxMax, theInside);
 }
 
@@ -488,18 +482,17 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
                                                          const SelectMgr_ViewClipRange& theClipRange,
                                                          SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   if (!hasOverlap (theBoxMin, theBoxMax))
     return Standard_False;
 
-  gp_Ax1 aRay (myNearPickedPnt, myViewRayDir);
-  Bnd_Range aRange = rayBoxIntersection (aRay,
-                                         gp_Pnt (theBoxMin.x(), theBoxMin.y(), theBoxMin.z()),
-                                         gp_Pnt (theBoxMax.x(), theBoxMax.y(), theBoxMax.z()));
-
   Standard_Real aDepth = 0.0;
-  aRange.GetMin (aDepth);
-
-  if (aDepth == DBL_MAX)
+  BVH_Ray<Standard_Real, 3> aRay(SelectMgr_Vec3(myNearPickedPnt.X(), myNearPickedPnt.Y(), myNearPickedPnt.Z()),
+                                 SelectMgr_Vec3(myViewRayDir.X(), myViewRayDir.Y(), myViewRayDir.Z()));
+  Standard_Real aTimeEnter, aTimeLeave;
+  if (!BVH_Tools<Standard_Real, 3>::RayBoxIntersection (aRay, theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
   {
     gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast());
     aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x()));
@@ -511,6 +504,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
     return !theClipRange.IsClipped (thePickResult.Depth());
   }
 
+  Bnd_Range aRange(Max (aTimeEnter, 0.0), aTimeLeave);
+  aRange.GetMin (aDepth);
+
   if (!theClipRange.GetNearestDepth (aRange, aDepth))
   {
     return Standard_False;
@@ -529,6 +525,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
                                                          const SelectMgr_ViewClipRange& theClipRange,
                                                          SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   if (!hasOverlap (thePnt))
     return Standard_False;
 
@@ -547,6 +546,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
 // =======================================================================
 Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   return hasOverlap (thePnt);
 }
 
@@ -559,6 +561,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
                                                          const SelectMgr_ViewClipRange& theClipRange,
                                                          SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   if (!hasOverlap (thePnt1, thePnt2))
     return Standard_False;
 
@@ -579,6 +584,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPn
                                                          const SelectMgr_ViewClipRange& theClipRange,
                                                          SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
     Standard_Integer aMatchingSegmentsNb = -1;
@@ -637,6 +645,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
                                                          const SelectMgr_ViewClipRange& theClipRange,
                                                          SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
     const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 };
@@ -727,6 +738,19 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
   return !theClipRange.IsClipped (thePickResult.Depth());
 }
 
+// =======================================================================
+// function : GetMousePosition
+// purpose  :
+// =======================================================================
+const gp_Pnt2d& SelectMgr_RectangularFrustum::GetMousePosition() const
+{
+  if (mySelectionType == SelectMgr_SelectionType_Point)
+  {
+    return mySelRectangle.MousePos();
+  }
+  return base_type::GetMousePosition();
+}
+
 // =======================================================================
 // function : DistToGeometryCenter
 // purpose  : Measures distance between 3d projection of user-picked
@@ -734,6 +758,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
 // =======================================================================
 Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::DistToGeometryCenter() should be called after selection frustum initialization");
+
   return theCOG.Distance (myNearPickedPnt) * myScale;
 }
 
@@ -744,6 +771,8 @@ Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt&
 // =======================================================================
 gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
 {
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
+    "SelectMgr_RectangularFrustum::DetectedPoint() should be called only for Point selection type");
   return myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * theDepth / myScale;
 }
 
@@ -780,7 +809,8 @@ void SelectMgr_RectangularFrustum::DumpJson (Standard_OStream& theOStream, Stand
   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myNearPickedPnt)
   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myFarPickedPnt)
   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myViewRayDir)
-  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myMousePos)
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelRectangle.MinPnt())
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelRectangle.MaxPnt())
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myScale)
 }
diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx
index d2d41157b1..4d88c1dac5 100644
--- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx
+++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx
@@ -33,14 +33,46 @@ class SelectMgr_RectangularFrustum : public SelectMgr_Frustum<4>
 {
 public:
 
-  SelectMgr_RectangularFrustum() : myScale (1.0) {};
+  //! Auxiliary structure to define selection primitive (point or box)
+  //! In case of point selection min and max points are identical.
+  struct SelectionRectangle
+  {
+    SelectionRectangle()
+    : myMinPnt(gp_Pnt2d(RealLast(), RealLast())),
+      myMaxPnt(gp_Pnt2d(RealLast(), RealLast())) {}
 
-  //! Builds volume according to the point and given pixel tolerance
-  Standard_EXPORT virtual void Build (const gp_Pnt2d& thePoint) Standard_OVERRIDE;
+    const gp_Pnt2d& MousePos() const { return myMinPnt; }
+    void SetMousePos (const gp_Pnt2d& thePos) { myMinPnt = thePos; myMaxPnt = thePos; }
 
-  //! Builds volume according to the selected rectangle
-  Standard_EXPORT virtual void Build (const gp_Pnt2d& theMinPnt,
-                                      const gp_Pnt2d& theMaxPnt) Standard_OVERRIDE;
+    const gp_Pnt2d& MinPnt() const { return myMinPnt; }
+    void SetMinPnt (const gp_Pnt2d& theMinPnt) { myMinPnt = theMinPnt; }
+
+    const gp_Pnt2d& MaxPnt() const { return myMaxPnt; }
+    void SetMaxPnt (const gp_Pnt2d& theMaxPnt) { myMaxPnt = theMaxPnt; }
+
+  private:
+
+    gp_Pnt2d myMinPnt;
+    gp_Pnt2d myMaxPnt;
+  };
+
+  //! Creates rectangular selecting frustum.
+  Standard_EXPORT SelectMgr_RectangularFrustum();
+
+  //! Initializes volume according to the point and given pixel tolerance
+  Standard_EXPORT void Init (const gp_Pnt2d& thePoint);
+
+  //! Initializes volume according to the selected rectangle
+  Standard_EXPORT void Init (const gp_Pnt2d& theMinPnt,
+                             const gp_Pnt2d& theMaxPnt);
+
+  //! Builds volume according to internal parameters.
+  //! NOTE: it should be called after Init() method
+  Standard_EXPORT virtual void Build() Standard_OVERRIDE;
+
+  //! Checks if it is possible to scale this frustum.
+  //! It is true for frustum built on a single point.
+  Standard_EXPORT virtual Standard_Boolean IsScalable() const Standard_OVERRIDE;
 
   //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
   //!            Note that this method does not perform any checks on type of the frustum.
@@ -49,9 +81,11 @@ public:
   //! There are no default parameters, but in case if:
   //!    - transformation only is needed: @theScaleFactor must be initialized as any negative value;
   //!    - scale only is needed: @theTrsf must be set to gp_Identity.
-  Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScaleFactor,
-                                                                           const gp_GTrsf& theTrsf) const Standard_OVERRIDE;
-
+  //! Builder is an optional argument that represents corresponding settings for re-constructing transformed
+  //! frustum from scratch. Can be null if reconstruction is not expected furthermore.
+  Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScaleFactor,
+                                                                               const gp_GTrsf& theTrsf,
+                                                                               const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE;
 
   // SAT Tests for different objects
 
@@ -100,30 +134,31 @@ public:
                                                      SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Measures distance between 3d projection of user-picked
-  //! screen point and given point theCOG
+  //! screen point and given point theCOG.
+  //! It makes sense only for frustums built on a single point.
   Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const Standard_OVERRIDE;
 
   //! Calculates the point on a view ray that was detected during the run of selection algo by given depth
   Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
 
   //! A set of helper functions that return rectangular selecting frustum data
-  inline const gp_Pnt* GetVertices() const { return myVertices; }
+  const gp_Pnt* GetVertices() const { return myVertices; }
 
   //! Returns projection of 2d mouse picked point or projection
   //! of center of 2d rectangle (for point and rectangular selection
   //! correspondingly) onto near view frustum plane
-  inline const gp_Pnt& GetNearPnt() const { return myNearPickedPnt; }
+  virtual const gp_Pnt& GetNearPnt() const Standard_OVERRIDE { return myNearPickedPnt; }
 
   //! Returns projection of 2d mouse picked point or projection
   //! of center of 2d rectangle (for point and rectangular selection
   //! correspondingly) onto far view frustum plane
-  inline const gp_Pnt& GetFarPnt() const { return myFarPickedPnt; }
+  virtual const gp_Pnt& GetFarPnt() const Standard_OVERRIDE { return myFarPickedPnt; }
 
-  //! Return view ray direction.
-  const gp_Dir& GetViewRayDirection() const { return myViewRayDir; }
+  //! Returns view ray direction.
+  virtual const gp_Dir& GetViewRayDirection() const Standard_OVERRIDE { return myViewRayDir; }
 
-  //! Return mouse coordinates.
-  const gp_Pnt2d& GetMousePosition() const { return myMousePos; }
+  //! Returns current mouse coordinates.
+  Standard_EXPORT virtual const gp_Pnt2d& GetMousePosition() const Standard_OVERRIDE;
 
   //! Stores plane equation coefficients (in the following form:
   //! Ax + By + Cz + D = 0) to the given vector
@@ -154,10 +189,10 @@ private:
 
 private:
 
+  SelectionRectangle      mySelRectangle;              //!< parameters for selection by point or box (it is used to build frustum)
   gp_Pnt                  myNearPickedPnt;             //!< 3d projection of user-picked selection point onto near view plane
   gp_Pnt                  myFarPickedPnt;              //!< 3d projection of user-picked selection point onto far view plane
-  gp_Dir                  myViewRayDir;
-  gp_Pnt2d                myMousePos;                  //!< Mouse coordinates
+  gp_Dir                  myViewRayDir;                //!< view ray direction
   Standard_Real           myScale;                     //!< Scale factor of applied transformation, if there was any
 
 };
diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
index 3df0a5b92f..b7ef91848b 100644
--- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
+++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
@@ -14,22 +14,22 @@
 // commercial license or contractual agreement.
 
 #include <SelectMgr_SelectingVolumeManager.hxx>
+
+#include <Graphic3d_SequenceOfHClipPlane.hxx>
+#include <SelectMgr_RectangularFrustum.hxx>
+#include <SelectMgr_TriangularFrustumSet.hxx>
+
+#include <BVH_Tools.hxx>
 #include <Standard_Dump.hxx>
 
 //=======================================================================
 // function : SelectMgr_SelectingVolumeManager
 // purpose  : Creates instances of all available selecting volume types
 //=======================================================================
-SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums)
+SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager()
+: myActiveSelectingVolume (NULL),
+  myToAllowOverlap (Standard_False)
 {
-  myActiveSelectionType = Unknown;
-  myToAllowOverlap = Standard_False;
-
-  if (theToAllocateFrustums)
-  {
-    mySelectingVolumes[Frustum] = new SelectMgr_RectangularFrustum();
-    mySelectingVolumes[FrustumSet] = new SelectMgr_TriangularFrustumSet();
-  }
 }
 
 //=======================================================================
@@ -51,16 +51,14 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans
                                                                                       const gp_GTrsf& theTrsf,
                                                                                       const Handle(SelectMgr_FrustumBuilder)& theBuilder) const
 {
-  SelectMgr_SelectingVolumeManager aMgr (Standard_False);
-
-  if (myActiveSelectionType == Unknown)
+  SelectMgr_SelectingVolumeManager aMgr;
+  if (myActiveSelectingVolume.IsNull())
+  {
     return aMgr;
+  }
 
-  aMgr.myActiveSelectionType = myActiveSelectionType;
-  aMgr.mySelectingVolumes[myActiveSelectionType / 2]
-    = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf);
+  aMgr.myActiveSelectingVolume = myActiveSelectingVolume->ScaleAndTransform (theScaleFactor, theTrsf, theBuilder);
   aMgr.myToAllowOverlap = myToAllowOverlap;
-  aMgr.mySelectingVolumes[myActiveSelectionType / 2]->SetBuilder (theBuilder);
   aMgr.myViewClipPlanes = myViewClipPlanes;
   aMgr.myObjectClipPlanes = myObjectClipPlanes;
   aMgr.myViewClipRange = myViewClipRange;
@@ -74,29 +72,36 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans
 //=======================================================================
 Standard_Integer SelectMgr_SelectingVolumeManager::GetActiveSelectionType() const
 {
-  return myActiveSelectionType;
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return SelectMgr_SelectionType_Unknown;
+  }
+  return myActiveSelectingVolume->GetSelectionType();
 }
 
 //=======================================================================
-// function : SetActiveSelectionType
+// function : Camera
 // purpose  :
 //=======================================================================
-void SelectMgr_SelectingVolumeManager::SetActiveSelectionType (const SelectionType& theType)
+const Handle(Graphic3d_Camera)& SelectMgr_SelectingVolumeManager::Camera() const
 {
-  myActiveSelectionType = theType;
+  if (myActiveSelectingVolume.IsNull())
+  {
+    static const Handle(Graphic3d_Camera) anEmptyCamera;
+    return anEmptyCamera;
+  }
+  return myActiveSelectingVolume->Camera();
 }
 
 //=======================================================================
 // function : SetCamera
-// purpose  : Updates camera projection and orientation matrices in all
-//            selecting volumes
+// purpose  :
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::SetCamera (const Handle(Graphic3d_Camera) theCamera)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
-  {
-    mySelectingVolumes[anIdx]->SetCamera (theCamera);
-  }
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetCamera() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetCamera (theCamera);
 }
 
 //=======================================================================
@@ -109,10 +114,9 @@ void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProj
                                                   const Standard_Boolean theIsOrthographic,
                                                   const Graphic3d_WorldViewProjState& theWVPState)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
-  {
-    mySelectingVolumes[anIdx]->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState);
-  }
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetCamera() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState);
 }
 
 //=======================================================================
@@ -122,7 +126,12 @@ void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProj
 //=======================================================================
 const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() const
 {
-  return mySelectingVolumes[Frustum]->ProjectionMatrix();
+  if (myActiveSelectingVolume.IsNull())
+  {
+    static const Graphic3d_Mat4d anEmptyMatrix;
+    return anEmptyMatrix;
+  }
+  return myActiveSelectingVolume->ProjectionMatrix();
 }
 
 //=======================================================================
@@ -132,7 +141,12 @@ const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() cons
 //=======================================================================
 const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const
 {
-  return mySelectingVolumes[Frustum]->WorldViewMatrix();
+  if (myActiveSelectingVolume.IsNull())
+  {
+    static const Graphic3d_Mat4d anEmptyMatrix;
+    return anEmptyMatrix;
+  }
+  return myActiveSelectingVolume->WorldViewMatrix();
 }
 
 //=======================================================================
@@ -142,7 +156,12 @@ const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const
 //=======================================================================
 const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewProjState() const
 {
-  return mySelectingVolumes[Frustum]->WorldViewProjState();
+  if (myActiveSelectingVolume.IsNull())
+  {
+    static const Graphic3d_WorldViewProjState anEmptyState;
+    return anEmptyState;
+  }
+  return myActiveSelectingVolume->WorldViewProjState();
 }
 
 //=======================================================================
@@ -151,7 +170,23 @@ const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewP
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) const
 {
-  mySelectingVolumes[Frustum]->WindowSize (theWidth, theHeight);
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return;
+  }
+  myActiveSelectingVolume->WindowSize (theWidth, theHeight);
+}
+
+//=======================================================================
+// function : SetWindowSize
+// purpose  : Updates window size in all selecting volumes
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth,
+                                                      const Standard_Integer theHeight)
+{
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetWindowSize() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetWindowSize (theWidth, theHeight);
 }
 
 //=======================================================================
@@ -163,23 +198,9 @@ void SelectMgr_SelectingVolumeManager::SetViewport (const Standard_Real theX,
                                                     const Standard_Real theWidth,
                                                     const Standard_Real theHeight)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
-  {
-    mySelectingVolumes[anIdx]->SetViewport (theX, theY, theWidth, theHeight);
-  }
-}
-
-//=======================================================================
-// function : SetWindowSize
-// purpose  : Updates window size in all selecting volumes
-//=======================================================================
-void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth,
-                                                      const Standard_Integer theHeight)
-{
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
-  {
-    mySelectingVolumes[anIdx]->SetWindowSize (theWidth, theHeight);
-  }
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetViewport() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetViewport (theX, theY, theWidth, theHeight);
 }
 
 //=======================================================================
@@ -188,49 +209,107 @@ void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer the
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetPixelTolerance() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetPixelTolerance (theTolerance);
+}
+
+//=======================================================================
+// function : InitPointSelectingVolume
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::InitPointSelectingVolume (const gp_Pnt2d& thePoint)
+{
+  Handle(SelectMgr_RectangularFrustum) aPntVolume = Handle(SelectMgr_RectangularFrustum)::DownCast(myActiveSelectingVolume);
+  if (aPntVolume.IsNull())
   {
-    mySelectingVolumes[anIdx]->SetPixelTolerance (theTolerance);
+    aPntVolume = new SelectMgr_RectangularFrustum();
   }
+  aPntVolume->Init (thePoint);
+  myActiveSelectingVolume = aPntVolume;
+}
+
+//=======================================================================
+// function : InitBoxSelectingVolume
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::InitBoxSelectingVolume (const gp_Pnt2d& theMinPt,
+                                                               const gp_Pnt2d& theMaxPt)
+{
+  Handle(SelectMgr_RectangularFrustum) aBoxVolume = Handle(SelectMgr_RectangularFrustum)::DownCast(myActiveSelectingVolume);
+  if (aBoxVolume.IsNull())
+  {
+    aBoxVolume = new SelectMgr_RectangularFrustum();
+  }
+  aBoxVolume->Init (theMinPt, theMaxPt);
+  myActiveSelectingVolume = aBoxVolume;
+}
+
+//=======================================================================
+// function : InitPolylineSelectingVolume
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::InitPolylineSelectingVolume (const TColgp_Array1OfPnt2d& thePoints)
+{
+  Handle(SelectMgr_TriangularFrustumSet) aPolylineVolume = Handle(SelectMgr_TriangularFrustumSet)::DownCast(myActiveSelectingVolume);
+  if (aPolylineVolume.IsNull())
+  {
+    aPolylineVolume = new SelectMgr_TriangularFrustumSet();
+  }
+  aPolylineVolume->Init (thePoints);
+  myActiveSelectingVolume = aPolylineVolume;
+  aPolylineVolume->SetAllowOverlapDetection (IsOverlapAllowed());
+}
+
+//=======================================================================
+// function : InitSelectingVolume
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::InitSelectingVolume(const Handle(SelectMgr_BaseIntersector)& theVolume)
+{
+  myActiveSelectingVolume = theVolume;
 }
 
 //=======================================================================
 // function : BuildSelectingVolume
-// purpose  : Builds rectangular selecting frustum for point selection
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::BuildSelectingVolume()
+{
+  Standard_ASSERT_RAISE (!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::BuildSelectingVolume() should be called after initialization of active selection volume.");
+  myActiveSelectingVolume->Build();
+}
+
+//=======================================================================
+// function : BuildSelectingVolume
+// purpose  :
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& thePoint)
 {
-  if (myActiveSelectionType != Point)
-    return;
-
-  mySelectingVolumes[Frustum]->Build (thePoint);
+  InitPointSelectingVolume (thePoint);
+  myActiveSelectingVolume->Build();
 }
 
 //=======================================================================
 // function : BuildSelectingVolume
-// purpose  : Builds rectangular selecting frustum for box selection
+// purpose  :
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& theMinPt,
                                                              const gp_Pnt2d& theMaxPt)
 {
-  if (myActiveSelectionType != Box)
-    return;
-
-  mySelectingVolumes[Frustum]->Build (theMinPt, theMaxPt);
+  InitBoxSelectingVolume (theMinPt, theMaxPt);
+  myActiveSelectingVolume->Build();
 }
 
 //=======================================================================
 // function : BuildSelectingVolume
-// purpose  : Builds set of triangular selecting frustums for polyline
-//            selection
+// purpose  :
 //=======================================================================
 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints)
 {
-  if (myActiveSelectionType != Polyline)
-    return;
-
-  mySelectingVolumes[FrustumSet]->Build (thePoints);
-  Handle(SelectMgr_TriangularFrustumSet)::DownCast (mySelectingVolumes[FrustumSet])->SetAllowOverlapDetection (IsOverlapAllowed());
+  InitPolylineSelectingVolume (thePoints);
+  myActiveSelectingVolume->Build();
 }
 
 //=======================================================================
@@ -242,10 +321,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec
                                                              const SelectMgr_Vec3& theBoxMax,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (theBoxMin, theBoxMax, myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -256,10 +337,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec
                                                              const SelectMgr_Vec3& theBoxMax,
                                                              Standard_Boolean*     theInside) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theInside);
+  return myActiveSelectingVolume->Overlaps (theBoxMin, theBoxMax, theInside);
 }
 
 //=======================================================================
@@ -269,10 +352,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec
 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt, myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (thePnt, myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -281,10 +366,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePn
 //=======================================================================
 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt);
+  return myActiveSelectingVolume->Overlaps (thePnt);
 }
 
 //=======================================================================
@@ -298,11 +385,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp
                                                              Standard_Integer theSensType,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts->Array1(), (Select3D_TypeOfSensitivity)theSensType,
-                                                                  myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (theArrayOfPnts->Array1(), (Select3D_TypeOfSensitivity)theSensType,
+                                            myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -316,11 +405,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const TColgp_Array1
                                                              Standard_Integer theSensType,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType,
-                                                                  myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType,
+                                            myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -331,10 +422,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt
                                                              const gp_Pnt& thePt2,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (thePt1, thePt2, myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -350,11 +443,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt
                                                              Standard_Integer theSensType,
                                                              SelectBasics_PickResult& thePickResult) const
 {
-  if (myActiveSelectionType == Unknown)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return Standard_False;
+  }
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, thePt3, (Select3D_TypeOfSensitivity)theSensType,
-                                                                  myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->Overlaps (thePt1, thePt2, thePt3, (Select3D_TypeOfSensitivity)theSensType,
+                                            myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -364,10 +459,11 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt
 //=======================================================================
 Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_Pnt& theCOG) const
 {
-  if (myActiveSelectionType == Unknown)
-    return Standard_False;
-
-  return mySelectingVolumes[myActiveSelectionType / 2]->DistToGeometryCenter (theCOG);
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return RealLast();
+  }
+  return myActiveSelectingVolume->DistToGeometryCenter (theCOG);
 }
 
 // =======================================================================
@@ -378,12 +474,9 @@ Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_P
 // =======================================================================
 gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const
 {
-  if (myActiveSelectionType != Point)
-  {
-    throw Standard_ProgramError("SelectMgr_SelectingVolumeManager::DetectedPoint() should be called only for Point selection type");
-  }
-
-  return mySelectingVolumes[Frustum]->DetectedPoint (theDepth);
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::DetectedPoint() should be called after initialization of selection volume");
+  return myActiveSelectingVolume->DetectedPoint (theDepth);
 }
 
 //=======================================================================
@@ -403,7 +496,7 @@ void SelectMgr_SelectingVolumeManager::AllowOverlapDetection (const Standard_Boo
 //=======================================================================
 Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
 {
-  return myToAllowOverlap || myActiveSelectionType == Point;
+  return myToAllowOverlap || GetActiveSelectionType() == SelectMgr_SelectionType_Point;
 }
 
 //=======================================================================
@@ -412,11 +505,17 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
 //=======================================================================
 const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const
 {
-  if (myActiveSelectionType == Polyline)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return NULL;
-
-  const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
-  return aFr->GetVertices();
+  }
+  const SelectMgr_RectangularFrustum* aRectFrustum =
+    static_cast<const SelectMgr_RectangularFrustum*> (myActiveSelectingVolume.get());
+  if (aRectFrustum == NULL)
+  {
+    return NULL;
+  }
+  return aRectFrustum->GetVertices();
 }
 
 //=======================================================================
@@ -425,11 +524,11 @@ const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const
 //=======================================================================
 gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPickedPnt() const
 {
-  if (myActiveSelectionType == Polyline)
+  if (myActiveSelectingVolume.IsNull())
+  {
     return gp_Pnt();
-
-  const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
-  return aFr->GetNearPnt();
+  }
+  return myActiveSelectingVolume->GetNearPnt();
 }
 
 //=======================================================================
@@ -438,11 +537,64 @@ gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPickedPnt() const
 //=======================================================================
 gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPickedPnt() const
 {
-  if (myActiveSelectionType == Polyline)
-    return gp_Pnt();
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return gp_Pnt(RealLast(), RealLast(), RealLast());
+  }
+  return myActiveSelectingVolume->GetFarPnt();
+}
 
-  const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
-  return aFr->GetFarPnt();
+//=======================================================================
+// function : GetViewRayDirection
+// purpose  :
+//=======================================================================
+gp_Dir SelectMgr_SelectingVolumeManager::GetViewRayDirection() const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return gp_Dir();
+  }
+  return myActiveSelectingVolume->GetViewRayDirection();
+}
+
+//=======================================================================
+// function : IsScalableActiveVolume
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_SelectingVolumeManager::IsScalableActiveVolume() const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return Standard_False;
+  }
+  return myActiveSelectingVolume->IsScalable();
+}
+
+//=======================================================================
+// function : GetMousePosition
+// purpose  :
+//=======================================================================
+gp_Pnt2d SelectMgr_SelectingVolumeManager::GetMousePosition() const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return gp_Pnt2d(RealLast(), RealLast());
+  }
+  return myActiveSelectingVolume->GetMousePosition();
+}
+
+//=======================================================================
+// function : GetPlanes
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    thePlaneEquations.Clear();
+    return;
+  }
+  return myActiveSelectingVolume->GetPlanes (thePlaneEquations);
 }
 
 //=======================================================================
@@ -455,21 +607,26 @@ void SelectMgr_SelectingVolumeManager::SetViewClipping (const Handle(Graphic3d_S
 {
   myViewClipPlanes   = theViewPlanes;
   myObjectClipPlanes = theObjPlanes;
-  if (myActiveSelectionType != Point)
+  if (GetActiveSelectionType() != SelectMgr_SelectionType_Point)
+  {
     return;
+  }
 
   const SelectMgr_SelectingVolumeManager* aWorldSelMgr = theWorldSelMgr != NULL ? theWorldSelMgr : this;
-  const SelectMgr_RectangularFrustum* aFrustum = static_cast<const SelectMgr_RectangularFrustum*>(aWorldSelMgr->mySelectingVolumes[Frustum].get());
   myViewClipRange.SetVoid();
   if (!theViewPlanes.IsNull()
    && !theViewPlanes->IsEmpty())
   {
-    myViewClipRange.AddClippingPlanes (*theViewPlanes, gp_Ax1 (aFrustum->GetNearPnt(), aFrustum->GetViewRayDirection()));
+    myViewClipRange.AddClippingPlanes (*theViewPlanes,
+      gp_Ax1(aWorldSelMgr->myActiveSelectingVolume->GetNearPnt(),
+             aWorldSelMgr->myActiveSelectingVolume->GetViewRayDirection()));
   }
   if (!theObjPlanes.IsNull()
    && !theObjPlanes->IsEmpty())
   {
-    myViewClipRange.AddClippingPlanes (*theObjPlanes, gp_Ax1 (aFrustum->GetNearPnt(), aFrustum->GetViewRayDirection()));
+    myViewClipRange.AddClippingPlanes (*theObjPlanes,
+      gp_Ax1(aWorldSelMgr->myActiveSelectingVolume->GetNearPnt(),
+             aWorldSelMgr->myActiveSelectingVolume->GetViewRayDirection()));
   }
 }
 
@@ -492,12 +649,7 @@ void SelectMgr_SelectingVolumeManager::DumpJson (Standard_OStream& theOStream, S
 {
   OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_SelectingVolumeManager)
 
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
-  {
-    const Handle(SelectMgr_BaseFrustum)& aSelectingVolume = mySelectingVolumes[anIdx];
-    OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aSelectingVolume.get())
-  }
-
+  OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myActiveSelectingVolume.get())
   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myViewClipPlanes.get())
   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myObjectClipPlanes.get())
 
diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
index 12b492761f..76f2d04e34 100644
--- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
+++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
@@ -16,28 +16,54 @@
 #ifndef _SelectMgr_SelectingVolumeManager_HeaderFile
 #define _SelectMgr_SelectingVolumeManager_HeaderFile
 
-#include <NCollection_Handle.hxx>
-
-#include <Graphic3d_Camera.hxx>
-#include <Graphic3d_SequenceOfHClipPlane.hxx>
-#include <Graphic3d_WorldViewProjState.hxx>
-
-#include <SelectMgr_BaseFrustum.hxx>
-#include <SelectMgr_RectangularFrustum.hxx>
-#include <SelectMgr_TriangularFrustumSet.hxx>
 #include <SelectBasics_SelectingVolumeManager.hxx>
 
+#include <SelectMgr_BaseIntersector.hxx>
+#include <SelectMgr_VectorTypes.hxx>
+#include <SelectMgr_ViewClipRange.hxx>
+
 //! This class is used to switch between active selecting volumes depending
-//! on selection type chosen by the user
+//! on selection type chosen by the user.
+//! The sample of correct selection volume initialization procedure:
+//! @code
+//!   aMgr.InitPointSelectingVolume (aMousePos);
+//!   aMgr.SetPixelTolerance (aTolerance);
+//!   aMgr.SetCamera (aCamera);
+//!   aMgr.SetWindowSize (aWidth, aHeight);
+//!   aMgr.BuildSelectingVolume();
+//! @endcode
 class SelectMgr_SelectingVolumeManager : public SelectBasics_SelectingVolumeManager
 {
 public:
 
   //! Creates instances of all available selecting volume types
-  Standard_EXPORT SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums = Standard_True);
+  Standard_EXPORT SelectMgr_SelectingVolumeManager();
 
   virtual ~SelectMgr_SelectingVolumeManager() {}
 
+  //! Creates, initializes and activates rectangular selecting frustum for point selection
+  Standard_EXPORT void InitPointSelectingVolume (const gp_Pnt2d& thePoint);
+
+  //! Creates, initializes and activates rectangular selecting frustum for box selection
+  Standard_EXPORT void InitBoxSelectingVolume (const gp_Pnt2d& theMinPt,
+                                               const gp_Pnt2d& theMaxPt);
+
+  //! Creates, initializes and activates set of triangular selecting frustums for polyline selection
+  Standard_EXPORT void InitPolylineSelectingVolume (const TColgp_Array1OfPnt2d& thePoints);
+
+  //! Sets as active the custom selecting volume
+  Standard_EXPORT void InitSelectingVolume (const Handle(SelectMgr_BaseIntersector)& theVolume);
+
+  //! Builds previously initialized selecting volume.
+  Standard_EXPORT void BuildSelectingVolume();
+
+  //! Returns active selecting volume that was built during last
+  //! run of OCCT selection mechanism
+  const Handle(SelectMgr_BaseIntersector)& ActiveVolume() const { return myActiveSelectingVolume; }
+
+  // Returns active selection type (point, box, polyline)
+  Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE;
+
   //! IMPORTANT: Scaling makes sense only for frustum built on a single point!
   //!            Note that this method does not perform any checks on type of the frustum.
   //!
@@ -50,19 +76,21 @@ public:
   //! frustum from scratch. Can be null if reconstruction is not expected furthermore.
   Standard_EXPORT virtual SelectMgr_SelectingVolumeManager ScaleAndTransform (const Standard_Integer theScaleFactor,
                                                                               const gp_GTrsf& theTrsf,
-                                                                              const Handle(SelectMgr_FrustumBuilder)& theBuilder = NULL) const;
+                                                                              const Handle(SelectMgr_FrustumBuilder)& theBuilder) const;
 
-  Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE;
-
-  Standard_EXPORT void SetActiveSelectionType (const SelectionType& theType);
+public:
 
   //! Returns current camera definition.
-  const Handle(Graphic3d_Camera)& Camera() const { return mySelectingVolumes[Frustum]->Camera(); }
+  Standard_EXPORT const Handle(Graphic3d_Camera)& Camera() const;
 
   //! Updates camera projection and orientation matrices in all selecting volumes
+  //! Note: this method should be called after selection volume building
+  //! else exception will be thrown
   Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera) theCamera);
 
   //! Updates camera projection and orientation matrices in all selecting volumes
+  //! Note: this method should be called after selection volume building
+  //! else exception will be thrown
   Standard_EXPORT void SetCamera (const Graphic3d_Mat4d& theProjection,
                                   const Graphic3d_Mat4d& theWorldView,
                                   const Standard_Boolean theIsOrthographic,
@@ -80,29 +108,24 @@ public:
   Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const;
 
   //! Updates viewport in all selecting volumes
+  //! Note: this method should be called after selection volume building
+  //! else exception will be thrown
   Standard_EXPORT void SetViewport (const Standard_Real theX,
                                     const Standard_Real theY,
                                     const Standard_Real theWidth,
                                     const Standard_Real theHeight);
 
   //! Updates pixel tolerance in all selecting volumes
+  //! Note: this method should be called after selection volume building
+  //! else exception will be thrown
   Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance);
 
   //! Updates window size in all selecting volumes
+  //! Note: this method should be called after selection volume building
+  //! else exception will be thrown
   Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight);
 
 
-  //! Builds rectangular selecting frustum for point selection
-  Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& thePoint);
-
-  //! Builds rectangular selecting frustum for box selection
-  Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& theMinPt,
-                                             const gp_Pnt2d& theMaxPt);
-
-  //! Builds set of triangular selecting frustums for polyline selection
-  Standard_EXPORT void BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints);
-
-
   //! SAT intersection test between defined volume and given axis-aligned box
   Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
                                                      const SelectMgr_Vec3& theBoxMax,
@@ -203,47 +226,50 @@ public:
   //! correspondingly) onto far view frustum plane
   Standard_EXPORT virtual gp_Pnt GetFarPickedPnt() const Standard_OVERRIDE;
 
-  //! Return mouse coordinates for Point selection mode.
-  virtual gp_Pnt2d GetMousePosition() const Standard_OVERRIDE
-  {
-    if (myActiveSelectionType != Point)
-    {
-      return gp_Pnt2d (RealLast(), RealLast());
-    }
-    const SelectMgr_RectangularFrustum* aFr = reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
-    return aFr->GetMousePosition();
-  }
+  //! Valid only for point and rectangular selection.
+  //! Returns view ray direction
+  Standard_EXPORT virtual gp_Dir GetViewRayDirection() const Standard_OVERRIDE;
 
-  //! Returns active selecting volume that was built during last
-  //! run of OCCT selection mechanism
-  Handle(SelectMgr_BaseFrustum) ActiveVolume() const
-  {
-    if (myActiveSelectionType == Unknown)
-      return Handle(SelectMgr_BaseFrustum)();
+  //! Checks if it is possible to scale current active selecting volume
+  Standard_EXPORT virtual Standard_Boolean IsScalableActiveVolume() const Standard_OVERRIDE;
 
-    return mySelectingVolumes[myActiveSelectionType / 2];
-  }
+  //! Returns mouse coordinates for Point selection mode.
+  //! @return infinite point in case of unsupport of mouse position for this active selection volume.
+  Standard_EXPORT virtual gp_Pnt2d GetMousePosition() const Standard_OVERRIDE;
 
   //! Stores plane equation coefficients (in the following form:
   //! Ax + By + Cz + D = 0) to the given vector
-  virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE
-  {
-    if (myActiveSelectionType == Unknown)
-    {
-      thePlaneEquations.Clear();
-      return;
-    }
-
-    return mySelectingVolumes[myActiveSelectionType / 2]->GetPlanes (thePlaneEquations);
-  }
+  Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;
 
   //! Dumps the content of me into the stream
-  Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+  Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
+
+public:
+
+  Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead")
+  static const SelectMgr_SelectionType Point = SelectMgr_SelectionType_Point;
+
+  Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead")
+  static const SelectMgr_SelectionType Box = SelectMgr_SelectionType_Point;
+
+  Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead")
+  static const SelectMgr_SelectionType Polyline = SelectMgr_SelectionType_Point;
+
+  Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead")
+  static const SelectMgr_SelectionType Unknown = SelectMgr_SelectionType_Point;
+
+  Standard_DEPRECATED("Deprecated method - InitPointSelectingVolume() and Build() methods should be used instead")
+  Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& thePoint);
+
+  Standard_DEPRECATED("Deprecated method - InitBoxSelectingVolume() and Build() should be used instead")
+  Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& theMinPt,
+                                             const gp_Pnt2d& theMaxPt);
+
+  Standard_DEPRECATED("Deprecated method - InitPolylineSelectingVolume() and Build() should be used instead")
+  Standard_EXPORT void BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints);
 
 private:
-  enum { Frustum, FrustumSet, VolumeTypesNb };       //!< Defines the amount of available selecting volumes
-
-  Handle(SelectMgr_BaseFrustum)          mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes
+  Handle(SelectMgr_BaseIntersector)      myActiveSelectingVolume;
   Handle(Graphic3d_SequenceOfHClipPlane) myViewClipPlanes;                  //!< view clipping planes
   Handle(Graphic3d_SequenceOfHClipPlane) myObjectClipPlanes;                //!< object clipping planes
   SelectMgr_ViewClipRange                myViewClipRange;
diff --git a/src/SelectMgr/SelectMgr_SelectionType.hxx b/src/SelectMgr/SelectMgr_SelectionType.hxx
new file mode 100644
index 0000000000..00e6e43cd2
--- /dev/null
+++ b/src/SelectMgr/SelectMgr_SelectionType.hxx
@@ -0,0 +1,26 @@
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _SelectMgr_SelectionType_HeaderFile
+#define _SelectMgr_SelectionType_HeaderFile
+
+//! Possible selection types
+enum SelectMgr_SelectionType
+{
+  SelectMgr_SelectionType_Unknown = -1, //!< undefined selection type
+  SelectMgr_SelectionType_Point,        //!< selection by point (frustum with some tolerance or axis)
+  SelectMgr_SelectionType_Box,          //!< rectangle selection
+  SelectMgr_SelectionType_Polyline      //!< polygonal selection
+};
+
+#endif // _SelectMgr_SelectionType_HeaderFile
diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx
index e7b9aa37c4..8395cb8a7a 100644
--- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx
+++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx
@@ -15,6 +15,8 @@
 
 #include <SelectMgr_TriangularFrustum.hxx>
 
+#include <SelectMgr_FrustumBuilder.hxx>
+
 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient)
 
 SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum()
@@ -77,27 +79,36 @@ void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFr
 }
 
 //=======================================================================
-// function : SelectMgr_TriangularFrustum
-// purpose  : Creates new triangular frustum with bases of triangles with
-//            vertices theP1, theP2 and theP3 projections onto near and
-//            far view frustum planes
+// function : Init
+// purpose  :
 //=======================================================================
-void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1,
-                                         const gp_Pnt2d& theP2,
-                                         const gp_Pnt2d& theP3)
+void SelectMgr_TriangularFrustum::Init (const gp_Pnt2d& theP1,
+                                        const gp_Pnt2d& theP2,
+                                        const gp_Pnt2d& theP3)
+{
+  mySelTriangle.Points[0] = theP1;
+  mySelTriangle.Points[1] = theP2;
+  mySelTriangle.Points[2] = theP3;
+}
+
+//=======================================================================
+// function : Build
+// purpose  :
+//=======================================================================
+void SelectMgr_TriangularFrustum::Build()
 {
   // V0_Near
-  myVertices[0] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 0.0);
+  myVertices[0] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 0.0);
   // V1_Near
-  myVertices[1] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 0.0);
+  myVertices[1] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 0.0);
   // V2_Near
-  myVertices[2] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 0.0);
+  myVertices[2] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 0.0);
   // V0_Far
-  myVertices[3] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 1.0);
+  myVertices[3] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 1.0);
   // V1_Far
-  myVertices[4] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 1.0);
+  myVertices[4] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 1.0);
   // V2_Far
-  myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0);
+  myVertices[5] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 1.0);
 
   // V0_Near - V0_Far
   myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ();
@@ -128,8 +139,9 @@ void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1,
 //                  as any negative value;
 //                - scale only is needed: @theTrsf must be set to gp_Identity.
 //=======================================================================
-Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/,
-                                                                              const gp_GTrsf& theTrsf) const
+Handle(SelectMgr_BaseIntersector) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer,
+                                                                                  const gp_GTrsf& theTrsf,
+                                                                                  const Handle(SelectMgr_FrustumBuilder)&) const
 {
   Handle(SelectMgr_TriangularFrustum) aRes = new SelectMgr_TriangularFrustum();
 
@@ -159,6 +171,8 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (co
 
   cacheVertexProjections (aRes.get());
 
+  aRes->mySelTriangle = mySelTriangle;
+
   return aRes;
 }
 
diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx
index 2a37887542..aacf530652 100644
--- a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx
+++ b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx
@@ -23,25 +23,39 @@
 //! frustum and sensitive entities.
 //! Overlap detection tests are implemented according to the terms of separating axis
 //! theorem (SAT).
+//! NOTE: the object of this class can be created only as part of SelectMgr_TriangularFrustumSet.
 class SelectMgr_TriangularFrustum : public SelectMgr_Frustum<3>
 {
-public:
+protected:
 
   //! Creates new triangular frustum with bases of triangles with vertices theP1,
   //! theP2 and theP3 projections onto near and far view frustum planes
-  SelectMgr_TriangularFrustum() {};
+  SelectMgr_TriangularFrustum() {}
+
+public:
+
+  //! Auxiliary structure to define selection triangle
+  struct SelectionTriangle
+  {
+    gp_Pnt2d Points[3];
+  };
 
   Standard_EXPORT ~SelectMgr_TriangularFrustum();
 
+  //! Initializes selection triangle by input points
+  Standard_EXPORT void Init (const gp_Pnt2d& theP1,
+                             const gp_Pnt2d& theP2,
+                             const gp_Pnt2d& theP3);
+
   //! Creates new triangular frustum with bases of triangles with vertices theP1, theP2 and theP3
   //! projections onto near and far view frustum planes (only for triangular frustums)
-  Standard_EXPORT virtual void Build (const gp_Pnt2d& theP1,
-                                      const gp_Pnt2d& theP2,
-                                      const gp_Pnt2d& theP3) Standard_OVERRIDE;
+  //! NOTE: it should be called after Init() method
+  Standard_EXPORT virtual void Build() Standard_OVERRIDE;
 
   //! Returns a copy of the frustum transformed according to the matrix given
-  Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale,
-                                                                           const gp_GTrsf& theTrsf) const Standard_OVERRIDE;
+  Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScale,
+                                                                               const gp_GTrsf& theTrsf,
+                                                                               const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE;
 
   // SAT Tests for different objects
 
@@ -100,7 +114,15 @@ private:
 
   void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const;
 
-  DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,SelectMgr_Frustum<3>)
+protected:
+
+  SelectionTriangle mySelTriangle; //!< parameters of selection triangle (it is used to build triangle frustum)
+
+public:
+
+  DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum, SelectMgr_Frustum<3>)
+
+  friend class SelectMgr_TriangularFrustumSet;
 };
 
 #endif // _SelectMgr_TriangularFrustum_HeaderFile
diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
index c7f50bf5bd..977201a7ad 100644
--- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
+++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
@@ -16,9 +16,9 @@
 #include <BRepMesh_DataStructureOfDelaun.hxx>
 #include <BRepMesh_Delaun.hxx>
 #include <NCollection_IncAllocator.hxx>
+#include <SelectMgr_FrustumBuilder.hxx>
 
 #include <SelectMgr_TriangularFrustumSet.hxx>
-#include <SelectMgr_TriangularFrustum.hxx>
 
 #define MEMORY_BLOCK_SIZE 512 * 7
 
@@ -28,42 +28,61 @@
 // =======================================================================
 SelectMgr_TriangularFrustumSet::SelectMgr_TriangularFrustumSet()
 :  myToAllowOverlap (Standard_False)
-{}
+{
+}
 
 // =======================================================================
-// function : BuildSelectingVolume
+// function : Init
+// purpose  :
+// =======================================================================
+void SelectMgr_TriangularFrustumSet::Init (const TColgp_Array1OfPnt2d& thePoints)
+{
+  if (mySelPolyline.Points.IsNull())
+  {
+    mySelPolyline.Points = new TColgp_HArray1OfPnt2d (thePoints.Lower(), thePoints.Upper());
+  }
+  mySelPolyline.Points->Resize (thePoints.Lower(), thePoints.Upper(), false);
+  *mySelPolyline.Points = thePoints;
+  mySelectionType = SelectMgr_SelectionType_Polyline;
+}
+
+// =======================================================================
+// function : Build
 // purpose  : Meshes polygon bounded by polyline. Than organizes a set of
 //            triangular frustums, where each triangle's projection onto
 //            near and far view frustum planes is considered as a frustum
 //            base
 // =======================================================================
-void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoints)
+void SelectMgr_TriangularFrustumSet::Build()
 {
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline || !mySelPolyline.Points.IsNull(),
+    "Error! SelectMgr_TriangularFrustumSet::Build() should be called after selection frustum initialization");
+
   myFrustums.Clear();
 
   Handle(NCollection_IncAllocator) anAllocator = new NCollection_IncAllocator (MEMORY_BLOCK_SIZE);
   Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun (anAllocator);
-  Standard_Integer aPtsLower = thePoints.Lower();
-  Standard_Integer aPtsUpper = thePoints.Upper();
-  IMeshData::VectorOfInteger anIndexes (thePoints.Size(), anAllocator);
-  myBoundaryPoints.Resize (aPtsLower, aPtsLower + 2 * (thePoints.Size()) - 1, Standard_False);
+  Standard_Integer aPtsLower = mySelPolyline.Points->Lower();
+  Standard_Integer aPtsUpper = mySelPolyline.Points->Upper();
+  IMeshData::VectorOfInteger anIndexes (mySelPolyline.Points->Size(), anAllocator);
+  myBoundaryPoints.Resize (aPtsLower, aPtsLower + 2 * (mySelPolyline.Points->Size()) - 1, Standard_False);
 
   for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx)
   {
-    BRepMesh_Vertex aVertex (thePoints.Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
+    BRepMesh_Vertex aVertex (mySelPolyline.Points->Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
     anIndexes.Append (aMeshStructure->AddNode (aVertex));
     const gp_Pnt aNearPnt = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 0.0);
     const gp_Pnt aFarPnt  = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 1.0);
     myBoundaryPoints.SetValue (aPtIdx, aNearPnt);
-    myBoundaryPoints.SetValue (aPtIdx + thePoints.Size(), aFarPnt);
+    myBoundaryPoints.SetValue (aPtIdx + mySelPolyline.Points->Size(), aFarPnt);
   }
 
   Standard_Real aPtSum = 0;
   for (Standard_Integer aIdx = aPtsLower; aIdx <= aPtsUpper; ++aIdx)
   {
-    Standard_Integer aNextIdx = (aIdx % thePoints.Length()) + 1;
-    aPtSum += (thePoints.Value (aNextIdx).Coord().X() - thePoints.Value (aIdx).Coord().X())
-              * (thePoints.Value (aNextIdx).Coord().Y() + thePoints.Value (aIdx).Coord().Y());
+    Standard_Integer aNextIdx = (aIdx % mySelPolyline.Points->Length()) + 1;
+    aPtSum += (mySelPolyline.Points->Value (aNextIdx).Coord().X() - mySelPolyline.Points->Value (aIdx).Coord().X())
+            * (mySelPolyline.Points->Value (aNextIdx).Coord().Y() + mySelPolyline.Points->Value (aIdx).Coord().Y());
   }
   Standard_Boolean isClockwiseOrdered = aPtSum < 0;
 
@@ -102,8 +121,9 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint
     }
 
     Handle(SelectMgr_TriangularFrustum) aTrFrustum = new SelectMgr_TriangularFrustum();
+    aTrFrustum->Init (aPts[0], aPts[1], aPts[2]);
     aTrFrustum->SetBuilder (myBuilder);
-    aTrFrustum->Build (aPts[0], aPts[1], aPts[2]);
+    aTrFrustum->Build();
     myFrustums.Append (aTrFrustum);
   }
 
@@ -122,14 +142,18 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint
 //                  as any negative value;
 //                - scale only is needed: @theTrsf must be set to gp_Identity.
 // =======================================================================
-Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale,
-                                                                                 const gp_GTrsf& theTrsf) const
+Handle(SelectMgr_BaseIntersector) SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale,
+                                                                                     const gp_GTrsf& theTrsf,
+                                                                                     const Handle(SelectMgr_FrustumBuilder)& theBuilder) const
 {
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::ScaleAndTransform() should be called after selection frustum initialization");
+
   Handle(SelectMgr_TriangularFrustumSet) aRes = new SelectMgr_TriangularFrustumSet();
 
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf)));
+    aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf, theBuilder)));
   }
 
   aRes->myBoundaryPoints.Resize (myBoundaryPoints.Lower(), myBoundaryPoints.Upper(), Standard_False);
@@ -140,6 +164,9 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform
     aRes->myBoundaryPoints.SetValue (anIdx, aPoint);
   }
 
+  aRes->mySelectionType = mySelectionType;
+  aRes->mySelPolyline.Points = mySelPolyline.Points;
+  aRes->SetBuilder (theBuilder);
   return aRes;
 }
 
@@ -152,6 +179,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3&
                                                            const SelectMgr_ViewClipRange& theClipRange,
                                                            SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, theClipRange, thePickResult))
@@ -169,6 +199,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3&
                                                            const SelectMgr_Vec3& theMaxPnt,
                                                            Standard_Boolean* theInside) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL))
@@ -217,6 +250,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt,
                                                            const SelectMgr_ViewClipRange& theClipRange,
                                                            SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (thePnt, theClipRange, thePickResult))
@@ -235,6 +271,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const TColgp_Array1Of
                                                            const SelectMgr_ViewClipRange& theClipRange,
                                                            SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (theArrayOfPts, theSensType, theClipRange, thePickResult))
@@ -271,6 +310,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1
                                                            const SelectMgr_ViewClipRange& theClipRange,
                                                            SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (thePnt1, thePnt2, theClipRange, thePickResult))
@@ -304,6 +346,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1
                                                            const SelectMgr_ViewClipRange& theClipRange,
                                                            SelectBasics_PickResult& thePickResult) const
 {
+  Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (thePnt1, thePnt2, thePnt3, theSensType, theClipRange, thePickResult))
@@ -421,6 +466,16 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::segmentTriangleIntersection (co
   return Standard_True;
 }
 
+// =======================================================================
+// function : DetectedPoint
+// purpose  :
+// =======================================================================
+gp_Pnt SelectMgr_TriangularFrustumSet::DetectedPoint (const Standard_Real theDepth) const
+{
+  (void )theDepth;
+  throw Standard_ProgramError ("SelectMgr_TriangularFrustumSet::DetectedPoint() should not be called for Polyline selection type");
+}
+
 //=======================================================================
 //function : DumpJson
 //purpose  : 
diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
index 372dcce208..8c53e407b8 100644
--- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
+++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
@@ -16,11 +16,8 @@
 #ifndef _SelectMgr_TriangularFrustumSet_HeaderFile
 #define _SelectMgr_TriangularFrustumSet_HeaderFile
 
-#include <NCollection_Handle.hxx>
-#include <NCollection_List.hxx>
-
-#include <SelectMgr_BaseFrustum.hxx>
 #include <SelectMgr_TriangularFrustum.hxx>
+#include <TColgp_HArray1OfPnt2d.hxx>
 
 typedef NCollection_List<Handle(SelectMgr_TriangularFrustum)> SelectMgr_TriangFrustums;
 typedef NCollection_List<Handle(SelectMgr_TriangularFrustum)>::Iterator SelectMgr_TriangFrustumsIter;
@@ -37,18 +34,29 @@ class SelectMgr_TriangularFrustumSet : public SelectMgr_BaseFrustum
 {
 public:
 
+  //! Auxiliary structure to define selection polyline
+  struct SelectionPolyline
+  {
+    Handle(TColgp_HArray1OfPnt2d) Points;
+  };
+
   SelectMgr_TriangularFrustumSet();
 
   ~SelectMgr_TriangularFrustumSet() {};
 
+  //! Initializes set of triangular frustums by polyline
+  Standard_EXPORT void Init (const TColgp_Array1OfPnt2d& thePoints);
+
   //! Meshes polygon bounded by polyline. Than organizes a set of triangular frustums,
   //! where each triangle's projection onto near and far view frustum planes is
   //! considered as a frustum base
-  Standard_EXPORT virtual void Build (const TColgp_Array1OfPnt2d& thePoints) Standard_OVERRIDE;
+  //! NOTE: it should be called after Init() method
+  Standard_EXPORT virtual void Build() Standard_OVERRIDE;
 
   //! Returns a copy of the frustum with all sub-volumes transformed according to the matrix given
-  Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale,
-                                                                           const gp_GTrsf& theTrsf) const Standard_OVERRIDE;
+  Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScale,
+                                                                               const gp_GTrsf& theTrsf,
+                                                                               const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE;
 
   Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
                                                      const SelectMgr_Vec3& theMaxPnt,
@@ -80,6 +88,9 @@ public:
                                                      const SelectMgr_ViewClipRange& theClipRange,
                                                      SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
+  //! Calculates the point on a view ray that was detected during the run of selection algo by given depth
+  Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
+
   //! Stores plane equation coefficients (in the following form:
   //! Ax + By + Cz + D = 0) to the given vector
   Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;
@@ -102,9 +113,10 @@ private:
 
 private:
 
-  SelectMgr_TriangFrustums myFrustums;
-  TColgp_Array1OfPnt       myBoundaryPoints;
-  Standard_Boolean         myToAllowOverlap;
+  SelectMgr_TriangFrustums      myFrustums;          //!< set of triangular frustums
+  SelectionPolyline             mySelPolyline;       //!< parameters of selection polyline (it is used to build triangle frustum set)
+  TColgp_Array1OfPnt            myBoundaryPoints;    //!< boundary points
+  Standard_Boolean              myToAllowOverlap;    //!< flag to detect only fully included sensitives or not
 };
 
 #endif // _SelectMgr_TriangularFrustumSet_HeaderFile
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
index 30805b3e38..a84e6c9243 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
@@ -24,6 +24,7 @@
 #include <Select3D_SensitiveEntity.hxx>
 #include <SelectBasics_PickResult.hxx>
 #include <SelectMgr_EntityOwner.hxx>
+#include <SelectMgr_FrustumBuilder.hxx>
 #include <SelectMgr_SortCriterion.hxx>
 #include <SelectMgr_SensitiveEntitySet.hxx>
 #include <TColStd_Array1OfInteger.hxx>
@@ -79,7 +80,7 @@ void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriter
                                               const gp_GTrsf& theInversedTrsf,
                                               const SelectMgr_SelectingVolumeManager& theMgr) const
 {
-  if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
+  if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
   {
     return;
   }
@@ -247,7 +248,7 @@ void SelectMgr_ViewerSelector::Clear()
 //=======================================================================
 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
 {
-  return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
+  return mySelectingVolumeMgr.IsScalableActiveVolume()
     && sensitivity (theEntity) < myTolerances.Tolerance();
 }
 
@@ -292,7 +293,7 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEnti
   {
     ++aPrevCriterion->NbOwnerMatches;
     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
-    if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
+    if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
     {
       if (aCriterion.IsCloserDepth (*aPrevCriterion))
       {
@@ -379,6 +380,10 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
     }
     else
     {
+      if (theCamera.IsNull())
+      {
+        return;
+      }
       gp_GTrsf aTPers;
       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
 
@@ -446,7 +451,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   }
 
   if (!theMgr.ViewClipping().IsNull() &&
-      theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
+      theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
   {
     Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
     // If box selection is active, and the whole sensitive tree is out of the clip planes
@@ -475,7 +480,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
   Standard_Integer aHead = -1;
   Standard_Integer aNode = 0; // a root node
   SelectMgr_FrustumCache aScaledTrnsfFrustums;
-  SelectMgr_SelectingVolumeManager aTmpMgr (false);
+  SelectMgr_SelectingVolumeManager aTmpMgr;
   for (;;)
   {
     if (!aSensitivesTree->IsOuter (aNode))
@@ -513,7 +518,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
     {
       bool aClipped = false;
       if (!theMgr.ViewClipping().IsNull() &&
-          theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
+          theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
       {
         Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
         // If box selection is active, and the whole sensitive tree is out of the clip planes
@@ -569,8 +574,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
 
   // 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))
+  || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
+   && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
   {
     return;
   }
@@ -599,8 +604,8 @@ void SelectMgr_ViewerSelector::TraverseSensitives()
 
   mystored.Clear();
 
-  Standard_Integer aWidth;
-  Standard_Integer aHeight;
+  Standard_Integer aWidth = 0;
+  Standard_Integer aHeight = 0;
   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
                                  mySelectingVolumeMgr.ProjectionMatrix(),
@@ -631,13 +636,17 @@ void SelectMgr_ViewerSelector::TraverseSensitives()
 
     gp_GTrsf aTFrustum;
 
-    SelectMgr_SelectingVolumeManager aMgr (Standard_False);
+    SelectMgr_SelectingVolumeManager aMgr;
 
     // 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)
     {
+      if (aCamera.IsNull())
+      {
+        continue;
+      }
       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
@@ -653,7 +662,7 @@ void SelectMgr_ViewerSelector::TraverseSensitives()
       // define corresponding frustum builder parameters
       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix(),
-                                     !aCamera.IsNull() && aCamera->IsZeroToOneDepth());
+                                     aCamera->IsZeroToOneDepth());
       aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
       aBuilder->SetWindowSize (aWidth, aHeight);
       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx b/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx
index cbd687c00e..94bf57236e 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx
@@ -49,20 +49,22 @@ void SelectMgr_ViewerSelector3d::Pick (const Standard_Integer theXPix,
                                        const Handle(V3d_View)& theView)
 {
   updateZLayers (theView);
+
+  gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
+                      static_cast<Standard_Real> (theYPix));
+  mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos);
+
   if(myToUpdateTolerance)
   {
     mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
     myToUpdateTolerance = Standard_False;
   }
-
   mySelectingVolumeMgr.SetCamera (theView->Camera());
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point);
   Standard_Integer aWidth = 0, aHeight = 0;
   theView->Window()->Size (aWidth, aHeight);
   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
-  gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
-                      static_cast<Standard_Real> (theYPix));
-  mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
+
+  mySelectingVolumeMgr.BuildSelectingVolume();
   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
 
   TraverseSensitives();
@@ -79,20 +81,21 @@ void SelectMgr_ViewerSelector3d::Pick (const Standard_Integer theXPMin,
                                        const Handle(V3d_View)& theView)
 {
   updateZLayers (theView);
-  mySelectingVolumeMgr.SetCamera (theView->Camera());
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box);
-  Standard_Integer aWidth = 0, aHeight = 0;
-  theView->Window()->Size (aWidth, aHeight);
-  mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
+
   gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin),
                          static_cast<Standard_Real> (theYPMin));
   gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax),
                          static_cast<Standard_Real> (theYPMax));
-  mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos,
-                                             aMaxMousePos);
+  mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos,
+                                               aMaxMousePos);
 
+  mySelectingVolumeMgr.SetCamera (theView->Camera());
+  Standard_Integer aWidth = 0, aHeight = 0;
+  theView->Window()->Size (aWidth, aHeight);
+  mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
+
+  mySelectingVolumeMgr.BuildSelectingVolume();
   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
-
   TraverseSensitives();
 }
 
@@ -104,13 +107,13 @@ void SelectMgr_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline,
                                        const Handle(V3d_View)& theView)
 {
   updateZLayers (theView);
+
+  mySelectingVolumeMgr.InitPolylineSelectingVolume (thePolyline);
   mySelectingVolumeMgr.SetCamera (theView->Camera());
-  mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline);
   Standard_Integer aWidth = 0, aHeight = 0;
   theView->Window()->Size (aWidth, aHeight);
   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
-  mySelectingVolumeMgr.BuildSelectingVolume (thePolyline);
-
+  mySelectingVolumeMgr.BuildSelectingVolume();
   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
 
   TraverseSensitives();