0026147: Visualization - restore the ability to pick only fully included objects...
authorvpa <vpa@opencascade.com>
Thu, 7 May 2015 15:53:21 +0000 (18:53 +0300)
committerabv <abv@opencascade.com>
Fri, 8 May 2015 05:54:08 +0000 (08:54 +0300)
2 modes of rectangular selection are available: inclusion-only and overlap-allowing;
The modes can be switched using method AllowOverlapDetection from StdSelect_ViewerSelector3d;
BVH for sensitive entities now builds if there is more than max number of leafs in collection;
Added option -allowoverlap to command vselect;
Interactive rectangular selection in Draw is now available in 2 modes:
- if the user starts selection from upper corners, only fully included objects will be selected;
- if the user starts selection from lower corners, both partially and fully overlapped objects will be selected.

44 files changed:
src/Graphic3d/Graphic3d_Camera.cxx
src/Select3D/Select3D_BVHPrimitiveContent.cxx
src/Select3D/Select3D_BVHPrimitiveContent.hxx
src/Select3D/Select3D_InteriorSensitivePointSet.cxx
src/Select3D/Select3D_InteriorSensitivePointSet.hxx
src/Select3D/Select3D_SensitiveBox.cxx
src/Select3D/Select3D_SensitiveCircle.cxx
src/Select3D/Select3D_SensitiveCurve.cxx
src/Select3D/Select3D_SensitiveCurve.hxx
src/Select3D/Select3D_SensitiveGroup.cxx
src/Select3D/Select3D_SensitiveGroup.hxx
src/Select3D/Select3D_SensitivePoint.cxx
src/Select3D/Select3D_SensitivePoly.cxx
src/Select3D/Select3D_SensitivePoly.hxx
src/Select3D/Select3D_SensitiveSegment.cxx
src/Select3D/Select3D_SensitiveSet.cxx
src/Select3D/Select3D_SensitiveSet.hxx
src/Select3D/Select3D_SensitiveTriangle.cxx
src/Select3D/Select3D_SensitiveTriangle.hxx
src/Select3D/Select3D_SensitiveTriangulation.cxx
src/Select3D/Select3D_SensitiveTriangulation.hxx
src/Select3D/Select3D_SensitiveWire.cxx
src/Select3D/Select3D_SensitiveWire.hxx
src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_BaseFrustum.cxx
src/SelectMgr/SelectMgr_BaseFrustum.hxx
src/SelectMgr/SelectMgr_Frustum.hxx
src/SelectMgr/SelectMgr_Frustum.lxx
src/SelectMgr/SelectMgr_FrustumBuilder.cxx
src/SelectMgr/SelectMgr_FrustumBuilder.hxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_TriangularFrustum.cxx
src/SelectMgr/SelectMgr_TriangularFrustum.hxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
src/StdSelect/StdSelect_ViewerSelector3d.cxx
src/StdSelect/StdSelect_ViewerSelector3d.hxx
src/ViewerTest/ViewerTest_EventManager.cdl
src/ViewerTest/ViewerTest_EventManager.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/bugs/vis/bug26147 [new file with mode: 0644]

index 4c684aa..8184f2e 100644 (file)
@@ -986,7 +986,7 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
   // fixed using tolerance distance, relative to boundaries size. The tolerance distance
   // should be computed using information on boundaries of primary application actors,
   // (e.g. representing the displayed model) - to ensure that they are not unreasonably clipped.
-  const Standard_ShortReal anEpsilon = 1e-4;
+  const Standard_ShortReal anEpsilon = 1e-4f;
 
   if (theGraphicBB.IsVoid())
   {
index 61aaec5..08cad7a 100644 (file)
@@ -26,7 +26,7 @@
 Select3D_BVHPrimitiveContent::Select3D_BVHPrimitiveContent (const Handle(Select3D_SensitiveSet)& theSensitiveSet)
 {
   mySensitiveSet = theSensitiveSet;
-  myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (8, 32);
+  myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (myLeafNodeSize, 32);
 
   MarkDirty();
 }
index 210c436..2296f44 100644 (file)
@@ -50,8 +50,14 @@ public:
   //! Returns the tree built for set of sensitives
   Standard_EXPORT const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& GetBVH();
 
+  //! Returns a number of nodes in 1 BVH leaf
+  Standard_Integer GetLeafNodeSize() const { return myLeafNodeSize; }
+
 protected:
   Handle(Select3D_SensitiveSet) mySensitiveSet;     //!< Set of sensitive entities
+
+private:
+  static const Standard_Integer myLeafNodeSize = 8;     //!< Number of sub-elements in the leaf
 };
 
 #endif // _Select3D_BVHPrimitiveContent_Header
index cc2c7f8..b86c23c 100644 (file)
@@ -136,7 +136,7 @@ Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Ha
         }
         Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
                                                                                   aPointsArray,
-                                                                                  Standard_False);
+                                                                                  Standard_True);
         myPlanarPolygons.Append (aPlanarPolyg);
         aStartIdx = aPntIter;
         anEndIdx = aPntIter;
@@ -154,7 +154,7 @@ Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Ha
           }
           Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
                                                                                     aPointsArray,
-                                                                                    Standard_False);
+                                                                                    Standard_True);
           myPlanarPolygons.Append (aPlanarPolyg);
         }
       }
@@ -280,6 +280,17 @@ Standard_Boolean Select3D_InteriorSensitivePointSet::overlapsElement (SelectBasi
 }
 
 // =======================================================================
+// function : elementIsInside
+// purpose  :
+// =======================================================================
+Standard_Boolean Select3D_InteriorSensitivePointSet::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                                      const Standard_Integer               theElemIdx)
+{
+  Standard_Real aDummy;
+  return overlapsElement (theMgr, theElemIdx, aDummy);
+}
+
+// =======================================================================
 // function : distanceToCOG
 // purpose  : Calculates distance from the 3d projection of used-picked
 //            screen point to center of the geometry
index 22df166..b9fd3e8 100644 (file)
@@ -90,6 +90,10 @@ protected:
                                                             Standard_Integer theElemIdx,
                                                             Standard_Real& theMatchDepth) Standard_OVERRIDE;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                            const Standard_Integer               theElemIdx) Standard_OVERRIDE;
+
   //! Calculates distance from the 3d projection of used-picked
   //! screen point to center of the geometry
   Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
index 114de8a..ead44d9 100644 (file)
@@ -91,18 +91,24 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveBox::GetConnected()
 Standard_Boolean Select3D_SensitiveBox::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                  SelectBasics_PickResult& thePickResult)
 {
-  Standard_Real aDepth     = RealLast();
-  Standard_Real aDistToCOG = RealLast();
-  Standard_Boolean isMatched = theMgr.Overlaps (myBox, aDepth);
+  thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
 
-  if (isMatched)
+  if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
-    aDistToCOG = theMgr.DistToGeometryCenter (myCenter3d);
+    Standard_Boolean isInside = Standard_True;
+    return theMgr.Overlaps (myBox.CornerMin(), myBox.CornerMax(), &isInside) && isInside;
   }
 
-  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+  Standard_Real aDepth;
+  if (!theMgr.Overlaps (myBox, aDepth)) // check for overlap
+  {
+    return Standard_False;
+  }
+
+  thePickResult = SelectBasics_PickResult (
+    aDepth, theMgr.DistToGeometryCenter (myCenter3d));
 
-  return isMatched;
+  return Standard_True;
 }
 
 //=======================================================================
index 53a246c..3f8eaa2 100644 (file)
@@ -241,28 +241,39 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
   Standard_Real aDepth     = RealLast();
   Standard_Real aDistToCOG = RealLast();
 
-  Standard_Boolean isCollisionDetected = Standard_False;
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
-    isCollisionDetected = Select3D_SensitivePoly::Matches (theMgr, thePickResult);
+    if (!Select3D_SensitivePoly::Matches (theMgr, thePickResult))
+    {
+      thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+      return Standard_False;
+    }
   }
   else if (mySensType == Select3D_TOS_INTERIOR)
   {
     Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
     Points3D (anArrayOfPnt);
-    isCollisionDetected = theMgr.Overlaps (anArrayOfPnt,
-                                           Select3D_TOS_INTERIOR,
-                                           aDepth);
-  }
+    if (!theMgr.IsOverlapAllowed())
+    {
+      thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+      if (!theMgr.Overlaps (myBndBox.CornerMin(), myBndBox.CornerMax(), Standard_False))
+      {
+        return Standard_False;
+      }
+      return Standard_True;
+    }
 
-  if (isCollisionDetected)
-  {
-    aDistToCOG = theMgr.DistToGeometryCenter (myCenter3D);
+    if (!theMgr.Overlaps (anArrayOfPnt, Select3D_TOS_INTERIOR, aDepth))
+    {
+      thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+      return Standard_False;
+    }
   }
 
-  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
 
-  return isCollisionDetected;
+  aDistToCOG = theMgr.DistToGeometryCenter (myCenter3D);
+  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+  return Standard_True;
 }
 
 void Select3D_SensitiveCircle::ArrayBounds (Standard_Integer & theLow,
index 149b8a8..91951b4 100644 (file)
@@ -28,7 +28,7 @@ IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveCurve, Select3D_SensitivePoly)
 Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
                                                   const Handle(Geom_Curve)& theCurve,
                                                   const Standard_Integer theNbPnts)
-: Select3D_SensitivePoly (theOwnerId, theNbPnts > 2, theNbPnts),
+: Select3D_SensitivePoly (theOwnerId, Standard_True, theNbPnts),
   myCurve (theCurve)
 {
   loadPoints (theCurve, theNbPnts);
@@ -41,7 +41,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
 //==================================================
 Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
                                                   const Handle(TColgp_HArray1OfPnt)& thePoints)
-: Select3D_SensitivePoly (theOwnerId, thePoints, thePoints->Length() > 2)
+: Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
 
 {
   SetSensitivityFactor (3.0);
@@ -53,7 +53,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
 //==================================================
 Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
                                                   const TColgp_Array1OfPnt& thePoints)
