1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0028801: Visualization, Select3D_SensitivePrimitiveArray - add option to keep index map of detected elements

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.
This commit is contained in:
kgv 2017-06-01 15:30:57 +03:00 committed by bugmaster
parent e9a7ec7a2b
commit a228288f61
8 changed files with 574 additions and 74 deletions

View File

@ -437,9 +437,11 @@ void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSel
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;

View File

@ -57,6 +57,9 @@ public:
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; }

View File

@ -32,6 +32,9 @@ public:
//! 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; }

View File

@ -28,6 +28,7 @@ Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_Enti
const Standard_Boolean theIsMustMatchAll)
: Select3D_SensitiveSet (theOwnerId),
myMustMatchAll (theIsMustMatchAll),
myToCheckOverlapAll (Standard_False),
myCenter (0.0, 0.0, 0.0) {}
//=======================================================================
@ -38,10 +39,10 @@ Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_Enti
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();
@ -187,29 +188,46 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
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;
}
}
}
aDepth = Min (aMatchResult.Depth(), aDepth);
else
{
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;
}

View File

@ -47,6 +47,25 @@ public:
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);
@ -74,6 +93,20 @@ public:
//! 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;
@ -86,9 +119,6 @@ public:
//! 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;
@ -130,6 +160,7 @@ private:
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

View File

@ -16,6 +16,7 @@
#include <Select3D_SensitivePrimitiveArray.hxx>
#include <NCollection_AlignedAllocator.hxx>
#include <OSD_Parallel.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
@ -71,6 +72,84 @@ namespace
}
//! 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 :
@ -99,6 +178,50 @@ Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle
//
}
// =======================================================================
// 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 :
@ -108,9 +231,11 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
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();
@ -121,6 +246,7 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
myBvhIndices.release();
myIs3d = false;
myInitLocation = theInitLoc;
myCDG3D.SetCoord (0.0, 0.0, 0.0);
if (theVerts.IsNull()
|| theVerts->NbElements == 0)
{
@ -171,11 +297,12 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
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;
}
@ -185,6 +312,30 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
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 };
@ -259,9 +410,11 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
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();
@ -320,12 +473,13 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
}
}
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;
}
@ -335,6 +489,30 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
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;
@ -427,12 +605,12 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected(
{
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;
@ -440,6 +618,55 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected(
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 :
@ -457,6 +684,11 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer
{
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)
{
@ -531,6 +763,13 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer
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());
@ -579,6 +818,15 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::BoundingBox()
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;
@ -639,6 +887,14 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::applyTransformation()
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();
@ -646,7 +902,77 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_Selecti
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;
}
// =======================================================================
@ -657,7 +983,19 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
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;
@ -693,6 +1031,17 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
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;
}
}
@ -705,7 +1054,8 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
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)
@ -728,11 +1078,16 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
{
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)
{
@ -745,6 +1100,11 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
myDetectedNode = aTriNodes[aNodeIter];
myMinDepthNode = aCurrentDepth;
}
if (!myDetectedNodeMap.IsNull()
&& theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
{
myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
}
aResult = Standard_True;
}
}
@ -797,7 +1157,13 @@ Standard_Real Select3D_SensitivePrimitiveArray::distanceToCOG (SelectBasics_Sele
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)
{
@ -822,6 +1188,18 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
{
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;
}
@ -830,7 +1208,8 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
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)
@ -852,6 +1231,20 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
{
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;
}

View File

@ -21,6 +21,7 @@
#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
@ -57,26 +58,30 @@ public:
//! @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.
@ -88,38 +93,44 @@ public:
//! @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.
@ -128,36 +139,61 @@ public:
{
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:
@ -174,7 +210,7 @@ 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
@ -213,6 +249,12 @@ public:
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.
@ -248,30 +290,40 @@ protected:
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:

View File

@ -74,10 +74,9 @@ void Select3D_SensitiveSet::BVH()
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)))
{
@ -90,7 +89,6 @@ Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeMan
Standard_Integer aMatchesNb = -1;
Standard_Real aMinDepth = RealLast();
for (;;)
{
const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];