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