1
0
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:
vpa
2015-05-07 18:53:21 +03:00
committed by abv
parent 35c4a17c46
commit 2157d6ac63
44 changed files with 728 additions and 547 deletions

View File

@@ -26,7 +26,7 @@
Select3D_BVHPrimitiveContent::Select3D_BVHPrimitiveContent (const Handle(Select3D_SensitiveSet)& theSensitiveSet)
{
mySensitiveSet = theSensitiveSet;
myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (8, 32);
myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (myLeafNodeSize, 32);
MarkDirty();
}

View File

@@ -50,8 +50,14 @@ public:
//! Returns the tree built for set of sensitives
Standard_EXPORT const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& GetBVH();
//! Returns a number of nodes in 1 BVH leaf
Standard_Integer GetLeafNodeSize() const { return myLeafNodeSize; }
protected:
Handle(Select3D_SensitiveSet) mySensitiveSet; //!< Set of sensitive entities
private:
static const Standard_Integer myLeafNodeSize = 8; //!< Number of sub-elements in the leaf
};
#endif // _Select3D_BVHPrimitiveContent_Header

View File

@@ -136,7 +136,7 @@ Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Ha
}
Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
aPointsArray,
Standard_False);
Standard_True);
myPlanarPolygons.Append (aPlanarPolyg);
aStartIdx = aPntIter;
anEndIdx = aPntIter;
@@ -154,7 +154,7 @@ Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Ha
}
Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
aPointsArray,
Standard_False);
Standard_True);
myPlanarPolygons.Append (aPlanarPolyg);
}
}
@@ -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

View File

@@ -90,6 +90,10 @@ protected:
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth) Standard_OVERRIDE;
//! Checks whether the entity with index theIdx is inside the current selecting volume
Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) Standard_OVERRIDE;
//! Calculates distance from the 3d projection of used-picked
//! screen point to center of the geometry
Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;

View File

@@ -91,18 +91,24 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveBox::GetConnected()
Standard_Boolean Select3D_SensitiveBox::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
Standard_Boolean isMatched = theMgr.Overlaps (myBox, aDepth);
thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
if (isMatched)
if (!theMgr.IsOverlapAllowed()) // check for inclusion
{
aDistToCOG = theMgr.DistToGeometryCenter (myCenter3d);
Standard_Boolean isInside = Standard_True;
return theMgr.Overlaps (myBox.CornerMin(), myBox.CornerMax(), &isInside) && isInside;
}
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
Standard_Real aDepth;
if (!theMgr.Overlaps (myBox, aDepth)) // check for overlap
{
return Standard_False;
}
return isMatched;
thePickResult = SelectBasics_PickResult (
aDepth, theMgr.DistToGeometryCenter (myCenter3d));
return Standard_True;
}
//=======================================================================

View File

@@ -241,28 +241,39 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
Standard_Boolean isCollisionDetected = Standard_False;
if (mySensType == Select3D_TOS_BOUNDARY)
{
isCollisionDetected = Select3D_SensitivePoly::Matches (theMgr, thePickResult);
if (!Select3D_SensitivePoly::Matches (theMgr, thePickResult))
{
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return Standard_False;
}
}
else if (mySensType == Select3D_TOS_INTERIOR)
{
Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
Points3D (anArrayOfPnt);
isCollisionDetected = theMgr.Overlaps (anArrayOfPnt,
Select3D_TOS_INTERIOR,
aDepth);
if (!theMgr.IsOverlapAllowed())
{
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
if (!theMgr.Overlaps (myBndBox.CornerMin(), myBndBox.CornerMax(), Standard_False))
{
return Standard_False;
}
return Standard_True;
}
if (!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,

View File

@@ -28,7 +28,7 @@ IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveCurve, Select3D_SensitivePoly)
Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
const Handle(Geom_Curve)& theCurve,
const Standard_Integer theNbPnts)
: Select3D_SensitivePoly (theOwnerId, theNbPnts > 2, theNbPnts),
: Select3D_SensitivePoly (theOwnerId, Standard_True, theNbPnts),
myCurve (theCurve)
{
loadPoints (theCurve, theNbPnts);
@@ -41,7 +41,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
//==================================================
Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
const Handle(TColgp_HArray1OfPnt)& thePoints)
: Select3D_SensitivePoly (theOwnerId, thePoints, thePoints->Length() > 2)
: Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
{
SetSensitivityFactor (3.0);
@@ -53,7 +53,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti
//==================================================
Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
const TColgp_Array1OfPnt& thePoints)
: Select3D_SensitivePoly (theOwnerId, thePoints, thePoints.Length() > 2)
: Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True)
{
SetSensitivityFactor (3.0);
}
@@ -100,41 +100,4 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveCurve::GetConnected()
}
return aNewEntity;
}
//=======================================================================
// function : Matches
// purpose : Checks whether the curve overlaps current selecting volume
//=======================================================================
Standard_Boolean Select3D_SensitiveCurve::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
if (myPolyg.Size() > 2)
return Select3D_SensitivePoly::Matches (theMgr, thePickResult);
const gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
const gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
Standard_Real aDepth = RealLast();
Standard_Boolean isMatched = theMgr.Overlaps (aPnt1, aPnt2, aDepth);
if (isMatched)
{
Standard_Real aDistToCOG = RealLast();
if (myCOG.X() == RealLast() && myCOG.Y() == RealLast() && myCOG.Z() == RealLast())
{
gp_XYZ aCenter (0.0, 0.0, 0.0);
for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
{
aCenter += myPolyg.Pnt (aIdx);
}
myCOG = aCenter / myPolyg.Size();
}
aDistToCOG = theMgr.DistToGeometryCenter (myCOG);
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return Standard_True;
}
return Standard_False;
}
}