-: Select3D_SensitivePoly (theOwnerId, thePoints, thePoints.Length() > 2)
+: Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
 {
   SetSensitivityFactor (3.0);
 }
@@ -100,41 +100,4 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveCurve::GetConnected()
   }
 
   return aNewEntity;
-}
-
-//=======================================================================
-// function : Matches
-// purpose  : Checks whether the curve overlaps current selecting volume
-//=======================================================================
-Standard_Boolean Select3D_SensitiveCurve::Matches (SelectBasics_SelectingVolumeManager& theMgr,
-                                                   SelectBasics_PickResult& thePickResult)
-{
-  if (myPolyg.Size() > 2)
-    return Select3D_SensitivePoly::Matches (theMgr, thePickResult);
-
-  const gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
-  const gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
-  Standard_Real aDepth = RealLast();
-  Standard_Boolean isMatched = theMgr.Overlaps (aPnt1, aPnt2, aDepth);
-
-  if (isMatched)
-  {
-    Standard_Real aDistToCOG = RealLast();
-    if (myCOG.X() == RealLast() && myCOG.Y() == RealLast() && myCOG.Z() == RealLast())
-    {
-      gp_XYZ aCenter (0.0, 0.0, 0.0);
-      for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
-      {
-        aCenter += myPolyg.Pnt (aIdx);
-      }
-      myCOG = aCenter / myPolyg.Size();
-    }
-
-    aDistToCOG = theMgr.DistToGeometryCenter (myCOG);
-
-    thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-    return Standard_True;
-  }
-
-  return Standard_False;
-}
+}
\ No newline at end of file
index ca265cc..35584f1 100644 (file)
@@ -65,10 +65,6 @@ public:
   Standard_EXPORT Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
                                            const TColgp_Array1OfPnt& thePoints);
 
-  //! Checks whether the curve overlaps current selecting volume
-  Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
-                                                    SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
-
   //! Returns the copy of this
   Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE;
 
index 583edf0..4b67e5c 100644 (file)
@@ -314,8 +314,7 @@ Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_Selectin
   theMatchDepth = RealLast();
   const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
   SelectBasics_PickResult aResult;
-  Standard_Boolean isMatching = myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult);
-  if (isMatching)
+  if (myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult))
   {
     theMatchDepth = aResult.Depth();
     return Standard_True;
@@ -325,6 +324,17 @@ Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_Selectin
 }
 
 // =======================================================================
+// function : elementIsInside
+// purpose  :
+// =======================================================================
+Standard_Boolean Select3D_SensitiveGroup::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                           const Standard_Integer               theElemIdx)
+{
+  Standard_Real aDummy;
+  return overlapsElement(theMgr, theElemIdx, aDummy);
+}
+
+// =======================================================================
 // function : distanceToCOG
 // purpose  : Calculates distance from the 3d projection of used-picked
 //            screen point to center of the geometry
index bb6b681..181af4f 100644 (file)
@@ -130,6 +130,10 @@ private:
                                             Standard_Integer theElemIdx,
                                             Standard_Real& theMatchDepth) Standard_OVERRIDE;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                            const Standard_Integer               theElemIdx) Standard_OVERRIDE;
+
   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
   virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
 
index 8c5acb6..10bacb5 100644 (file)
@@ -42,13 +42,15 @@ Standard_Boolean Select3D_SensitivePoint::Matches (SelectBasics_SelectingVolumeM
 {
   Standard_Real aDepth      = RealLast();
   Standard_Real aDistToCOG  = RealLast();
-  Standard_Boolean isMatched = theMgr.Overlaps (myPoint, aDepth);
-  if (isMatched)
-    aDistToCOG = aDepth;
+  if (!theMgr.Overlaps (myPoint, aDepth))
+  {
+    thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+    return Standard_False;
+  }
 
+  aDistToCOG = aDepth;
   thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-
-  return isMatched;
+  return Standard_True;
 }
 
 //=======================================================================
index 3a161fd..ee3f9fe 100644 (file)
@@ -58,6 +58,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
       mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
     }
   }
+
+  myIsComputed = Standard_True;
 }
 
 //==================================================
@@ -97,6 +99,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
       mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
     }
   }
+
+  myIsComputed = Standard_True;
 }
 
 //==================================================
@@ -118,6 +122,7 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
     }
   }
   myCOG = gp_Pnt (RealLast(), RealLast(), RealLast());
+  myIsComputed = Standard_False;
 }
 
 //==================================================
@@ -237,6 +242,20 @@ Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_Selecting
 }
 
 //==================================================
+// Function : elementIsInside
+// Purpose  :
+//==================================================
+Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                          const Standard_Integer               theElemIdx)
+{
+  const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
+
+  Standard_Real aDummy;
+  return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), aDummy)
+      && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1), aDummy);
+}
+
+//==================================================
 // Function: distanceToCOG
 // Purpose : Calculates distance from the 3d
 //           projection of used-picked screen point
@@ -244,7 +263,7 @@ Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_Selecting
 //==================================================
 Standard_Real Select3D_SensitivePoly::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
 {
-  if (myCOG.X() == RealLast() && myCOG.Y() == RealLast() && myCOG.Z() == RealLast())
+  if (!myIsComputed)
   {
     gp_XYZ aCenter (0.0, 0.0, 0.0);
     for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
@@ -252,6 +271,7 @@ Standard_Real Select3D_SensitivePoly::distanceToCOG (SelectBasics_SelectingVolum
       aCenter += myPolyg.Pnt (aIdx);
     }
     myCOG = aCenter / myPolyg.Size();
+    myIsComputed = Standard_True;
   }
 
   return theMgr.DistToGeometryCenter (myCOG);
@@ -274,5 +294,16 @@ Standard_Integer Select3D_SensitivePoly::NbSubElements()
 //==================================================
 gp_Pnt Select3D_SensitivePoly::CenterOfGeometry() const
 {
+  if (!myIsComputed)
+  {
+    gp_XYZ aCenter (0.0, 0.0, 0.0);
+    for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
+    {
+      aCenter += myPolyg.Pnt (aIdx);
+    }
+    myCOG = aCenter / myPolyg.Size();
+    myIsComputed = Standard_True;
+  }
+
   return myCOG;
 }
index b92f984..beb7e06 100644 (file)
@@ -106,6 +106,10 @@ private:
                                             Standard_Integer theElemIdx,
                                             Standard_Real& theMatchDepth) Standard_OVERRIDE;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                            const Standard_Integer               theElemIdx) Standard_OVERRIDE;
+
   //! Calculates distance from the 3d projection of used-picked screen point
   //! to center of the geometry
   virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
@@ -116,6 +120,7 @@ protected:
   mutable gp_Pnt                  myCOG;                //!< Center of the poly
   Handle_TColStd_HArray1OfInteger mySegmentIndexes;     //!< Segment indexes for BVH tree build
   Select3D_BndBox3d               myBndBox;             //!< Bounding box of the poly
+  mutable Standard_Boolean        myIsComputed;         //!< Is true if all the points and data structures of polygon are initialized
 };
 
 DEFINE_STANDARD_HANDLE(Select3D_SensitivePoly, Select3D_SensitiveSet)
index 867985e..d20f598 100644 (file)
@@ -42,21 +42,23 @@ Select3D_SensitiveSegment::Select3D_SensitiveSegment (const Handle(SelectBasics_
 Standard_Boolean Select3D_SensitiveSegment::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                      SelectBasics_PickResult& thePickResult)
 {
-  Standard_Real aDepth     = RealLast();
-  Standard_Real aDistToCOG = RealLast();
-  Standard_Boolean isMatched = theMgr.Overlaps (myStart,
-                                                myEnd,
-                                                aDepth);
+  thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
 
-  if (isMatched)
+  Standard_Real aDepth;
+  if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
-    gp_Pnt aCenter = CenterOfGeometry();
-    aDistToCOG = theMgr.DistToGeometryCenter (aCenter);
+    return theMgr.Overlaps (myStart, aDepth) && theMgr.Overlaps (myEnd, aDepth);
   }
 
-  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+  if (!theMgr.Overlaps (myStart, myEnd, aDepth)) // check for overlap
+  {
+    return Standard_False;
+  }
+
+  thePickResult = SelectBasics_PickResult (aDepth,
+    theMgr.DistToGeometryCenter (CenterOfGeometry()));
 
-  return isMatched;
+  return Standard_True;
 }
 
 //=======================================================================
index ed9b8b3..9e618e2 100644 (file)
@@ -49,92 +49,114 @@ void Select3D_SensitiveSet::BVH()
 Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                  SelectBasics_PickResult& thePickResult)
 {
-  const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = myContent->GetBVH();
+  const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH = myContent->GetBVH();
 
-  Standard_Integer aNode = 0; // a root node
-  if (!theMgr.Overlaps (aBVHTree->MinPoint (0),
-                        aBVHTree->MaxPoint (0)))
+  thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+
+  if (!theMgr.Overlaps (aBVH->MinPoint (0),
+                        aBVH->MaxPoint (0)))
   {
     return Standard_False;
   }
 
   Standard_Integer aStack[32];
+  Standard_Integer aNode =  0;
   Standard_Integer aHead = -1;
-  Standard_Real aDepth      = RealLast();
-  Standard_Real aDistToCOG  = RealLast();
-  SelectMgr_Vec3 aClosestPnt (RealLast());
+
   Standard_Integer aMatchesNb = -1;
+  Standard_Real    aMinDepth  = RealLast();
+
   for (;;)
   {
-    if (!aBVHTree->IsOuter (aNode))
+    const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];
+
+    if (aData.x() == 0) // is inner node
     {
-      const Standard_Integer aLeftChildIdx  = aBVHTree->LeftChild  (aNode);
-      const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
-      const Standard_Boolean isLeftChildIn  = theMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
-                                                               aBVHTree->MaxPoint (aLeftChildIdx));
-      const Standard_Boolean isRightChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx),
-                                                               aBVHTree->MaxPoint (aRightChildIdx));
-      if (isLeftChildIn
-       && isRightChildIn)
+      const Standard_Integer aLftIdx = aData.y();
+      const Standard_Integer aRghIdx = aData.z();
+
+      Standard_Boolean isLftInside = Standard_True;
+      Standard_Boolean isRghInside = Standard_True;
+
+      Standard_Boolean toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLftIdx),
+                                                     aBVH->MaxPoint (aLftIdx),
+                                                     theMgr.IsOverlapAllowed() ? NULL : &isLftInside);
+
+      Standard_Boolean toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRghIdx),
+                                                     aBVH->MaxPoint (aRghIdx),
+                                                     theMgr.IsOverlapAllowed() ? NULL : &isRghInside);
+
+      if (!theMgr.IsOverlapAllowed()) // inclusion test
       {
-        aNode = aLeftChildIdx;
-        ++aHead;
-        aStack[aHead] = aRightChildIdx;
+        if (!toCheckLft || !toCheckRgh)
+        {
+          return Standard_False; // no inclusion
+        }
+
+        toCheckLft &= !isLftInside;
+        toCheckRgh &= !isRghInside;
       }
