Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/opencascade/BVH_Traverse.lxx is written in an unsupported language. File is not indexed.

0001 // Created by: Eugeny MALTCHIKOV
0002 // Created on: 2019-04-17
0003 // Copyright (c) 2019 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 namespace
0017 {
0018   //! Auxiliary structure for keeping the nodes to process
0019   template<class MetricType> struct BVH_NodeInStack
0020   {
0021     //! Constructor
0022     BVH_NodeInStack (const Standard_Integer theNodeID = 0,
0023                      const MetricType& theMetric = MetricType())
0024       : NodeID (theNodeID), Metric (theMetric)
0025     {}
0026 
0027     // Fields
0028     Standard_Integer NodeID; //!< Id of the node in the BVH tree
0029     MetricType Metric;       //!< Metric computed for the node
0030   };
0031 }
0032 
0033 // =======================================================================
0034 // function : BVH_Traverse::Select
0035 // purpose  :
0036 // =======================================================================
0037 template <class NumType, int Dimension, class BVHSetType, class MetricType>
0038 Standard_Integer BVH_Traverse <NumType, Dimension, BVHSetType, MetricType>::Select
0039   (const opencascade::handle<BVH_Tree <NumType, Dimension>>& theBVH)
0040 {
0041   if (theBVH.IsNull())
0042     return 0;
0043 
0044   if (theBVH->NodeInfoBuffer().empty())
0045     return 0;
0046 
0047   // Create stack
0048   BVH_NodeInStack<MetricType> aStack[BVH_Constants_MaxTreeDepth];
0049 
0050   BVH_NodeInStack<MetricType> aNode (0);         // Currently processed node, starting with the root node
0051   BVH_NodeInStack<MetricType> aPrevNode = aNode; // Previously processed node
0052 
0053   Standard_Integer aHead = -1;      // End of the stack
0054   Standard_Integer aNbAccepted = 0; // Counter for accepted elements
0055 
0056   for (;;)
0057   {
0058     const BVH_Vec4i& aData = theBVH->NodeInfoBuffer()[aNode.NodeID];
0059 
0060     if (aData.x() == 0)
0061     {
0062       // Inner node:
0063       // - check the metric of the node
0064       // - test the children of the node
0065 
0066       if (!this->AcceptMetric (aNode.Metric))
0067       {
0068         // Test the left branch
0069         MetricType aMetricLft;
0070         Standard_Boolean isGoodLft = !RejectNode (theBVH->MinPoint (aData.y()),
0071                                                   theBVH->MaxPoint (aData.y()),
0072                                                   aMetricLft);
0073         if (this->Stop())
0074           return aNbAccepted;
0075 
0076         // Test the right branch
0077         MetricType aMetricRgh;
0078         Standard_Boolean isGoodRgh = !RejectNode (theBVH->MinPoint (aData.z()),
0079                                                   theBVH->MaxPoint (aData.z()),
0080                                                   aMetricRgh);
0081         if (this->Stop())
0082           return aNbAccepted;
0083 
0084         if (isGoodLft && isGoodRgh)
0085         {
0086           // Chose the branch with the best metric to be processed next,
0087           // put the other branch in the stack
0088           if (this->IsMetricBetter (aMetricLft, aMetricRgh))
0089           {
0090             aNode           = BVH_NodeInStack<MetricType> (aData.y(), aMetricLft);
0091             aStack[++aHead] = BVH_NodeInStack<MetricType> (aData.z(), aMetricRgh);
0092           }
0093           else
0094           {
0095             aNode           = BVH_NodeInStack<MetricType> (aData.z(), aMetricRgh);
0096             aStack[++aHead] = BVH_NodeInStack<MetricType> (aData.y(), aMetricLft);
0097           }
0098         }
0099         else if (isGoodLft || isGoodRgh)
0100         {
0101           aNode = isGoodLft ?
0102             BVH_NodeInStack<MetricType> (aData.y(), aMetricLft) :
0103             BVH_NodeInStack<MetricType> (aData.z(), aMetricRgh);
0104         }
0105       }
0106       else
0107       {
0108         // Both children will be accepted
0109         // Take one for processing, put the other into stack
0110         aNode           = BVH_NodeInStack<MetricType> (aData.y(), aNode.Metric);
0111         aStack[++aHead] = BVH_NodeInStack<MetricType> (aData.z(), aNode.Metric);
0112       }
0113     }
0114     else
0115     {
0116       // Leaf node - apply the leaf node operation to each element
0117       for (Standard_Integer iN = aData.y(); iN <= aData.z(); ++iN)
0118       {
0119         if (Accept (iN, aNode.Metric))
0120           ++aNbAccepted;
0121 
0122         if (this->Stop())
0123           return aNbAccepted;
0124       }
0125     }
0126 
0127     if (aNode.NodeID == aPrevNode.NodeID)
0128     {
0129       if (aHead < 0)
0130         return aNbAccepted;
0131 
0132       // Remove the nodes with bad metric from the stack
0133       aNode = aStack[aHead--];
0134       while (this->RejectMetric (aNode.Metric))
0135       {
0136         if (aHead < 0)
0137           return aNbAccepted;
0138         aNode = aStack[aHead--];
0139       }
0140     }
0141 
0142     aPrevNode = aNode;
0143   }
0144 }
0145 
0146 namespace
0147 {
0148   //! Auxiliary structure for keeping the pair of nodes to process
0149   template<class MetricType> struct BVH_PairNodesInStack
0150   {
0151     //! Constructor
0152     BVH_PairNodesInStack (const Standard_Integer theNodeID1 = 0,
0153                           const Standard_Integer theNodeID2 = 0,
0154                           const MetricType& theMetric = MetricType())
0155       : NodeID1 (theNodeID1), NodeID2 (theNodeID2), Metric (theMetric)
0156     {}
0157 
0158     // Fields
0159     Standard_Integer NodeID1; //!< Id of the node in the first BVH tree
0160     Standard_Integer NodeID2; //!< Id of the node in the second BVH tree
0161     MetricType Metric;        //!< Metric computed for the pair of nodes
0162   };
0163 }
0164 
0165 // =======================================================================
0166 // function : BVH_PairTraverse::Select
0167 // purpose  :
0168 // =======================================================================
0169 template <class NumType, int Dimension, class BVHSetType, class MetricType>
0170 Standard_Integer BVH_PairTraverse<NumType, Dimension, BVHSetType, MetricType>::Select
0171   (const opencascade::handle<BVH_Tree <NumType, Dimension>>& theBVH1,
0172    const opencascade::handle<BVH_Tree <NumType, Dimension>>& theBVH2)
0173 {
0174   if (theBVH1.IsNull() || theBVH2.IsNull())
0175     return 0;
0176 
0177   const BVH_Array4i& aBVHNodes1 = theBVH1->NodeInfoBuffer();
0178   const BVH_Array4i& aBVHNodes2 = theBVH2->NodeInfoBuffer();
0179   if (aBVHNodes1.empty() || aBVHNodes2.empty())
0180     return 0;
0181 
0182   // On each iteration we can add max four new pairs of nodes to process.
0183   // One of these pairs goes directly to processing, while others
0184   // are put in the stack. So the max number of pairs in the stack is
0185   // the max tree depth multiplied by 3.
0186   const Standard_Integer aMaxNbPairsInStack = 3 * BVH_Constants_MaxTreeDepth;
0187 
0188   // Stack of pairs of nodes to process
0189   BVH_PairNodesInStack<MetricType> aStack[aMaxNbPairsInStack];
0190 
0191   // Currently processed pair, starting with the root nodes
0192   BVH_PairNodesInStack<MetricType> aNode (0, 0);
0193   // Previously processed pair
0194   BVH_PairNodesInStack<MetricType> aPrevNode = aNode;
0195   // End of the stack
0196   Standard_Integer aHead = -1;
0197   // Counter for accepted elements
0198   Standard_Integer aNbAccepted = 0;
0199 
0200   for (;;)
0201   {
0202     const BVH_Vec4i& aData1 = aBVHNodes1[aNode.NodeID1];
0203     const BVH_Vec4i& aData2 = aBVHNodes2[aNode.NodeID2];
0204 
0205     if (aData1.x() != 0 && aData2.x() != 0)
0206     {
0207       // Outer/Outer
0208       for (Standard_Integer iN1 = aData1.y(); iN1 <= aData1.z(); ++iN1)
0209       {
0210         for (Standard_Integer iN2 = aData2.y(); iN2 <= aData2.z(); ++iN2)
0211         {
0212           if (Accept (iN1, iN2))
0213             ++aNbAccepted;
0214 
0215           if (this->Stop())
0216             return aNbAccepted;
0217         }
0218       }
0219     }
0220     else
0221     {
0222       BVH_PairNodesInStack<MetricType> aPairs[4];
0223       Standard_Integer aNbPairs = 0;
0224 
0225       if (aData1.x() == 0 && aData2.x() == 0)
0226       {
0227         // Inner/Inner
0228         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.y(), aData2.y());
0229         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.y(), aData2.z());
0230         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.z(), aData2.y());
0231         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.z(), aData2.z());
0232       }
0233       else if (aData1.x() == 0)
0234       {
0235         // Inner/Outer
0236         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.y(), aNode.NodeID2);
0237         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aData1.z(), aNode.NodeID2);
0238       }
0239       else if (aData2.x() == 0)
0240       {
0241         // Outer/Inner
0242         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aNode.NodeID1, aData2.y());
0243         aPairs[aNbPairs++] = BVH_PairNodesInStack<MetricType> (aNode.NodeID1, aData2.z());
0244       }
0245 
0246       BVH_PairNodesInStack<MetricType> aKeptPairs[4];
0247       Standard_Integer aNbKept = 0;
0248       // Compute metrics for the nodes
0249       for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair)
0250       {
0251         const Standard_Boolean isPairRejected =
0252           RejectNode (theBVH1->MinPoint (aPairs[iPair].NodeID1), theBVH1->MaxPoint (aPairs[iPair].NodeID1),
0253                       theBVH2->MinPoint (aPairs[iPair].NodeID2), theBVH2->MaxPoint (aPairs[iPair].NodeID2),
0254                       aPairs[iPair].Metric);
0255         if (!isPairRejected)
0256         {
0257           // Put the item into the sorted array of pairs
0258           Standard_Integer iSort = aNbKept;
0259           while (iSort > 0 && this->IsMetricBetter (aPairs[iPair].Metric, aKeptPairs[iSort - 1].Metric))
0260           {
0261             aKeptPairs[iSort] = aKeptPairs[iSort - 1];
0262             --iSort;
0263           }
0264           aKeptPairs[iSort] = aPairs[iPair];
0265           aNbKept++;
0266         }
0267       }
0268 
0269       if (aNbKept > 0)
0270       {
0271         aNode = aKeptPairs[0];
0272 
0273         for (Standard_Integer iPair = 1; iPair < aNbKept; ++iPair)
0274         {
0275           aStack[++aHead] = aKeptPairs[iPair];
0276         }
0277       }
0278     }
0279 
0280     if (aNode.NodeID1 == aPrevNode.NodeID1 &&
0281         aNode.NodeID2 == aPrevNode.NodeID2)
0282     {
0283       // No pairs to add
0284       if (aHead < 0)
0285         return aNbAccepted;
0286 
0287       // Remove the pairs of nodes with bad metric from the stack
0288       aNode = aStack[aHead--];
0289       while (this->RejectMetric (aNode.Metric))
0290       {
0291         if (aHead < 0)
0292           return aNbAccepted;
0293         aNode = aStack[aHead--];
0294       }
0295     }
0296 
0297     aPrevNode = aNode;
0298   }
0299 }