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.
// 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())
{
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();
}
//! 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
}
Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
aPointsArray,
- Standard_False);
+ Standard_True);
myPlanarPolygons.Append (aPlanarPolyg);
aStartIdx = aPntIter;
anEndIdx = aPntIter;
}
Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
aPointsArray,
- Standard_False);
+ Standard_True);
myPlanarPolygons.Append (aPlanarPolyg);
}
}
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
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;
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;
}
//=======================================================================
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,
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);
//==================================================
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);
//==================================================
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);
}
}
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
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;
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;
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
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;
{
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;
}
//=======================================================================
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
}
}
+
+ myIsComputed = Standard_True;
}
//==================================================
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
}
}
+
+ myIsComputed = Standard_True;
}
//==================================================
}
}
myCOG = gp_Pnt (RealLast(), RealLast(), RealLast());
+ myIsComputed = Standard_False;
}
//==================================================
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
//==================================================
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)
aCenter += myPolyg.Pnt (aIdx);
}
myCOG = aCenter / myPolyg.Size();
+ myIsComputed = Standard_True;
}
return theMgr.DistToGeometryCenter (myCOG);
//==================================================
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;
}
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;
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)
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;
}
//=======================================================================
Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
- const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = myContent->GetBVH();
+ const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH = myContent->GetBVH();
- Standard_Integer aNode = 0; // a root node
- if (!theMgr.Overlaps (aBVHTree->MinPoint (0),
- aBVHTree->MaxPoint (0)))
+ thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+
+ if (!theMgr.Overlaps (aBVH->MinPoint (0),
+ aBVH->MaxPoint (0)))
{
return Standard_False;
}
Standard_Integer aStack[32];
+ Standard_Integer aNode = 0;
Standard_Integer aHead = -1;
- Standard_Real aDepth = RealLast();
- Standard_Real aDistToCOG = RealLast();
- SelectMgr_Vec3 aClosestPnt (RealLast());
+
Standard_Integer aMatchesNb = -1;
+ Standard_Real aMinDepth = RealLast();
+
for (;;)
{
- if (!aBVHTree->IsOuter (aNode))
+ const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];
+
+ if (aData.x() == 0) // is inner node
{
- const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
- const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
- const Standard_Boolean isLeftChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
- aBVHTree->MaxPoint (aLeftChildIdx));
- const Standard_Boolean isRightChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx),
- aBVHTree->MaxPoint (aRightChildIdx));
- if (isLeftChildIn
- && isRightChildIn)
+ const Standard_Integer aLftIdx = aData.y();
+ const Standard_Integer aRghIdx = aData.z();
+
+ Standard_Boolean isLftInside = Standard_True;
+ Standard_Boolean isRghInside = Standard_True;
+
+ Standard_Boolean toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLftIdx),
+ aBVH->MaxPoint (aLftIdx),
+ theMgr.IsOverlapAllowed() ? NULL : &isLftInside);
+
+ Standard_Boolean toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRghIdx),
+ aBVH->MaxPoint (aRghIdx),
+ theMgr.IsOverlapAllowed() ? NULL : &isRghInside);
+
+ if (!theMgr.IsOverlapAllowed()) // inclusion test
{
- aNode = aLeftChildIdx;
- ++aHead;
- aStack[aHead] = aRightChildIdx;
+ if (!toCheckLft || !toCheckRgh)
+ {
+ return Standard_False; // no inclusion
+ }
+
+ toCheckLft &= !isLftInside;
+ toCheckRgh &= !isRghInside;
}
- else if (isLeftChildIn
- || isRightChildIn)
+
+ if (toCheckLft || toCheckRgh)
{
- aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
+ aNode = toCheckLft ? aLftIdx : aRghIdx;
+
+ if (toCheckLft && toCheckRgh)
+ {
+ aStack[++aHead] = aRghIdx;
+ }
}
else
{
if (aHead < 0)
- {
break;
- }
- aNode = aStack[aHead];
- --aHead;
+ aNode = aStack[aHead--];
}
}
else
{
- Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
- Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
- Standard_Boolean isMatched = Standard_False;
- for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
+ for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
{
- Standard_Real anElementDepth = 0.0;
- isMatched = overlapsElement (theMgr, anIdx, anElementDepth);
- if (isMatched)
+ if (!theMgr.IsOverlapAllowed()) // inclusion test
{
- if (aDepth > anElementDepth)
+ if (!elementIsInside (theMgr, anElemIdx))
{
- aDepth = anElementDepth;
- myDetectedIdx = anIdx;
+ return Standard_False;
}
- aMatchesNb++;
+ }
+ else // overlap test
+ {
+ Standard_Real aCurrentDepth = 0.0;
+
+ if (!overlapsElement (theMgr, anElemIdx, aCurrentDepth))
+ {
+ continue;
+ }
+
+ if (aMinDepth > aCurrentDepth)
+ {
+ aMinDepth = aCurrentDepth;
+ myDetectedIdx = anElemIdx;
+ }
+
+ ++aMatchesNb;
}
}
+
if (aHead < 0)
- {
break;
- }
- aNode = aStack[aHead];
- --aHead;
+ aNode = aStack[aHead--];
}
}
if (aMatchesNb != -1)
{
- aDistToCOG = distanceToCOG (theMgr);
- thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
- return Standard_True;
+ thePickResult = SelectBasics_PickResult (aMinDepth, distanceToCOG (theMgr));
}
- thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
- return Standard_False;
+ return !theMgr.IsOverlapAllowed() || aMatchesNb != -1;
}
//=======================================================================
{
myContent.Nullify();
}
+
+//=======================================================================
+// function : GetLeafNodeSize
+// purpose : Returns a number of nodes in 1 BVH leaf
+//=======================================================================
+Standard_Integer Select3D_SensitiveSet::GetLeafNodeSize() const
+{
+ return myContent->GetLeafNodeSize();
+}
//! 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].
//! 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)
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;
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);
}
//==================================================
{
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;
}
//==================================================
//==================================================
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];
}
//==================================================
//==================================================
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;
}
//==================================================
{
// 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;
}
//==================================================
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;
-}
//! 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:
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)
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)
}
}
+//==================================================
+// 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
Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
{
return myTriangul->Nodes().Length();
-}
+}
\ No newline at end of file
//! 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;
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
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;
//! Returns true if selecting volume is overlapped by axis-aligned bounding box with minimum
//! corner at point theMinPt and maximum at point theMaxPt
- virtual Standard_Boolean Overlaps (const NCollection_Vec3<Standard_Real>& theMinPt,
- const NCollection_Vec3<Standard_Real>& theMaxPt) = 0;
+ virtual Standard_Boolean Overlaps (const NCollection_Vec3<Standard_Real>& theBoxMin,
+ const NCollection_Vec3<Standard_Real>& theBoxMax,
+ Standard_Boolean* theInside = NULL) = 0;
//! Returns true if selecting volume is overlapped by point thePt
virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
virtual NCollection_Vec3<Standard_Real> DetectedPoint (const Standard_Real theDepth) const = 0;
+ virtual Standard_Boolean IsOverlapAllowed() const = 0;
+
protected:
SelectionType myActiveSelectionType; //!< Active selection type: point, box or polyline
};
// function : Overlaps
// purpose : Intersection test between defined volume and given point
//=======================================================================
-Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theMinPt*/,
- const SelectMgr_Vec3& /*theMaxPt*/)
+Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBoxMin*/,
+ const SelectMgr_Vec3& /*theBoxMax*/,
+ Standard_Boolean* /*theInside*/)
{
return Standard_False;
}
//! Returns true if selecting volume is overlapped by axis-aligned bounding box
//! with minimum corner at point theMinPt and maximum at point theMaxPt
- virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPt,
- const SelectMgr_Vec3& theMaxPt);
+ virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin,
+ const SelectMgr_Vec3& theBoxMax,
+ Standard_Boolean* theInside = NULL);
//! Intersection test between defined volume and given point
virtual Standard_Boolean Overlaps (const gp_Pnt& thePt,
//! Returns true if selecting volume is overlapped by axis-aligned bounding box
//! with minimum corner at point theMinPt and maximum at point theMaxPt
- Standard_Boolean hasOverlap (const SelectMgr_Vec3& theMinPnt,
- const SelectMgr_Vec3& theMaxPnt);
+ Standard_Boolean hasOverlap (const SelectMgr_Vec3& theBoxMin,
+ const SelectMgr_Vec3& theBoxMax,
+ Standard_Boolean* theInside = NULL);
//! SAT intersection test between defined volume and given point
Standard_Boolean hasOverlap (const gp_Pnt& thePnt);
//! Checks if AABB and frustum are separated along the given axis
Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin,
const SelectMgr_Vec3& theBoxMax,
- const SelectMgr_Vec3& theAxis) const;
+ const SelectMgr_Vec3& theDirect,
+ Standard_Boolean* theInside) const;
//! Checks if triangle and frustum are separated along the given axis
Standard_Boolean isSeparated (const gp_Pnt& thePnt1,
#include <NCollection_Vector.hxx>
#include <Poly_Array1OfTriangle.hxx>
+#include <Standard_Assert.hxx>
#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
template <int N>
Standard_Boolean SelectMgr_Frustum<N>::isSeparated (const SelectMgr_Vec3& theBoxMin,
const SelectMgr_Vec3& theBoxMax,
- const SelectMgr_Vec3& theAxis) const
+ const SelectMgr_Vec3& theDirect,
+ Standard_Boolean* theInside) const
{
- // frustum projection
- Standard_Real aMinF = DBL_MAX;
- Standard_Real aMaxF = -DBL_MAX;
-
- // box projection
- Standard_Real aMinB = DBL_MAX;
- Standard_Real aMaxB = -DBL_MAX;
+ const Standard_Real aMinB =
+ theDirect.x() * (theDirect.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
+ theDirect.y() * (theDirect.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
+ theDirect.z() * (theDirect.z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
- const Standard_Real aBoxProj1 =
- theAxis.x() * (theAxis.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) +
- theAxis.y() * (theAxis.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) +
- theAxis.z() * (theAxis.z() < 0.0 ? theBoxMax.z() : theBoxMin.z());
+ const Standard_Real aMaxB =
+ theDirect.x() * (theDirect.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
+ theDirect.y() * (theDirect.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
+ theDirect.z() * (theDirect.z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
- const Standard_Real aBoxProj2 =
- theAxis.x() * (theAxis.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) +
- theAxis.y() * (theAxis.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) +
- theAxis.z() * (theAxis.z() < 0.0 ? theBoxMin.z() : theBoxMax.z());
+ Standard_ASSERT_RAISE (aMaxB >= aMinB, "Error! Failed to project box");
- aMinB = Min (aBoxProj1, aBoxProj2);
- aMaxB = Max (aBoxProj1, aBoxProj2);
+ // frustum projection
+ Standard_Real aMinF = DBL_MAX;
+ Standard_Real aMaxF = -DBL_MAX;
for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx)
{
- const Standard_Real aProj = DOT (myVertices[aVertIdx], theAxis);
+ const Standard_Real aProj = DOT (myVertices[aVertIdx], theDirect);
aMinF = Min (aMinF, aProj);
aMaxF = Max (aMaxF, aProj);
if (aMinF <= aMaxB && aMaxF >= aMinB)
{
- return Standard_False;
+ if (theInside == NULL || !(*theInside)) // only overlap test
+ {
+ return Standard_False;
+ }
}
}
- return aMinF > aMaxB || aMaxF < aMinB;
+ if (aMinF > aMaxB || aMaxF < aMinB)
+ {
+ return Standard_True; // fully separated
+ }
+ else if (theInside != NULL) // to check for inclusion?
+ {
+ *theInside &= aMinB >= aMinF && aMaxB <= aMaxF;
+ }
+
+ return Standard_False;
}
// =======================================================================
// =======================================================================
template <int N>
Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const SelectMgr_Vec3& theMinPnt,
- const SelectMgr_Vec3& theMaxPnt)
+ const SelectMgr_Vec3& theMaxPnt,
+ Standard_Boolean* theInside)
{
- // E0 test
- if (theMinPnt.x() > myMaxOrthoVertsProjections[0]
- || theMaxPnt.x() < myMinOrthoVertsProjections[0])
- {
- return Standard_False;
- }
-
- // E1 test
- if (theMinPnt.y() > myMaxOrthoVertsProjections[1]
- || theMaxPnt.y() < myMinOrthoVertsProjections[1])
- {
- return Standard_False;
- }
-
- // E2 test
- if (theMinPnt.z() > myMaxOrthoVertsProjections[2]
- || theMaxPnt.z() < myMinOrthoVertsProjections[2])
+ for (Standard_Integer anAxis = 0; anAxis < 3; ++anAxis)
{
- return Standard_False;
+ if (theMinPnt[anAxis] > myMaxOrthoVertsProjections[anAxis]
+ || theMaxPnt[anAxis] < myMinOrthoVertsProjections[anAxis])
+ {
+ return Standard_False; // fully separated
+ }
+ else if (theInside != NULL) // to check for inclusion?
+ {
+ *theInside &= theMinPnt[anAxis] >= myMinOrthoVertsProjections[anAxis]
+ && theMaxPnt[anAxis] <= myMaxOrthoVertsProjections[anAxis];
+ }
}
const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
+
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
{
- Standard_Real aBoxProjMax = RealFirst();
- Standard_Real aBoxProjMin = RealLast();
- Standard_Real aFrustumProjMax = RealFirst();
- Standard_Real aFrustumProjMin = RealLast();
SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
- aFrustumProjMax = myMaxVertsProjections[aPlaneIdx];
- aFrustumProjMin = myMinVertsProjections[aPlaneIdx];
-
- const Standard_Real aBoxProj1 =
+ const Standard_Real aBoxProjMin =
aPlane.x() * (aPlane.x() < 0.f ? theMaxPnt.x() : theMinPnt.x()) +
aPlane.y() * (aPlane.y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) +
aPlane.z() * (aPlane.z() < 0.f ? theMaxPnt.z() : theMinPnt.z());
- const Standard_Real aBoxProj2 =
+ const Standard_Real aBoxProjMax =
aPlane.x() * (aPlane.x() < 0.f ? theMinPnt.x() : theMaxPnt.x()) +
aPlane.y() * (aPlane.y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) +
aPlane.z() * (aPlane.z() < 0.f ? theMinPnt.z() : theMaxPnt.z());
- aBoxProjMin = Min (aBoxProj1, aBoxProj2);
- aBoxProjMax = Max (aBoxProj1, aBoxProj2);
+ Standard_ASSERT_RAISE (aBoxProjMax >= aBoxProjMin, "Error! Failed to project box");
- if (aBoxProjMin > aFrustumProjMax
- || aBoxProjMax < aFrustumProjMin)
+ if (aBoxProjMin > myMaxVertsProjections[aPlaneIdx]
+ || aBoxProjMax < myMinVertsProjections[aPlaneIdx])
{
- return Standard_False;
+ return Standard_False; // fully separated
+ }
+ else if (theInside != NULL) // to check for inclusion?
+ {
+ *theInside &= aBoxProjMin >= myMinVertsProjections[aPlaneIdx]
+ && aBoxProjMax <= myMaxVertsProjections[aPlaneIdx];
}
}
- SelectMgr_Vec3 aBndBoxDimensions[3] =
- {
- SelectMgr_Vec3 (1.0, 0.0, 0.0),
- SelectMgr_Vec3 (0.0, 1.0, 0.0),
- SelectMgr_Vec3 (0.0, 0.0, 1.0)
- };
-
- Standard_Integer aDirectionsNb = myIsOrthographic ? 4 : 6;
for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
{
- for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir)
+ SelectMgr_Vec3 anEdge1 (aDim == 0, aDim == 1, aDim == 2);
+
+ for (Standard_Integer aVolDir = 0, aDirectionsNb = myIsOrthographic ? 4 : 6; aVolDir < aDirectionsNb; ++aVolDir)
{
- SelectMgr_Vec3 anEdge1 = aBndBoxDimensions[aDim];
- SelectMgr_Vec3 anEdge2 = myEdgeDirs[aVolDir];
- SelectMgr_Vec3 aTestDirection = SelectMgr_Vec3 (anEdge1.y() * anEdge2.z() - anEdge1.z() * anEdge2.y(),
- anEdge1.z() * anEdge2.x() - anEdge1.x() * anEdge2.z(),
- anEdge1.x() * anEdge2.y() - anEdge1.y() * anEdge2.x());
+ SelectMgr_Vec3 aDirection (anEdge1.y() * myEdgeDirs[aVolDir].z() - anEdge1.z() * myEdgeDirs[aVolDir].y(),
+ anEdge1.z() * myEdgeDirs[aVolDir].x() - anEdge1.x() * myEdgeDirs[aVolDir].z(),
+ anEdge1.x() * myEdgeDirs[aVolDir].y() - anEdge1.y() * myEdgeDirs[aVolDir].x());
- if (isSeparated (theMinPnt, theMaxPnt, aTestDirection))
+ if (isSeparated (theMinPnt, theMaxPnt, aDirection, theInside))
{
return Standard_False;
}
template <int N>
Standard_Boolean SelectMgr_Frustum<N>::hasOverlap (const gp_Pnt& thePnt)
{
- SelectMgr_Vec3 aPnt (thePnt.X(), thePnt.Y(), thePnt.Z());
-
const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1;
+
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor)
{
- Standard_Real aPointProj = RealLast();
- Standard_Real aFrustumProjMax = RealFirst();
- Standard_Real aFrustumProjMin = RealLast();
- SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
-
- aPointProj = DOT (aPlane, aPnt);
+ const Select3D_Vec3& aPlane = myPlanes[aPlaneIdx];
- aFrustumProjMax = myMaxVertsProjections[aPlaneIdx];
- aFrustumProjMin = myMinVertsProjections[aPlaneIdx];
+ const Standard_Real aPointProj = aPlane.x() * thePnt.X() +
+ aPlane.y() * thePnt.Y() +
+ aPlane.z() * thePnt.Z();
- if (aPointProj > aFrustumProjMax
- || aPointProj < aFrustumProjMin)
+ if (aPointProj > myMaxVertsProjections[aPlaneIdx]
+ || aPointProj < myMinVertsProjections[aPlaneIdx])
{
return Standard_False;
}
return anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z();
}
-// =======================================================================
-// function : PlaneEquation
-// purpose : Creates plane equation from 3 points: thePntA, thePntB and
-// thePntC containing point theInnerPnt
-// =======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::PlaneEquation (const SelectMgr_Vec3& thePntA,
- const SelectMgr_Vec3& thePntB,
- const SelectMgr_Vec3& thePntC,
- const SelectMgr_Vec3& theInnerPnt) const
-{
- NCollection_Vec4<Standard_Real> aPlaneEquation (0.0);
-
- const SelectMgr_Vec3& aDirVecAB = thePntB - thePntA;
- const SelectMgr_Vec3& aDirVecAC = thePntC - thePntA;
- SelectMgr_Vec3 aPlaneNormal = SelectMgr_Vec3 (aDirVecAB.y() * aDirVecAC.z() - aDirVecAB.z() * aDirVecAC.y(),
- aDirVecAB.z() * aDirVecAC.x() - aDirVecAB.x() * aDirVecAC.z(),
- aDirVecAB.x() * aDirVecAC.y() - aDirVecAB.y() * aDirVecAC.x());
-
- if (SignedPlanePntDist (aPlaneNormal, theInnerPnt) > 0)
- {
- aPlaneNormal *= -1.0;
- }
-
- return aPlaneNormal;
-}
-
-//=======================================================================
-// function : PlaneEquation
-// purpose : Calculates plane equation from 3 points
-//=======================================================================
-SelectMgr_Vec3 SelectMgr_FrustumBuilder::PlaneEquation (const SelectMgr_Vec3& thePntA,
- const SelectMgr_Vec3& thePntB,
- const SelectMgr_Vec3& thePntC) const
-{
- const SelectMgr_Vec3& aVec1 = thePntB - thePntA;
- const SelectMgr_Vec3& aVec2 = thePntC - thePntA;
- SelectMgr_Vec3 aPlaneEquation = SelectMgr_Vec3 (aVec1.y() * aVec2.z() - aVec1.z() * aVec2.y(),
- aVec1.z() * aVec2.x() - aVec1.x() * aVec2.z(),
- aVec1.x() * aVec2.y() - aVec1.y() * aVec2.x());
-
- return aPlaneEquation;
-}
-
//=======================================================================
// function : safePointCast
// purpose :
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
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);
}
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
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)
{
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)
{
// 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)
{
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)
{
// 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);
}
// =======================================================================
//! 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,
SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums)
{
myActiveSelectionType = Unknown;
+ myToAllowOverlap = Standard_False;
if (theToAllocateFrustums)
{
aMgr.myActiveSelectionType = myActiveSelectionType;
aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->Transform (theTrsf);
+ aMgr.myToAllowOverlap = myToAllowOverlap;
return aMgr;
}
if (myActiveSelectionType == Unknown)
return Standard_False;
- return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox,
- theDepth);
+ return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox, theDepth);
}
//=======================================================================
// function : Overlaps
// purpose : Intersection test between defined volume and given point
//=======================================================================
-Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theMinPt,
- const SelectMgr_Vec3& theMaxPt)
+Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin,
+ const SelectMgr_Vec3& theBoxMax,
+ Standard_Boolean* theInside)
{
if (myActiveSelectionType == Unknown)
return Standard_False;
- return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theMinPt, theMaxPt);
+ return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theInside);
}
//=======================================================================
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;
+}
//! 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,
Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
const Standard_Real& theDepth);
+ //! Is used for rectangular selection only
+ //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
+ //! mark both included and overlapped entities as matched
+ Standard_EXPORT virtual void AllowOverlapDetection (const Standard_Boolean theIsToAllow);
+
+ Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE;
+
private:
enum { Frustum, FrustumSet, VolumeTypesNb }; //!< Defines the amount of available selecting volumes
NCollection_Handle<SelectMgr_BaseFrustum> mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes
+ Standard_Boolean myToAllowOverlap; //!< Defines if partially overlapped entities will me detected or not
};
#endif
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
// 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)
{
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)
{
// theMinPt and maximum at point theMaxPt
// =======================================================================
Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt,
- const SelectMgr_Vec3& theMaxPt)
+ const SelectMgr_Vec3& theMaxPt,
+ Standard_Boolean* /*theInside*/)
{
- return hasOverlap (theMinPt, theMaxPt);
+ return hasOverlap (theMinPt, theMaxPt, NULL);
}
// =======================================================================
//! Returns true if selecting volume is overlapped by axis-aligned bounding box
//! with minimum corner at point theMinPt and maximum at point theMaxPt
virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPt,
- const SelectMgr_Vec3& theMaxPt) Standard_OVERRIDE;
+ const SelectMgr_Vec3& theMaxPt,
+ Standard_Boolean* theInside) Standard_OVERRIDE;
//! Intersection test between defined volume and given point
virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt,
// purpose :
// =======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& theMinPnt,
- const SelectMgr_Vec3& theMaxPnt)
+ const SelectMgr_Vec3& theMaxPnt,
+ Standard_Boolean* /*theInside*/)
{
for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
{
- if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt))
+ if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL))
return Standard_True;
}
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;
{
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);
+}
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:
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;
//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();
}
//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();
}
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);
}
}
}
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)
"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"
--- /dev/null
+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}