-      else if (isLeftChildIn
-            || isRightChildIn)
+
+      if (toCheckLft || toCheckRgh)
       {
-        aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+        aNode = toCheckLft ? aLftIdx : aRghIdx;
+
+        if (toCheckLft && toCheckRgh)
+        {
+          aStack[++aHead] = aRghIdx;
+        }
       }
       else
       {
         if (aHead < 0)
-        {
           break;
-        }
 
-        aNode = aStack[aHead];
-        --aHead;
+        aNode = aStack[aHead--];
       }
     }
     else
     {
-      Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
-      Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
-      Standard_Boolean isMatched = Standard_False;
-      for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
+      for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
       {
-        Standard_Real anElementDepth = 0.0;
-        isMatched = overlapsElement (theMgr, anIdx, anElementDepth);
-        if (isMatched)
+        if (!theMgr.IsOverlapAllowed()) // inclusion test
         {
-          if (aDepth > anElementDepth)
+          if (!elementIsInside (theMgr, anElemIdx))
           {
-            aDepth = anElementDepth;
-            myDetectedIdx = anIdx;
+            return Standard_False;
           }
-          aMatchesNb++;
+        }
+        else // overlap test
+        {
+          Standard_Real aCurrentDepth = 0.0;
+
+          if (!overlapsElement (theMgr, anElemIdx, aCurrentDepth))
+          {
+            continue;
+          }
+
+          if (aMinDepth > aCurrentDepth)
+          {
+            aMinDepth = aCurrentDepth;
+            myDetectedIdx = anElemIdx;
+          }
+
+          ++aMatchesNb;
         }
       }
+
       if (aHead < 0)
-      {
         break;
-      }
 
-      aNode = aStack[aHead];
-      --aHead;
+      aNode = aStack[aHead--];
     }
   }
 
   if (aMatchesNb != -1)
   {
-    aDistToCOG = distanceToCOG (theMgr);
-    thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-    return Standard_True;
+    thePickResult = SelectBasics_PickResult (aMinDepth, distanceToCOG (theMgr));
   }
 
-  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-  return Standard_False;
+  return !theMgr.IsOverlapAllowed() || aMatchesNb != -1;
 }
 
 //=======================================================================
@@ -176,3 +198,12 @@ void Select3D_SensitiveSet::Clear()
 {
   myContent.Nullify();
 }
+
+//=======================================================================
+// function : GetLeafNodeSize
+// purpose  : Returns a number of nodes in 1 BVH leaf
+//=======================================================================
+Standard_Integer Select3D_SensitiveSet::GetLeafNodeSize() const
+{
+  return myContent->GetLeafNodeSize();
+}
index 9c9d5f1..a351306 100644 (file)
@@ -31,7 +31,7 @@ class Select3D_BVHPrimitiveContent;
 //! This class is base class for handling overlap detection of complex sensitive
 //! entities. It provides an interface for building BVH tree for some set of entities.
 //! Thereby, each iteration of overlap detection is a traverse of BVH tree in fact.
-//! To use speed-up heirarchical structure in a custom complex sensitive entity, it is
+//! To use speed-up hierarchical structure in a custom complex sensitive entity, it is
 //! necessary to make that custom entity a descendant of this class and organize sub-entities
 //! in some container which allows referencing to elements by index. Note that methods taking
 //! index as a parameter are used for BVH build and the range of given index is [0; Size() - 1].
@@ -87,6 +87,9 @@ public:
   //! Destroys cross-reference to avoid memory leak
   Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
 
+  //! Returns a number of nodes in 1 BVH leaf
+  Standard_EXPORT Standard_Integer GetLeafNodeSize() const;
+
 public:
   DEFINE_STANDARD_RTTI(Select3D_SensitiveSet)
 
@@ -97,6 +100,10 @@ protected:
                                             Standard_Integer theElemIdx,
                                             Standard_Real& theMatchDepth) = 0;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                            const Standard_Integer               theElemIdx) = 0;
+
   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
   virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) = 0;
 
index 0436ad4..7f43e7f 100644 (file)
@@ -33,14 +33,13 @@ Select3D_SensitiveTriangle::Select3D_SensitiveTriangle (const Handle(SelectBasic
                                                         const gp_Pnt& thePnt1,
                                                         const gp_Pnt& thePnt2,
                                                         const Select3D_TypeOfSensitivity theType)
-: Select3D_SensitivePoly (theOwnerId, Standard_False, 3),
+: Select3D_SensitiveEntity (theOwnerId),
   mySensType (theType)
 {
-  myPolyg.SetPnt (0, thePnt0);
-  myPolyg.SetPnt (1, thePnt1);
-  myPolyg.SetPnt (2, thePnt2);
-  myCentroid = (gp_XYZ (myPolyg.Pnt (0)) + gp_XYZ (myPolyg.Pnt (1)) + gp_XYZ (myPolyg.Pnt (2)))
-                * (0.3);
+  myPoints[0] = thePnt0;
+  myPoints[1] = thePnt1;
+  myPoints[2] = thePnt2;
+  myCentroid = (thePnt0.XYZ() + thePnt1.XYZ() + thePnt2.XYZ()) * (1.0 / 3.0);
 }
 
 //==================================================
@@ -53,18 +52,23 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
 {
   Standard_Real aDepth     = RealLast();
   Standard_Real aDistToCOG = RealLast();
-  gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
-  gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
-  gp_Pnt aPnt3 = myPolyg.Pnt3d (2);
-  Standard_Boolean isMatched = theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDepth);
-  if (isMatched)
+  if (!theMgr.IsOverlapAllowed())
   {
-    aDistToCOG = theMgr.DistToGeometryCenter (myCentroid);
+    Standard_Real aDummy;
+    return theMgr.Overlaps (myPoints[0], aDummy)
+        && theMgr.Overlaps (myPoints[1], aDummy)
+        && theMgr.Overlaps (myPoints[2], aDummy);
   }
 
-  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+  if (!theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDepth))
+  {
+    thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+    return Standard_False;
+  }
 
-  return isMatched;
+  aDistToCOG = theMgr.DistToGeometryCenter (myCentroid);
+  thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
+  return Standard_True;
 }
 
 //==================================================
@@ -73,9 +77,9 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
 //==================================================
 void Select3D_SensitiveTriangle::Points3D (gp_Pnt& thePnt0, gp_Pnt& thePnt1, gp_Pnt& thePnt2) const
 {
-  thePnt0 = myPolyg.Pnt (0);
-  thePnt1 = myPolyg.Pnt (1);
-  thePnt2 = myPolyg.Pnt (2);
+  thePnt0 = myPoints[0];
+  thePnt1 = myPoints[1];
+  thePnt2 = myPoints[2];
 }
 
 //==================================================
@@ -84,11 +88,7 @@ void Select3D_SensitiveTriangle::Points3D (gp_Pnt& thePnt0, gp_Pnt& thePnt1, gp_
 //==================================================
 gp_Pnt Select3D_SensitiveTriangle::Center3D() const
 {
-  gp_XYZ aPnt1, aPnt2, aPnt3;
-  aPnt1 = myPolyg.Pnt (0);
-  aPnt2 = myPolyg.Pnt (1);
-  aPnt3 = myPolyg.Pnt (2);
-  return gp_Pnt ((aPnt1 + aPnt2 + aPnt3) / 3.0);
+  return myCentroid;
 }
 
 //==================================================
@@ -99,7 +99,7 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::GetConnected()
 {
   // Create a copy of this
   Handle(Select3D_SensitiveEntity) aNewEntity =
-    new Select3D_SensitiveTriangle (myOwnerId, myPolyg.Pnt(0), myPolyg.Pnt(1), myPolyg.Pnt(2), mySensType);
+    new Select3D_SensitiveTriangle (myOwnerId, myPoints[0], myPoints[1], myPoints[2], mySensType);
 
   return aNewEntity;
 }
@@ -112,23 +112,11 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::GetConnected()
 //==================================================
 Select3D_BndBox3d Select3D_SensitiveTriangle::BoundingBox()
 {
-  gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
-  gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
-  gp_Pnt aPnt3 = myPolyg.Pnt3d (2);
-  const SelectMgr_Vec3 aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())),
-                                                 Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())),
-                                                 Min (aPnt1.Z(), Min (aPnt2.Z(), aPnt3.Z())));
-  const SelectMgr_Vec3 aMaxPnt = SelectMgr_Vec3 (Max (aPnt1.X(), Max (aPnt2.X(), aPnt3.X())),
-                                                 Max (aPnt1.Y(), Max (aPnt2.Y(), aPnt3.Y())),
-                                                 Max (aPnt1.Z(), Max (aPnt2.Z(), aPnt3.Z())));
+  const SelectMgr_Vec3 aMinPnt = SelectMgr_Vec3 (Min (myPoints[0].X(), Min (myPoints[1].X(), myPoints[2].X())),
+                                                 Min (myPoints[0].Y(), Min (myPoints[1].Y(), myPoints[2].Y())),
+                                                 Min (myPoints[0].Z(), Min (myPoints[1].Z(), myPoints[2].Z())));
+  const SelectMgr_Vec3 aMaxPnt = SelectMgr_Vec3 (Max (myPoints[0].X(), Max (myPoints[1].X(), myPoints[2].X())),
+                                                 Max (myPoints[0].Y(), Max (myPoints[1].Y(), myPoints[2].Y())),
+                                                 Max (myPoints[0].Z(), Max (myPoints[1].Z(), myPoints[2].Z())));
   return Select3D_BndBox3d (aMinPnt, aMaxPnt);
 }
