Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-18 08:29:25

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