]> OCCT Git - occt.git/commitdiff
0032365: Visualization - refactoring of viewer selector
authorosa <osa@opencascade.com>
Thu, 13 May 2021 15:52:39 +0000 (18:52 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 22 May 2021 07:36:39 +0000 (10:36 +0300)
Add SelectMgr_BaseIntersector class as base intersector that can have any geometry not only frustum.
Remove cached static array of selecting volumes from selecting volume manager. Keep only one the latest active selection volume.
Change initialization interface of active volume frustum inside of selecting volume manager: Init*SelectingVolume(), set required parameters, BuildSelectingVolume(). Mark existing BuildSelectingVolume() methods as deprecated.
Use SelectMgr_SelectionType instead of SelectBasics_SelectingVolumeManager::SelectionType (the last one is marked as deprecated).
Add interface GetViewRayDirection() to selecting volume manager to get view ray direction (instead of computation it as vector from near to far point).
Add interface IsScalableActiveVolume() to selecting volume manager to check possibility of scaling of current active selecting volume.

34 files changed:
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_Manipulator.cxx
src/AIS/AIS_ViewCube.cxx
src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
src/MeshVS/MeshVS_SensitiveQuad.cxx
src/QABugs/QABugs_19.cxx
src/Select3D/Select3D_SensitiveCircle.cxx
src/Select3D/Select3D_SensitiveGroup.cxx
src/Select3D/Select3D_SensitivePoly.cxx
src/Select3D/Select3D_SensitivePrimitiveArray.cxx
src/Select3D/Select3D_SensitiveSegment.cxx
src/Select3D/Select3D_SensitiveSet.cxx
src/Select3D/Select3D_SensitiveTriangle.cxx
src/Select3D/Select3D_SensitiveTriangulation.cxx
src/Select3D/Select3D_SensitiveTriangulation.hxx
src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
src/SelectMgr/FILES
src/SelectMgr/SelectMgr_BaseFrustum.cxx
src/SelectMgr/SelectMgr_BaseFrustum.hxx
src/SelectMgr/SelectMgr_BaseIntersector.cxx [new file with mode: 0644]
src/SelectMgr/SelectMgr_BaseIntersector.hxx [new file with mode: 0644]
src/SelectMgr/SelectMgr_Frustum.hxx
src/SelectMgr/SelectMgr_Frustum.lxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_SelectionType.hxx [new file with mode: 0644]
src/SelectMgr/SelectMgr_TriangularFrustum.cxx
src/SelectMgr/SelectMgr_TriangularFrustum.hxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/SelectMgr/SelectMgr_ViewerSelector3d.cxx

index ba42fb6f8a37cb3f12d6f8a98bd914437556cb67..35aada5f86443184c0372cf5675af3cba4747d24 100644 (file)
@@ -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))
     {
index 7ff3327b1a7f0bb5cee8ff0b56ba161d5491780e..99a003e93b0bb3b2a802392fa28a61a5d9683cd0 100644 (file)
@@ -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:
index a1719c6d61512152fe8507afe76e93cff1aab279..756f6226a3838c95713317443af7bf735304ae1a 100644 (file)
@@ -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);
     }
index cecbca2a7800e0b7d644981cef66244ceefa5e6a..982a12ddc18622208ac7a75f6532c24ca234a93f 100644 (file)
@@ -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();
 }
index e12f3f70ce25a39275b495665fb36ec7ad45740f..860e50986de9591bcd21aef13b40f16b9f77db56 100644 (file)
@@ -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)
index 53765081760711de9504e25774dcd2fe3d2cceaa..cf168485bd3ce48ea21dee697100d7b9e419b437 100644 (file)
@@ -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);
-  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);
+    aMgr->InitBoxSelectingVolume (aPxPnt1, aPxPnt2);
   }
   else
   {
-    aMgr->BuildSelectingVolume (aPxPnt1);
+    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);
+  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);
 