-
-//==================================================
-// Function: NbSubElements
-// Purpose : Returns the amount of points
-//==================================================
-Standard_Integer Select3D_SensitiveTriangle::NbSubElements()
-{
-  return 3;
-}
index 1f17b09..7893954 100644 (file)
@@ -41,7 +41,7 @@ class TopLoc_Location;
 //! This comes into play in the detection of meshing and triangulation in surfaces.
 //! In some cases this class can raise Standard_ConstructionError and
 //! Standard_OutOfRange exceptions. For more details see Select3D_SensitivePoly.
-class Select3D_SensitiveTriangle : public Select3D_SensitivePoly
+class Select3D_SensitiveTriangle : public Select3D_SensitiveEntity
 {
 public:
 
@@ -71,7 +71,9 @@ public:
   Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
 
   //! Returns the amount of points
-  Standard_EXPORT virtual Standard_Integer NbSubElements() Standard_OVERRIDE;
+  virtual Standard_Integer NbSubElements() Standard_OVERRIDE { return 3; }
+
+  virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE { return myCentroid; }
 
   DEFINE_STANDARD_RTTI(Select3D_SensitiveTriangle)
 
@@ -79,6 +81,7 @@ private:
 
   Select3D_TypeOfSensitivity mySensType;     //!< Type of sensitivity: boundary or interior
   gp_Pnt                     myCentroid;     //!< Center of triangle
+  gp_Pnt                     myPoints[3];
 };
 
 DEFINE_STANDARD_HANDLE(Select3D_SensitiveTriangle, Select3D_SensitiveEntity)
index b552d92..c3973af 100644 (file)
@@ -298,6 +298,55 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_
   }
 }
 
+//==================================================
+// Function : elementIsInside
+// Purpose  :
+//==================================================
+Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                                   const Standard_Integer               theElemIdx)
+{
+  Standard_Real aDummy;
+
+  const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
+
+  if (mySensType == Select3D_TOS_BOUNDARY)
+  {
+    gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
+    gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
+
+    if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
+    {
+      aSegmPnt1.Transform (myInitLocation.Transformation());
+      aSegmPnt2.Transform (myInitLocation.Transformation());
+    }
+
+    return theMgr.Overlaps (aSegmPnt1, aDummy) && theMgr.Overlaps (aSegmPnt2, aDummy);
+  }
+  else
+  {
+    Standard_Integer aNode1;
+    Standard_Integer aNode2;
+    Standard_Integer aNode3;
+
+    myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
+
+    gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
+    gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
+    gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
+
+    if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
+    {
+      aPnt1.Transform (myInitLocation.Transformation());
+      aPnt2.Transform (myInitLocation.Transformation());
+      aPnt3.Transform (myInitLocation.Transformation());
+    }
+
+    return theMgr.Overlaps (aPnt1, aDummy)
+        && theMgr.Overlaps (aPnt2, aDummy)
+        && theMgr.Overlaps (aPnt3, aDummy);
+  }
+}
+
 //=======================================================================
 // function : distanceToCOG
 // purpose  : Calculates distance from the 3d projection of used-picked
@@ -392,4 +441,4 @@ gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
 Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
 {
   return myTriangul->Nodes().Length();
-}
+}
\ No newline at end of file
index ae90d64..537e053 100644 (file)
@@ -130,6 +130,10 @@ private:
   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
   virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                            const Standard_Integer               theElemIdx) Standard_OVERRIDE;
+
 public:
   Standard_Real myBVHBuildTime;
 
index e7280b7..111c5e2 100644 (file)
@@ -129,6 +129,17 @@ Standard_Boolean Select3D_SensitiveWire::overlapsElement (SelectBasics_Selecting
 }
 
 // =======================================================================
+// function : elementIsInside
+// purpose  :
+// =======================================================================
+Standard_Boolean Select3D_SensitiveWire::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                          const Standard_Integer               theElemIdx)
+{
+  SelectBasics_PickResult aMatchResult;
+  return myEntities.Value (myEntityIndexes.Value (theElemIdx))->Matches (theMgr, aMatchResult);
+}
+
+// =======================================================================
 // function : distanceToCOG
 // purpose  : Calculates distance from the 3d projection of used-picked
 //            screen point to center of the geometry
index 7513759..7e4f69e 100644 (file)
@@ -89,6 +89,10 @@ protected:
                                                             Standard_Integer theElemIdx,
                                                             Standard_Real& theMatchDepth) Standard_OVERRIDE;
 
+  //! Checks whether the entity with index theIdx is inside the current selecting volume
+  Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                            const Standard_Integer               theElemIdx) Standard_OVERRIDE;
+
   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
   Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
 
index 02a349c..df795b5 100644 (file)
@@ -49,8 +49,9 @@ public:
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box with minimum
   //! corner at point theMinPt and maximum at point theMaxPt
-  virtual Standard_Boolean Overlaps (const NCollection_Vec3<Standard_Real>& theMinPt,
-                                     const NCollection_Vec3<Standard_Real>& theMaxPt) = 0;
+  virtual Standard_Boolean Overlaps (const NCollection_Vec3<Standard_Real>& theBoxMin,
+                                     const NCollection_Vec3<Standard_Real>& theBoxMax,
+                                     Standard_Boolean*                      theInside = NULL) = 0;
 
   //! Returns true if selecting volume is overlapped by point thePt
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
@@ -82,6 +83,8 @@ public:
 
   virtual NCollection_Vec3<Standard_Real> DetectedPoint (const Standard_Real theDepth) const = 0;
 
+  virtual Standard_Boolean IsOverlapAllowed() const = 0;
+
 protected:
   SelectionType myActiveSelectionType;      //!< Active selection type: point, box or polyline
 };
index 4d615bf..858b24a 100644 (file)
@@ -107,8 +107,9 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const BVH_Box<Standard_Real, 3
 // function : Overlaps
 // purpose  : Intersection test between defined volume and given point
 //=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theMinPt*/,
-                                                  const SelectMgr_Vec3& /*theMaxPt*/)
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBoxMin*/,
+                                                  const SelectMgr_Vec3& /*theBoxMax*/,
+                                                  Standard_Boolean*     /*theInside*/)
 {
   return Standard_False;
 }
index 83ce1e6..0aa9c18 100644 (file)
@@ -98,8 +98,9 @@ public:
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
   //! with minimum corner at point theMinPt and maximum at point theMaxPt
-  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPt,
-                                     const SelectMgr_Vec3& theMaxPt);
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                     const SelectMgr_Vec3& theBoxMax,
+                                     Standard_Boolean*     theInside = NULL);
 
   //! Intersection test between defined volume and given point
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
index 01eaab3..1ba4a35 100644 (file)
@@ -63,8 +63,9 @@ protected:
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
   //! with minimum corner at point theMinPt and maximum at point theMaxPt
-  Standard_Boolean hasOverlap (const SelectMgr_Vec3& theMinPnt,
-                               const SelectMgr_Vec3& theMaxPnt);
+  Standard_Boolean hasOverlap (const SelectMgr_Vec3& theBoxMin,
+                               const SelectMgr_Vec3& theBoxMax,
+                               Standard_Boolean*     theInside = NULL);
 
   //! SAT intersection test between defined volume and given point
   Standard_Boolean hasOverlap (const gp_Pnt& thePnt);
@@ -88,7 +89,8 @@ private:
   //! Checks if AABB and frustum are separated along the given axis
   Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin,
                                 const SelectMgr_Vec3& theBoxMax,