View File

@@ -65,10 +65,6 @@ public:
Standard_EXPORT Select3D_SensitiveCurve (const Handle(SelectBasics_EntityOwner)& theOwnerId,
const TColgp_Array1OfPnt& thePoints);
//! Checks whether the curve overlaps current selecting volume
Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
//! Returns the copy of this
Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE;

View File

@@ -314,8 +314,7 @@ Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_Selectin
theMatchDepth = RealLast();
const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
SelectBasics_PickResult aResult;
Standard_Boolean isMatching = myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult);
if (isMatching)
if (myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult))
{
theMatchDepth = aResult.Depth();
return Standard_True;
@@ -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

View File

@@ -130,6 +130,10 @@ private:
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth) Standard_OVERRIDE;
//! Checks whether the entity with index theIdx is inside the current selecting volume
virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) Standard_OVERRIDE;
//! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;

View File

@@ -42,13 +42,15 @@ Standard_Boolean Select3D_SensitivePoint::Matches (SelectBasics_SelectingVolumeM
{
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
Standard_Boolean isMatched = theMgr.Overlaps (myPoint, aDepth);
if (isMatched)
aDistToCOG = aDepth;
if (!theMgr.Overlaps (myPoint, aDepth))
{
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return Standard_False;
}
aDistToCOG = aDepth;
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return isMatched;
return Standard_True;
}
//=======================================================================

View File

@@ -58,6 +58,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
}
}
myIsComputed = Standard_True;
}
//==================================================
@@ -97,6 +99,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
}
}
myIsComputed = Standard_True;
}
//==================================================
@@ -118,6 +122,7 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_Entity
}
}
myCOG = gp_Pnt (RealLast(), RealLast(), RealLast());
myIsComputed = Standard_False;
}
//==================================================
@@ -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;
}

View File

@@ -106,6 +106,10 @@ private:
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth) Standard_OVERRIDE;
//! Checks whether the entity with index theIdx is inside the current selecting volume
virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) Standard_OVERRIDE;
//! Calculates distance from the 3d projection of used-picked screen point
//! to center of the geometry
virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
@@ -116,6 +120,7 @@ protected:
mutable gp_Pnt myCOG; //!< Center of the poly
Handle_TColStd_HArray1OfInteger mySegmentIndexes; //!< Segment indexes for BVH tree build
Select3D_BndBox3d myBndBox; //!< Bounding box of the poly
mutable Standard_Boolean myIsComputed; //!< Is true if all the points and data structures of polygon are initialized
};
DEFINE_STANDARD_HANDLE(Select3D_SensitivePoly, Select3D_SensitiveSet)

View File

