Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:20

0001 // Created on: 2002-07-30
0002 // Created by: Michael SAZONOV
0003 // Copyright (c) 2002-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef NCollection_UBTree_HeaderFile
0017 #define NCollection_UBTree_HeaderFile
0018 
0019 #include <NCollection_BaseAllocator.hxx>
0020 #include <NCollection_DefineAlloc.hxx>
0021 
0022 /**
0023  * The algorithm of unbalanced binary tree of overlapped bounding boxes.
0024  *
0025  * Once the tree of boxes  of geometric objects is constructed, the algorithm
0026  * is capable of fast geometric selection of objects.  The tree can be easily
0027  * updated by adding to it a new object with bounding box.
0028  * 
0029  * The time of adding to the tree  of one object is O(log(N)), where N is the
0030  * total number of  objects, so the time  of building a tree of  N objects is
0031  * O(N(log(N)). The search time of one object is O(log(N)).
0032  * 
0033  * Defining  various classes  inheriting NCollection_UBTree::Selector  we can
0034  * perform various kinds of selection over the same b-tree object
0035  * 
0036  * The object  may be of any  type allowing copying. Among  the best suitable
0037  * solutions there can  be a pointer to an object,  handled object or integer
0038  * index of object inside some  collection.  The bounding object may have any
0039  * dimension  and  geometry. The  minimal  interface  of TheBndType  (besides
0040  * public empty and copy constructor and operator =) used in UBTree algorithm
0041  * is as the following:
0042  * @code
0043  *   class MyBndType
0044  *   {
0045  *    public:
0046  *     inline void                   Add (const MyBndType& other);
0047  *     // Updates me with other bounding
0048  * 
0049  *     inline Standard_Boolean       IsOut (const MyBndType& other) const;
0050  *     // Classifies other bounding relatively me
0051  * 
0052  *     inline Standard_Real          SquareExtent() const;
0053  *     // Computes the squared maximal linear extent of me.
0054  *     // (For box it is the squared diagonal of box)
0055  *   };
0056  * @endcode
0057  * To select objects you need to define a class derived from UBTree::Selector
0058  * that  should  redefine  the  necessary  virtual methods  to  maintain  the
0059  * selection condition.  The object  of this class  is also used  to retrieve
0060  * selected objects after search.
0061  */
0062 
0063 template <class TheObjType, class TheBndType> class NCollection_UBTree
0064 {
0065 public:
0066   //! Memory allocation
0067   DEFINE_STANDARD_ALLOC
0068   DEFINE_NCOLLECTION_ALLOC
0069 
0070 public:
0071   // ---------- PUBLIC TYPES ----------
0072 
0073   /**
0074    * Class defining the minimal interface of selector.
0075    */
0076   class Selector
0077   {
0078   public:
0079     /**
0080      * Constructor
0081      */
0082     Selector () : myStop(Standard_False) {}
0083 
0084     /**
0085      * Rejection base on the bounding type.
0086      * @return
0087      *   True if the bounding box does not conform to some selection conditions
0088      */
0089     virtual Standard_Boolean Reject (const TheBndType&) const = 0;
0090 
0091     /**
0092      * Confirm the object while making necessary tests on it. This method is
0093      * called when the bounding box of the object conforms to the conditions
0094      * (see Reject()). It is also supposed to keep record of accepted objects.
0095      * @return
0096      *   True if the object is accepted
0097      */
0098     virtual Standard_Boolean Accept (const TheObjType&) = 0;
0099 
0100     /**
0101      * This condition is checked after each call to Accept().
0102      * @return
0103      *   True signals that the selection process is stopped
0104      */
0105     Standard_Boolean Stop () const { return myStop; }
0106 
0107     /**
0108      * Destructor
0109      */
0110     virtual ~Selector () {}
0111 
0112   protected:
0113     /**
0114      * The method Accept() should set this flag if the selection process
0115      * is to be stopped
0116      */
0117     Standard_Boolean myStop;
0118   };
0119 
0120   /**
0121    * Class describing the node of the tree.
0122    * Initially the tree consists of one leaf. A node can grow to a branch
0123    * holding two childs:
0124    * - one correspondent to initial node
0125    * - the new one with a new object and bounding box
0126    */
0127   class TreeNode
0128   {
0129   public:
0130     DEFINE_STANDARD_ALLOC
0131     DEFINE_NCOLLECTION_ALLOC
0132 
0133   public:
0134     TreeNode (const TheObjType& theObj, const TheBndType& theBnd)
0135       : myBnd(theBnd), myObject(theObj), myChildren(0), myParent(0) {}
0136 
0137     Standard_Boolean       IsLeaf       () const { return !myChildren; }
0138     Standard_Boolean       IsRoot       () const { return !myParent; }
0139     const TheBndType&      Bnd          () const { return myBnd; }
0140     TheBndType&            ChangeBnd    ()       { return myBnd; }
0141     const TheObjType&      Object       () const { return myObject; }
0142     const TreeNode&        Child        (const Standard_Integer i) const
0143                                                  { return myChildren[i]; }
0144     TreeNode&              ChangeChild  (const Standard_Integer i)
0145                                                  { return myChildren[i]; }
0146     const TreeNode&        Parent       () const { return *myParent; }
0147     TreeNode&              ChangeParent ()       { return *myParent; }
0148 
0149     /**
0150      * Forces *this node being gemmated such a way that it becomes
0151      * a branch holding the previous content of *this node at the 
0152      * first child and theObj at the second child.
0153      * @param theNewBnd
0154      *   new bounding box comprizing both child nodes.
0155      * @param theObj
0156      *   added object.
0157      * @param theBnd
0158      *   bounding box of theObj.
0159      * @theAlloc
0160      *   allocator providing memory to the new child nodes, provided by the
0161      *   calling Tree instance.
0162      */
0163     void Gemmate            (const TheBndType& theNewBnd,
0164                              const TheObjType& theObj,
0165                              const TheBndType& theBnd,
0166                              const Handle(NCollection_BaseAllocator)& theAlloc)
0167     {
0168       //TreeNode *children = new TreeNode [2];
0169       TreeNode *children = (TreeNode *) theAlloc->Allocate (2*sizeof(TreeNode));
0170       new (&children[0]) TreeNode;
0171       new (&children[1]) TreeNode;
0172       children[0] = *this;
0173       children[1].myObject = theObj;
0174       children[1].myBnd = theBnd;
0175       children[0].myParent = children[1].myParent = this;
0176       if (!IsLeaf()) {
0177         myChildren[0].myParent = children;
0178         myChildren[1].myParent = children;
0179       }
0180       myChildren = children;
0181       myBnd = theNewBnd;
0182       myObject = TheObjType();      // nullify myObject
0183     }
0184 
0185     /**
0186      * Kills the i-th child, and *this accepts the content of another child
0187      */
0188     void Kill               (const Standard_Integer i,
0189                              const Handle(NCollection_BaseAllocator)& theAlloc)
0190     {
0191       if (!IsLeaf()) {
0192         TreeNode *oldChildren = myChildren;
0193         const Standard_Integer iopp = 1 - i;
0194         myBnd      = oldChildren[iopp].myBnd;
0195         myObject   = oldChildren[iopp].myObject;
0196         myChildren = oldChildren[iopp].myChildren;
0197         if (!IsLeaf()) {
0198           myChildren[0].myParent = this;
0199           myChildren[1].myParent = this;
0200         }
0201         // oldChildren[0].myChildren = oldChildren[1].myChildren = 0L;
0202         // delete [] oldChildren;
0203         oldChildren[iopp].~TreeNode();
0204         delNode(&oldChildren[i], theAlloc); // remove the whole branch
0205         theAlloc->Free(oldChildren);
0206       }
0207     }
0208 
0209 //  ~TreeNode () { if (myChildren) delete [] myChildren; }
0210     ~TreeNode () { myChildren = 0L; }
0211 
0212     /**
0213      * Deleter of tree node. The whole hierarchy of its children also deleted.
0214      * This method should be used instead of operator delete.
0215      */ 
0216     static void delNode (TreeNode * theNode,
0217                          const Handle(NCollection_BaseAllocator)& theAlloc)
0218     {
0219       if (theNode) {
0220         if (theNode -> myChildren) {
0221           delNode (&theNode -> myChildren[0], theAlloc);
0222           delNode (&theNode -> myChildren[1], theAlloc);
0223           theAlloc->Free(theNode -> myChildren);
0224         }
0225         theNode->~TreeNode();
0226       }
0227     }
0228 
0229   private:
0230     TreeNode () : myChildren(0L), myParent(0L) {}
0231 
0232     TheBndType  myBnd;          ///< bounding geometry
0233     TheObjType  myObject;       ///< the object
0234     TreeNode   *myChildren;     ///< 2 children forming a b-tree
0235     TreeNode   *myParent;       ///< the pointer to a parent node
0236   };
0237 
0238   // ---------- PUBLIC METHODS ----------
0239 
0240   /**
0241    * Empty constructor.
0242    */
0243   NCollection_UBTree() : myRoot(0L), myLastNode(0L), myAlloc (NCollection_BaseAllocator::CommonBaseAllocator()) {}
0244 
0245   /**
0246    * Constructor.
0247    */
0248   explicit NCollection_UBTree (const Handle(NCollection_BaseAllocator)& theAllocator)
0249   : myRoot(0L), myLastNode(0L), myAlloc (!theAllocator.IsNull() ? theAllocator : NCollection_BaseAllocator::CommonBaseAllocator()) {}
0250 
0251   /**
0252    * Update the tree with a new object and its bounding box.
0253    * @param theObj
0254    *   added object
0255    * @param theBnd
0256    *   bounding box of the object.
0257    * @return
0258    *   always True
0259    */
0260   virtual Standard_Boolean Add (const TheObjType& theObj, const TheBndType& theBnd);
0261 
0262   /**
0263    * Searches in the tree all objects conforming to the given selector.
0264    * return
0265    *   Number of objects accepted
0266    */
0267   virtual Standard_Integer Select (Selector& theSelector) const
0268         { return (IsEmpty() ? 0 : Select (Root(), theSelector)); }
0269 
0270   /**
0271    * Clears the contents of the tree.
0272    * @param aNewAlloc
0273    *   Optional:   a new allocator that will be used when the tree is rebuilt
0274    *   anew. This makes sense if the memory allocator needs re-initialisation
0275    *   (like NCollection_IncAllocator).  By default the previous allocator is
0276    *   kept.
0277    */
0278   virtual void Clear (const Handle(NCollection_BaseAllocator)& aNewAlloc = 0L)
0279 //      { if (myRoot) delete myRoot; myRoot = 0L; }
0280   {
0281     if (myRoot) {
0282       TreeNode::delNode (myRoot, this->myAlloc);
0283       this->myAlloc->Free (myRoot);
0284       myRoot = 0L;
0285     }
0286     if (aNewAlloc.IsNull() == Standard_False)
0287       myAlloc = aNewAlloc;
0288   }
0289 
0290   Standard_Boolean IsEmpty () const { return !myRoot; }
0291 
0292   /**
0293    * @return
0294    *   the root node of the tree
0295    */
0296   const TreeNode& Root () const { return *myRoot; }
0297 
0298   /**
0299    * Destructor.
0300    */
0301   virtual ~NCollection_UBTree () { Clear(); }
0302 
0303   /**
0304    * Recommended to be used only in sub-classes.
0305    * @return
0306    *   Allocator object used in this instance of UBTree.
0307    */
0308   const Handle(NCollection_BaseAllocator)& Allocator () const
0309   { return myAlloc; }
0310 
0311  protected:
0312   // ---------- PROTECTED METHODS ----------
0313 
0314   /**
0315    * @return
0316    *   the last added node
0317    */
0318   TreeNode& ChangeLastNode () { return *myLastNode; }
0319 
0320   /**
0321    * Searches in the branch all objects conforming to the given selector.
0322    * @return
0323    *   the number of objects accepted
0324    */
0325   Standard_Integer Select (const TreeNode& theBranch, Selector& theSelector) const;
0326 
0327  private:
0328   // ---------- PRIVATE METHODS ----------
0329 
0330   /// Copy constructor (prohibited).
0331   NCollection_UBTree (const NCollection_UBTree&);
0332 
0333   /// Assignment operator (prohibited).
0334   NCollection_UBTree& operator = (const NCollection_UBTree&);
0335 
0336   // ---------- PRIVATE FIELDS ----------
0337 
0338   TreeNode                            *myRoot;    ///< root of the tree
0339   TreeNode                            *myLastNode;///< the last added node
0340   Handle(NCollection_BaseAllocator)    myAlloc;   ///< Allocator for TreeNode
0341 };
0342 
0343 // ================== METHODS TEMPLATES =====================
0344 //=======================================================================
0345 //function : Add
0346 //purpose  : Updates the tree with a new object and its bounding box
0347 //=======================================================================
0348 
0349 template <class TheObjType, class TheBndType>
0350 Standard_Boolean NCollection_UBTree<TheObjType,TheBndType>::Add
0351                         (const TheObjType& theObj,
0352                          const TheBndType& theBnd)
0353 {
0354   if (IsEmpty()) {
0355     // Accepting first object
0356     myRoot = new (this->myAlloc) TreeNode (theObj, theBnd);
0357     myLastNode = myRoot;
0358     return Standard_True;
0359   }
0360 
0361   TreeNode *pBranch = myRoot;
0362   Standard_Boolean isOutOfBranch = pBranch->Bnd().IsOut (theBnd);
0363 
0364   for(;;) {
0365     // condition of stopping the search
0366     if (isOutOfBranch || pBranch->IsLeaf()) {
0367       TheBndType aNewBnd = theBnd;
0368       aNewBnd.Add (pBranch->Bnd());
0369       // put the new leaf aside on the level of pBranch
0370       pBranch->Gemmate (aNewBnd, theObj, theBnd, this->myAlloc);
0371       myLastNode = &pBranch->ChangeChild(1);
0372       break;
0373     }
0374 
0375     // Update the bounding box of the branch
0376     pBranch->ChangeBnd().Add (theBnd);
0377 
0378     // Select the best child branch to accept the object:
0379     // 1. First check if one branch is out and another one is not.
0380     // 2. Else select the child having the least union with theBnd
0381     Standard_Integer iBest = 0;
0382     Standard_Boolean isOut[] = { pBranch->Child(0).Bnd().IsOut (theBnd),
0383                                  pBranch->Child(1).Bnd().IsOut (theBnd) };
0384     if (isOut[0] != isOut[1])
0385       iBest = (isOut[0] ? 1 : 0);
0386     else {
0387       TheBndType aUnion[] = { theBnd, theBnd };
0388       aUnion[0].Add (pBranch->Child(0).Bnd());
0389       aUnion[1].Add (pBranch->Child(1).Bnd());
0390       const Standard_Real d1 = aUnion[0].SquareExtent();
0391       const Standard_Real d2 = aUnion[1].SquareExtent();
0392       if (d1 > d2)
0393         iBest = 1;
0394     }
0395 
0396     // Continue with the selected branch
0397     isOutOfBranch = isOut[iBest];
0398     pBranch = &pBranch->ChangeChild(iBest);
0399   }
0400   return Standard_True;
0401 }
0402 
0403 //=======================================================================
0404 //function : Select
0405 //purpose  : Recursively searches in the branch all objects conforming 
0406 //           to the given selector.
0407 //           Returns the number of objects found.
0408 //=======================================================================
0409 
0410 template <class TheObjType, class TheBndType>
0411 Standard_Integer NCollection_UBTree<TheObjType,TheBndType>::Select
0412                                  (const TreeNode& theBranch,
0413                                   Selector&       theSelector) const
0414 {
0415   // Try to reject the branch by bounding box
0416   if (theSelector.Reject (theBranch.Bnd()))
0417     return 0;
0418 
0419   Standard_Integer nSel = 0;
0420 
0421   if (theBranch.IsLeaf()) {
0422     // It is a leaf => try to accept the object
0423     if (theSelector.Accept (theBranch.Object()))
0424       nSel++;
0425   }
0426   else {
0427     // It is a branch => select from its children
0428     nSel += Select (theBranch.Child(0), theSelector);
0429     if (!theSelector.Stop())
0430       nSel += Select (theBranch.Child(1), theSelector);
0431   }
0432 
0433   return nSel;
0434 }
0435 
0436 // ======================================================================
0437 /**
0438  * Declaration of handled version of NCollection_UBTree.
0439  * In the macros below the arguments are:
0440  * _HUBTREE      - the desired name of handled class
0441  * _OBJTYPE      - the name of the object type
0442  * _BNDTYPE      - the name of the bounding box type
0443  * _HPARENT      - the name of parent class (usually Standard_Transient)
0444  */
0445 #define DEFINE_HUBTREE(_HUBTREE, _OBJTYPE, _BNDTYPE, _HPARENT)          \
0446 class _HUBTREE : public _HPARENT                                        \
0447 {                                                                       \
0448  public:                                                                \
0449   typedef NCollection_UBTree <_OBJTYPE, _BNDTYPE> UBTree;               \
0450                                                                         \
0451   _HUBTREE () : myTree(new UBTree) {}                                   \
0452   /* Empty constructor */                                               \
0453   _HUBTREE (const Handle(NCollection_BaseAllocator)& theAlloc)           \
0454      : myTree(new UBTree(theAlloc)) {}                                  \
0455   /* Constructor */                                                     \
0456                                                                         \
0457   /* Access to the methods of UBTree */                                 \
0458                                                                         \
0459   Standard_Boolean Add (const _OBJTYPE& theObj,                         \
0460                         const _BNDTYPE& theBnd)                         \
0461         { return ChangeTree().Add (theObj, theBnd); }                   \
0462                                                                         \
0463   Standard_Integer Select (UBTree::Selector& theSelector) const         \
0464         { return Tree().Select (theSelector); }                         \
0465                                                                         \
0466   void Clear () { ChangeTree().Clear (); }                              \
0467                                                                         \
0468   Standard_Boolean IsEmpty () const { return Tree().IsEmpty(); }        \
0469                                                                         \
0470   const UBTree::TreeNode& Root () const { return Tree().Root(); }       \
0471                                                                         \
0472                                                                         \
0473   /* Access to the tree algorithm */                                    \
0474                                                                         \
0475   const UBTree& Tree () const { return *myTree; }                       \
0476   UBTree&       ChangeTree () { return *myTree; }                       \
0477                                                                         \
0478   ~_HUBTREE () { delete myTree; }                                       \
0479   /* Destructor */                                                      \
0480                                                                         \
0481   DEFINE_STANDARD_RTTI_INLINE(_HUBTREE,_HPARENT)                                       \
0482   /* Type management */                                                 \
0483                                                                         \
0484  private:                                                               \
0485   /* Copying and assignment are prohibited  */                          \
0486   _HUBTREE (UBTree*);                                                   \
0487   _HUBTREE (const _HUBTREE&);                                           \
0488   void operator = (const _HUBTREE&);                                    \
0489                                                                         \
0490  private:                                                               \
0491   UBTree       *myTree;        /* pointer to the tree algorithm */      \
0492 };                                                                      \
0493 DEFINE_STANDARD_HANDLE (_HUBTREE, _HPARENT)
0494 
0495 #define IMPLEMENT_HUBTREE(_HUBTREE, _HPARENT)                           
0496 
0497 
0498 
0499 #endif