/usr/include/oce/NCollection_UBTree.hxx is in liboce-foundation-dev 0.17.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | // Created on: 2002-07-30
// Created by: Michael SAZONOV
// Copyright (c) 2002-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef NCollection_UBTree_HeaderFile
#define NCollection_UBTree_HeaderFile
#include <NCollection_BaseAllocator.hxx>
#include <NCollection_DefineAlloc.hxx>
/**
* 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:
//! Memory allocation
DEFINE_STANDARD_ALLOC
DEFINE_NCOLLECTION_ALLOC
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:
DEFINE_STANDARD_ALLOC
DEFINE_NCOLLECTION_ALLOC
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; }
/**
* 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
*/
virtual 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 */ \
_HUBTREE (const Handle(NCollection_BaseAllocator)& theAlloc) \
: myTree(new UBTree(theAlloc)) {} \
/* 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 */ \
\
private: \
/* Copying and assignment are prohibited */ \
_HUBTREE (UBTree*); \
_HUBTREE (const _HUBTREE&); \
void operator = (const _HUBTREE&); \
\
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)
#endif
|