mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-08-08 23:07:28 +08:00
Integration of OCCT 6.5.0 from SVN
This commit is contained in:
Executable
+502
@@ -0,0 +1,502 @@
|
||||
// File: NCollection_UBTree.hxx
|
||||
// Created: 30.07.02 09:51:33
|
||||
// Author: Michael SAZONOV
|
||||
// Copyright: Open CASCADE 2002
|
||||
|
||||
#ifndef NCollection_UBTree_HeaderFile
|
||||
#define NCollection_UBTree_HeaderFile
|
||||
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
|
||||
#ifdef WNT
|
||||
// Disable the warning: "operator new unmatched by delete"
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4291)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The algorithm of unbalanced binary tree of overlapped bounding boxes.
|
||||
*
|
||||
* Once the tree of boxes of geometric objects is constructed, the algorithm
|
||||
* is capable of fast geometric selection of objects. The tree can be easily
|
||||
* updated by adding to it a new object with bounding box.
|
||||
*
|
||||
* The time of adding to the tree of one object is O(log(N)), where N is the
|
||||
* total number of objects, so the time of building a tree of N objects is
|
||||
* O(N(log(N)). The search time of one object is O(log(N)).
|
||||
*
|
||||
* Defining various classes inheriting NCollection_UBTree::Selector we can
|
||||
* perform various kinds of selection over the same b-tree object
|
||||
*
|
||||
* The object may be of any type allowing copying. Among the best suitable
|
||||
* solutions there can be a pointer to an object, handled object or integer
|
||||
* index of object inside some collection. The bounding object may have any
|
||||
* dimension and geometry. The minimal interface of TheBndType (besides
|
||||
* public empty and copy constructor and operator =) used in UBTree algorithm
|
||||
* is as the following:
|
||||
* @code
|
||||
* class MyBndType
|
||||
* {
|
||||
* public:
|
||||
* inline void Add (const MyBndType& other);
|
||||
* // Updates me with other bounding
|
||||
*
|
||||
* inline Standard_Boolean IsOut (const MyBndType& other) const;
|
||||
* // Classifies other bounding relatively me
|
||||
*
|
||||
* inline Standard_Real SquareExtent() const;
|
||||
* // Computes the squared maximal linear extent of me.
|
||||
* // (For box it is the squared diagonal of box)
|
||||
* };
|
||||
* @endcode
|
||||
* To select objects you need to define a class derived from UBTree::Selector
|
||||
* that should redefine the necessary virtual methods to maintain the
|
||||
* selection condition. The object of this class is also used to retrieve
|
||||
* selected objects after search.
|
||||
*/
|
||||
|
||||
template <class TheObjType, class TheBndType> class NCollection_UBTree
|
||||
{
|
||||
public:
|
||||
// ---------- PUBLIC TYPES ----------
|
||||
|
||||
/**
|
||||
* Class defining the minimal interface of selector.
|
||||
*/
|
||||
class Selector
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Selector () : myStop(Standard_False) {}
|
||||
|
||||
/**
|
||||
* Rejection base on the bounding type.
|
||||
* @return
|
||||
* True if the bounding box does not conform to some selection conditions
|
||||
*/
|
||||
virtual Standard_Boolean Reject (const TheBndType&) const = 0;
|
||||
|
||||
/**
|
||||
* Confirm the object while making necessary tests on it. This method is
|
||||
* called when the bounding box of the object conforms to the conditions
|
||||
* (see Reject()). It is also supposed to keep record of accepted objects.
|
||||
* @return
|
||||
* True if the object is accepted
|
||||
*/
|
||||
virtual Standard_Boolean Accept (const TheObjType&) = 0;
|
||||
|
||||
/**
|
||||
* This condition is checked after each call to Accept().
|
||||
* @return
|
||||
* True signals that the selection process is stopped
|
||||
*/
|
||||
Standard_Boolean Stop () const { return myStop; }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Selector () {}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The method Accept() should set this flag if the selection process
|
||||
* is to be stopped
|
||||
*/
|
||||
Standard_Boolean myStop;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class describing the node of the tree.
|
||||
* Initially the tree consists of one leaf. A node can grow to a branch
|
||||
* holding two childs:
|
||||
* - one correspondent to initial node
|
||||
* - the new one with a new object and bounding box
|
||||
*/
|
||||
class TreeNode
|
||||
{
|
||||
public:
|
||||
TreeNode (const TheObjType& theObj, const TheBndType& theBnd)
|
||||
: myBnd(theBnd), myObject(theObj), myChildren(0), myParent(0) {}
|
||||
|
||||
Standard_Boolean IsLeaf () const { return !myChildren; }
|
||||
Standard_Boolean IsRoot () const { return !myParent; }
|
||||
const TheBndType& Bnd () const { return myBnd; }
|
||||
TheBndType& ChangeBnd () { return myBnd; }
|
||||
const TheObjType& Object () const { return myObject; }
|
||||
const TreeNode& Child (const Standard_Integer i) const
|
||||
{ return myChildren[i]; }
|
||||
TreeNode& ChangeChild (const Standard_Integer i)
|
||||
{ return myChildren[i]; }
|
||||
const TreeNode& Parent () const { return *myParent; }
|
||||
TreeNode& ChangeParent () { return *myParent; }
|
||||
|
||||
/**
|
||||
* Forces *this node being gemmated such a way that it becomes
|
||||
* a branch holding the previous content of *this node at the
|
||||
* first child and theObj at the second child.
|
||||
* @param TheNewBnd
|
||||
* new bounding box comprizing both child nodes.
|
||||
* @param theObj
|
||||
* added object.
|
||||
* @param theBnd
|
||||
* bounding box of theObj.
|
||||
* @theAlloc
|
||||
* allocator providing memory to the new child nodes, provided by the
|
||||
* calling Tree instance.
|
||||
*/
|
||||
void Gemmate (const TheBndType& theNewBnd,
|
||||
const TheObjType& theObj,
|
||||
const TheBndType& theBnd,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc)
|
||||
{
|
||||
//TreeNode *children = new TreeNode [2];
|
||||
TreeNode *children = (TreeNode *) theAlloc->Allocate (2*sizeof(TreeNode));
|
||||
new (&children[0]) TreeNode;
|
||||
new (&children[1]) TreeNode;
|
||||
children[0] = *this;
|
||||
children[1].myObject = theObj;
|
||||
children[1].myBnd = theBnd;
|
||||
children[0].myParent = children[1].myParent = this;
|
||||
if (!IsLeaf()) {
|
||||
myChildren[0].myParent = children;
|
||||
myChildren[1].myParent = children;
|
||||
}
|
||||
myChildren = children;
|
||||
myBnd = theNewBnd;
|
||||
myObject = TheObjType(); // nullify myObject
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills the i-th child, and *this accepts the content of another child
|
||||
*/
|
||||
void Kill (const Standard_Integer i,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc)
|
||||
{
|
||||
if (!IsLeaf()) {
|
||||
TreeNode *oldChildren = myChildren;
|
||||
const Standard_Integer iopp = 1 - i;
|
||||
myBnd = oldChildren[iopp].myBnd;
|
||||
myObject = oldChildren[iopp].myObject;
|
||||
myChildren = oldChildren[iopp].myChildren;
|
||||
if (!IsLeaf()) {
|
||||
myChildren[0].myParent = this;
|
||||
myChildren[1].myParent = this;
|
||||
}
|
||||
// oldChildren[0].myChildren = oldChildren[1].myChildren = 0L;
|
||||
// delete [] oldChildren;
|
||||
oldChildren[iopp].~TreeNode();
|
||||
delNode(&oldChildren[i], theAlloc); // remove the whole branch
|
||||
theAlloc->Free(oldChildren);
|
||||
}
|
||||
}
|
||||
|
||||
// ~TreeNode () { if (myChildren) delete [] myChildren; }
|
||||
~TreeNode () { myChildren = 0L; }
|
||||
|
||||
/**
|
||||
* Allocator of a tree node.
|
||||
*/
|
||||
void * operator new (size_t theSize,
|
||||
const Handle(NCollection_BaseAllocator)& theAllocator)
|
||||
{ return theAllocator->Allocate(theSize); }
|
||||
|
||||
/**
|
||||
* Allocator of a tree node.
|
||||
*/
|
||||
void * operator new (size_t,
|
||||
void * theMem)
|
||||
{ return theMem; }
|
||||
|
||||
/**
|
||||
* Deleter of tree node. The whole hierarchy of its children also deleted.
|
||||
* This method should be used instead of operator delete.
|
||||
*/
|
||||
static void delNode (TreeNode * theNode,
|
||||
Handle(NCollection_BaseAllocator)& theAlloc)
|
||||
{
|
||||
if (theNode) {
|
||||
if (theNode -> myChildren) {
|
||||
delNode (&theNode -> myChildren[0], theAlloc);
|
||||
delNode (&theNode -> myChildren[1], theAlloc);
|
||||
theAlloc->Free(theNode -> myChildren);
|
||||
}
|
||||
theNode->~TreeNode();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TreeNode () : myChildren(0L), myParent(0L) {}
|
||||
|
||||
TheBndType myBnd; ///< bounding geometry
|
||||
TheObjType myObject; ///< the object
|
||||
TreeNode *myChildren; ///< 2 children forming a b-tree
|
||||
TreeNode *myParent; ///< the pointer to a parent node
|
||||
};
|
||||
|
||||
// ---------- PUBLIC METHODS ----------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
NCollection_UBTree
|
||||
(const Handle(NCollection_BaseAllocator)& theAllocator=0L)
|
||||
: myRoot(0L), myLastNode(0L)
|
||||
{
|
||||
if (theAllocator.IsNull())
|
||||
myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
|
||||
else
|
||||
myAlloc = theAllocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the tree with a new object and its bounding box.
|
||||
* @param theObj
|
||||
* added object
|
||||
* @param theBnd
|
||||
* bounding box of the object.
|
||||
* @return
|
||||
* always True
|
||||
*/
|
||||
Standard_EXPORT virtual Standard_Boolean Add (const TheObjType& theObj,
|
||||
const TheBndType& theBnd);
|
||||
|
||||
/**
|
||||
* Searches in the tree all objects conforming to the given selector.
|
||||
* return
|
||||
* Number of objects accepted
|
||||
*/
|
||||
Standard_Integer Select (Selector& theSelector) const
|
||||
{ return (IsEmpty() ? 0 : Select (Root(), theSelector)); }
|
||||
|
||||
/**
|
||||
* Clears the contents of the tree.
|
||||
* @param aNewAlloc
|
||||
* Optional: a new allocator that will be used when the tree is rebuilt
|
||||
* anew. This makes sense if the memory allocator needs re-initialisation
|
||||
* (like NCollection_IncAllocator). By default the previous allocator is
|
||||
* kept.
|
||||
*/
|
||||
virtual void Clear (const Handle(NCollection_BaseAllocator)& aNewAlloc = 0L)
|
||||
// { if (myRoot) delete myRoot; myRoot = 0L; }
|
||||
{
|
||||
if (myRoot) {
|
||||
TreeNode::delNode (myRoot, this->myAlloc);
|
||||
this->myAlloc->Free (myRoot);
|
||||
myRoot = 0L;
|
||||
}
|
||||
if (aNewAlloc.IsNull() == Standard_False)
|
||||
myAlloc = aNewAlloc;
|
||||
}
|
||||
|
||||
Standard_Boolean IsEmpty () const { return !myRoot; }
|
||||
|
||||
/**
|
||||
* @return
|
||||
* the root node of the tree
|
||||
*/
|
||||
const TreeNode& Root () const { return *myRoot; }
|
||||
|
||||
/**
|
||||
* Desctructor.
|
||||
*/
|
||||
virtual ~NCollection_UBTree () { Clear(); }
|
||||
|
||||
/**
|
||||
* Recommended to be used only in sub-classes.
|
||||
* @return
|
||||
* Allocator object used in this instance of UBTree.
|
||||
*/
|
||||
const Handle(NCollection_BaseAllocator)& Allocator () const
|
||||
{ return myAlloc; }
|
||||
|
||||
protected:
|
||||
// ---------- PROTECTED METHODS ----------
|
||||
|
||||
/**
|
||||
* @return
|
||||
* the last added node
|
||||
*/
|
||||
TreeNode& ChangeLastNode () { return *myLastNode; }
|
||||
|
||||
/**
|
||||
* Searches in the branch all objects conforming to the given selector.
|
||||
* @return
|
||||
* the number of objects accepted
|
||||
*/
|
||||
Standard_EXPORT Standard_Integer Select (const TreeNode& theBranch,
|
||||
Selector& theSelector) const;
|
||||
|
||||
private:
|
||||
// ---------- PRIVATE METHODS ----------
|
||||
|
||||
/// Copy constructor (prohibited).
|
||||
NCollection_UBTree (const NCollection_UBTree&);
|
||||
|
||||
/// Assignment operator (prohibited).
|
||||
NCollection_UBTree& operator = (const NCollection_UBTree&);
|
||||
|
||||
// ---------- PRIVATE FIELDS ----------
|
||||
|
||||
TreeNode *myRoot; ///< root of the tree
|
||||
TreeNode *myLastNode;///< the last added node
|
||||
Handle(NCollection_BaseAllocator) myAlloc; ///< Allocator for TreeNode
|
||||
};
|
||||
|
||||
// ================== METHODS TEMPLATES =====================
|
||||
//=======================================================================
|
||||
//function : Add
|
||||
//purpose : Updates the tree with a new object and its bounding box
|
||||
//=======================================================================
|
||||
|
||||
template <class TheObjType, class TheBndType>
|
||||
Standard_Boolean NCollection_UBTree<TheObjType,TheBndType>::Add
|
||||
(const TheObjType& theObj,
|
||||
const TheBndType& theBnd)
|
||||
{
|
||||
if (IsEmpty()) {
|
||||
// Accepting first object
|
||||
myRoot = new (this->myAlloc) TreeNode (theObj, theBnd);
|
||||
myLastNode = myRoot;
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
TreeNode *pBranch = myRoot;
|
||||
Standard_Boolean isOutOfBranch = pBranch->Bnd().IsOut (theBnd);
|
||||
|
||||
for(;;) {
|
||||
// condition of stopping the search
|
||||
if (isOutOfBranch || pBranch->IsLeaf()) {
|
||||
TheBndType aNewBnd = theBnd;
|
||||
aNewBnd.Add (pBranch->Bnd());
|
||||
// put the new leaf aside on the level of pBranch
|
||||
pBranch->Gemmate (aNewBnd, theObj, theBnd, this->myAlloc);
|
||||
myLastNode = &pBranch->ChangeChild(1);
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the bounding box of the branch
|
||||
pBranch->ChangeBnd().Add (theBnd);
|
||||
|
||||
// Select the best child branch to accept the object:
|
||||
// 1. First check if one branch is out and another one is not.
|
||||
// 2. Else select the child having the least union with theBnd
|
||||
Standard_Integer iBest = 0;
|
||||
Standard_Boolean isOut[] = { pBranch->Child(0).Bnd().IsOut (theBnd),
|
||||
pBranch->Child(1).Bnd().IsOut (theBnd) };
|
||||
if (isOut[0] != isOut[1])
|
||||
iBest = (isOut[0] ? 1 : 0);
|
||||
else {
|
||||
TheBndType aUnion[] = { theBnd, theBnd };
|
||||
aUnion[0].Add (pBranch->Child(0).Bnd());
|
||||
aUnion[1].Add (pBranch->Child(1).Bnd());
|
||||
const Standard_Real d1 = aUnion[0].SquareExtent();
|
||||
const Standard_Real d2 = aUnion[1].SquareExtent();
|
||||
if (d1 > d2)
|
||||
iBest = 1;
|
||||
}
|
||||
|
||||
// Continue with the selected branch
|
||||
isOutOfBranch = isOut[iBest];
|
||||
pBranch = &pBranch->ChangeChild(iBest);
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Select
|
||||
//purpose : Recursively searches in the branch all objects conforming
|
||||
// to the given selector.
|
||||
// Returns the number of objects found.
|
||||
//=======================================================================
|
||||
|
||||
template <class TheObjType, class TheBndType>
|
||||
Standard_Integer NCollection_UBTree<TheObjType,TheBndType>::Select
|
||||
(const TreeNode& theBranch,
|
||||
Selector& theSelector) const
|
||||
{
|
||||
// Try to reject the branch by bounding box
|
||||
if (theSelector.Reject (theBranch.Bnd()))
|
||||
return 0;
|
||||
|
||||
Standard_Integer nSel = 0;
|
||||
|
||||
if (theBranch.IsLeaf()) {
|
||||
// It is a leaf => try to accept the object
|
||||
if (theSelector.Accept (theBranch.Object()))
|
||||
nSel++;
|
||||
}
|
||||
else {
|
||||
// It is a branch => select from its children
|
||||
nSel += Select (theBranch.Child(0), theSelector);
|
||||
if (!theSelector.Stop())
|
||||
nSel += Select (theBranch.Child(1), theSelector);
|
||||
}
|
||||
|
||||
return nSel;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
/**
|
||||
* Declaration of handled version of NCollection_UBTree.
|
||||
* In the macros below the arguments are:
|
||||
* _HUBTREE - the desired name of handled class
|
||||
* _OBJTYPE - the name of the object type
|
||||
* _BNDTYPE - the name of the bounding box type
|
||||
* _HPARENT - the name of parent class (usually MMgt_TShared)
|
||||
*/
|
||||
#define DEFINE_HUBTREE(_HUBTREE, _OBJTYPE, _BNDTYPE, _HPARENT) \
|
||||
class _HUBTREE : public _HPARENT \
|
||||
{ \
|
||||
public: \
|
||||
typedef NCollection_UBTree <_OBJTYPE, _BNDTYPE> UBTree; \
|
||||
\
|
||||
_HUBTREE () : myTree(new UBTree) {} \
|
||||
/* Empty constructor */ \
|
||||
\
|
||||
/* Access to the methods of UBTree */ \
|
||||
\
|
||||
Standard_Boolean Add (const _OBJTYPE& theObj, \
|
||||
const _BNDTYPE& theBnd) \
|
||||
{ return ChangeTree().Add (theObj, theBnd); } \
|
||||
\
|
||||
Standard_Integer Select (UBTree::Selector& theSelector) const \
|
||||
{ return Tree().Select (theSelector); } \
|
||||
\
|
||||
void Clear () { ChangeTree().Clear (); } \
|
||||
\
|
||||
Standard_Boolean IsEmpty () const { return Tree().IsEmpty(); } \
|
||||
\
|
||||
const UBTree::TreeNode& Root () const { return Tree().Root(); } \
|
||||
\
|
||||
\
|
||||
/* Access to the tree algorithm */ \
|
||||
\
|
||||
const UBTree& Tree () const { return *myTree; } \
|
||||
UBTree& ChangeTree () { return *myTree; } \
|
||||
\
|
||||
~_HUBTREE () { delete myTree; } \
|
||||
/* Destructor */ \
|
||||
\
|
||||
DEFINE_STANDARD_RTTI (_HUBTREE) \
|
||||
/* Type management */ \
|
||||
\
|
||||
protected: \
|
||||
_HUBTREE (UBTree *theTree) : myTree(theTree) {} \
|
||||
/* Constructor from an existing tree. */ \
|
||||
\
|
||||
private: \
|
||||
UBTree *myTree; /* pointer to the tree algorithm */ \
|
||||
}; \
|
||||
DEFINE_STANDARD_HANDLE (_HUBTREE, _HPARENT)
|
||||
|
||||
#define IMPLEMENT_HUBTREE(_HUBTREE, _HPARENT) \
|
||||
IMPLEMENT_STANDARD_HANDLE (_HUBTREE, _HPARENT) \
|
||||
IMPLEMENT_STANDARD_RTTIEXT(_HUBTREE, _HPARENT)
|
||||
|
||||
#ifdef WNT
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user