index df02327e56c74f2eb8857ceced89a4d12ce53aed..fca5dfbfd057b7b51ca13bc2166b8c6d40c7353f 100644 (file)
@@ -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);
index a89fd931bfa0451c7b63e20701943791b8529d7b..e35ffac63f92472771ab3329b3c8f0e6dc31297f 100644 (file)
@@ -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)
   {
index d582fef161e31afb01d8c3a5b0f35574da122a29..ebce9296292ae575045b7f25aed9f196c7a590be 100644 (file)
@@ -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);
index 00939c5c07881edd400c2c9986886daf739f3860..7da9ba350ec61b557bbb81c78501c4f3f6b7450b 100644 (file)
@@ -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())
           {
index c402199ce984befde8bc2f598e3d369e842aaa11..8726d9d94337baaab72ff6f899bfe3e7a329d3cc 100644 (file)
@@ -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);
     }
index 3c2b460b1fb564272778608d744ec2d2e5f3fe29..d19b216dfde5b75fb7d54613ae7b41acf0a2b769 100644 (file)
@@ -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();
index 47291ad68a673befef117c89a3a2488038e32aed..f16c2dfb9915820d18a18ed971acc8fd85579baa 100644 (file)
@@ -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);
index 7e2ddfb4f5bd910874384258fe45964ef1e4a6b9..f7bbfa61a2d801bd806aac0953783bcde8deba0f 100644 (file)
@@ -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);
index dbc88713969f56a57fbeff231ce68fae9e17410b..17f5bab650c39dee4a71930baf24838ab2a36f67 100644 (file)
@@ -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.
index c846147082a624815f948bba5d1094347d0cb13c..4e065def7b63b96eb104592f941b4ac8b650048f 100644 (file)
@@ -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
index 315af35eef05f3d513e9a8cc0319265dd1cd06af..8b457da1d6b20bf58c0f0efbfea29f5ea486f9f4 100755 (executable)
@@ -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
index a373ad0224ebda901aa33772f35103224ef4a3d8..d90fba52786f87352d7fa508e8f049de004d3c14 100644 (file)
 #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)
index 05e82ebad94611e0f8f511dea19ab72a49ce5c5b..bfb7107f98a768209fd3a4f298ddccaec4741900 100644 (file)
 #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() {}
 
+  //! Nullifies the builder created in the constructor and copies the pointer given
+  Standard_EXPORT void SetBuilder (const Handle(SelectMgr_FrustumBuilder)& theBuilder);
+
   //! Return camera definition.
-  const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
+  virtual const Handle(Graphic3d_Camera)& Camera() const Standard_OVERRIDE { return myCamera; }
 
   //! Passes camera projection and orientation matrices to builder
-  Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera)& theCamera);
+  Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE;
 
   //! 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());
+  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;
 
   //! @return current camera projection transformation common for all selecting volumes
-  Standard_EXPORT const Graphic3d_Mat4d& ProjectionMatrix() const;
+  Standard_EXPORT virtual const Graphic3d_Mat4d& ProjectionMatrix() const Standard_OVERRIDE;
 
   //! @return current camera world view transformation common for all selecting volumes
-  Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const;
+  Standard_EXPORT virtual const Graphic3d_Mat4d& WorldViewMatrix() const Standard_OVERRIDE;
 
   //! @return current camera world view projection transformation state
-  Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const;
+  Standard_EXPORT virtual const Graphic3d_WorldViewProjState& WorldViewProjState() const Standard_OVERRIDE;
 
-  Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTol);
+  Standard_EXPORT virtual void SetPixelTolerance (const Standard_Integer theTol) Standard_OVERRIDE;
 
-  Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, 
-                                      const Standard_Integer theHeight);
+  Standard_EXPORT virtual void SetWindowSize (const Standard_Integer theWidth,
+                                              const Standard_Integer theHeight) Standard_OVERRIDE;
 
