Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-16 09:18:01

0001 // Created on: 2002-10-18
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_UBTreeFiller_HeaderFile
0017 #define NCollection_UBTreeFiller_HeaderFile
0018 
0019 #include <NCollection_UBTree.hxx>
0020 #include <NCollection_DynamicArray.hxx>
0021 
0022 #include <random>
0023 
0024 /**
0025  * This class is used to fill an UBTree in a random order.
0026  * The quality of a tree is much better (from the point of view of
0027  * the search time) if objects are added to it in a random order to
0028  * avoid adding a chain of neerby objects one following each other.
0029  *
0030  * This class collects objects to be added, and then add them to the tree
0031  * in a random order.
0032  */
0033 template <class TheObjType, class TheBndType>
0034 class NCollection_UBTreeFiller
0035 {
0036 public:
0037   // ---------- PUBLIC TYPES ----------
0038 
0039   //! Structure of pair (object, bnd box)
0040   struct ObjBnd
0041   {
0042     TheObjType myObj;
0043     TheBndType myBnd;
0044 
0045     ObjBnd(const TheObjType& theObj, const TheBndType& theBnd)
0046         : myObj(theObj),
0047           myBnd(theBnd)
0048     {
0049     }
0050 
0051     ObjBnd()
0052         : myObj(TheObjType()),
0053           myBnd(TheBndType())
0054     {
0055     }
0056   };
0057 
0058   //! UBTree algorithm
0059   typedef NCollection_UBTree<TheObjType, TheBndType> UBTree;
0060   typedef typename UBTree::TreeNode                  UBTreeNode;
0061 
0062   // ---------- PUBLIC METHODS ----------
0063 
0064   /**
0065    * Constructor.
0066    * @param theTree
0067    *   Tree instance that is to be filled.
0068    * @param theAlloc
0069    *   Allocator for the Filler data.
0070    * @param isFullRandom
0071    *   Takes effect when the number of items is large (order of 50,000). When
0072    *   it is True, the code uses the maximal randomization allowing a better
0073    *   balanced tree. If False, the randomization/tree balance are worse but
0074    *   the tree filling is faster due to better utilisation of CPU L1/L2 cache.
0075    */
0076   NCollection_UBTreeFiller (UBTree& theTree,
0077                             const occ::handle<NCollection_BaseAllocator>& theAlloc=nullptr,
0078                             const bool isFullRandom = true)
0079     : myTree(theTree), mySeqPtr(256, theAlloc),
0080       myRandGen (5489u /* == std::mt19937::default_seed, not defined in older environments, e.g, on Debian 6.0 with GCC 4.4.5 */),
0081       myIsFullRandom (isFullRandom)
0082   {
0083   }
0084 
0085   //! Adds a pair (theObj, theBnd) to my sequence
0086   void Add(const TheObjType& theObj, const TheBndType& theBnd)
0087   {
0088     mySeqPtr.Append(ObjBnd(theObj, theBnd));
0089   }
0090 
0091   /**
0092    * Fills the tree with the objects from my sequence. This method clears
0093    * the internal buffer of added items making sure that no item would be added
0094    * twice.
0095    * @return
0096    *   the number of objects added to the tree.
0097    */
0098   int Fill();
0099 
0100   /**
0101    * Remove all data from Filler, partculary if the Tree no more needed
0102    * so the destructor of this Filler should not populate the useless Tree.
0103    */
0104   void Reset() { mySeqPtr.Clear(); }
0105 
0106   /**
0107    * Check the filled tree for the total number of items and the balance
0108    * outputting these results to std::ostream.
0109    * @return
0110    *   the tree size (the same value is returned by method Fill()).
0111    */
0112   int CheckTree(Standard_OStream& theStream);
0113 
0114   /**
0115    * Destructor. Fills the tree with accumulated items if they have not been
0116    * passed by a previous call of method Fill().
0117    */
0118   ~NCollection_UBTreeFiller()
0119   {
0120     if (mySeqPtr.Length() > 0)
0121 #ifdef OCCT_DEBUG_UBTREE
0122       std::cout << "~NCollection_UBTreeFiller: " << Fill() << " objects added to the tree"
0123                 << std::endl;
0124 #else
0125       Fill();
0126 #endif
0127   }
0128 
0129 private:
0130   // Explicitly delete assignment operator
0131   NCollection_UBTreeFiller& operator=(const NCollection_UBTreeFiller&) = delete;
0132 
0133   static double checkNode(const UBTreeNode& theNode, const int theLength, int& theNumber);
0134 
0135 private:
0136   // ---------- PRIVATE FIELDS ----------
0137 
0138   UBTree&                          myTree;
0139   NCollection_DynamicArray<ObjBnd> mySeqPtr;
0140   std::mt19937                     myRandGen; //!< random number generator
0141   bool                             myIsFullRandom;
0142 };
0143 
0144 //=================================================================================================
0145 
0146 template <class TheObjType, class TheBndType>
0147 int NCollection_UBTreeFiller<TheObjType, TheBndType>::Fill()
0148 {
0149   int i, nbAdd = mySeqPtr.Length();
0150   // Fisher-Yates randomization
0151   if (myIsFullRandom)
0152   {
0153     for (i = nbAdd; i > 0; i--)
0154     {
0155       const int     ind     = static_cast<int>(static_cast<unsigned int>(myRandGen()) % i);
0156       const ObjBnd& aObjBnd = mySeqPtr(ind);
0157       myTree.Add(aObjBnd.myObj, aObjBnd.myBnd);
0158       mySeqPtr(ind) = mySeqPtr(i - 1);
0159     }
0160   }
0161   else
0162   {
0163     for (i = nbAdd; i > 0; i--)
0164     {
0165       const int     ind     = i - static_cast<int>(static_cast<unsigned int>(myRandGen()) % i) - 1;
0166       const ObjBnd& aObjBnd = mySeqPtr(ind);
0167       myTree.Add(aObjBnd.myObj, aObjBnd.myBnd);
0168       mySeqPtr(ind) = mySeqPtr(i - 1);
0169     }
0170   }
0171   mySeqPtr.Clear();
0172   return nbAdd;
0173 }
0174 
0175 //=================================================================================================
0176 
0177 template <class TheObjType, class TheBndType>
0178 int NCollection_UBTreeFiller<TheObjType, TheBndType>::CheckTree(Standard_OStream& theStream)
0179 {
0180   int          aNumber(0);
0181   const double aLen  = checkNode(myTree.Root(), 0, aNumber);
0182   const double num   = (double)aNumber;
0183   const double aLen1 = sqrt(aLen / num);
0184   const double aLen0 = log(num) / log(2.);
0185   char         buf[128];
0186   Sprintf(buf, "Checking UBTree:%8d leaves, balance =%7.2f", aNumber, aLen1 / aLen0);
0187   theStream << buf << std::endl;
0188   return aNumber;
0189 }
0190 
0191 //=================================================================================================
0192 
0193 template <class TheObjType, class TheBndType>
0194 double NCollection_UBTreeFiller<TheObjType, TheBndType>::checkNode(
0195   const typename NCollection_UBTree<TheObjType, TheBndType>::TreeNode& theNode,
0196   const int                                                            theLength,
0197   int&                                                                 theNumber)
0198 {
0199   double aLength;
0200   if (!theNode.IsLeaf())
0201     aLength = (checkNode(theNode.Child(0), theLength + 1, theNumber)
0202                + checkNode(theNode.Child(1), theLength + 1, theNumber));
0203   else
0204   {
0205     theNumber++;
0206     aLength = theLength * theLength;
0207   }
0208   return aLength;
0209 }
0210 
0211 #endif