Select3D_SensitiveGroup - added option to force overlap check for all entities in the group.
Added interface for accessing last detected entity in the group.
Select3D_SensitivePrimitiveArray - added option to keep index map of detected elements
and option to split array into groups for faster initialization of extra-large arrays.
BVH_Geometry, BVH_Object - added missing accessor ::IsDirty() for checking BVH tree state.
if (!aPoints.IsNull()
&& !aPoints->Attributes().IsNull())
{
+ // split large point clouds into several groups
+ const Standard_Integer aNbGroups = aPoints->Attributes()->NbElements > 500000 ? 8 : 1;
Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
aSensitive->SetSensitivityFactor (8);
- aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location());
+ aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location(), true, aNbGroups);
aSensitive->BVH();
theSelection->Add (aSensitive);
return;
public:
+ //! Returns TRUE if geometry state should be updated.
+ virtual Standard_Boolean IsDirty() const { return myIsDirty; }
+
//! Marks geometry as outdated.
virtual void MarkDirty() { myIsDirty = Standard_True; }
//! Sets properties of the geometric object.
virtual void SetProperties (const Handle(BVH_Properties)& theProperties) { myProperties = theProperties; }
+ //! Returns TRUE if object state should be updated.
+ virtual Standard_Boolean IsDirty() const { return myIsDirty; }
+
//! Marks object state as outdated (needs BVH rebuilding).
virtual void MarkDirty() { myIsDirty = Standard_True; }
const Standard_Boolean theIsMustMatchAll)
: Select3D_SensitiveSet (theOwnerId),
myMustMatchAll (theIsMustMatchAll),
+ myToCheckOverlapAll (Standard_False),
myCenter (0.0, 0.0, 0.0) {}
//=======================================================================
Select3D_EntitySequence& theEntities,
const Standard_Boolean theIsMustMatchAll)
: Select3D_SensitiveSet (theOwnerId),
- myMustMatchAll (theIsMustMatchAll)
+ myMustMatchAll (theIsMustMatchAll),
+ myToCheckOverlapAll (Standard_False),
+ myCenter (0.0, 0.0, 0.0)
{
- myCenter = gp_Pnt (0.0, 0.0, 0.0);
-
for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
{
const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value();
Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
- if (!myMustMatchAll
- || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
+ const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+ && myMustMatchAll;
+ const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+ && myToCheckOverlapAll;
+ if (!toMatchAll && !toCheckAll)
+ {
return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
+ }
Standard_Real aDepth = RealLast();
Standard_Real aDistToCOG = RealLast();
-
+ Standard_Boolean isFailed = Standard_False;
for (Select3D_EntitySequenceIter anIt (myEntities); anIt.More(); anIt.Next())
{
SelectBasics_PickResult aMatchResult;
Handle(Select3D_SensitiveEntity)& aChild = anIt.ChangeValue();
if (!aChild->Matches (theMgr, aMatchResult))
{
- aMatchResult = SelectBasics_PickResult (RealLast(), RealLast());
- return Standard_False;
+ if (toMatchAll)
+ {
+ isFailed = Standard_True;
+ if (!toCheckAll)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ aDepth = Min (aMatchResult.Depth(), aDepth);
}
-
- aDepth = Min (aMatchResult.Depth(), aDepth);
+ }
+ if (isFailed)
+ {
+ thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+ return Standard_False;
}
aDistToCOG = theMgr.DistToGeometryCenter (CenterOfGeometry());
thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-
return Standard_True;
}
Select3D_EntitySequence& theEntities,
const Standard_Boolean theIsMustMatchAll = Standard_True);
+ //! Gets group content
+ const Select3D_EntitySequence& GetEntities() const { return myEntities; }
+
+ //! Access entity by index [1, NbSubElements()].
+ const Handle(Select3D_SensitiveEntity)& SubEntity (const Standard_Integer theIndex) const
+ {
+ return myEntities.Value (theIndex);
+ }
+
+ //! Return last detected entity.
+ Handle(Select3D_SensitiveEntity) LastDetectedEntity() const
+ {
+ const Standard_Integer anIndex = LastDetectedEntityIndex();
+ return anIndex != -1 ? myEntities.Value (anIndex) : Handle(Select3D_SensitiveEntity)();
+ }
+
+ //! Return index of last detected entity.
+ Standard_Integer LastDetectedEntityIndex() const { return myDetectedIdx != -1 ? myBVHPrimIndexes.Value (myDetectedIdx) : -1; }
+
//! Adds the list of sensitive entities LL to the empty
//! sensitive group object created at construction time.
Standard_EXPORT void Add (Select3D_EntitySequence& theEntities);
//! at the time of construction, or added using the function Add must be matched.
Standard_Boolean MustMatchAll() const { return myMustMatchAll; }
+ //! Returns TRUE if all sensitive entities should be checked within rectangular/polygonal selection, FALSE by default.
+ //! Can be useful for sensitive entities holding detection results as class property.
+ Standard_Boolean ToCheckOverlapAll() const
+ {
+ return myToCheckOverlapAll;
+ }
+
+ //! Returns TRUE if all sensitive entities should be checked within rectangular/polygonal selection, FALSE by default.
+ //! Can be useful for sensitive entities holding detection results as class property.
+ void SetCheckOverlapAll (Standard_Boolean theToCheckAll)
+ {
+ myToCheckOverlapAll = theToCheckAll;
+ }
+
//! Checks whether the group overlaps current selecting volume
Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
//! Sets the owner for all entities in group
Standard_EXPORT void Set (const Handle(SelectBasics_EntityOwner)& theOwnerId) Standard_OVERRIDE;
- //! Gets group content
- const Select3D_EntitySequence& GetEntities() const { return myEntities; }
-
//! Returns bounding box of the group. If location transformation
//! is set, it will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
Select3D_EntitySequence myEntities; //!< Grouped sensitive entities
Standard_Boolean myMustMatchAll; //!< Determines whether all entities in the group should be overlapped or not
+ Standard_Boolean myToCheckOverlapAll; //!< flag to check overlapping with all entities within rectangular/polygonal selection
gp_Pnt myCenter; //!< Center of geometry of the group
mutable Select3D_BndBox3d myBndBox; //!< Bounding box of the group
NCollection_Vector<Standard_Integer> myBVHPrimIndexes; //!< Vector of sub-entities indexes for BVH tree build
#include <Select3D_SensitivePrimitiveArray.hxx>
#include <NCollection_AlignedAllocator.hxx>
+#include <OSD_Parallel.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
}
+//! Functor for initializing groups in parallel threads.
+struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_InitFunctor
+{
+ Select3D_SensitivePrimitiveArray_InitFunctor (Select3D_SensitivePrimitiveArray& thePrimArray,
+ Standard_Integer theDivStep,
+ Standard_Boolean theToEvalMinMax)
+ : myPrimArray (thePrimArray),
+ myDivStep (theDivStep),
+ myToEvalMinMax (theToEvalMinMax),
+ myToComputeBvh (Standard_True),
+ myNbFailures (0) {}
+ void operator()(const Standard_Integer& theIndex) const
+ {
+ Handle(Select3D_SensitivePrimitiveArray)& anEntity = myPrimArray.myGroups->ChangeValue (theIndex);
+ const Standard_Integer aLower = myPrimArray.myIndexLower + theIndex * myDivStep;
+ const Standard_Integer anUpper = Min (aLower + myDivStep - 1, myPrimArray.myIndexUpper);
+ anEntity = new Select3D_SensitivePrimitiveArray (myPrimArray.myOwnerId);
+ anEntity->SetPatchSizeMax (myPrimArray.myPatchSizeMax);
+ anEntity->SetPatchDistance (myPrimArray.myPatchDistance);
+ anEntity->SetDetectElements (myPrimArray.myToDetectElem);
+ anEntity->SetDetectElementMap (myPrimArray.ToDetectElementMap());
+ anEntity->SetDetectNodes (myPrimArray.myToDetectNode);
+ anEntity->SetDetectNodeMap (myPrimArray.ToDetectNodeMap());
+ anEntity->SetSensitivityFactor(myPrimArray.SensitivityFactor());
+ switch (myPrimArray.myPrimType)
+ {
+ case Graphic3d_TOPA_POINTS:
+ {
+ if (!anEntity->InitPoints (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
+ {
+ Standard_Atomic_Increment (&myNbFailures);
+ return;
+ }
+ break;
+ }
+ case Graphic3d_TOPA_TRIANGLES:
+ {
+ if (!anEntity->InitTriangulation (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
+ {
+ Standard_Atomic_Increment (&myNbFailures);
+ return;
+ }
+ break;
+ }
+ default:
+ {
+ Standard_Atomic_Increment (&myNbFailures);
+ return;
+ }
+ }
+
+ if (myToComputeBvh)
+ {
+ anEntity->BVH();
+ }
+ }
+ Standard_Boolean IsDone() const { return myNbFailures == 0; }
+private:
+ Select3D_SensitivePrimitiveArray_InitFunctor operator= (Select3D_SensitivePrimitiveArray_InitFunctor& );
+private:
+ Select3D_SensitivePrimitiveArray& myPrimArray;
+ Standard_Integer myDivStep;
+ Standard_Boolean myToEvalMinMax;
+ Standard_Boolean myToComputeBvh;
+ mutable volatile Standard_Integer myNbFailures;
+};
+
+//! Functor for computing BVH in parallel threads.
+struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_BVHFunctor
+{
+ Select3D_SensitivePrimitiveArray_BVHFunctor (NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& theGroups) : myGroups (theGroups) {}
+ void operator()(const Standard_Integer& theIndex) const { myGroups.ChangeValue (theIndex)->BVH(); }
+private:
+ Select3D_SensitivePrimitiveArray_BVHFunctor operator= (Select3D_SensitivePrimitiveArray_BVHFunctor& );
+private:
+ NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& myGroups;
+};
+
// =======================================================================
// function : Select3D_SensitivePrimitiveArray
// purpose :
//
}
+// =======================================================================
+// function : SetDetectElementMap
+// purpose :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::SetDetectElementMap (bool theToDetect)
+{
+ if (!theToDetect)
+ {
+ myDetectedElemMap.Nullify();
+ return;
+ }
+
+ if (myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap = new TColStd_HPackedMapOfInteger();
+ }
+ else
+ {
+ myDetectedElemMap->ChangeMap().Clear();
+ }
+}
+
+// =======================================================================
+// function : SetDetectNodeMap
+// purpose :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::SetDetectNodeMap (bool theToDetect)
+{
+ if (!theToDetect)
+ {
+ myDetectedNodeMap.Nullify();
+ return;
+ }
+
+ if (myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap = new TColStd_HPackedMapOfInteger();
+ }
+ else
+ {
+ myDetectedNodeMap->ChangeMap().Clear();
+ }
+}
+
// =======================================================================
// function : InitTriangulation
// purpose :
const TopLoc_Location& theInitLoc,
const Standard_Integer theIndexLower,
const Standard_Integer theIndexUpper,
- const bool theToEvalMinMax)
+ const bool theToEvalMinMax,
+ const Standard_Integer theNbGroups)
{
MarkDirty();
+ myGroups.Nullify();
myPrimType = Graphic3d_TOPA_TRIANGLES;
myBndBox.Clear();
myVerts.Nullify();
myBvhIndices.release();
myIs3d = false;
myInitLocation = theInitLoc;
+ myCDG3D.SetCoord (0.0, 0.0, 0.0);
if (theVerts.IsNull()
|| theVerts->NbElements == 0)
{
Standard_Integer aTriFrom = theIndexLower / 3;
Standard_Integer aNbTris = (theIndexUpper - theIndexLower + 1) / 3;
+ const bool hasGroups = (theNbGroups > 1) && (aNbTris / theNbGroups > 10);
if (aNbTris < 1)
{
return false;
}
- if (!myBvhIndices.Init (aNbTris, myPatchSizeMax > 1))
+ if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbTris, !hasGroups && myPatchSizeMax > 1))
{
return false;
}
myIndexLower = theIndexLower;
myIndexUpper = theIndexUpper;
myInvInitLocation = myInitLocation.Transformation().Inverted();
+ if (hasGroups)
+ {
+ myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
+ const Standard_Integer aDivStep = (aNbTris / theNbGroups) * 3;
+ Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
+ OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
+ if (!anInitFunctor.IsDone())
+ {
+ return false;
+ }
+ for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
+ {
+ Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
+ myBndBox.Combine (anEntity->BoundingBox());
+ myBvhIndices.SetIndex (aGroupIter, aGroupIter);
+ myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+ }
+ myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
+ if (theToEvalMinMax)
+ {
+ computeBoundingBox();
+ }
+ return true;
+ }
Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
Standard_Integer aTriNodes1[3] = { -1, -1, -1 };
const TopLoc_Location& theInitLoc,
const Standard_Integer theIndexLower,
const Standard_Integer theIndexUpper,
- const bool theToEvalMinMax)
+ const bool theToEvalMinMax,
+ const Standard_Integer theNbGroups)
{
MarkDirty();
+ myGroups.Nullify();
myPrimType = Graphic3d_TOPA_POINTS;
myBndBox.Clear();
myVerts.Nullify();
}
}
- Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
+ const Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
+ const bool hasGroups = (theNbGroups > 1) && (aNbPoints / theNbGroups > 10);
if (aNbPoints < 1)
{
return false;
}
- if (!myBvhIndices.Init (aNbPoints, myPatchSizeMax > 1))
+ if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbPoints, !hasGroups && myPatchSizeMax > 1))
{
return false;
}
myIndexLower = theIndexLower;
myIndexUpper = theIndexUpper;
myInvInitLocation = myInitLocation.Transformation().Inverted();
+ if (hasGroups)
+ {
+ myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
+ const Standard_Integer aDivStep = aNbPoints / theNbGroups;
+ Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
+ OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
+ if (!anInitFunctor.IsDone())
+ {
+ return false;
+ }
+ for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
+ {
+ Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
+ myBndBox.Combine (anEntity->BoundingBox());
+ myBvhIndices.SetIndex (aGroupIter, aGroupIter);
+ myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+ }
+ myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
+ if (theToEvalMinMax)
+ {
+ computeBoundingBox();
+ }
+ return true;
+ }
Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
Standard_Integer aPatchFrom = 0;
{
case Graphic3d_TOPA_POINTS:
{
- aNewEntity->InitPoints (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper);
+ aNewEntity->InitPoints (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
break;
}
case Graphic3d_TOPA_TRIANGLES:
{
- aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper);
+ aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
break;
}
default: break;
return aNewEntity;
}
+//=======================================================================
+//function : Set
+//purpose :
+//=======================================================================
+void Select3D_SensitivePrimitiveArray::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
+{
+ base_type::Set (theOwnerId);
+ if (!myGroups.IsNull())
+ {
+ for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+ {
+ aGroupIter.Value()->Set (theOwnerId);
+ }
+ }
+}
+
+// =======================================================================
+// function : BVH
+// purpose :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::BVH()
+{
+ if (!myContent.IsDirty())
+ {
+ return;
+ }
+
+ base_type::BVH();
+ if (myGroups.IsNull())
+ {
+ return;
+ }
+
+ Standard_Integer aNbToUpdate = 0;
+ for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+ {
+ if (aGroupIter.Value()->myContent.IsDirty())
+ {
+ ++aNbToUpdate;
+ }
+ }
+
+ if (aNbToUpdate > 0)
+ {
+ Select3D_SensitivePrimitiveArray_BVHFunctor aFunctor (*myGroups);
+ OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, aFunctor, aNbToUpdate <= 1);
+ }
+}
+
// =======================================================================
// function : Size
// purpose :
{
const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theIdx);
+ if (!myGroups.IsNull())
+ {
+ return myGroups->Value (anElemIdx)->BoundingBox();
+ }
+
Select3D_BndBox3d aBox;
switch (myPrimType)
{
Standard_Real Select3D_SensitivePrimitiveArray::Center (const Standard_Integer theIdx,
const Standard_Integer theAxis) const
{
+ if (!myGroups.IsNull())
+ {
+ const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
+ const gp_Pnt aCenter = myGroups->Value (anElemIdx)->CenterOfGeometry();
+ return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
+ }
+
const Select3D_BndBox3d& aBox = Box (theIdx);
SelectMgr_Vec3 aCenter = (aBox.CornerMin() + aBox.CornerMax()) * 0.5;
return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
void Select3D_SensitivePrimitiveArray::computeBoundingBox()
{
myBndBox.Clear();
+ if (!myGroups.IsNull())
+ {
+ for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+ {
+ myBndBox.Combine (aGroupIter.Value()->BoundingBox());
+ }
+ return;
+ }
+
if (myVerts.IsNull())
{
return;
Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
+ if (!myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap->ChangeMap().Clear();
+ }
+ if (!myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap->ChangeMap().Clear();
+ }
myMinDepthElem = RealLast();
myMinDepthNode = RealLast();
myMinDepthEdge = RealLast();
myDetectedNode = -1;
myDetectedEdgeNode1 = -1;
myDetectedEdgeNode2 = -1;
- return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
+ const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull();
+ if (myGroups.IsNull()
+ || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point
+ || !toDetectRange)
+ {
+ if (!Select3D_SensitiveSet::Matches (theMgr, thePickResult))
+ {
+ return Standard_False;
+ }
+
+ if (!myGroups.IsNull() && myDetectedIdx != -1)
+ {
+ const Standard_Integer anIndex = myBvhIndices.Index (myDetectedIdx);
+ const Handle(Select3D_SensitivePrimitiveArray)& aLastGroup = myGroups->Value (anIndex);
+ myMinDepthElem = aLastGroup->myMinDepthElem;
+ myMinDepthNode = aLastGroup->myMinDepthNode;
+ myMinDepthEdge = aLastGroup->myMinDepthEdge;
+ myDetectedElem = aLastGroup->myDetectedElem;
+ myDetectedNode = aLastGroup->myDetectedNode;
+ myDetectedEdgeNode1 = aLastGroup->myDetectedEdgeNode1;
+ myDetectedEdgeNode2 = aLastGroup->myDetectedEdgeNode2;
+ }
+ return Standard_True;
+ }
+
+ Standard_Real aDepth = RealLast();
+ bool isFailed = false;
+ const bool toMatchAll = !theMgr.IsOverlapAllowed();
+ for (Standard_Integer aGroupIter = 0; aGroupIter < myBvhIndices.NbElements; ++aGroupIter)
+ {
+ const Standard_Integer anElemIdx = myBvhIndices.Index (aGroupIter);
+ SelectBasics_PickResult aMatchResult;
+ Handle(Select3D_SensitivePrimitiveArray)& aChild = myGroups->ChangeValue (anElemIdx);
+ const bool isMatched = aChild->Matches (theMgr, aMatchResult);
+ if (!myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap->ChangeMap().Unite (aChild->myDetectedElemMap->Map());
+ }
+ if (!myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap->ChangeMap().Unite (aChild->myDetectedNodeMap->Map());
+ }
+
+ if (!isMatched)
+ {
+ if (toMatchAll)
+ {
+ isFailed = true;
+ if (!toDetectRange)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (aDepth > aMatchResult.Depth())
+ {
+ myDetectedIdx = aGroupIter;
+ aDepth = aMatchResult.Depth();
+ }
+ }
+ }
+ if (isFailed)
+ {
+ thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+ return Standard_False;
+ }
+
+ thePickResult = SelectBasics_PickResult (aDepth, theMgr.DistToGeometryCenter (CenterOfGeometry()));
+ return Standard_True;
}
// =======================================================================
Standard_Integer theElemIdx,
Standard_Real& theMatchDepth)
{
- const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+ const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+ if (!myGroups.IsNull())
+ {
+ SelectBasics_PickResult aResult;
+ if (myGroups->Value (anElemIdx)->Matches (theMgr, aResult))
+ {
+ theMatchDepth = aResult.Depth();
+ return Standard_True;
+ }
+ theMatchDepth = RealLast();
+ return Standard_False;
+ }
+
const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
Select3D_BndBox3d aBox;
Standard_Boolean aResult = Standard_False;
myDetectedElem = myDetectedNode = aPointIndex;
myMinDepthElem = myMinDepthNode = aCurrentDepth;
}
+ if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ if (!myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap->ChangeMap().Add (aPointIndex);
+ }
+ if (!myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+ }
+ }
aResult = Standard_True;
}
}
Graphic3d_Vec3i aTriNodes;
for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
{
- const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
+ const Standard_Integer aTriIndex = anElemIdx + anElemIter;
+ const Standard_Integer anIndexOffset = aTriIndex * 3;
getTriIndices (myIndices, anIndexOffset, aTriNodes);
gp_Pnt aPnts[3];
if (myIs3d)
{
if (aCurrentDepth <= myMinDepthElem)
{
- myDetectedElem = anElemIdx + anElemIter;
+ myDetectedElem = aTriIndex;
myMinDepthElem = aCurrentDepth;
}
aResult = Standard_True;
}
+ if (!myDetectedElemMap.IsNull()
+ && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ myDetectedElemMap->ChangeMap().Add (aTriIndex);
+ }
}
if (myToDetectNode)
{
myDetectedNode = aTriNodes[aNodeIter];
myMinDepthNode = aCurrentDepth;
}
+ if (!myDetectedNodeMap.IsNull()
+ && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
+ }
aResult = Standard_True;
}
}
Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
const Standard_Integer theElemIdx)
{
- const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+ const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+ if (!myGroups.IsNull())
+ {
+ Standard_Real aDummy;
+ return overlapsElement (theMgr, theElemIdx, aDummy);
+ }
+
const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
switch (myPrimType)
{
{
return Standard_False;
}
+
+ if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ if (!myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap->ChangeMap().Add (aPointIndex);
+ }
+ if (!myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+ }
+ }
}
return Standard_True;
}
Graphic3d_Vec3i aTriNodes;
for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
{
- const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
+ const Standard_Integer aTriIndex = anElemIdx + anElemIter;
+ const Standard_Integer anIndexOffset = aTriIndex * 3;
getTriIndices (myIndices, anIndexOffset, aTriNodes);
gp_Pnt aPnts[3];
if (myIs3d)
{
return Standard_False;
}
+
+ if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ if (!myDetectedElemMap.IsNull())
+ {
+ myDetectedElemMap->ChangeMap().Add (aTriIndex);
+ }
+ if (!myDetectedNodeMap.IsNull())
+ {
+ myDetectedNodeMap->ChangeMap().Add (aTriNodes[0]);
+ myDetectedNodeMap->ChangeMap().Add (aTriNodes[1]);
+ myDetectedNodeMap->ChangeMap().Add (aTriNodes[2]);
+ }
+ }
}
return Standard_True;
}
#include <Graphic3d_TypeOfPrimitiveArray.hxx>
#include <Select3D_SensitiveSet.hxx>
#include <Select3D_BVHIndexBuffer.hxx>
+#include <TColStd_HPackedMapOfInteger.hxx>
//! Sensitive for triangulation or point set defined by Primitive Array.
//! The primitives can be optionally combined into patches within BVH tree
//! @param theIndexLower the theIndices range - first value (inclusive), starting from 0 and multiple by 3
//! @param theIndexUpper the theIndices range - last value (inclusive), upto theIndices->NbElements-1 and multiple by 3
//! @param theToEvalMinMax compute bounding box within initialization
+ //! @param theNbGroups number of groups to split the vertex array into several parts
Standard_EXPORT bool InitTriangulation (const Handle(Graphic3d_Buffer)& theVerts,
const Handle(Graphic3d_IndexBuffer)& theIndices,
const TopLoc_Location& theInitLoc,
const Standard_Integer theIndexLower,
const Standard_Integer theIndexUpper,
- const bool theToEvalMinMax = true);
+ const bool theToEvalMinMax = true,
+ const Standard_Integer theNbGroups = 1);
//! Initialize the sensitive object from triangualtion.
//! @param theVerts attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
//! @param theIndices index array defining triangulation
//! @param theInitLoc location
//! @param theToEvalMinMax compute bounding box within initialization
+ //! @param theNbGroups number of groups to split the vertex array into several parts
bool InitTriangulation (const Handle(Graphic3d_Buffer)& theVerts,
const Handle(Graphic3d_IndexBuffer)& theIndices,
const TopLoc_Location& theInitLoc,
- const bool theToEvalMinMax = true)
+ const bool theToEvalMinMax = true,
+ const Standard_Integer theNbGroups = 1)
{
const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
: (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
- return InitTriangulation (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax);
+ return InitTriangulation (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
}
//! Initialize the sensitive object from point set.
//! @param theIndexLower the theIndices range - first value (inclusive), starting from 0
//! @param theIndexUpper the theIndices range - last value (inclusive), upto theIndices->NbElements-1
//! @param theToEvalMinMax compute bounding box within initialization
+ //! @param theNbGroups number of groups to split the vertex array into several parts
Standard_EXPORT bool InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
const Handle(Graphic3d_IndexBuffer)& theIndices,
const TopLoc_Location& theInitLoc,
const Standard_Integer theIndexLower,
const Standard_Integer theIndexUpper,
- const bool theToEvalMinMax = true);
+ const bool theToEvalMinMax = true,
+ const Standard_Integer theNbGroups = 1);
//! Initialize the sensitive object from point set.
//! @param theVerts attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
//! @param theIndices index array to define subset of points
//! @param theInitLoc location
//! @param theToEvalMinMax compute bounding box within initialization
+ //! @param theNbGroups number of groups to split the vertex array into several parts
bool InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
const Handle(Graphic3d_IndexBuffer)& theIndices,
const TopLoc_Location& theInitLoc,
- const bool theToEvalMinMax = true)
+ const bool theToEvalMinMax = true,
+ const Standard_Integer theNbGroups = 1)
{
const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
: (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
- return InitPoints (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax);
+ return InitPoints (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
}
//! Initialize the sensitive object from point set.
//! @param theVerts attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
//! @param theInitLoc location
//! @param theToEvalMinMax compute bounding box within initialization
+ //! @param theNbGroups number of groups to split the vertex array into several parts
bool InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
const TopLoc_Location& theInitLoc,
- const bool theToEvalMinMax = true)
+ const bool theToEvalMinMax = true,
+ const Standard_Integer theNbGroups = 1)
{
const Standard_Integer anUpper = !theVerts.IsNull() ? (theVerts->NbElements - 1) : 0;
- return InitPoints (theVerts, Handle(Graphic3d_IndexBuffer)(), theInitLoc, 0, anUpper, theToEvalMinMax);
+ return InitPoints (theVerts, Handle(Graphic3d_IndexBuffer)(), theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
}
//! Assign new not transformed bounding box.
{
myBndBox = Select3D_BndBox3d (SelectMgr_Vec3 (theMinX, theMinY, theMinZ),
SelectMgr_Vec3 (theMaxX, theMaxY, theMaxZ));
+ if (!myGroups.IsNull())
+ {
+ for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+ {
+ aGroupIter.Value()->myBndBox = myBndBox;
+ }
+ }
}
- //! Return flag indicating detection of elements (true by default).
+ //! Return flag to keep index of last topmost detected element, TRUE by default.
bool ToDetectElements() const { return myToDetectElem; }
- //! Setup detection of elements.
+ //! Setup keeping of the index of last topmost detected element (axis picking).
void SetDetectElements (bool theToDetect) { myToDetectElem = theToDetect; }
- //! Return flag indicating detection of nodes (false by default).
+ //! Return flag to keep index map of last detected elements, FALSE by default (rectangle selection).
+ bool ToDetectElementMap() const { return !myDetectedElemMap.IsNull(); }
+
+ //! Setup keeping of the index map of last detected elements (rectangle selection).
+ Standard_EXPORT void SetDetectElementMap (bool theToDetect);
+
+ //! Return flag to keep index of last topmost detected node, FALSE by default.
bool ToDetectNodes() const { return myToDetectNode; }
- //! Setup detection of nodes.
+ //! Setup keeping of the index of last topmost detected node (for axis picking).
void SetDetectNodes (bool theToDetect) { myToDetectNode = theToDetect; }
- //! Return flag indicating detection of edges (false by default).
+ //! Return flag to keep index map of last detected nodes, FALSE by default (rectangle selection).
+ bool ToDetectNodeMap() const { return !myDetectedNodeMap.IsNull(); }
+
+ //! Setup keeping of the index map of last detected nodes (rectangle selection).
+ Standard_EXPORT void SetDetectNodeMap (bool theToDetect);
+
+ //! Return flag to keep index of last topmost detected edge, FALSE by default.
bool ToDetectEdges() const { return myToDetectEdge; }
- //! Setup detection of edges.
+ //! Setup keeping of the index of last topmost detected edge (axis picking).
void SetDetectEdges (bool theToDetect) { myToDetectEdge = theToDetect; }
- //! Return last detected element or -1 if undefined.
+ //! Return last topmost detected element or -1 if undefined (axis picking).
Standard_Integer LastDetectedElement() const { return myDetectedElem; }
- //! Return last detected node or -1 if undefined.
+ //! Return the index map of last detected elements (rectangle selection).
+ const Handle(TColStd_HPackedMapOfInteger)& LastDetectedElementMap() const { return myDetectedElemMap; }
+
+ //! Return last topmost detected node or -1 if undefined (axis picking).
Standard_Integer LastDetectedNode() const { return myDetectedNode; }
- //! Return the first node of last detected edge or -1 if undefined.
+ //! Return the index map of last detected nodes (rectangle selection).
+ const Handle(TColStd_HPackedMapOfInteger)& LastDetectedNodeMap() const { return myDetectedNodeMap; }
+
+ //! Return the first node of last topmost detected edge or -1 if undefined (axis picking).
Standard_Integer LastDetectedEdgeNode1() const { return myDetectedEdgeNode1; }
- //! Return the second node of last detected edge or -1 if undefined.
+ //! Return the second node of last topmost detected edge or -1 if undefined (axis picking).
Standard_Integer LastDetectedEdgeNode2() const { return myDetectedEdgeNode2; }
public:
//! Returns the amount of nodes in triangulation
virtual Standard_Integer NbSubElements() Standard_OVERRIDE
{
- return myBvhIndices.NbElements;
+ return !myGroups.IsNull() ? myGroups->Size() : myBvhIndices.NbElements;
}
//! Returns bounding box of triangle/edge with index theIdx
return myInvInitLocation;
}
+ //! Sets the owner for all entities in group
+ Standard_EXPORT virtual void Set (const Handle(SelectBasics_EntityOwner)& theOwnerId) Standard_OVERRIDE;
+
+ //! Builds BVH tree for sensitive set.
+ Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+
protected:
//! Compute bounding box.
private:
- Handle(Graphic3d_Buffer) myVerts; //!< source data - nodes position
- Handle(Graphic3d_IndexBuffer) myIndices; //!< source data - primitive indexes
- Graphic3d_TypeOfPrimitiveArray myPrimType; //!< primitives type
- Standard_Integer myIndexLower; //!< index range - first index in myIndices (inclusive)
- Standard_Integer myIndexUpper; //!< index range - last index in myIndices (inclusive)
- Standard_Size myPosOffset; //!< offset to the position vertex attribute
- Standard_Integer myPatchSizeMax; //!< patch size limit (1 by default)
- float myPatchDistance; //!< distance between elements in patch
- bool myIs3d; //!< flag indicating that position attribute has 3 components
- TopLoc_Location myInitLocation;
- gp_Pnt myCDG3D; //!< Center of the whole triangulation
- Select3D_BVHIndexBuffer myBvhIndices; //!< Indexes of edges or triangles for BVH tree
- mutable Select3D_BndBox3d myBndBox; //!< Bounding box of the whole triangulation
- gp_GTrsf myInvInitLocation;
- Standard_Real myMinDepthElem; //!< the depth of nearest detected element
- Standard_Real myMinDepthNode; //!< the depth of nearest detected node
- Standard_Real myMinDepthEdge; //!< the depth of nearest detected edge
- Standard_Integer myDetectedElem; //!< index of detected element
- Standard_Integer myDetectedNode; //!< index of detected node
- Standard_Integer myDetectedEdgeNode1; //!< index of detected edge node 1
- Standard_Integer myDetectedEdgeNode2; //!< index of detected edge node 2
- bool myToDetectElem; //!< flag to detect element
- bool myToDetectNode; //!< flag to detect node
- bool myToDetectEdge; //!< flag to detect edge
+ typedef NCollection_Shared<NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)> > Select3D_PrimArraySubGroupArray;
+ struct Select3D_SensitivePrimitiveArray_InitFunctor;
+ struct Select3D_SensitivePrimitiveArray_BVHFunctor;
+
+private:
+
+ Handle(Select3D_PrimArraySubGroupArray) myGroups; //!< sub-groups of sensitive entities
+
+ Handle(Graphic3d_Buffer) myVerts; //!< source data - nodes position
+ Handle(Graphic3d_IndexBuffer) myIndices; //!< source data - primitive indexes
+ Graphic3d_TypeOfPrimitiveArray myPrimType; //!< primitives type
+ Standard_Integer myIndexLower; //!< index range - first index in myIndices (inclusive)
+ Standard_Integer myIndexUpper; //!< index range - last index in myIndices (inclusive)
+ Standard_Size myPosOffset; //!< offset to the position vertex attribute
+ Standard_Integer myPatchSizeMax; //!< patch size limit (1 by default)
+ float myPatchDistance; //!< distance between elements in patch
+ bool myIs3d; //!< flag indicating that position attribute has 3 components
+ TopLoc_Location myInitLocation;
+ gp_Pnt myCDG3D; //!< Center of the whole triangulation
+ Select3D_BVHIndexBuffer myBvhIndices; //!< Indexes of edges or triangles for BVH tree
+ mutable Select3D_BndBox3d myBndBox; //!< Bounding box of the whole triangulation
+ gp_GTrsf myInvInitLocation;
+ Handle(TColStd_HPackedMapOfInteger) myDetectedElemMap; //!< index map of last detected elements
+ Handle(TColStd_HPackedMapOfInteger) myDetectedNodeMap; //!< index map of last detected nodes
+ Standard_Real myMinDepthElem; //!< the depth of nearest detected element
+ Standard_Real myMinDepthNode; //!< the depth of nearest detected node
+ Standard_Real myMinDepthEdge; //!< the depth of nearest detected edge
+ Standard_Integer myDetectedElem; //!< index of last detected element
+ Standard_Integer myDetectedNode; //!< index of last detected node
+ Standard_Integer myDetectedEdgeNode1; //!< index of last detected edge node 1
+ Standard_Integer myDetectedEdgeNode2; //!< index of last detected edge node 2
+ bool myToDetectElem; //!< flag to keep info about last detected element
+ bool myToDetectNode; //!< flag to keep info about last detected node
+ bool myToDetectEdge; //!< flag to keep info about last detected edge
public:
Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
+ myDetectedIdx = -1;
const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
-
thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
-
if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
aBVH->MaxPoint (0)))
{
Standard_Integer aMatchesNb = -1;
Standard_Real aMinDepth = RealLast();
-
for (;;)
{
const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];