mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
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.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
return isMatched;
|
||||
thePickResult = SelectBasics_PickResult (
|
||||
aDepth, theMgr.DistToGeometryCenter (myCenter3d));
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -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 (!theMgr.Overlaps (anArrayOfPnt, Select3D_TOS_INTERIOR, aDepth))
|
||||
{
|
||||
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCollisionDetected)
|
||||
{
|
||||
aDistToCOG = theMgr.DistToGeometryCenter (myCenter3D);
|
||||
}
|
||||
|
||||
aDistToCOG = theMgr.DistToGeometryCenter (myCenter3D);
|
||||
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
|
||||
|
||||
return isCollisionDetected;
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
void Select3D_SensitiveCircle::ArrayBounds (Standard_Integer & theLow,
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
return isMatched;
|
||||
thePickResult = SelectBasics_PickResult (aDepth,
|
||||
theMgr.DistToGeometryCenter (CenterOfGeometry()));
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -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;
|
||||
if (aHead < 0)
|
||||
break;
|
||||
|
||||
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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user