@@ -42,21 +42,23 @@ Select3D_SensitiveSegment::Select3D_SensitiveSegment (const Handle(SelectBasics_
Standard_Boolean Select3D_SensitiveSegment::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
Standard_Boolean isMatched = theMgr.Overlaps (myStart,
myEnd,
aDepth);
thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
if (isMatched)
Standard_Real aDepth;
if (!theMgr.IsOverlapAllowed()) // check for inclusion
{
gp_Pnt aCenter = CenterOfGeometry();
aDistToCOG = theMgr.DistToGeometryCenter (aCenter);
return theMgr.Overlaps (myStart, aDepth) && theMgr.Overlaps (myEnd, aDepth);
}
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
if (!theMgr.Overlaps (myStart, myEnd, aDepth)) // check for overlap
{
return Standard_False;
}
return isMatched;
thePickResult = SelectBasics_PickResult (aDepth,
theMgr.DistToGeometryCenter (CenterOfGeometry()));
return Standard_True;
}
//=======================================================================

View File

@@ -49,92 +49,114 @@ void Select3D_SensitiveSet::BVH()
Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = myContent->GetBVH();
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH = myContent->GetBVH();
Standard_Integer aNode = 0; // a root node
if (!theMgr.Overlaps (aBVHTree->MinPoint (0),
aBVHTree->MaxPoint (0)))
thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
if (!theMgr.Overlaps (aBVH->MinPoint (0),
aBVH->MaxPoint (0)))
{
return Standard_False;
}
Standard_Integer aStack[32];
Standard_Integer aNode = 0;
Standard_Integer aHead = -1;
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
SelectMgr_Vec3 aClosestPnt (RealLast());
Standard_Integer aMatchesNb = -1;
Standard_Real aMinDepth = RealLast();
for (;;)
{
if (!aBVHTree->IsOuter (aNode))
const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];
if (aData.x() == 0) // is inner node
{
const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
const Standard_Boolean isLeftChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
aBVHTree->MaxPoint (aLeftChildIdx));
const Standard_Boolean isRightChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx),
aBVHTree->MaxPoint (aRightChildIdx));
if (isLeftChildIn
&& isRightChildIn)
const Standard_Integer aLftIdx = aData.y();
const Standard_Integer aRghIdx = aData.z();
Standard_Boolean isLftInside = Standard_True;
Standard_Boolean isRghInside = Standard_True;
Standard_Boolean toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLftIdx),
aBVH->MaxPoint (aLftIdx),
theMgr.IsOverlapAllowed() ? NULL : &isLftInside);
Standard_Boolean toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRghIdx),
aBVH->MaxPoint (aRghIdx),
theMgr.IsOverlapAllowed() ? NULL : &isRghInside);
if (!theMgr.IsOverlapAllowed()) // inclusion test
{
aNode = aLeftChildIdx;
++aHead;
aStack[aHead] = aRightChildIdx;
if (!toCheckLft || !toCheckRgh)
{
return Standard_False; // no inclusion
}
toCheckLft &= !isLftInside;
toCheckRgh &= !isRghInside;
}
else if (isLeftChildIn
|| isRightChildIn)
if (toCheckLft || toCheckRgh)
{
aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
aNode = toCheckLft ? aLftIdx : aRghIdx;
if (toCheckLft && toCheckRgh)
{
aStack[++aHead] = aRghIdx;
}
}
else
{
if (aHead < 0)
{
break;
}
aNode = aStack[aHead];
--aHead;
aNode = aStack[aHead--];
}
}
else
{
Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
Standard_Boolean isMatched = Standard_False;
for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
{
Standard_Real anElementDepth = 0.0;
isMatched = overlapsElement (theMgr, anIdx, anElementDepth);
if (isMatched)
if (!theMgr.IsOverlapAllowed()) // inclusion test
{
if (aDepth > anElementDepth)
if (!elementIsInside (theMgr, anElemIdx))
{
aDepth = anElementDepth;
myDetectedIdx = anIdx;
return Standard_False;
}
aMatchesNb++;
}
else // overlap test
{
Standard_Real aCurrentDepth = 0.0;
if (!overlapsElement (theMgr, anElemIdx, aCurrentDepth))
{
continue;
}
if (aMinDepth > aCurrentDepth)
{
aMinDepth = aCurrentDepth;
myDetectedIdx = anElemIdx;
}
++aMatchesNb;
}
}
if (aHead < 0)
{
break;
}
aNode = aStack[aHead];
--aHead;
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();
}

View File

@@ -31,7 +31,7 @@ class Select3D_BVHPrimitiveContent;
//! This class is base class for handling overlap detection of complex sensitive
//! entities. It provides an interface for building BVH tree for some set of entities.
//! Thereby, each iteration of overlap detection is a traverse of BVH tree in fact.
//! To use speed-up heirarchical structure in a custom complex sensitive entity, it is
//! To use speed-up hierarchical structure in a custom complex sensitive entity, it is
//! necessary to make that custom entity a descendant of this class and organize sub-entities
//! in some container which allows referencing to elements by index. Note that methods taking
//! index as a parameter are used for BVH build and the range of given index is [0; Size() - 1].
@@ -87,6 +87,9 @@ public:
//! Destroys cross-reference to avoid memory leak
Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
//! Returns a number of nodes in 1 BVH leaf
Standard_EXPORT Standard_Integer GetLeafNodeSize() const;
public:
DEFINE_STANDARD_RTTI(Select3D_SensitiveSet)
@@ -97,6 +100,10 @@ protected:
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth) = 0;
//! Checks whether the entity with index theIdx is inside the current selecting volume
virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) = 0;
//! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) = 0;