-                                const SelectMgr_Vec3& theAxis) const;
+                                const SelectMgr_Vec3& theDirect,
+                                Standard_Boolean*     theInside) const;
 
   //! Checks if triangle and frustum are separated along the given axis
   Standard_Boolean isSeparated (const gp_Pnt& thePnt1,
index 4c8b22a..b245522 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <NCollection_Vector.hxx>
 #include <Poly_Array1OfTriangle.hxx>
+#include <Standard_Assert.hxx>
 
 #define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
 #define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
 template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const SelectMgr_Vec3& theBoxMin,
                                                     const SelectMgr_Vec3& theBoxMax,
-                                                    const SelectMgr_Vec3& theAxis) const
+                                                    const SelectMgr_Vec3& theDirect,
+                                                    Standard_Boolean*     theInside) const
 {
-  // frustum projection
-  Standard_Real aMinF =  DBL_MAX;
-  Standard_Real aMaxF = -DBL_MAX;
-
-  // box projection
-  Standard_Real aMinB =  DBL_MAX;
-  Standard_Real aMaxB = -DBL_MAX;
+  const Standard_Real aMinB =
+    theDirect.x() * (theDirect.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
+    theDirect.y() * (theDirect.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
+    theDirect.z() * (theDirect.z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
 
-  const Standard_Real aBoxProj1 =
-    theAxis.x() * (theAxis.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
-    theAxis.y() * (theAxis.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
-    theAxis.z() * (theAxis.z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
+  const Standard_Real aMaxB =
+    theDirect.x() * (theDirect.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
+    theDirect.y() * (theDirect.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
+    theDirect.z() * (theDirect.z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
 
-  const Standard_Real aBoxProj2 =
-    theAxis.x() * (theAxis.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
-    theAxis.y() * (theAxis.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
-    theAxis.z() * (theAxis.z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
+  Standard_ASSERT_RAISE (aMaxB >= aMinB, "Error! Failed to project box");
 
-  aMinB = Min (aBoxProj1, aBoxProj2);
-  aMaxB = Max (aBoxProj1, aBoxProj2);
+  // frustum projection
+  Standard_Real aMinF =  DBL_MAX;
+  Standard_Real aMaxF = -DBL_MAX;
 
   for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
   {
-    const Standard_Real aProj = DOT (myVertices[aVertIdx], theAxis);
+    const Standard_Real aProj = DOT (myVertices[aVertIdx], theDirect);
 
     aMinF = Min (aMinF, aProj);
     aMaxF = Max (aMaxF, aProj);
 
     if (aMinF <= aMaxB && aMaxF >= aMinB)
     {
-      return Standard_False;
+      if (theInside == NULL || !(*theInside)) // only overlap test
+      {
+        return Standard_False;
+      }
     }
   }
 
-  return aMinF > aMaxB || aMaxF < aMinB;
+  if (aMinF > aMaxB || aMaxF < aMinB)
+  {
+    return Standard_True; // fully separated
+  }
+  else if (theInside != NULL) // to check for inclusion?
+  {
+    *theInside &= aMinB >= aMinF && aMaxB <= aMaxF;
+  }
+
+  return Standard_False;
 }
 
 // =======================================================================
@@ -122,80 +131,64 @@ Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const gp_Pnt& thePnt1,
 // =======================================================================
 template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const SelectMgr_Vec3& theMinPnt,
-                                                   const SelectMgr_Vec3& theMaxPnt)
+                                                   const SelectMgr_Vec3& theMaxPnt,
+                                                   Standard_Boolean*     theInside)
 {
-  // E0 test
-  if (theMinPnt.x() > myMaxOrthoVertsProjections[0]
-  || theMaxPnt.x() < myMinOrthoVertsProjections[0])
-  {
-    return Standard_False;
-  }
-
-  // E1 test
-  if (theMinPnt.y() > myMaxOrthoVertsProjections[1]
-  || theMaxPnt.y() < myMinOrthoVertsProjections[1])
-  {
-    return Standard_False;
-  }
-
-  // E2 test
-  if (theMinPnt.z() > myMaxOrthoVertsProjections[2]
-  || theMaxPnt.z() < myMinOrthoVertsProjections[2])
+  for (Standard_Integer anAxis = 0; anAxis < 3; ++anAxis)
   {
-    return Standard_False;
+    if (theMinPnt[anAxis] > myMaxOrthoVertsProjections[anAxis]
+     || theMaxPnt[anAxis] < myMinOrthoVertsProjections[anAxis])
+    {
+      return Standard_False; // fully separated
+    }
+    else if (theInside != NULL) // to check for inclusion?
+    {
+      *theInside &= theMinPnt[anAxis] >= myMinOrthoVertsProjections[anAxis]
+                 && theMaxPnt[anAxis] <= myMaxOrthoVertsProjections[anAxis];
+    }
   }
 
   const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
+
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
   {
-    Standard_Real aBoxProjMax = RealFirst();
-    Standard_Real aBoxProjMin = RealLast();
-    Standard_Real aFrustumProjMax = RealFirst();
-    Standard_Real aFrustumProjMin = RealLast();
     SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
 
-    aFrustumProjMax = myMaxVertsProjections[aPlaneIdx];
-    aFrustumProjMin = myMinVertsProjections[aPlaneIdx];
-
-    const Standard_Real aBoxProj1 =
+    const Standard_Real aBoxProjMin =
       aPlane.x() * (aPlane.x() < 0.f ? theMaxPnt.x() : theMinPnt.x()) +
       aPlane.y() * (aPlane.y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) +
       aPlane.z() * (aPlane.z() < 0.f ? theMaxPnt.z() : theMinPnt.z());
 
-    const Standard_Real aBoxProj2 =
+    const Standard_Real aBoxProjMax =
       aPlane.x() * (aPlane.x() < 0.f ? theMinPnt.x() : theMaxPnt.x()) +
       aPlane.y() * (aPlane.y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) +
       aPlane.z() * (aPlane.z() < 0.f ? theMinPnt.z() : theMaxPnt.z());
 
-    aBoxProjMin = Min (aBoxProj1, aBoxProj2);
-    aBoxProjMax = Max (aBoxProj1, aBoxProj2);
+    Standard_ASSERT_RAISE (aBoxProjMax >= aBoxProjMin, "Error! Failed to project box");
 
-    if (aBoxProjMin > aFrustumProjMax
-      || aBoxProjMax < aFrustumProjMin)
+    if (aBoxProjMin > myMaxVertsProjections[aPlaneIdx]
+     || aBoxProjMax < myMinVertsProjections[aPlaneIdx])
     {
-      return Standard_False;
+      return Standard_False; // fully separated
+    }
+    else if (theInside != NULL) // to check for inclusion?
+    {
+      *theInside &= aBoxProjMin >= myMinVertsProjections[aPlaneIdx]
+                 && aBoxProjMax <= myMaxVertsProjections[aPlaneIdx];
     }
   }
 
-  SelectMgr_Vec3 aBndBoxDimensions[3] =
-  {
-    SelectMgr_Vec3 (1.0, 0.0, 0.0),
-    SelectMgr_Vec3 (0.0, 1.0, 0.0),
-    SelectMgr_Vec3 (0.0, 0.0, 1.0)
-  };
-
-  Standard_Integer aDirectionsNb = myIsOrthographic ? 4 : 6;
   for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
   {
-    for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir)
+    SelectMgr_Vec3 anEdge1 (aDim == 0, aDim == 1, aDim == 2);
+
+    for (Standard_Integer aVolDir = 0, aDirectionsNb = myIsOrthographic ? 4 : 6; aVolDir < aDirectionsNb; ++aVolDir)
     {
-      SelectMgr_Vec3 anEdge1 = aBndBoxDimensions[aDim];
-      SelectMgr_Vec3 anEdge2 = myEdgeDirs[aVolDir];
-      SelectMgr_Vec3 aTestDirection = SelectMgr_Vec3 (anEdge1.y() * anEdge2.z() - anEdge1.z() * anEdge2.y(),
-                                                      anEdge1.z() * anEdge2.x() - anEdge1.x() * anEdge2.z(),
-                                                      anEdge1.x() * anEdge2.y() - anEdge1.y() * anEdge2.x());
+      SelectMgr_Vec3 aDirection (anEdge1.y() * myEdgeDirs[aVolDir].z() - anEdge1.z() * myEdgeDirs[aVolDir].y(),
+                                 anEdge1.z() * myEdgeDirs[aVolDir].x() - anEdge1.x() * myEdgeDirs[aVolDir].z(),
+                                 anEdge1.x() * myEdgeDirs[aVolDir].y() - anEdge1.y() * myEdgeDirs[aVolDir].x());
 
-      if (isSeparated (theMinPnt, theMaxPnt, aTestDirection))
+      if (isSeparated (theMinPnt, theMaxPnt, aDirection, theInside))
       {
         return Standard_False;
       }
@@ -212,23 +205,18 @@ Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const SelectMgr_Vec3& theMinP
 template <int N>
 Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt)
 {
-  SelectMgr_Vec3 aPnt (thePnt.X(), thePnt.Y(), thePnt.Z());
-
   const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
+
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
   {
-    Standard_Real aPointProj      = RealLast();
-    Standard_Real aFrustumProjMax = RealFirst();
-    Standard_Real aFrustumProjMin = RealLast();
-    SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
-
-    aPointProj = DOT (aPlane, aPnt);
+    const Select3D_Vec3& aPlane = myPlanes[aPlaneIdx];
 
-    aFrustumProjMax = myMaxVertsProjections[aPlaneIdx];
-    aFrustumProjMin = myMinVertsProjections[aPlaneIdx];
+    const Standard_Real aPointProj = aPlane.x() * thePnt.X() +
+                                     aPlane.y() * thePnt.Y() +
+                                     aPlane.z() * thePnt.Z();
 
-    if (aPointProj > aFrustumProjMax
-      || aPointProj < aFrustumProjMin)
+    if (aPointProj > myMaxVertsProjections[aPlaneIdx]
+     || aPointProj < myMinVertsProjections[aPlaneIdx])
     {
       return Standard_False;
     }
index f57fc47..904bbd9 100644 (file)
@@ -96,49 +96,6 @@ Standard_Real SelectMgr_FrustumBuilder::SignedPlanePntDist (const SelectMgr_Vec3
   return anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z();
 }
 
-// =======================================================================
-// function : PlaneEquation
-// purpose  : Creates plane equation from 3 points: thePntA, thePntB and
-//            thePntC containing point theInnerPnt
-// =======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::PlaneEquation (const SelectMgr_Vec3& thePntA,
-                                                        const SelectMgr_Vec3& thePntB,
-                                                        const SelectMgr_Vec3& thePntC,
-                                                        const SelectMgr_Vec3& theInnerPnt) const
-{
-  NCollection_Vec4<Standard_Real> aPlaneEquation (0.0);
-
-  const SelectMgr_Vec3& aDirVecAB = thePntB - thePntA;
-  const SelectMgr_Vec3& aDirVecAC = thePntC - thePntA;
-  SelectMgr_Vec3 aPlaneNormal = SelectMgr_Vec3 (aDirVecAB.y() * aDirVecAC.z() - aDirVecAB.z() * aDirVecAC.y(),
-                                                aDirVecAB.z() * aDirVecAC.x() - aDirVecAB.x() * aDirVecAC.z(),
-                                                aDirVecAB.x() * aDirVecAC.y() - aDirVecAB.y() * aDirVecAC.x());
-
-  if (SignedPlanePntDist (aPlaneNormal, theInnerPnt) > 0)
-  {
-    aPlaneNormal *= -1.0;
-  }
-
-  return aPlaneNormal;
-}
-
-//=======================================================================
-// function : PlaneEquation
-// purpose  : Calculates plane equation from 3 points
-//=======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::PlaneEquation (const SelectMgr_Vec3& thePntA,
-                                                        const SelectMgr_Vec3& thePntB,
-                                                        const SelectMgr_Vec3& thePntC) const
-{
-  const SelectMgr_Vec3& aVec1 = thePntB - thePntA;
-  const SelectMgr_Vec3& aVec2 = thePntC - thePntA;
-  SelectMgr_Vec3 aPlaneEquation = SelectMgr_Vec3 (aVec1.y() * aVec2.z() - aVec1.z() * aVec2.y(),
-                                                  aVec1.z() * aVec2.x() - aVec1.x() * aVec2.z(),
-                                                  aVec1.x() * aVec2.y() - aVec1.y() * aVec2.x());
-
-  return aPlaneEquation;
-}
-
 //=======================================================================
 // function : safePointCast
 // purpose  :
index 419b355..1d4cd80 100644 (file)
@@ -55,18 +55,6 @@ public:
   Standard_Real SignedPlanePntDist (const SelectMgr_Vec3& theEq,
                                    const SelectMgr_Vec3& thePnt) const;
 
-  //! Creates plane equation from 3 points: thePntA, thePntB and
-  //! thePntC containing point theInnerPnt
-  SelectMgr_Vec3 PlaneEquation (const SelectMgr_Vec3& thePntA,
-                                const SelectMgr_Vec3& thePntB,
-                                const SelectMgr_Vec3& thePntC,
-                                const SelectMgr_Vec3& theInnerPnt) const;
-
-  //! Calculates plane equation from 3 points
-  SelectMgr_Vec3 PlaneEquation (const SelectMgr_Vec3& thePntA,
-                                const SelectMgr_Vec3& thePntB,
-                                const SelectMgr_Vec3& thePntC) const;
-
   //! Projects 2d screen point onto view frustum plane:
   //! theZ = 0 - near plane,
   //! theZ = 1 - far plane
index 2c2f492..bf658c9 100644 (file)
@@ -99,7 +99,6 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP
   aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd);
   aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
 
-  SelectMgr_Vec3 aDiff = aW + (anU * aSc) - (aV * aTc);
   SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc;
   theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
 }
@@ -144,6 +143,35 @@ void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec
   theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
 }
 
+namespace
+{
+  // =======================================================================
+  // function : computeNormals
+  // purpose  : Computes normals to frustum faces
+  // =======================================================================
+  void computeNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals)
+  {
+    // Top
+    theNormals[0] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
+                                           theVertices[4] - theVertices[0]);
+    // Bottom
+    theNormals[1] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[2],
+                                           theVertices[6] - theVertices[2]);
+    // Left
+    theNormals[2] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
+                                           theVertices[2] - theVertices[0]);
+    // Right
+    theNormals[3] = SelectMgr_Vec3::Cross (theVertices[5] - theVertices[4],
+                                           theVertices[6] - theVertices[4]);
+    // Near
+    theNormals[4] = SelectMgr_Vec3::Cross (theVertices[6] - theVertices[4],
+                                           theVertices[0] - theVertices[4]);
+    // Far
+    theNormals[5] = SelectMgr_Vec3::Cross (theVertices[7] - theVertices[5],
+                                           theVertices[1] - theVertices[5]);
+  }
+}
+
 // =======================================================================
 // function : Build
 // purpose  : Build volume according to the point and given pixel
@@ -188,36 +216,9 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
   myVertices[7] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
                                                     thePoint.Y() - myPixelTolerance / 2.0,
                                                     1.0);
-  // Top
-  myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
-                                          myVertices[0],
-                                          myVertices[5],
-                                          myVertices[6]);
-  // Bottom
-  myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
-                                          myVertices[2],
-                                          myVertices[7],
-                                          myVertices[4]);
-  // Left
-  myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
-                                          myVertices[0],
-                                          myVertices[2],
-                                          myVertices[6]);
-  // Right
-  myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
-                                          myVertices[4],
-                                          myVertices[6],
-                                          myVertices[2]);
-  // Near
-  myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
-                                          myVertices[6],
-                                          myVertices[2],
-                                          myVertices[3]);
-  // Far
-  myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
-                                          myVertices[7],
-                                          myVertices[3],
-                                          myVertices[2]);
+
+  // compute frustum normals
+  computeNormals (myVertices, myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
   {
@@ -313,40 +314,12 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
                                                     theMinPnt.Y(),
                                                     0.0);
   // RightBottomFar
-  myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X() ,
+  myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
                                                     theMinPnt.Y(),
                                                     1.0);
 
