IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
+const int Stride = sizeof(unsigned int) * 8; // number of bits in unsigned int
+
+const Select3D_BitField& Select3D_BitField::Map() const
+{
+ return *this;
+}
+
+Select3D_BitField& Select3D_BitField::ChangeMap() const
+{
+ return *const_cast<Select3D_BitField*>(this);
+}
+
+void Select3D_BitField::Clear()
+{
+ if (!myData.empty())
+ memset(&myData[0], 0, sizeof(unsigned int)*myData.size());
+}
+
+void Select3D_BitField::Reserve(const Standard_Integer theMax)
+{
+ myData.resize(theMax / Stride + 1, 0);
+}
+
+void Select3D_BitField::Add(const Standard_Integer theIndex)
+{
+ myData[theIndex / Stride] |= (1 << (theIndex % Stride));
+}
+
+void Select3D_BitField::Unite(const Select3D_BitField& theField)
+{
+ size_t aSize = myData.size();
+ if (theField.myData.size() > aSize)
+ aSize = theField.myData.size();
+ Reserve((int)aSize);
+
+ for (int i = 0; i < aSize; i++)
+ myData[i] |= theField.myData[i];
+}
+
+inline void bits_to_vector(unsigned int v, std::vector<unsigned int>& theVector, size_t& s, size_t& j)
+{
+ for (size_t k = 0; k < Stride && v != 0; k++)
+ {
+ if (v % 2 == 1)
+ {
+ theVector[j++] = (unsigned int)(s + k);
+ }
+ v = v >> 1;
+ }
+ s += Stride;
+}
+
+void Select3D_BitField::ToVector(std::vector<unsigned int>& theVector) const
+{
+ size_t n = myData.size();
+ theVector.resize(n*Stride);
+ size_t j = 0, s = 0;
+ for (size_t i = 0; i < n; i++)
+ {
+ bits_to_vector(myData[i], theVector, s, j);
+ }
+ theVector.resize(j);
+}
+
+
+
namespace
{
// function : Select3D_SensitivePrimitiveArray
// purpose :
// =======================================================================
-Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId)
+Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+ const Standard_Boolean theIsFastMap)
: Select3D_SensitiveSet (theOwnerId),
myPrimType (Graphic3d_TOPA_UNDEFINED),
myIndexLower (0),
myDetectedEdgeNode2 (-1),
myToDetectElem (true),
myToDetectNode (false),
- myToDetectEdge (false)
+ myToDetectEdge (false),
+ myIsFastMap(theIsFastMap)
{
//
}
if (!theToDetect)
{
myDetectedElemMap.Nullify();
+ myDetectedElemMapFast.Nullify();
return;
}
if (myDetectedElemMap.IsNull())
{
myDetectedElemMap = new TColStd_HPackedMapOfInteger();
+ myDetectedElemMapFast = new Select3D_BitField();
}
else
{
myDetectedElemMap->ChangeMap().Clear();
+ myDetectedElemMapFast->ChangeMap().Clear();
}
}
if (!theToDetect)
{
myDetectedNodeMap.Nullify();
+ myDetectedNodeMapFast.Nullify();
return;
}
if (myDetectedNodeMap.IsNull())
{
myDetectedNodeMap = new TColStd_HPackedMapOfInteger();
+ myDetectedNodeMapFast = new Select3D_BitField();
}
else
{
myDetectedNodeMap->ChangeMap().Clear();
+ myDetectedNodeMapFast->ChangeMap().Clear();
}
}
if (!myDetectedElemMap.IsNull())
{
myDetectedElemMap->ChangeMap().Clear();
+ myDetectedElemMapFast->ChangeMap().Clear();
+ int nbTriangles = myIndices->NbElements / 3;
+ myDetectedElemMapFast->Reserve(nbTriangles);
}
if (!myDetectedNodeMap.IsNull())
{
myDetectedNodeMap->ChangeMap().Clear();
+ myDetectedNodeMapFast->ChangeMap().Clear();
+ int nbPoints = myVerts->NbElements;
+ myDetectedNodeMapFast->Reserve(nbPoints);
}
myMinDepthElem = RealLast();
myMinDepthNode = RealLast();
hasResults = true;
if (!myDetectedElemMap.IsNull())
{
- myDetectedElemMap->ChangeMap().Unite (aChild->myDetectedElemMap->Map());
+ if (myIsFastMap)
+ myDetectedElemMapFast->ChangeMap().Unite(aChild->myDetectedElemMapFast->Map());
+ else
+ myDetectedElemMap->ChangeMap().Unite(aChild->myDetectedElemMap->Map());
}
if (!myDetectedNodeMap.IsNull())
{
- myDetectedNodeMap->ChangeMap().Unite (aChild->myDetectedNodeMap->Map());
+ if (myIsFastMap)
+ myDetectedNodeMapFast->ChangeMap().Unite(aChild->myDetectedNodeMapFast->Map());
+ else
+ myDetectedNodeMap->ChangeMap().Unite(aChild->myDetectedNodeMap->Map());
}
if (thePickResult.Depth() > aPickResult.Depth())
{
{
if (!myDetectedElemMap.IsNull())
{
- myDetectedElemMap->ChangeMap().Add (aPointIndex);
+ if (myIsFastMap)
+ myDetectedElemMapFast->ChangeMap().Add(aPointIndex);
+ else
+ myDetectedElemMap->ChangeMap().Add(aPointIndex);
}
if (!myDetectedNodeMap.IsNull())
{
- myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+ if (myIsFastMap)
+ myDetectedNodeMapFast->ChangeMap().Add(aPointIndex);
+ else
+ myDetectedNodeMap->ChangeMap().Add(aPointIndex);
}
}
aResult = Standard_True;
if (!myDetectedElemMap.IsNull()
&& theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
{
- myDetectedElemMap->ChangeMap().Add(aTriIndex);
+ if (myIsFastMap)
+ myDetectedElemMapFast->ChangeMap().Add(aTriIndex);
+ else
+ myDetectedElemMap->ChangeMap().Add(aTriIndex);
}
}
}
if (!myDetectedNodeMap.IsNull()
&& theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
{
- myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
+ if (myIsFastMap)
+ myDetectedNodeMapFast->ChangeMap().Add(aTriNodes[aNodeIter]);
+ else
+ myDetectedNodeMap->ChangeMap().Add(aTriNodes[aNodeIter]);
}
aResult = Standard_True;
}
{
if (!myDetectedElemMap.IsNull())
{
- myDetectedElemMap->ChangeMap().Add (aPointIndex);
+ if (myIsFastMap)
+ myDetectedElemMapFast->ChangeMap().Add(aPointIndex);
+ else
+ myDetectedElemMap->ChangeMap().Add(aPointIndex);
}
if (!myDetectedNodeMap.IsNull())
{
- myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+ if (myIsFastMap)
+ myDetectedNodeMapFast->ChangeMap().Add(aPointIndex);
+ else
+ myDetectedNodeMap->ChangeMap().Add(aPointIndex);
}
}
}
{
if (!myDetectedElemMap.IsNull())
{
- myDetectedElemMap->ChangeMap().Add (aTriIndex);
+ if (myIsFastMap)
+ myDetectedElemMapFast->ChangeMap().Add(aTriIndex);
+ else
+ myDetectedElemMap->ChangeMap().Add(aTriIndex);
}
if (!myDetectedNodeMap.IsNull())
{
- myDetectedNodeMap->ChangeMap().Add (aTriNodes[0]);
- myDetectedNodeMap->ChangeMap().Add (aTriNodes[1]);
- myDetectedNodeMap->ChangeMap().Add (aTriNodes[2]);
+ if (myIsFastMap)
+ {
+ myDetectedNodeMapFast->ChangeMap().Add(aTriNodes[0]);
+ myDetectedNodeMapFast->ChangeMap().Add(aTriNodes[1]);
+ myDetectedNodeMapFast->ChangeMap().Add(aTriNodes[2]);
+ }
+ else
+ {
+ myDetectedNodeMap->ChangeMap().Add(aTriNodes[0]);
+ myDetectedNodeMap->ChangeMap().Add(aTriNodes[1]);
+ myDetectedNodeMap->ChangeMap().Add(aTriNodes[2]);
+ }
}
}
}
#include <Select3D_BVHIndexBuffer.hxx>
#include <TColStd_HPackedMapOfInteger.hxx>
+class Select3D_BitField : public Standard_Transient
+{
+public:
+ Standard_EXPORT const Select3D_BitField& Map() const;
+ Standard_EXPORT Select3D_BitField& ChangeMap() const;
+
+ Standard_EXPORT void Clear();
+ Standard_EXPORT void Add(const Standard_Integer);
+ Standard_EXPORT void Reserve(const Standard_Integer);
+ Standard_EXPORT void Unite(const Select3D_BitField&);
+ Standard_EXPORT void ToVector(std::vector<unsigned int>&) const;
+
+private:
+ std::vector<unsigned int> myData;
+};
+
+
//! Sensitive for triangulation or point set defined by Primitive Array.
//! The primitives can be optionally combined into patches within BVH tree
//! to reduce its building time in expense of extra traverse time.
public:
//! Constructs an empty sensitive object.
- Standard_EXPORT Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId);
+ Standard_EXPORT Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+ const Standard_Boolean theIsFastMap = Standard_False);
//! Return patch size limit (1 by default).
Standard_Integer PatchSizeMax() const { return myPatchSizeMax; }
+ Standard_Boolean IsFastMap() const { return myIsFastMap; }
+
//! Assign patch size limit.
//! Should be set before initialization.
void SetPatchSizeMax (const Standard_Integer thePatchSizeMax) { myPatchSizeMax = thePatchSizeMax; }
//! Return the index map of last detected elements (rectangle selection).
const Handle(TColStd_HPackedMapOfInteger)& LastDetectedElementMap() const { return myDetectedElemMap; }
+ const Handle(Select3D_BitField)& LastDetectedElementMapFast() const { return myDetectedElemMapFast; }
//! Return last topmost detected node or -1 if undefined (axis picking).
Standard_Integer LastDetectedNode() const { return myDetectedNode; }
//! Return the index map of last detected nodes (rectangle selection).
const Handle(TColStd_HPackedMapOfInteger)& LastDetectedNodeMap() const { return myDetectedNodeMap; }
+ const Handle(Select3D_BitField)& LastDetectedNodeMapFast() const { return myDetectedNodeMapFast; }
//! Return the first node of last topmost detected edge or -1 if undefined (axis picking).
Standard_Integer LastDetectedEdgeNode1() const { return myDetectedEdgeNode1; }
gp_GTrsf myInvInitLocation;
Handle(TColStd_HPackedMapOfInteger) myDetectedElemMap; //!< index map of last detected elements
Handle(TColStd_HPackedMapOfInteger) myDetectedNodeMap; //!< index map of last detected nodes
+ Handle(Select3D_BitField) myDetectedElemMapFast; //!< index map of last detected elements
+ Handle(Select3D_BitField) myDetectedNodeMapFast; //!< 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
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
+ Standard_Boolean myIsFastMap; //!< flag to use optimized (bit field) map
public: