From 2157d6ac6378bc7d9898aa5c1e8e85a9fe62ab80 Mon Sep 17 00:00:00 2001 From: vpa Date: Thu, 7 May 2015 18:53:21 +0300 Subject: [PATCH] 0026147: Visualization - restore the ability to pick only fully included objects in rectangular selection 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. --- src/Graphic3d/Graphic3d_Camera.cxx | 2 +- src/Select3D/Select3D_BVHPrimitiveContent.cxx | 2 +- src/Select3D/Select3D_BVHPrimitiveContent.hxx | 6 + .../Select3D_InteriorSensitivePointSet.cxx | 15 +- .../Select3D_InteriorSensitivePointSet.hxx | 4 + src/Select3D/Select3D_SensitiveBox.cxx | 20 ++- src/Select3D/Select3D_SensitiveCircle.cxx | 33 ++-- src/Select3D/Select3D_SensitiveCurve.cxx | 45 +---- src/Select3D/Select3D_SensitiveCurve.hxx | 4 - src/Select3D/Select3D_SensitiveGroup.cxx | 14 +- src/Select3D/Select3D_SensitiveGroup.hxx | 4 + src/Select3D/Select3D_SensitivePoint.cxx | 12 +- src/Select3D/Select3D_SensitivePoly.cxx | 33 +++- src/Select3D/Select3D_SensitivePoly.hxx | 5 + src/Select3D/Select3D_SensitiveSegment.cxx | 22 +-- src/Select3D/Select3D_SensitiveSet.cxx | 123 ++++++++----- src/Select3D/Select3D_SensitiveSet.hxx | 9 +- src/Select3D/Select3D_SensitiveTriangle.cxx | 70 +++----- src/Select3D/Select3D_SensitiveTriangle.hxx | 7 +- .../Select3D_SensitiveTriangulation.cxx | 51 +++++- .../Select3D_SensitiveTriangulation.hxx | 4 + src/Select3D/Select3D_SensitiveWire.cxx | 11 ++ src/Select3D/Select3D_SensitiveWire.hxx | 4 + .../SelectBasics_SelectingVolumeManager.hxx | 7 +- src/SelectMgr/SelectMgr_BaseFrustum.cxx | 5 +- src/SelectMgr/SelectMgr_BaseFrustum.hxx | 5 +- src/SelectMgr/SelectMgr_Frustum.hxx | 8 +- src/SelectMgr/SelectMgr_Frustum.lxx | 150 +++++++--------- src/SelectMgr/SelectMgr_FrustumBuilder.cxx | 43 ----- src/SelectMgr/SelectMgr_FrustumBuilder.hxx | 12 -- .../SelectMgr_RectangularFrustum.cxx | 168 +++++------------- .../SelectMgr_RectangularFrustum.hxx | 5 +- .../SelectMgr_SelectingVolumeManager.cxx | 32 +++- .../SelectMgr_SelectingVolumeManager.hxx | 13 +- src/SelectMgr/SelectMgr_TriangularFrustum.cxx | 75 +++----- src/SelectMgr/SelectMgr_TriangularFrustum.hxx | 3 +- .../SelectMgr_TriangularFrustumSet.cxx | 5 +- .../SelectMgr_TriangularFrustumSet.hxx | 3 +- src/StdSelect/StdSelect_ViewerSelector3d.cxx | 12 ++ src/StdSelect/StdSelect_ViewerSelector3d.hxx | 5 + src/ViewerTest/ViewerTest_EventManager.cdl | 14 +- src/ViewerTest/ViewerTest_EventManager.cxx | 90 ++++++++-- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 54 ++++-- tests/bugs/vis/bug26147 | 60 +++++++ 44 files changed, 725 insertions(+), 544 deletions(-) create mode 100644 tests/bugs/vis/bug26147 diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index 4c684aa102..8184f2eec7 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -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()) { diff --git a/src/Select3D/Select3D_BVHPrimitiveContent.cxx b/src/Select3D/Select3D_BVHPrimitiveContent.cxx index 61aaec5301..08cad7aefc 100644 --- a/src/Select3D/Select3D_BVHPrimitiveContent.cxx +++ b/src/Select3D/Select3D_BVHPrimitiveContent.cxx @@ -26,7 +26,7 @@ Select3D_BVHPrimitiveContent::Select3D_BVHPrimitiveContent (const Handle(Select3D_SensitiveSet)& theSensitiveSet) { mySensitiveSet = theSensitiveSet; - myBuilder = new BVH_LinearBuilder (8, 32); + myBuilder = new BVH_LinearBuilder (myLeafNodeSize, 32); MarkDirty(); } diff --git a/src/Select3D/Select3D_BVHPrimitiveContent.hxx b/src/Select3D/Select3D_BVHPrimitiveContent.hxx index 210c43686c..2296f44860 100644 --- a/src/Select3D/Select3D_BVHPrimitiveContent.hxx +++ b/src/Select3D/Select3D_BVHPrimitiveContent.hxx @@ -50,8 +50,14 @@ public: //! Returns the tree built for set of sensitives Standard_EXPORT const NCollection_Handle >& 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 diff --git a/src/Select3D/Select3D_InteriorSensitivePointSet.cxx b/src/Select3D/Select3D_InteriorSensitivePointSet.cxx index cc2c7f8af0..b86c23cac8 100644 --- a/src/Select3D/Select3D_InteriorSensitivePointSet.cxx +++ b/src/Select3D/Select3D_InteriorSensitivePointSet.cxx @@ -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); } } @@ -279,6 +279,17 @@ Standard_Boolean Select3D_InteriorSensitivePointSet::overlapsElement (SelectBasi return theMgr.Overlaps (aPoints, Select3D_TOS_INTERIOR, theMatchDepth); } +// ======================================================================= +// 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 diff --git a/src/Select3D/Select3D_InteriorSensitivePointSet.hxx b/src/Select3D/Select3D_InteriorSensitivePointSet.hxx index 22df1664a4..b9fd3e878c 100644 --- a/src/Select3D/Select3D_InteriorSensitivePointSet.hxx +++ b/src/Select3D/Select3D_InteriorSensitivePointSet.hxx @@ -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; diff --git a/src/Select3D/Select3D_SensitiveBox.cxx b/src/Select3D/Select3D_SensitiveBox.cxx index 114de8ad9e..ead44d99d3 100644 --- a/src/Select3D/Select3D_SensitiveBox.cxx +++ b/src/Select3D/Select3D_SensitiveBox.cxx @@ -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; } //======================================================================= diff --git a/src/Select3D/Select3D_SensitiveCircle.cxx b/src/Select3D/Select3D_SensitiveCircle.cxx index 53a246c097..3f8eaa23a5 100644 --- a/src/Select3D/Select3D_SensitiveCircle.cxx +++ b/src/Select3D/Select3D_SensitiveCircle.cxx @@ -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, diff --git a/src/Select3D/Select3D_SensitiveCurve.cxx b/src/Select3D/Select3D_SensitiveCurve.cxx index 149b8a8378..91951b4c31 100644 --- a/src/Select3D/Select3D_SensitiveCurve.cxx +++ b/src/Select3D/Select3D_SensitiveCurve.cxx @@ -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 diff --git a/src/Select3D/Select3D_SensitiveCurve.hxx b/src/Select3D/Select3D_SensitiveCurve.hxx index ca265cc368..35584f1288 100644 --- a/src/Select3D/Select3D_SensitiveCurve.hxx +++ b/src/Select3D/Select3D_SensitiveCurve.hxx @@ -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; diff --git a/src/Select3D/Select3D_SensitiveGroup.cxx b/src/Select3D/Select3D_SensitiveGroup.cxx index 583edf04c3..4b67e5c324 100644 --- a/src/Select3D/Select3D_SensitiveGroup.cxx +++ b/src/Select3D/Select3D_SensitiveGroup.cxx @@ -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; @@ -324,6 +323,17 @@ Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_Selectin return Standard_False; } +// ======================================================================= +// 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 diff --git a/src/Select3D/Select3D_SensitiveGroup.hxx b/src/Select3D/Select3D_SensitiveGroup.hxx index bb6b681029..181af4f796 100644 --- a/src/Select3D/Select3D_SensitiveGroup.hxx +++ b/src/Select3D/Select3D_SensitiveGroup.hxx @@ -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; diff --git a/src/Select3D/Select3D_SensitivePoint.cxx b/src/Select3D/Select3D_SensitivePoint.cxx index 8c5acb67a2..10bacb5d0f 100644 --- a/src/Select3D/Select3D_SensitivePoint.cxx +++ b/src/Select3D/Select3D_SensitivePoint.cxx @@ -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; } //======================================================================= diff --git a/src/Select3D/Select3D_SensitivePoly.cxx b/src/Select3D/Select3D_SensitivePoly.cxx index 3a161fd96f..ee3f9fe149 100644 --- a/src/Select3D/Select3D_SensitivePoly.cxx +++ b/src/Select3D/Select3D_SensitivePoly.cxx @@ -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; } //================================================== @@ -236,6 +241,20 @@ Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_Selecting return theMgr.Overlaps (aPnt1, aPnt2, theMatchDepth); } +//================================================== +// 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 @@ -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; } diff --git a/src/Select3D/Select3D_SensitivePoly.hxx b/src/Select3D/Select3D_SensitivePoly.hxx index b92f9848ee..beb7e063d8 100644 --- a/src/Select3D/Select3D_SensitivePoly.hxx +++ b/src/Select3D/Select3D_SensitivePoly.hxx @@ -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) diff --git a/src/Select3D/Select3D_SensitiveSegment.cxx b/src/Select3D/Select3D_SensitiveSegment.cxx index 867985e575..d20f598eb3 100644 --- a/src/Select3D/Select3D_SensitiveSegment.cxx +++ b/src/Select3D/Select3D_SensitiveSegment.cxx @@ -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; } //======================================================================= diff --git a/src/Select3D/Select3D_SensitiveSet.cxx b/src/Select3D/Select3D_SensitiveSet.cxx index ed9b8b30ec..9e618e25b7 100644 --- a/src/Select3D/Select3D_SensitiveSet.cxx +++ b/src/Select3D/Select3D_SensitiveSet.cxx @@ -49,92 +49,114 @@ void Select3D_SensitiveSet::BVH() Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) { - const NCollection_Handle >& aBVHTree = myContent->GetBVH(); + const NCollection_Handle >& 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(); +} diff --git a/src/Select3D/Select3D_SensitiveSet.hxx b/src/Select3D/Select3D_SensitiveSet.hxx index 9c9d5f1a49..a351306f78 100644 --- a/src/Select3D/Select3D_SensitiveSet.hxx +++ b/src/Select3D/Select3D_SensitiveSet.hxx @@ -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; diff --git a/src/Select3D/Select3D_SensitiveTriangle.cxx b/src/Select3D/Select3D_SensitiveTriangle.cxx index 0436ad432b..7f43e7f5cf 100644 --- a/src/Select3D/Select3D_SensitiveTriangle.cxx +++ b/src/Select3D/Select3D_SensitiveTriangle.cxx @@ -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; -} diff --git a/src/Select3D/Select3D_SensitiveTriangle.hxx b/src/Select3D/Select3D_SensitiveTriangle.hxx index 1f17b09a08..7893954f5e 100644 --- a/src/Select3D/Select3D_SensitiveTriangle.hxx +++ b/src/Select3D/Select3D_SensitiveTriangle.hxx @@ -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) diff --git a/src/Select3D/Select3D_SensitiveTriangulation.cxx b/src/Select3D/Select3D_SensitiveTriangulation.cxx index b552d92202..c3973af13d 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.cxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.cxx @@ -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 diff --git a/src/Select3D/Select3D_SensitiveTriangulation.hxx b/src/Select3D/Select3D_SensitiveTriangulation.hxx index ae90d645f4..537e05346f 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.hxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.hxx @@ -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; diff --git a/src/Select3D/Select3D_SensitiveWire.cxx b/src/Select3D/Select3D_SensitiveWire.cxx index e7280b702c..111c5e2b68 100644 --- a/src/Select3D/Select3D_SensitiveWire.cxx +++ b/src/Select3D/Select3D_SensitiveWire.cxx @@ -128,6 +128,17 @@ Standard_Boolean Select3D_SensitiveWire::overlapsElement (SelectBasics_Selecting return Standard_False; } +// ======================================================================= +// 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 diff --git a/src/Select3D/Select3D_SensitiveWire.hxx b/src/Select3D/Select3D_SensitiveWire.hxx index 75137593df..7e4f69e0d0 100644 --- a/src/Select3D/Select3D_SensitiveWire.hxx +++ b/src/Select3D/Select3D_SensitiveWire.hxx @@ -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; diff --git a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx index 02a349cc5f..df795b5e34 100644 --- a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx +++ b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx @@ -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& theMinPt, - const NCollection_Vec3& theMaxPt) = 0; + virtual Standard_Boolean Overlaps (const NCollection_Vec3& theBoxMin, + const NCollection_Vec3& 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 DetectedPoint (const Standard_Real theDepth) const = 0; + virtual Standard_Boolean IsOverlapAllowed() const = 0; + protected: SelectionType myActiveSelectionType; //!< Active selection type: point, box or polyline }; diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index 4d615bfe29..858b24ac2d 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -107,8 +107,9 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const BVH_Box #include +#include #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()) @@ -26,43 +27,51 @@ template Standard_Boolean SelectMgr_Frustum::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::isSeparated (const gp_Pnt& thePnt1, // ======================================================================= template Standard_Boolean SelectMgr_Frustum::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::hasOverlap (const SelectMgr_Vec3& theMinP template Standard_Boolean SelectMgr_Frustum::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; } diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx index f57fc47efc..904bbd90a8 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx @@ -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 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 : diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx index 419b3551d9..1d4cd80574 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx @@ -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 diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index 2c2f492f73..bf658c9689 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -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_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_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_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); } // ======================================================================= diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index fd41e47830..ef97920ceb 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -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, diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index a1c46ed385..aa1ff3ba70 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -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_BoxOverlaps (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; +} diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 3a13e43bc2..6c6a7d7238 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -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 mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes + Standard_Boolean myToAllowOverlap; //!< Defines if partially overlapped entities will me detected or not }; #endif diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx index 9d27b01e44..696168d121 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx @@ -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_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_BoxOverlaps (theMinPnt, theMaxPnt)) + if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL)) return Standard_True; } diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index a1a5e91e4d..8003d4f140 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -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; diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.cxx b/src/StdSelect/StdSelect_ViewerSelector3d.cxx index a8881d8af4..3c0967bb07 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.cxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.cxx @@ -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); +} diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.hxx b/src/StdSelect/StdSelect_ViewerSelector3d.hxx index 8931f11962..86407bcfd5 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.hxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.hxx @@ -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: diff --git a/src/ViewerTest/ViewerTest_EventManager.cdl b/src/ViewerTest/ViewerTest_EventManager.cdl index 73f2d123d1..83e98a6d9e 100644 --- a/src/ViewerTest/ViewerTest_EventManager.cdl +++ b/src/ViewerTest/ViewerTest_EventManager.cdl @@ -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; diff --git a/src/ViewerTest/ViewerTest_EventManager.cxx b/src/ViewerTest/ViewerTest_EventManager.cxx index cba9c35486..cd64b4c98c 100644 --- a/src/ViewerTest/ViewerTest_EventManager.cxx +++ b/src/ViewerTest/ViewerTest_EventManager.cxx @@ -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(); } diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index a0e414d06c..fdcc7e700d 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -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 index 0000000000..4a92b18224 --- /dev/null +++ b/tests/bugs/vis/bug26147 @@ -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} -- 2.20.1