-  // Top
-  myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
-                                          myVertices[0],
-                                          myVertices[5],
-                                          myVertices[6]);
-  // Bottom
-  myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
-                                          myVertices[2],
-                                          myVertices[7],
-                                          myVertices[4]);
-  // Left
-  myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
-                                          myVertices[0],
-                                          myVertices[2],
-                                          myVertices[6]);
-  // Right
-  myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
-                                          myVertices[4],
-                                          myVertices[6],
-                                          myVertices[2]);
-  // Near
-  myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
-                                          myVertices[6],
-                                          myVertices[2],
-                                          myVertices[3]);
-  // Far
-  myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
-                                          myVertices[7],
-                                          myVertices[3],
-                                          myVertices[2]);
+  // compute frustum normals
+  computeNormals (myVertices, myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
   {
@@ -429,36 +402,8 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Transfor
   // RightBottomFar
   aRes->myVertices[7] = SelectMgr_MatOp::Transform (theTrsf, myVertices[7]);
 
-  // Top
-  aRes->myPlanes[0] = myBuilder->PlaneEquation (aRes->myVertices[1],
-                                                aRes->myVertices[0],
-                                                aRes->myVertices[5],
-                                                aRes->myVertices[6]);
-  // Bottom
-  aRes->myPlanes[1] = myBuilder->PlaneEquation (aRes->myVertices[3],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[7],
-                                                aRes->myVertices[4]);
-  // Left
-  aRes->myPlanes[2] = myBuilder->PlaneEquation (aRes->myVertices[1],
-                                                aRes->myVertices[0],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[6]);
-  // Right
-  aRes->myPlanes[3] = myBuilder->PlaneEquation (aRes->myVertices[5],
-                                                aRes->myVertices[4],
-                                                aRes->myVertices[6],
-                                                aRes->myVertices[2]);
-  // Near
-  aRes->myPlanes[4] = myBuilder->PlaneEquation (aRes->myVertices[4],
-                                                aRes->myVertices[6],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[3]);
-  // Far
-  aRes->myPlanes[5] = myBuilder->PlaneEquation (aRes->myVertices[5],
-                                                aRes->myVertices[7],
-                                                aRes->myVertices[3],
-                                                aRes->myVertices[2]);
+  // compute frustum normals
+  computeNormals (aRes->myVertices, aRes->myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
   {
@@ -559,36 +504,8 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Scale (c
   aRes->myVertices[7] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
                                                           myMousePos.Y() - theScaleFactor / 2.0,
                                                           1.0);
-  // Top
-  aRes->myPlanes[0] = myBuilder->PlaneEquation (aRes->myVertices[1],
-                                                aRes->myVertices[0],
-                                                aRes->myVertices[5],
-                                                aRes->myVertices[6]);
-  // Bottom
-  aRes->myPlanes[1] = myBuilder->PlaneEquation (aRes->myVertices[3],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[7],
-                                                aRes->myVertices[4]);
-  // Left
-  aRes->myPlanes[2] = myBuilder->PlaneEquation (aRes->myVertices[1],
-                                                aRes->myVertices[0],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[6]);
-  // Right
-  aRes->myPlanes[3] = myBuilder->PlaneEquation (aRes->myVertices[5],
-                                                aRes->myVertices[4],
-                                                aRes->myVertices[6],
-                                                aRes->myVertices[2]);
-  // Near
-  aRes->myPlanes[4] = myBuilder->PlaneEquation (aRes->myVertices[4],
-                                                aRes->myVertices[6],
-                                                aRes->myVertices[2],
-                                                aRes->myVertices[3]);
-  // Far
-  aRes->myPlanes[5] = myBuilder->PlaneEquation (aRes->myVertices[5],
-                                                aRes->myVertices[7],
-                                                aRes->myVertices[3],
-                                                aRes->myVertices[2]);
+  // compute frustum normals
+  computeNormals (aRes->myVertices, aRes->myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
   {
@@ -648,10 +565,11 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Scale (c
 //            axis-aligned bounding box with minimum corner at point
 //            theMinPnt and maximum at point theMaxPnt
 // =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPnt,
-                                                         const SelectMgr_Vec3& theMaxPnt)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                         const SelectMgr_Vec3& theBoxMax,
+                                                         Standard_Boolean*     theInside)
 {
-  return hasOverlap (theMinPnt, theMaxPnt);
+  return hasOverlap (theBoxMin, theBoxMax, theInside);
 }
 
 // =======================================================================
index fd41e47..ef97920 100644 (file)
@@ -58,8 +58,9 @@ public:
 
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
   //! with minimum corner at point theMinPt and maximum at point theMaxPt
-  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
-                                     const SelectMgr_Vec3& theMaxPnt) Standard_OVERRIDE;
+  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                     const SelectMgr_Vec3& theBoxMax,
+                                     Standard_Boolean*     theInside = NULL) Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
index a1c46ed..aa1ff3b 100644 (file)
@@ -22,6 +22,7 @@
 SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums)
 {
   myActiveSelectionType = Unknown;
+  myToAllowOverlap = Standard_False;
 
   if (theToAllocateFrustums)
   {
@@ -44,6 +45,7 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (co
   aMgr.myActiveSelectionType = myActiveSelectionType;
 
   aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->Transform (theTrsf);
+  aMgr.myToAllowOverlap = myToAllowOverlap;
 
   return aMgr;
 }
@@ -202,21 +204,21 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const BVH_Box<Stand
   if (myActiveSelectionType == Unknown)
     return Standard_False;
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox,
-                                                                  theDepth);
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox, theDepth);
 }
 
 //=======================================================================
 // function : Overlaps
 // purpose  : Intersection test between defined volume and given point
 //=======================================================================
-Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theMinPt,
-                                                             const SelectMgr_Vec3& theMaxPt)
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                             const SelectMgr_Vec3& theBoxMax,
+                                                             Standard_Boolean*     theInside)
 {
   if (myActiveSelectionType == Unknown)
     return Standard_False;
 
-  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theMinPt, theMaxPt);
+  return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theInside);
 }
 
 //=======================================================================