View File

@@ -33,14 +33,13 @@ Select3D_SensitiveTriangle::Select3D_SensitiveTriangle (const Handle(SelectBasic
const gp_Pnt& thePnt1,
const gp_Pnt& thePnt2,
const Select3D_TypeOfSensitivity theType)
: Select3D_SensitivePoly (theOwnerId, Standard_False, 3),
: Select3D_SensitiveEntity (theOwnerId),
mySensType (theType)
{
myPolyg.SetPnt (0, thePnt0);
myPolyg.SetPnt (1, thePnt1);
myPolyg.SetPnt (2, thePnt2);
myCentroid = (gp_XYZ (myPolyg.Pnt (0)) + gp_XYZ (myPolyg.Pnt (1)) + gp_XYZ (myPolyg.Pnt (2)))
* (0.3);
myPoints[0] = thePnt0;
myPoints[1] = thePnt1;
myPoints[2] = thePnt2;
myCentroid = (thePnt0.XYZ() + thePnt1.XYZ() + thePnt2.XYZ()) * (1.0 / 3.0);
}
//==================================================
@@ -53,18 +52,23 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
{
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
gp_Pnt aPnt3 = myPolyg.Pnt3d (2);
Standard_Boolean isMatched = theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDepth);
if (isMatched)
if (!theMgr.IsOverlapAllowed())
{
aDistToCOG = theMgr.DistToGeometryCenter (myCentroid);
Standard_Real aDummy;
return theMgr.Overlaps (myPoints[0], aDummy)
&& theMgr.Overlaps (myPoints[1], aDummy)
&& theMgr.Overlaps (myPoints[2], aDummy);
}
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
if (!theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDepth))
{
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return Standard_False;
}
return isMatched;
aDistToCOG = theMgr.DistToGeometryCenter (myCentroid);
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
return Standard_True;
}
//==================================================
@@ -73,9 +77,9 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
//==================================================
void Select3D_SensitiveTriangle::Points3D (gp_Pnt& thePnt0, gp_Pnt& thePnt1, gp_Pnt& thePnt2) const
{
thePnt0 = myPolyg.Pnt (0);
thePnt1 = myPolyg.Pnt (1);
thePnt2 = myPolyg.Pnt (2);
thePnt0 = myPoints[0];
thePnt1 = myPoints[1];
thePnt2 = myPoints[2];
}
//==================================================
@@ -84,11 +88,7 @@ void Select3D_SensitiveTriangle::Points3D (gp_Pnt& thePnt0, gp_Pnt& thePnt1, gp_
//==================================================
gp_Pnt Select3D_SensitiveTriangle::Center3D() const
{
gp_XYZ aPnt1, aPnt2, aPnt3;
aPnt1 = myPolyg.Pnt (0);
aPnt2 = myPolyg.Pnt (1);
aPnt3 = myPolyg.Pnt (2);
return gp_Pnt ((aPnt1 + aPnt2 + aPnt3) / 3.0);
return myCentroid;
}
//==================================================
@@ -99,7 +99,7 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::GetConnected()
{
// Create a copy of this
Handle(Select3D_SensitiveEntity) aNewEntity =
new Select3D_SensitiveTriangle (myOwnerId, myPolyg.Pnt(0), myPolyg.Pnt(1), myPolyg.Pnt(2), mySensType);
new Select3D_SensitiveTriangle (myOwnerId, myPoints[0], myPoints[1], myPoints[2], mySensType);
return aNewEntity;
}
@@ -112,23 +112,11 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::GetConnected()
//==================================================
Select3D_BndBox3d Select3D_SensitiveTriangle::BoundingBox()
{
gp_Pnt aPnt1 = myPolyg.Pnt3d (0);
gp_Pnt aPnt2 = myPolyg.Pnt3d (1);
gp_Pnt aPnt3 = myPolyg.Pnt3d (2);
const SelectMgr_Vec3 aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())),
Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())),
Min (aPnt1.Z(), Min (aPnt2.Z(), aPnt3.Z())));
const SelectMgr_Vec3 aMaxPnt = SelectMgr_Vec3 (Max (aPnt1.X(), Max (aPnt2.X(), aPnt3.X())),
Max (aPnt1.Y(), Max (aPnt2.Y(), aPnt3.Y())),
Max (aPnt1.Z(), Max (aPnt2.Z(), aPnt3.Z())));
const SelectMgr_Vec3 aMinPnt = SelectMgr_Vec3 (Min (myPoints[0].X(), Min (myPoints[1].X(), myPoints[2].X())),
Min (myPoints[0].Y(), Min (myPoints[1].Y(), myPoints[2].Y())),
Min (myPoints[0].Z(), Min (myPoints[1].Z(), myPoints[2].Z())));
const SelectMgr_Vec3 aMaxPnt = SelectMgr_Vec3 (Max (myPoints[0].X(), Max (myPoints[1].X(), myPoints[2].X())),
Max (myPoints[0].Y(), Max (myPoints[1].Y(), myPoints[2].Y())),
Max (myPoints[0].Z(), Max (myPoints[1].Z(), myPoints[2].Z())));
return Select3D_BndBox3d (aMinPnt, aMaxPnt);
}
//==================================================
// Function: NbSubElements
// Purpose : Returns the amount of points
//==================================================
Standard_Integer Select3D_SensitiveTriangle::NbSubElements()
{
return 3;
}

