Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:18

0001 // Created on: 2016-06-20
0002 // Created by: Denis BOGOLEPOV
0003 // Copyright (c) 2016 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 _BVH_BinaryTree_Header
0017 #define _BVH_BinaryTree_Header
0018 
0019 #include <BVH_QuadTree.hxx>
0020 
0021 #include <deque>
0022 #include <tuple>
0023 
0024 //! Specialization of binary BVH tree.
0025 template<class T, int N>
0026 class BVH_Tree<T, N, BVH_BinaryTree> : public BVH_TreeBase<T, N>
0027 {
0028 public: //! @name custom data types
0029 
0030   typedef typename BVH_TreeBase<T, N>::BVH_VecNt BVH_VecNt;
0031 
0032 public: //! @name methods for accessing individual nodes
0033 
0034   //! Creates new empty BVH tree.
0035   BVH_Tree() : BVH_TreeBase<T, N>() { }
0036 
0037   //! Sets node type to 'outer'.
0038   void SetOuter (const int theNodeIndex) { BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 1; }
0039 
0040   //! Sets node type to 'inner'.
0041   void SetInner (const int theNodeIndex) { BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex).x() = 0; }
0042 
0043   //! Returns index of the K-th child of the given inner node.
0044   //! \tparam K the index of node child (0 or 1)
0045   template<int K>
0046   int Child (const int theNodeIndex) const { return BVH::Array<int, 4>::Value (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; }
0047 
0048   //! Returns index of the K-th child of the given inner node.
0049   //! \tparam K the index of node child (0 or 1)
0050   template<int K>
0051   int& ChangeChild (const int theNodeIndex) { return BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; }
0052 
0053   //! Returns index of the K-th child of the given inner node.
0054   //! \tparam K the index of node child (0 or 1)
0055   template<int K>
0056   int& Child (const int theNodeIndex) { return BVH::Array<int, 4>::ChangeValue (this->myNodeInfoBuffer, theNodeIndex)[K + 1]; }
0057 
0058 public: //! @name methods for adding/removing tree nodes
0059 
0060   //! Removes all nodes from the tree.
0061   void Clear()
0062   {
0063     this->myDepth = 0;
0064     BVH::Array<T, N>::Clear  (this->myMinPointBuffer);
0065     BVH::Array<T, N>::Clear  (this->myMaxPointBuffer);
0066     BVH::Array<int, 4>::Clear(this->myNodeInfoBuffer);
0067   }
0068 
0069   //! Reserves internal BVH storage, so that it
0070   //! can contain the given number of BVH nodes.
0071   void Reserve (const int theNbNodes)
0072   {
0073     BVH::Array<T,   N>::Reserve (this->myMinPointBuffer, theNbNodes);
0074     BVH::Array<T,   N>::Reserve (this->myMaxPointBuffer, theNbNodes);
0075     BVH::Array<int, 4>::Reserve (this->myNodeInfoBuffer, theNbNodes);
0076   }
0077 
0078   //! Adds new leaf node to the BVH.
0079   int AddLeafNode (const BVH_VecNt& theMinPoint,
0080                    const BVH_VecNt& theMaxPoint,
0081                    const int        theBegElem,
0082                    const int        theEndElem)
0083   {
0084     BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint);
0085     BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint);
0086     BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0));
0087     return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1;
0088   }
0089 
0090   //! Adds new inner node to the BVH.
0091   int AddInnerNode (const BVH_VecNt& theMinPoint,
0092                     const BVH_VecNt& theMaxPoint,
0093                     const int        theLftChild,
0094                     const int        theRghChild)
0095   {
0096     BVH::Array<T, N>::Append (this->myMinPointBuffer, theMinPoint);
0097     BVH::Array<T, N>::Append (this->myMaxPointBuffer, theMaxPoint);
0098     BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0));
0099     return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1;
0100   }
0101 
0102   //! Adds new leaf node to the BVH.
0103   int AddLeafNode (const BVH_Box<T, N>& theAABB,
0104                    const int            theBegElem,
0105                    const int            theEndElem)
0106   {
0107     return AddLeafNode (theAABB.CornerMin(), theAABB.CornerMax(), theBegElem, theEndElem);
0108   }
0109 
0110   //! Adds new inner node to the BVH.
0111   int AddInnerNode (const BVH_Box<T, N>& theAABB,
0112                     const int            theLftChild,
0113                     const int            theRghChild)
0114   {
0115     return AddInnerNode (theAABB.CornerMin(), theAABB.CornerMax(), theLftChild, theRghChild);
0116   }
0117 
0118   //! Adds new leaf node to the BVH with UNINITIALIZED bounds.
0119   int AddLeafNode (const int theBegElem,
0120                    const int theEndElem)
0121   {
0122     BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (1, theBegElem, theEndElem, 0));
0123     return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1;
0124   }
0125 
0126   //! Adds new inner node to the BVH with UNINITIALIZED bounds.
0127   int AddInnerNode (const int theLftChild,
0128                     const int theRghChild)
0129   {
0130     BVH::Array<int, 4>::Append (this->myNodeInfoBuffer, BVH_Vec4i (0, theLftChild, theRghChild, 0));
0131     return BVH::Array<int, 4>::Size (this->myNodeInfoBuffer) - 1;
0132   }
0133 
0134 public: //! @name methods specific to binary BVH
0135 
0136   //! Returns value of SAH (surface area heuristic).
0137   //! Allows to compare the quality of BVH trees constructed for
0138   //! the same sets of geometric objects with different methods.
0139   T EstimateSAH() const;
0140 
0141   //! Collapses the tree into QBVH an returns it. As a result, each
0142   //! 2-nd level of current tree is kept and the rest are discarded.
0143   BVH_Tree<T, N, BVH_QuadTree>* CollapseToQuadTree() const;
0144 
0145 };
0146 
0147 namespace BVH
0148 {
0149   //! Internal function for recursive calculation of
0150   //! surface area heuristic (SAH) of the given tree.
0151   template<class T, int N>
0152   void EstimateSAH (const BVH_Tree<T, N, BVH_BinaryTree>* theTree, const int theNode, T theProb, T& theSAH)
0153   {
0154     BVH_Box<T, N> aBox (theTree->MinPoint (theNode),
0155                         theTree->MaxPoint (theNode));
0156 
0157     if (theTree->IsOuter (theNode))
0158     {
0159       theSAH += theProb * (theTree->EndPrimitive (theNode) - theTree->BegPrimitive (theNode) + 1);
0160     }
0161     else
0162     {
0163       theSAH += theProb * static_cast<T> (2.0);
0164 
0165       BVH_Box<T, N> aLftBox (theTree->MinPoint (theTree->template Child<0> (theNode)),
0166                              theTree->MaxPoint (theTree->template Child<0> (theNode)));
0167 
0168       if (theProb > 0.0)
0169       {
0170         EstimateSAH (theTree, theTree->template Child<0> (theNode),
0171                      theProb * aLftBox.Area() / aBox.Area(), theSAH);
0172       }
0173 
0174       BVH_Box<T, N> aRghBox (theTree->MinPoint (theTree->template Child<1> (theNode)),
0175                              theTree->MaxPoint (theTree->template Child<1> (theNode)));
0176 
0177       if (theProb > 0.0)
0178       {
0179         EstimateSAH (theTree, theTree->template Child<1> (theNode),
0180                      theProb * aRghBox.Area() / aBox.Area(), theSAH);
0181       }
0182     }
0183   }
0184 }
0185 
0186 // =======================================================================
0187 // function : EstimateSAH
0188 // purpose  :
0189 // =======================================================================
0190 template<class T, int N>
0191 T BVH_Tree<T, N, BVH_BinaryTree>::EstimateSAH() const
0192 {
0193   T aSAH = static_cast<T> (0.0);
0194   BVH::EstimateSAH<T, N> (this, 0, static_cast<T> (1.0), aSAH);
0195   return aSAH;
0196 }
0197 
0198 // =======================================================================
0199 // function : CollapseToQuadTree
0200 // purpose  :
0201 // =======================================================================
0202 template<class T, int N>
0203 BVH_Tree<T, N, BVH_QuadTree>* BVH_Tree<T, N, BVH_BinaryTree>::CollapseToQuadTree() const
0204 {
0205   BVH_Tree<T, N, BVH_QuadTree>* aQBVH = new BVH_Tree<T, N, BVH_QuadTree>;
0206 
0207   if (this->Length() == 0)
0208   {
0209     return aQBVH;
0210   }
0211 
0212   std::deque<std::pair<int, int> > aQueue (1, std::make_pair (0, 0));
0213 
0214   for (int aNbNodes = 1; !aQueue.empty();)
0215   {
0216     const std::pair<int, int> aNode = aQueue.front();
0217 
0218     BVH::Array<T, N>::Append (aQBVH->myMinPointBuffer, BVH::Array<T, N>::Value (this->myMinPointBuffer, std::get<0> (aNode)));
0219     BVH::Array<T, N>::Append (aQBVH->myMaxPointBuffer, BVH::Array<T, N>::Value (this->myMaxPointBuffer, std::get<0> (aNode)));
0220 
0221     BVH_Vec4i aNodeInfo;
0222     if (this->IsOuter (std::get<0> (aNode))) // is leaf node
0223     {
0224       aNodeInfo = BVH_Vec4i (1 /* leaf flag */,
0225         this->BegPrimitive (std::get<0> (aNode)), this->EndPrimitive (std::get<0> (aNode)), std::get<1> (aNode) /* level */);
0226     }
0227     else
0228     {
0229       NCollection_Vector<int> aGrandChildNodes;
0230 
0231       const int aLftChild = Child<0> (std::get<0> (aNode));
0232       const int aRghChild = Child<1> (std::get<0> (aNode));
0233       if (this->IsOuter (aLftChild)) // is leaf node
0234       {
0235         aGrandChildNodes.Append (aLftChild);
0236       }
0237       else
0238       {
0239         aGrandChildNodes.Append (Child<0> (aLftChild));
0240         aGrandChildNodes.Append (Child<1> (aLftChild));
0241       }
0242 
0243       if (this->IsOuter (aRghChild)) // is leaf node
0244       {
0245         aGrandChildNodes.Append (aRghChild);
0246       }
0247       else
0248       {
0249         aGrandChildNodes.Append (Child<0> (aRghChild));
0250         aGrandChildNodes.Append (Child<1> (aRghChild));
0251       }
0252 
0253       for (int aNodeIdx = 0; aNodeIdx < aGrandChildNodes.Size(); ++aNodeIdx)
0254       {
0255         aQueue.push_back (std::make_pair (aGrandChildNodes (aNodeIdx), std::get<1> (aNode) + 1));
0256       }
0257 
0258       aNodeInfo = BVH_Vec4i (0 /* inner flag */,
0259         aNbNodes, aGrandChildNodes.Size() - 1, std::get<1> (aNode) /* level */);
0260 
0261       aQBVH->myDepth = Max (aQBVH->myDepth, std::get<1> (aNode) + 1);
0262 
0263       aNbNodes += aGrandChildNodes.Size();
0264     }
0265 
0266     BVH::Array<int, 4>::Append (aQBVH->myNodeInfoBuffer, aNodeInfo);
0267     aQueue.pop_front(); // node processing completed
0268   }
0269 
0270   return aQBVH;
0271 }
0272 
0273 #endif // _BVH_BinaryTree_Header