-  Standard_EXPORT void WindowSize (Standard_Integer& theWidth,
-                                   Standard_Integer& theHeight) const;
+  Standard_EXPORT virtual void WindowSize (Standard_Integer& theWidth,
+                                           Standard_Integer& theHeight) const Standard_OVERRIDE;
 
   //! 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);
-
+  Standard_EXPORT virtual void SetViewport (const Standard_Real theX,
+                                            const Standard_Real theY,
+                                            const Standard_Real theWidth,
+                                            const Standard_Real theHeight) Standard_OVERRIDE;
 
-  //! Builds volume according to the point and given pixel tolerance
-  virtual void Build (const gp_Pnt2d& /*thePoint*/) {}
 
-  //! Builds volume according to the selected rectangle
-  virtual void Build (const gp_Pnt2d& /*theMinPt*/,
-                      const gp_Pnt2d& /*theMaxPt*/) {}
-
-  //! Builds volume according to the triangle given
-  virtual void Build (const gp_Pnt2d& /*theP1*/,
-                      const gp_Pnt2d& /*theP2*/,
-                      const gp_Pnt2d& /*theP3*/) {}
-
-  //! 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 (file)
index 0000000..4552ca1
--- /dev/null
@@ -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 (file)
index 0000000..ef6e238
--- /dev/null
@@ -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
index b2bcdecf83ccdbbdbb9bd7c13533f6b6fafc47b9..52a97c5e9dc5a53a9e284b10383f284d7f12e480 100644 (file)
 #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
index 248a9c258cfe81dadf4590e8515c684fe6372e67..fabfd004e9dc6accfce216f5d153ff9266572948 100644 (file)
@@ -16,6 +16,7 @@
 #include <NCollection_Vector.hxx>
 #include <Poly_Array1OfTriangle.hxx>
 #include <Standard_Assert.hxx>
+#include <SelectMgr_FrustumBuilder.hxx>
 
 // =======================================================================
 // function : isSeparated
index 61a0743b85cee5c5009eea1860f12876792fc42d..27ee45642141e115f739dd25c83eed66d83f4a68 100644 (file)
 // 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;
-
-  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);
+  mySelectionType = SelectMgr_SelectionType_Point;
+  mySelRectangle.SetMousePos (thePoint);
+}
 
-  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)
 }
index d2d41157b1c9044d0f0964e415d30372cf4b12b5..4d88c1dac508000376fce5dde39a3cf737bb04a9 100644 (file)
@@ -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
 
 };
index 3df0a5b92f3021b0a0f02decc2517ca4da460bbe..b7ef91848b89399320e633cb752801f6340bc102 100644 (file)
 // 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,74 +198,118 @@ void SelectMgr_SelectingVolumeManager::SetViewport (const Standard_Real theX,
                                                     const Standard_Real theWidth,
                                                     const Standard_Real theHeight)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
+  Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::SetViewport() should be called after initialization of selection volume ");
+  myActiveSelectingVolume->SetViewport (theX, theY, theWidth, theHeight);
+}
+
+//=======================================================================
+// function : SetPixelTolerance
+// purpose  : Updates pixel tolerance in all selecting volumes
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance)
+{
+  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]->SetViewport (theX, theY, theWidth, theHeight);
+    aPntVolume = new SelectMgr_RectangularFrustum();
   }
+  aPntVolume->Init (thePoint);
+  myActiveSelectingVolume = aPntVolume;
 }
 
 //=======================================================================
-// function : SetWindowSize
-// purpose  : Updates window size in all selecting volumes
+// function : InitBoxSelectingVolume
+// purpose  :
 //=======================================================================
