57 enum { dimworld = GeometricEntitySet::dimensionworld };
58 using ctype =
typename GeometricEntitySet::ctype;
65 struct BoundingBoxNode
83 void build(std::shared_ptr<const GeometricEntitySet> set)
89 boundingBoxNodes_.clear();
90 boundingBoxCoordinates_.clear();
96 const auto numLeaves = set->size();
99 const auto numNodes = 2*numLeaves - 1;
100 boundingBoxNodes_.reserve(numNodes);
101 boundingBoxCoordinates_.reserve(numNodes*2*dimworld);
104 std::vector<ctype> leafBoxes(2*dimworld*numLeaves);
106 for (
const auto& geometricEntity : *set)
107 computeEntityBoundingBox_(leafBoxes.data() + 2*dimworld*set->index(geometricEntity), geometricEntity);
110 std::vector<std::size_t> leafPartition(numLeaves);
111 std::iota(leafPartition.begin(), leafPartition.end(), 0);
114 build_(leafBoxes, leafPartition.begin(), leafPartition.end());
118 <<
" nodes for " << numLeaves <<
" grid entities in "
119 << timer.stop() <<
" seconds." << std::endl;
124 {
return *entitySet_; }
132 {
return boundingBoxNodes_[nodeIdx]; }
136 {
return boundingBoxCoordinates_.data() + 2*dimworld*nodeIdx; }
140 {
return boundingBoxNodes_.size(); }
144 bool isLeaf(
const BoundingBoxNode& node, std::size_t nodeIdx)
const
145 {
return node.child0 == nodeIdx; }
150 std::vector<BoundingBoxNode> boundingBoxNodes_;
153 std::vector<ctype> boundingBoxCoordinates_;
156 std::shared_ptr<const EntitySet> entitySet_;
159 template <
class Entity>
160 void computeEntityBoundingBox_(ctype* b,
const Entity& entity)
const
164 ctype* xMax = b + dimworld;
167 auto geometry = entity.geometry();
170 auto corner = geometry.corner(0);
171 for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
172 xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx];
175 for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx)
177 corner = geometry.corner(cornerIdx);
178 for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
182 xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]);
183 xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]);
189 std::size_t build_(
const std::vector<ctype>& leafBoxes,
190 const std::vector<std::size_t>::iterator& begin,
191 const std::vector<std::size_t>::iterator& end)
196 if (end - begin == 1)
199 const std::size_t leafNodeIdx = *begin;
200 const auto beginCoords = leafBoxes.begin() + 2*dimworld*leafNodeIdx;
201 const auto endCoords = beginCoords + 2*dimworld;
206 return addBoundingBox_(BoundingBoxNode{
numBoundingBoxes(), leafNodeIdx}, beginCoords, endCoords);
210 const auto bCoords = computeBBoxOfBBoxes_(leafBoxes, begin, end);
213 const auto axis = computeLongestAxis_(bCoords);
217 auto middle = begin + (end - begin)/2;
218 std::nth_element(begin, middle, end, [&leafBoxes, axis](std::size_t i, std::size_t j)
220 const ctype* bi = leafBoxes.data() + 2*dimworld*i;
221 const ctype*
bj = leafBoxes.data() + 2*dimworld*j;
222 return bi[axis] + bi[axis + dimworld] <
bj[axis] +
bj[axis + dimworld];
227 return addBoundingBox_(BoundingBoxNode{build_(leafBoxes, begin, middle), build_(leafBoxes, middle, end)},
228 bCoords.begin(), bCoords.end());
232 template <
class Iterator>
233 std::size_t addBoundingBox_(BoundingBoxNode&& node,
234 const Iterator& coordBegin,
235 const Iterator& coordEnd)
238 boundingBoxNodes_.emplace_back(node);
241 boundingBoxCoordinates_.insert(boundingBoxCoordinates_.end(), coordBegin, coordEnd);
244 return boundingBoxNodes_.size() - 1;
248 std::array<ctype, 2*dimworld>
249 computeBBoxOfBBoxes_(
const std::vector<ctype>& leafBoxes,
250 const std::vector<std::size_t>::iterator& begin,
251 const std::vector<std::size_t>::iterator& end)
253 std::array<ctype, 2*dimworld> bBoxCoords;
257 const auto* bFirst = leafBoxes.data() + 2*dimworld*(*it);
259 for (
int coordIdx = 0; coordIdx < 2*dimworld; ++coordIdx)
260 bBoxCoords[coordIdx] = bFirst[coordIdx];
263 for (; it != end; ++it)
265 const auto* b = leafBoxes.data() + 2*dimworld*(*it);
266 for (
int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
267 if (b[coordIdx] < bBoxCoords[coordIdx])
268 bBoxCoords[coordIdx] = b[coordIdx];
269 for (
int coordIdx = dimworld; coordIdx < 2*dimworld; ++coordIdx)
270 if (b[coordIdx] > bBoxCoords[coordIdx])
271 bBoxCoords[coordIdx] = b[coordIdx];
278 std::size_t computeLongestAxis_(
const std::array<ctype, 2*dimworld>& bCoords)
280 std::array<ctype, dimworld> axisLength;
281 for (
int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
282 axisLength[coordIdx] = bCoords[dimworld + coordIdx] - bCoords[coordIdx];
284 return std::distance(axisLength.begin(), std::max_element(axisLength.begin(), axisLength.end()));