1 // Created on: 2014-01-09
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <BVH_Sorter.hxx>
18 // =======================================================================
19 // function : BVH_SweepPlaneBuilder
21 // =======================================================================
22 template<class T, int N>
23 BVH_SweepPlaneBuilder<T, N>::BVH_SweepPlaneBuilder (const Standard_Integer theLeafNodeSize,
24 const Standard_Integer theMaxTreeDepth)
25 : BVH_Builder<T, N> (theLeafNodeSize,
31 // =======================================================================
32 // function : ~BVH_SweepPlaneBuilder
34 // =======================================================================
35 template<class T, int N>
36 BVH_SweepPlaneBuilder<T, N>::~BVH_SweepPlaneBuilder()
41 // =======================================================================
42 // function : BuildNode
44 // =======================================================================
45 template<class T, int N>
46 void BVH_SweepPlaneBuilder<T, N>::BuildNode (BVH_Set<T, N>* theSet,
47 BVH_Tree<T, N>* theBVH,
48 const Standard_Integer theNode)
50 const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode);
51 const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode);
52 const Standard_Integer aNodeNbPrimitives = theBVH->NbPrimitives (theNode);
54 // Parameters for storing best split
55 Standard_Integer aMinSplitAxis = -1;
56 Standard_Integer aMinSplitIndex = 0;
58 Standard_Real* aLftSet = new Standard_Real[aNodeNbPrimitives];
59 Standard_Real* aRghSet = new Standard_Real[aNodeNbPrimitives];
61 Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max();
64 for (Standard_Integer anAxis = 0; anAxis < (N < 4 ? N : 3); ++anAxis)
66 const T aNodeSize = BVHTools::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), anAxis) -
67 BVHTools::VecComp<T, N>::Get (theBVH->MinPoint (theNode), anAxis);
68 if (aNodeSize <= THE_NODE_MIN_SIZE)
73 BVH_Sorter<T, N>::Perform (theSet, anAxis, aNodeBegPrimitive, aNodeEndPrimitive);
75 BVH_Box<T, N> aLftBox;
76 BVH_Box<T, N> aRghBox;
78 *aLftSet = std::numeric_limits<T>::max();
79 *aRghSet = std::numeric_limits<T>::max();
82 for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex)
84 aLftBox.Combine (theSet->Box (anIndex + aNodeBegPrimitive - 1));
86 aLftSet[anIndex] = static_cast<Standard_Real> (aLftBox.Area());
90 for (Standard_Integer anIndex = 1; anIndex < aNodeNbPrimitives; ++anIndex)
92 aRghBox.Combine (theSet->Box (aNodeEndPrimitive - anIndex + 1));
94 aRghSet[anIndex] = static_cast<Standard_Real> (aRghBox.Area());
97 // Find best split using simplified SAH
98 for (Standard_Integer aNbLft = 1, aNbRgh = aNodeNbPrimitives - 1; aNbLft < aNodeNbPrimitives; ++aNbLft, --aNbRgh)
100 Standard_Real aCost = (aLftSet[aNbLft] /* / aNodeArea */) * aNbLft +
101 (aRghSet[aNbRgh] /* / aNodeArea */) * aNbRgh;
103 if (aCost < aMinSplitCost)
105 aMinSplitCost = aCost;
106 aMinSplitAxis = anAxis;
107 aMinSplitIndex = aNbLft;
112 if (aMinSplitAxis == -1)
117 theBVH->SetInner (theNode);
119 if (aMinSplitAxis != (N < 4 ? N - 1 : 2))
121 BVH_Sorter<T, N>::Perform (theSet, aMinSplitAxis, aNodeBegPrimitive, aNodeEndPrimitive);
124 BVH_Box<T, N> aMinSplitBoxLft;
125 BVH_Box<T, N> aMinSplitBoxRgh;
127 // Compute bounding boxes for selected split plane
128 for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMinSplitIndex + aNodeBegPrimitive; ++anIndex)
130 aMinSplitBoxLft.Combine (theSet->Box (anIndex));
133 for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMinSplitIndex + aNodeBegPrimitive; --anIndex)
135 aMinSplitBoxRgh.Combine (theSet->Box (anIndex));
138 const Standard_Integer aMiddle = aNodeBegPrimitive + aMinSplitIndex;
140 static const Standard_Integer aLftNode = 1;
141 static const Standard_Integer aRghNode = 2;
143 // Setting up tasks for child nodes
144 for (Standard_Integer aSide = aLftNode; aSide <= aRghNode; ++aSide)
146 typename BVH_Box<T, N>::BVH_VecNt aChildMinPoint = (aSide == aLftNode)
147 ? aMinSplitBoxLft.CornerMin()
148 : aMinSplitBoxRgh.CornerMin();
149 typename BVH_Box<T, N>::BVH_VecNt aChildMaxPoint = (aSide == aLftNode)
150 ? aMinSplitBoxLft.CornerMax()
151 : aMinSplitBoxRgh.CornerMax();
153 Standard_Integer aChildBegPrimitive = (aSide == aLftNode)
156 Standard_Integer aChildEndPrimitive = (aSide == aLftNode)
160 Standard_Integer aChildIndex = theBVH->AddLeafNode (aChildMinPoint, aChildMaxPoint,
161 aChildBegPrimitive, aChildEndPrimitive);
163 theBVH->Level (aChildIndex) = theBVH->Level (theNode) + 1;
165 // Check to see if child node must be split
166 const Standard_Integer aChildNbPimitives = (aSide == aLftNode)
167 ? aMiddle - aNodeBegPrimitive
168 : aNodeEndPrimitive - aMiddle + 1;
170 if (aSide == aLftNode)
171 theBVH->LeftChild (theNode) = aChildIndex;
173 theBVH->RightChild (theNode) = aChildIndex;
175 const Standard_Boolean isLeaf = aChildNbPimitives <= BVH_Builder<T, N>::myLeafNodeSize
176 || theBVH->Level (aChildIndex) >= BVH_Builder<T, N>::myMaxTreeDepth;
180 BVH_Builder<T, N>::myTasksQueue.Append (aChildIndex);