@@ -329,3 +331,23 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_Se
 
   return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth);
 }
+
+//=======================================================================
+// function : AllowOverlapDetection
+// purpose  : If theIsToAllow is false, only fully included sensitives will
+//            be detected, otherwise the algorithm will mark both included
+//            and overlapped entities as matched
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
+{
+  myToAllowOverlap = theIsToAllow;
+}
+
+//=======================================================================
+// function : IsOverlapAllowed
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
+{
+  return myActiveSelectionType != Box || myToAllowOverlap;
+}
index 3a13e43..6c6a7d7 100644 (file)
@@ -86,8 +86,9 @@ public:
 
   //! 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& theMinPt,
-                                                      const SelectMgr_Vec3& theMaxPt) Standard_OVERRIDE;
+  Standard_EXPORT  virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+                                                      const SelectMgr_Vec3& theBoxMax,
+                                                      Standard_Boolean*     theInside = NULL) Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
   Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
@@ -128,10 +129,18 @@ public:
   Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                                       const Standard_Real& theDepth);
 
+  //! Is used for rectangular selection only
+  //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
+  //! mark both included and overlapped entities as matched
+  Standard_EXPORT virtual void AllowOverlapDetection (const Standard_Boolean theIsToAllow);
+
+  Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE;
+
 private:
   enum { Frustum, FrustumSet, VolumeTypesNb };       //!< Defines the amount of available selecting volumes
 
   NCollection_Handle<SelectMgr_BaseFrustum> mySelectingVolumes[VolumeTypesNb];      //!< Array of selecting volumes
+  Standard_Boolean                          myToAllowOverlap;      //!< Defines if partially overlapped entities will me detected or not
 };
 
 #endif
index 9d27b01..696168d 100644 (file)
@@ -24,6 +24,28 @@ SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum()
   Clear();
 }
 
+namespace
+{
+  void computeFrustumNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals)
+  {
+    // V0V1
+    theNormals[0] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0],
+                                           theVertices[4] - theVertices[0]);
+    // V1V2
+    theNormals[1] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[1],
+                                           theVertices[5] - theVertices[1]);
+    // V0V2
+    theNormals[2] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0],
+                                           theVertices[5] - theVertices[0]);
+    // Near
+    theNormals[3] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
+                                           theVertices[2] - theVertices[0]);
+    // Far
+    theNormals[4] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[3],
+                                           theVertices[5] - theVertices[3]);
+  }
+}
+
 //=======================================================================
 // function : SelectMgr_TriangularFrustum
 // purpose  : Creates new triangular frustum with bases of triangles with
@@ -47,29 +69,7 @@ void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1,
   // V2_Far
   myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0);
 
-  // V0V1
-  myPlanes[0] = myBuilder->PlaneEquation (myVertices[0],
-                                          myVertices[3],
-                                          myVertices[4],
-                                          myVertices[1]);
-  // V1V2
-  myPlanes[1] = myBuilder->PlaneEquation (myVertices[1],
-                                          myVertices[4],
-                                          myVertices[5],
-                                          myVertices[2]);
-  // V0V2
-  myPlanes[2] = myBuilder->PlaneEquation (myVertices[0],
-                                          myVertices[3],
-                                          myVertices[5],
-                                          myVertices[2]);
-  // Near
-  myPlanes[3] = myBuilder->PlaneEquation (myVertices[0],
-                                          myVertices[1],
-                                          myVertices[2]);
-  // Far
-  myPlanes[4] = myBuilder->PlaneEquation (myVertices[3],
-                                          myVertices[4],
-                                          myVertices[5]);
+  computeFrustumNormals (myVertices, myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
   {
@@ -144,29 +144,7 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_TriangularFrustum::Transform
 
   aRes->myIsOrthographic = myIsOrthographic;
 
-  // V0V1
-  aRes->myPlanes[0] = myBuilder->PlaneEquation (aRes->myVertices[0],
-                                                aRes->myVertices[3],
-                                                aRes->myVertices[4],
-                                                aRes->myVertices[1]);
-  // V1V2
-  aRes->myPlanes[1] = myBuilder->PlaneEquation (aRes->myVertices[1],
-                                                aRes->myVertices[4],
-                                                aRes->myVertices[5],
-                                                aRes->myVertices[2]);
-  // V0V2
-  aRes->myPlanes[2] = myBuilder->PlaneEquation (aRes->myVertices[0],
-                                                aRes->myVertices[3],
-                                                aRes->myVertices[5],
-                                                aRes->myVertices[2]);
-  // Near
-  aRes->myPlanes[3] = myBuilder->PlaneEquation (aRes->myVertices[0],
-                                               aRes->myVertices[1],
-                                               aRes->myVertices[2]);
-  // Far
-  aRes->myPlanes[4] = myBuilder->PlaneEquation (aRes->myVertices[3],
-                                                aRes->myVertices[4],
-                                                aRes->myVertices[5]);
+  computeFrustumNormals (aRes->myVertices, aRes->myPlanes);
 
   for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
   {
@@ -238,9 +216,10 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const BVH_Box<Standard_R
 //            theMinPt and maximum at point theMaxPt
 // =======================================================================
 Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt,
-                                                        const SelectMgr_Vec3& theMaxPt)
+                                                        const SelectMgr_Vec3& theMaxPt,
+                                                        Standard_Boolean* /*theInside*/)
 {
-  return hasOverlap (theMinPt, theMaxPt);
+  return hasOverlap (theMinPt, theMaxPt, NULL);
 }
 
 // =======================================================================
index 1c3feb0..a94fc7e 100644 (file)
@@ -51,7 +51,8 @@ public:
   //! Returns true if selecting volume is overlapped by axis-aligned bounding box
   //! with minimum corner at point theMinPt and maximum at point theMaxPt
   virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPt,
-                                     const SelectMgr_Vec3& theMaxPt) Standard_OVERRIDE;
+                                     const SelectMgr_Vec3& theMaxPt,
+                                     Standard_Boolean* theInside) Standard_OVERRIDE;
 
   //! Intersection test between defined volume and given point
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
index 0848cc1..2ee203b 100644 (file)
@@ -139,11 +139,12 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const BVH_Box<Standar
 // purpose  :
 // =======================================================================
 Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& theMinPnt,
-                                                           const SelectMgr_Vec3& theMaxPnt)
+                                                           const SelectMgr_Vec3& theMaxPnt,
+                                                           Standard_Boolean* /*theInside*/)
 {
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt))
+    if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL))
       return Standard_True;
   }
 
index a1a5e91..8003d4f 100644 (file)
@@ -54,7 +54,8 @@ public:
                                      Standard_Real& theDepth) Standard_OVERRIDE;
 
   virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt,
-                                     const SelectMgr_Vec3& theMaxPnt) Standard_OVERRIDE;
+                                     const SelectMgr_Vec3& theMaxPnt,
+                                     Standard_Boolean* theInside) Standard_OVERRIDE;
 
   virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
                                      Standard_Real& theDepth) Standard_OVERRIDE;
index a8881d8..3c0967b 100644 (file)
@@ -668,3 +668,15 @@ void StdSelect_ViewerSelector3d::ResetSelectionActivationStatus()
 {
   resetSelectionActivationStatus();
 }
+
+//=======================================================================
+//function : AllowOverlapDetection
+//purpose  : Sets the detection type: if theIsToAllow is false,
+//           only fully included sensitives will be detected, otherwise
+//           the algorithm will mark both included and overlapped entities
+//           as matched
+//=======================================================================
+void StdSelect_ViewerSelector3d::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
+{
+  mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
+}
index 8931f11..86407bc 100644 (file)
@@ -87,6 +87,11 @@ public:
 
   Standard_EXPORT virtual Standard_Boolean HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const Standard_OVERRIDE;
 
+  //! Is used for rectangular selection only
+  //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
+  //! mark both included and overlapped entities as matched
+  Standard_EXPORT void AllowOverlapDetection (const Standard_Boolean theIsToAllow);
+
   DEFINE_STANDARD_RTTI(StdSelect_ViewerSelector3d)
 
 protected:
index 73f2d12..83e98a6 100644 (file)
@@ -37,9 +37,19 @@ is
     
     ShiftSelect(me:mutable) is virtual;
 
-    Select(me:mutable;xmin,ymin,xmax,ymax:Integer) is virtual;
+    Select (me                    : mutable;
+            theXPressed           : Integer;
+            theYPressed           : Integer;
+            theXMotion            : Integer;
+            theYMotion            : Integer;
+            theIsAutoAllowOverlap : Boolean from Standard = Standard_True) is virtual;
     
-    ShiftSelect(me:mutable;xmin,ymin,xmax,ymax:Integer) is virtual;
+    ShiftSelect (me                    : mutable;
+                 theXPressed           : Integer;
+                 theYPressed           : Integer;
+                 theXMotion            : Integer;
+                 theYMotion            : Integer;
+                 theIsAutoAllowOverlap : Boolean from Standard = Standard_True) is virtual;
     
     Select(me:mutable;thePolyline:Array1OfPnt2d from TColgp) is virtual;
     