-void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth,
-                                                      const Standard_Integer theHeight)
+void SelectMgr_SelectingVolumeManager::InitBoxSelectingVolume (const gp_Pnt2d& theMinPt,
+                                                               const gp_Pnt2d& theMaxPt)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
+  Handle(SelectMgr_RectangularFrustum) aBoxVolume = Handle(SelectMgr_RectangularFrustum)::DownCast(myActiveSelectingVolume);
+  if (aBoxVolume.IsNull())
   {
-    mySelectingVolumes[anIdx]->SetWindowSize (theWidth, theHeight);
+    aBoxVolume = new SelectMgr_RectangularFrustum();
   }
+  aBoxVolume->Init (theMinPt, theMaxPt);
+  myActiveSelectingVolume = aBoxVolume;
 }
 
 //=======================================================================
-// function : SetPixelTolerance
-// purpose  : Updates pixel tolerance in all selecting volumes
+// function : InitPolylineSelectingVolume
+// purpose  :
 //=======================================================================
-void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance)
+void SelectMgr_SelectingVolumeManager::InitPolylineSelectingVolume (const TColgp_Array1OfPnt2d& thePoints)
 {
-  for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
+  Handle(SelectMgr_TriangularFrustumSet) aPolylineVolume = Handle(SelectMgr_TriangularFrustumSet)::DownCast(myActiveSelectingVolume);
+  if (aPolylineVolume.IsNull())
   {
-    mySelectingVolumes[anIdx]->SetPixelTolerance (theTolerance);
+    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 (const gp_Pnt2d& thePoint)
+void SelectMgr_SelectingVolumeManager::BuildSelectingVolume()
 {
-  if (myActiveSelectionType != Point)
-    return;
+  Standard_ASSERT_RAISE (!myActiveSelectingVolume.IsNull(),
+    "SelectMgr_SelectingVolumeManager::BuildSelectingVolume() should be called after initialization of active selection volume.");
+  myActiveSelectingVolume->Build();
+}
 
-  mySelectingVolumes[Frustum]->Build (thePoint);
+//=======================================================================
+// function : BuildSelectingVolume
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& 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();
+}
+
+//=======================================================================
+// 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();
+}
 
-  const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
-  return aFr->GetFarPnt();
+//=======================================================================
+// 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())
 
index 12b492761f59e8c88f37e6d762a50423429b8091..76f2d04e34e2f3e8aedbf122c684c06f5f51fa5b 100644 (file)
 #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;
 
-private:
-  enum { Frustum, FrustumSet, VolumeTypesNb };       //!< Defines the amount of available selecting volumes
+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;
 
-  Handle(SelectMgr_BaseFrustum)          mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes
+  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:
+  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 (file)
index 0000000..00e6e43
--- /dev/null
@@ -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
index e7b9aa37c42a340d3f140461ec6a25a805f87854..8395cb8a7a9af6722a46c608dc61466f48afbecc 100644 (file)
@@ -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;
 }
 
index 2a37887542b54397a9fa79de51260adcaa8c7d2e..aacf530652a1319d604ecba18e33bec8e9559e58 100644 (file)
 //! 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
index c7f50bf5bdb046b39edbe24b35b00a2e8eb28f82..977201a7ade9fa8d36fd43bf0fcc5f293a4eabc6 100644 (file)
@@ -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
 
 // =======================================================================
 SelectMgr_TriangularFrustumSet::SelectMgr_TriangularFrustumSet()
 :  myToAllowOverlap (Standard_False)
-{}
+{
+}
+
+// =======================================================================
+// 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 : BuildSelectingVolume
+// 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  : 
index 372dcce2080c6e8e785eaa84f750f45d0a5134aa..8c53e407b8bd8882af615779dd578f068dfb9358 100644 (file)
 #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
index 30805b3e38375a5a359c2f6208b9946340cfbae2..a84e6c92432afde50e34622b527054780825dbc4 100644 (file)
@@ -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);
index cbd687c00e47c2a57c07e5d5b9e6d1aa382ef573..94bf57236ee70993e00519a4eb66d6428dbf2c70 100644 (file)
@@ -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.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
+  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();