View File

@@ -41,7 +41,7 @@ class TopLoc_Location;
//! This comes into play in the detection of meshing and triangulation in surfaces.
//! In some cases this class can raise Standard_ConstructionError and
//! Standard_OutOfRange exceptions. For more details see Select3D_SensitivePoly.
class Select3D_SensitiveTriangle : public Select3D_SensitivePoly
class Select3D_SensitiveTriangle : public Select3D_SensitiveEntity
{
public:
@@ -71,7 +71,9 @@ public:
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
//! Returns the amount of points
Standard_EXPORT virtual Standard_Integer NbSubElements() Standard_OVERRIDE;
virtual Standard_Integer NbSubElements() Standard_OVERRIDE { return 3; }
virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE { return myCentroid; }
DEFINE_STANDARD_RTTI(Select3D_SensitiveTriangle)
@@ -79,6 +81,7 @@ private:
Select3D_TypeOfSensitivity mySensType; //!< Type of sensitivity: boundary or interior
gp_Pnt myCentroid; //!< Center of triangle
gp_Pnt myPoints[3];
};
DEFINE_STANDARD_HANDLE(Select3D_SensitiveTriangle, Select3D_SensitiveEntity)

View File

@@ -298,6 +298,55 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_
}
}
//==================================================
// Function : elementIsInside
// Purpose :
//==================================================
Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx)
{
Standard_Real aDummy;
const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
if (mySensType == Select3D_TOS_BOUNDARY)
{
gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
{
aSegmPnt1.Transform (myInitLocation.Transformation());
aSegmPnt2.Transform (myInitLocation.Transformation());
}
return theMgr.Overlaps (aSegmPnt1, aDummy) && theMgr.Overlaps (aSegmPnt2, aDummy);
}
else
{
Standard_Integer aNode1;
Standard_Integer aNode2;
Standard_Integer aNode3;
myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
if (HasInitLocation()) // Note: Should be removed (by transforming frustum)
{
aPnt1.Transform (myInitLocation.Transformation());
aPnt2.Transform (myInitLocation.Transformation());
aPnt3.Transform (myInitLocation.Transformation());
}
return theMgr.Overlaps (aPnt1, aDummy)
&& theMgr.Overlaps (aPnt2, aDummy)
&& theMgr.Overlaps (aPnt3, aDummy);
}
}
//=======================================================================
// function : distanceToCOG
// purpose : Calculates distance from the 3d projection of used-picked
@@ -392,4 +441,4 @@ gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
{
return myTriangul->Nodes().Length();
}
}

View File

@@ -130,6 +130,10 @@ private:
//! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
//! Checks whether the entity with index theIdx is inside the current selecting volume
virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) Standard_OVERRIDE;
public:
Standard_Real myBVHBuildTime;

View File

@@ -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

View File

@@ -89,6 +89,10 @@ protected:
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth) Standard_OVERRIDE;
//! Checks whether the entity with index theIdx is inside the current selecting volume
Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx) Standard_OVERRIDE;
//! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;