index cba9c35..cd64b4c 100644 (file)
@@ -84,27 +84,56 @@ void ViewerTest_EventManager::MoveTo (const Standard_Integer theXPix,
 //purpose  :
 //=======================================================================
 
-void ViewerTest_EventManager::Select (const Standard_Integer theXPMin,
-                                      const Standard_Integer theYPMin,
-                                      const Standard_Integer theXPMax,
-                                      const Standard_Integer theYPMax)
+void ViewerTest_EventManager::Select (const Standard_Integer theXPressed,
+                                      const Standard_Integer theYPressed,
+                                      const Standard_Integer theXMotion,
+                                      const Standard_Integer theYMotion,
+                                      const Standard_Boolean theIsAutoAllowOverlap)
 {
   #define IS_FULL_INCLUSION Standard_True
   if (myView.IsNull()
-   || Abs (theXPMax - theXPMin) < 2
-   || Abs (theYPMax - theYPMin) < 2)
+   || Abs (theXPressed - theXMotion) < 2
+   || Abs (theYPressed - theYMotion) < 2)
   {
     return;
   }
   else if (!myCtx.IsNull())
   {
-    myCtx->Select (theXPMin, theYPMin, theXPMax, theYPMax, myView, Standard_False);
+    if (theIsAutoAllowOverlap)
+    {
+      if (theYPressed == Min (theYPressed, theYMotion))
+      {
+        myCtx->MainSelector()->AllowOverlapDetection (Standard_False);
+      }
+      else
+      {
+        myCtx->MainSelector()->AllowOverlapDetection (Standard_True);
+      }
+    }
+    myCtx->Select (Min (theXPressed, theXMotion),
+                   Min (theYPressed, theYMotion),
+                   Max (theXPressed, theXMotion),
+                   Max (theYPressed, theYMotion),
+                   myView,
+                   Standard_False);
+
+    // to restore default state of viewer selector
+    if (theIsAutoAllowOverlap)
+    {
+      myCtx->MainSelector()->AllowOverlapDetection (Standard_False);
+    }
   }
 
   const Handle(NIS_View) aView = Handle(NIS_View)::DownCast (myView);
   if (!aView.IsNull())
   {
-    aView->Select (theXPMin, theYPMin, theXPMax, theYPMax, Standard_False, IS_FULL_INCLUSION, Standard_False);
+    aView->Select (Min (theXPressed, theXMotion),
+                   Min (theYPressed, theYMotion),
+                   Max (theXPressed, theXMotion),
+                   Max (theYPressed, theYMotion),
+                   Standard_False,
+                   IS_FULL_INCLUSION,
+                   Standard_False);
   }
   myView->Redraw();
 }
@@ -114,25 +143,54 @@ void ViewerTest_EventManager::Select (const Standard_Integer theXPMin,
 //purpose  :
 //=======================================================================
 
-void ViewerTest_EventManager::ShiftSelect (const Standard_Integer theXPMin,
-                                           const Standard_Integer theYPMin,
-                                           const Standard_Integer theXPMax,
-                                           const Standard_Integer theYPMax)
+void ViewerTest_EventManager::ShiftSelect (const Standard_Integer theXPressed,
+                                           const Standard_Integer theYPressed,
+                                           const Standard_Integer theXMotion,
+                                           const Standard_Integer theYMotion,
+                                           const Standard_Boolean theIsAutoAllowOverlap)
 {
   if (myView.IsNull()
-   || Abs (theXPMax - theXPMin) < 2
-   || Abs (theYPMax - theYPMin) < 2)
+   || Abs (theXPressed - theXMotion) < 2
+   || Abs (theYPressed - theYMotion) < 2)
   {
     return;
   }
   else if (!myCtx.IsNull())
   {
-    myCtx->AIS_InteractiveContext::ShiftSelect (theXPMin, theYPMin, theXPMax, theYPMax, myView, Standard_False);
+    if (theIsAutoAllowOverlap)
+    {
+      if (theYPressed == Min (theYPressed, theYMotion))
+      {
+        myCtx->MainSelector()->AllowOverlapDetection (Standard_False);
+      }
+      else
+      {
+        myCtx->MainSelector()->AllowOverlapDetection (Standard_True);
+      }
+    }
+    myCtx->ShiftSelect (Min (theXPressed, theXMotion),
+                        Min (theYPressed, theYMotion),
+                        Max (theXPressed, theXMotion),
+                        Max (theYPressed, theYMotion),
+                        myView,
+                        Standard_False);
+
+    // to restore default state of viewer selector
+    if (theIsAutoAllowOverlap)
+    {
+      myCtx->MainSelector()->AllowOverlapDetection (Standard_False);
+    }
   }
   const Handle(NIS_View) aView = Handle(NIS_View)::DownCast (myView);
   if (!aView.IsNull())
   {
-    aView->Select (theXPMin, theYPMin, theXPMax, theYPMax, Standard_True, IS_FULL_INCLUSION, Standard_False);
+    aView->Select (Min (theXPressed, theXMotion),
+                   Min (theYPressed, theYMotion),
+                   Max (theXPressed, theXMotion),
+                   Max (theYPressed, theYMotion),
+                   Standard_True,
+                   IS_FULL_INCLUSION,
+                   Standard_False);
   }
   myView->Redraw();
 }
index a0e414d..fdcc7e7 100644 (file)
@@ -1606,13 +1606,13 @@ void VT_ProcessButton1Release (Standard_Boolean theIsShift)
     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
     if (theIsShift)
     {
-      EM->ShiftSelect (Min (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
-                       Max (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion));
+      EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
+                       X_Motion, Y_Motion);
     }
     else
     {
-      EM->Select (Min (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
-                  Max (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion));
+      EM->Select (X_ButtonPress, Y_ButtonPress,
+                  X_Motion, Y_Motion);
     }
   }
 }
@@ -5767,34 +5767,48 @@ static Standard_Integer VSelect (Draw_Interpretor& di,
     di << "use 'vinit' command before " << argv[0] << "\n";
     return 1;
   }
-  const Standard_Boolean isShiftSelection = (argc>3 && !(argc%2) && (atoi(argv[argc-1])==1));
+
+  const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
+  Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
+  TCollection_AsciiString anArg;
+  anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
+  anArg.LowerCase();
+  if (anArg == "-allowoverlap")
+  {
+    Standard_Boolean isValidated = isShiftSelection ? argc == 8
+      : argc == 7;
+    if (!isValidated)
+    {
+      di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
+      return 1;
+    }
+
+    Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
+    myAIScontext->MainSelector()->AllowOverlapDetection((Standard_Boolean)isToAllow);
+    aCoordsNb -= 2;
+  }
+
   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
-  if(argc <= 4)
+  if(aCoordsNb == 2)
   {
     if(isShiftSelection)
       aCurrentEventManager->ShiftSelect();
     else
       aCurrentEventManager->Select();
   }
-  else if(argc <= 6)
+  else if(aCoordsNb == 4)
   {
     if(isShiftSelection)
-      aCurrentEventManager->ShiftSelect(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
+      aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
     else
-      aCurrentEventManager->Select(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
+      aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
   }
   else
   {
-    Standard_Integer anUpper = 0;
-
-    if(isShiftSelection)
-      anUpper = (argc-1)/2;
-    else
-      anUpper = argc/2;
-    TColgp_Array1OfPnt2d aPolyline(1,anUpper);
+    TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
 
-    for(Standard_Integer i=1;i<=anUpper;++i)
+    for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
 
     if(isShiftSelection)
@@ -8626,12 +8640,14 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
     __FILE__, VDiffImage, group);
   theCommands.Add ("vselect",
-    "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [shift_selection = 0|1]\n"
+    "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
     "- emulates different types of selection:\n"
     "- 1) single click selection\n"
     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
-    "- 4) any of these selections with shift button pressed",
+    "- 4) -allowoverlap determines will partially included objects be selected in rectangular selection"
+    " (partial inclusion - overlap - is not allowed by default)\n"
+    "- 5) any of these selections with shift button pressed",
     __FILE__, VSelect, group);
   theCommands.Add ("vmoveto",
     "vmoveto x y"
diff --git a/tests/bugs/vis/bug26147 b/tests/bugs/vis/bug26147
new file mode 100644 (file)
index 0000000..4a92b18
--- /dev/null
@@ -0,0 +1,60 @@
+puts "============"
+puts "CR26147"
+puts "============"
+puts ""
+
+##########################################################################################
+puts "Visualization - restore the ability to pick only fully included objects in rectangular selection"
+##########################################################################################
+
+pload VISUALIZATION MODELING
+
+box b1 0 0 0 1 1 1
+box b2 2 2 2 1 1 1
+box b3 4 4 4 1 1 1
+
+vinit View1
+vdisplay b1 b2 b3
+vfit
+
+vselmode b1 1 1
+vselmode b1 2 1
+vselmode b2 1 1
+vselmode b2 2 1
+
+vselect 75 230 235 320 -allowoverlap 0
+set aNbSelected1 [vnbselected]
+if {$aNbSelected1 != 4} {
+  puts "ERROR: Wrong number of entities in vertice-edge selection without overlap allowed!"
+}
+
+vselect 75 230 235 320 -allowoverlap 1
+vnbselected
+set aNbSelected2 [vnbselected]
+if {$aNbSelected2 != 11} {
+  puts "ERROR: Wrong number of entities in vertice-edge selection with overlap allowed!"
+}
+
+vselect 0 0
+
+vselmode b3 4 1
+
+vselect 75 230 235 320 -allowoverlap 0 1
+vselect 350 150 380 170 1
+vnbselected
+set aNbSelected3 [vnbselected]
+if {$aNbSelected3 != 4} {
+  puts "ERROR: Wrong number of entities in vertice-edge-face shift selection without overlap allowed!"
+}
+
+vselect 0 0
+
+vselect 75 230 235 320 -allowoverlap 1 1
+vselect 350 150 380 170 1
+vnbselected
+set aNbSelected4 [vnbselected]
+if {$aNbSelected4 != 13} {
+  puts "ERROR: Wrong number of entities in vertice-edge-face shift selection with overlap allowed!"
+}
+
+vdump $imagedir/${casename}