GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/geometry/boundingboxtree.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 133 133 100.0%
Functions: 487 507 96.1%
Branches: 267 329 81.2%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup Geometry
10 * \brief An axis-aligned bounding box volume hierarchy for dune grids
11 *
12 * Dumux implementation of an AABB tree
13 * Inspired by the AABB tree implementation in DOLFIN by Anders Logg which has the
14 * following license info: DOLFIN is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 */
19 #ifndef DUMUX_GEOMETRY_BOUNDINGBOXTREE_HH
20 #define DUMUX_GEOMETRY_BOUNDINGBOXTREE_HH
21
22 #include <vector>
23 #include <array>
24 #include <algorithm>
25 #include <memory>
26 #include <numeric>
27 #include <limits>
28 #include <type_traits>
29 #include <iostream>
30
31 #include <dune/common/promotiontraits.hh>
32 #include <dune/common/timer.hh>
33 #include <dune/common/fvector.hh>
34
35 namespace Dumux {
36
37
38 #ifndef DOXYGEN
39 namespace Detail {
40
41 template<typename ctype>
42 inline constexpr ctype minimumBaseEpsilon = 10.0*std::numeric_limits<ctype>::epsilon();
43
44 } // namespace Detail
45 #endif // DOXYGEN
46
47 /*!
48 * \ingroup Geometry
49 * \brief An axis-aligned bounding box volume tree implementation
50 *
51 * The class constructs a hierarchical structure of bounding box volumes around
52 * grid entities. This class can be used to efficiently compute intersections
53 * between a grid and other geometrical object. It only implements the intersection
54 * of two of such bounding box trees, so that two independent grids can be intersected.
55 * \tparam GeometricEntitySet has the following requirements
56 * * export dimensionworld, ctype
57 * * a size() member function returning the number of entities
58 * * begin() and end() member function returning at least forward iterators to entities
59 * * an index() method returning a consecutive index given an entity
60 * * an entity() method returning an entity given the consecutive index
61 * * entities have the following requirements:
62 * * a member function geometry() returning a geometry with the member functions
63 * * corner() and corners() returning global coordinates and number of corners
64 */
65 template <class GeometricEntitySet>
66 class BoundingBoxTree
67 {
68 enum { dimworld = GeometricEntitySet::dimensionworld };
69 using ctype = typename GeometricEntitySet::ctype;
70
71 /*!
72 * \brief Bounding box node data structure
73 * leaf nodes are indicated by setting child0 to
74 * the node itself and child1 to the index of the entity in the bounding box.
75 */
76 struct BoundingBoxNode
77 {
78 std::size_t child0;
79 std::size_t child1;
80 };
81
82 public:
83 //! the type of entity set this tree was built with
84 using EntitySet = GeometricEntitySet;
85
86 //! Default Constructor
87 26 BoundingBoxTree() = default;
88
89 //! Constructor with gridView
90 4750 explicit BoundingBoxTree(std::shared_ptr<const GeometricEntitySet> set)
91
1/8
✓ Branch 2 taken 2664 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
9500 { build(set); }
92
93 //! Build up bounding box tree for a grid with leafGridView
94 4822 void build(std::shared_ptr<const GeometricEntitySet> set)
95 {
96 // set the pointer to the entity set
97 4822 entitySet_ = set;
98
99 // clear all internal data
100
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2698 times.
4822 boundingBoxNodes_.clear();
101
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2698 times.
4830 boundingBoxCoordinates_.clear();
102
103 // start the timer
104 4822 Dune::Timer timer;
105
106 // Create bounding boxes for all elements
107 4822 const auto numLeaves = set->size();
108
109 // reserve enough space for the nodes and the coordinates
110 4822 const auto numNodes = 2*numLeaves - 1;
111 4822 boundingBoxNodes_.reserve(numNodes);
112 4822 boundingBoxCoordinates_.reserve(numNodes*2*dimworld);
113
114 // create a vector for leaf boxes (min and max for all dims)
115
1/2
✓ Branch 2 taken 815 times.
✗ Branch 3 not taken.
4822 std::vector<ctype> leafBoxes(2*dimworld*numLeaves);
116
117
14/17
✓ Branch 1 taken 55630 times.
✓ Branch 2 taken 964 times.
✓ Branch 4 taken 80584 times.
✓ Branch 5 taken 334179 times.
✓ Branch 7 taken 787522 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 768374 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 768433 times.
✓ Branch 13 taken 242 times.
✓ Branch 16 taken 141 times.
✗ Branch 17 not taken.
✓ Branch 6 taken 2864779 times.
✓ Branch 9 taken 19695 times.
✓ Branch 3 taken 5929 times.
✓ Branch 0 taken 1744 times.
✓ Branch 15 taken 19122 times.
17656070 for (const auto& geometricEntity : *set)
118
3/5
✓ Branch 1 taken 774303 times.
✓ Branch 2 taken 98442 times.
✓ Branch 4 taken 768374 times.
✗ Branch 5 not taken.
✗ Branch 3 not taken.
6103006 computeEntityBoundingBox_(leafBoxes.data() + 2*dimworld*set->index(geometricEntity), geometricEntity);
119
120 // create the leaf partition, the set of available indices (to be sorted)
121
1/4
✓ Branch 1 taken 2702 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4822 std::vector<std::size_t> leafPartition(numLeaves);
122
1/2
✓ Branch 1 taken 2702 times.
✗ Branch 2 not taken.
9644 std::iota(leafPartition.begin(), leafPartition.end(), 0);
123
124 // Recursively build the bounding box tree
125
2/6
✓ Branch 1 taken 2702 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2702 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4822 build_(leafBoxes, leafPartition.begin(), leafPartition.end());
126
127 // We are done, log output
128
1/2
✓ Branch 1 taken 2702 times.
✗ Branch 2 not taken.
4822 std::cout << "Computed bounding box tree with " << numBoundingBoxes()
129
2/4
✓ Branch 1 taken 2702 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2702 times.
✗ Branch 5 not taken.
4822 << " nodes for " << numLeaves << " grid entities in "
130
4/8
✓ Branch 2 taken 2702 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2702 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2702 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1617 times.
✗ Branch 11 not taken.
4822 << timer.stop() << " seconds." << std::endl;
131 9643 }
132
133 //! the entity set this tree was built with
134 4884490 const EntitySet& entitySet() const
135
11/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2254 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 36 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 4 taken 83 times.
✓ Branch 5 taken 11340 times.
✓ Branch 3 taken 24 times.
✓ Branch 2 taken 11829 times.
✓ Branch 8 taken 4640 times.
✓ Branch 9 taken 1 times.
✓ Branch 12 taken 143776 times.
✗ Branch 6 not taken.
4640048 { return *entitySet_; }
136
137 /////////////////////////////////////////////////////
138 //! Interface to be used by other bounding box trees
139 /////////////////////////////////////////////////////
140
141 //! Get an existing bounding box for a given node
142 30195427 const BoundingBoxNode& getBoundingBoxNode(std::size_t nodeIdx) const
143
24/24
✓ Branch 0 taken 2783711 times.
✓ Branch 1 taken 2171654 times.
✓ Branch 2 taken 5439337 times.
✓ Branch 3 taken 5140836 times.
✓ Branch 4 taken 271887 times.
✓ Branch 5 taken 467418 times.
✓ Branch 6 taken 135151 times.
✓ Branch 7 taken 221909 times.
✓ Branch 8 taken 2202622 times.
✓ Branch 9 taken 4480198 times.
✓ Branch 10 taken 917311 times.
✓ Branch 11 taken 2385395 times.
✓ Branch 12 taken 2462 times.
✓ Branch 13 taken 1343 times.
✓ Branch 14 taken 1575 times.
✓ Branch 15 taken 1038 times.
✓ Branch 16 taken 86414 times.
✓ Branch 17 taken 60943 times.
✓ Branch 18 taken 65232 times.
✓ Branch 19 taken 48077 times.
✓ Branch 20 taken 1255532 times.
✓ Branch 21 taken 684532 times.
✓ Branch 22 taken 893421 times.
✓ Branch 23 taken 477429 times.
30195427 { return boundingBoxNodes_[nodeIdx]; }
144
145 //! Get an existing bounding box for a given node
146 27091171 const ctype* getBoundingBoxCoordinates(std::size_t nodeIdx) const
147
24/24
✓ Branch 0 taken 2787984 times.
✓ Branch 1 taken 2089395 times.
✓ Branch 2 taken 5441548 times.
✓ Branch 3 taken 5136945 times.
✓ Branch 4 taken 374715 times.
✓ Branch 5 taken 129184 times.
✓ Branch 6 taken 184215 times.
✓ Branch 7 taken 64062 times.
✓ Branch 8 taken 3479865 times.
✓ Branch 9 taken 1431601 times.
✓ Branch 10 taken 1652342 times.
✓ Branch 11 taken 741317 times.
✓ Branch 12 taken 2462 times.
✓ Branch 13 taken 1343 times.
✓ Branch 14 taken 1575 times.
✓ Branch 15 taken 1038 times.
✓ Branch 16 taken 86414 times.
✓ Branch 17 taken 60943 times.
✓ Branch 18 taken 65232 times.
✓ Branch 19 taken 48077 times.
✓ Branch 20 taken 1255532 times.
✓ Branch 21 taken 684532 times.
✓ Branch 22 taken 893421 times.
✓ Branch 23 taken 477429 times.
27091171 { return boundingBoxCoordinates_.data() + 2*dimworld*nodeIdx; }
148
149 //! Get the number of bounding boxes currently in the tree
150 4202239 std::size_t numBoundingBoxes() const
151
33/47
✓ Branch 1 taken 800 times.
✓ Branch 2 taken 120 times.
✓ Branch 4 taken 1098 times.
✓ Branch 5 taken 170 times.
✓ Branch 7 taken 59459 times.
✓ Branch 8 taken 50 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 120 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 140 times.
✓ Branch 21 taken 2 times.
✓ Branch 22 taken 9 times.
✓ Branch 25 taken 10 times.
✓ Branch 26 taken 120 times.
✓ Branch 28 taken 22 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 6 times.
✓ Branch 33 taken 120 times.
✓ Branch 35 taken 6 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 2 times.
✓ Branch 40 taken 120 times.
✓ Branch 42 taken 2 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 2 times.
✗ Branch 50 not taken.
✓ Branch 10 taken 282230 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 13 taken 14 times.
✓ Branch 16 taken 179 times.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 23 taken 120 times.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✓ Branch 30 taken 120 times.
✓ Branch 31 taken 16 times.
✓ Branch 34 taken 4 times.
✓ Branch 37 taken 128 times.
✗ Branch 38 not taken.
✗ Branch 41 not taken.
414893 { return boundingBoxNodes_.size(); }
152
153 //! Check whether a bounding box node is a leaf node
154 //! Leaf nodes have itself as child0
155 21528582 bool isLeaf(const BoundingBoxNode& node, std::size_t nodeIdx) const
156
24/24
✓ Branch 0 taken 422263 times.
✓ Branch 1 taken 2455118 times.
✓ Branch 2 taken 297953 times.
✓ Branch 3 taken 5145849 times.
✓ Branch 4 taken 241967 times.
✓ Branch 5 taken 473955 times.
✓ Branch 6 taken 115965 times.
✓ Branch 7 taken 229070 times.
✓ Branch 8 taken 1915130 times.
✓ Branch 9 taken 4623970 times.
✓ Branch 10 taken 917311 times.
✓ Branch 11 taken 2385395 times.
✓ Branch 12 taken 700 times.
✓ Branch 13 taken 1762 times.
✓ Branch 14 taken 401 times.
✓ Branch 15 taken 1174 times.
✓ Branch 16 taken 14222 times.
✓ Branch 17 taken 72192 times.
✓ Branch 18 taken 10064 times.
✓ Branch 19 taken 55168 times.
✓ Branch 20 taken 290819 times.
✓ Branch 21 taken 964713 times.
✓ Branch 22 taken 213315 times.
✓ Branch 23 taken 680106 times.
21528582 { return node.child0 == nodeIdx; }
157
158 private:
159
160 //! vector of bounding box nodes
161 std::vector<BoundingBoxNode> boundingBoxNodes_;
162
163 //! vector of bounding box coordinates
164 std::vector<ctype> boundingBoxCoordinates_;
165
166 //! a pointer to the entity set
167 std::shared_ptr<const EntitySet> entitySet_;
168
169 //! Compute the bounding box of a grid entity
170 template <class Entity>
171 6101262 void computeEntityBoundingBox_(ctype* b, const Entity& entity) const
172 {
173 // get the bounding box coordinates
174 6101262 ctype* xMin = b;
175 6101262 ctype* xMax = b + dimworld;
176
177 // get mesh entity data
178 6101262 auto geometry = entity.geometry();
179
180 // Get coordinates of first vertex
181 13373949 auto corner = geometry.corner(0);
182
4/4
✓ Branch 0 taken 8609346 times.
✓ Branch 1 taken 3983292 times.
✓ Branch 2 taken 139848 times.
✓ Branch 3 taken 528 times.
20969689 for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
183 14868427 xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx];
184
185 // Compute the min and max over the remaining vertices
186
3/3
✓ Branch 1 taken 3794364 times.
✓ Branch 2 taken 94698 times.
✓ Branch 0 taken 15323524 times.
32958162 for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx)
187 {
188 26856900 corner = geometry.corner(cornerIdx);
189
3/3
✓ Branch 0 taken 38971314 times.
✓ Branch 1 taken 15700790 times.
✓ Branch 2 taken 245078 times.
97497515 for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
190 {
191 using std::max;
192 using std::min;
193
4/4
✓ Branch 0 taken 1224912 times.
✓ Branch 1 taken 38239286 times.
✓ Branch 2 taken 8754432 times.
✓ Branch 3 taken 30709766 times.
72331197 xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]);
194
2/2
✓ Branch 0 taken 8754432 times.
✓ Branch 1 taken 30709766 times.
85299326 xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]);
195 }
196 }
197 6099518 }
198
199 //! Build bounding box tree for all entities recursively
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7571990 times.
12201190 std::size_t build_(const std::vector<ctype>& leafBoxes,
201 const std::vector<std::size_t>::iterator& begin,
202 const std::vector<std::size_t>::iterator& end)
203 {
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7571990 times.
12201190 assert(begin < end);
205
206 // If we reached the end of the recursion, i.e. only a leaf box is left
207
2/2
✓ Branch 0 taken 3787346 times.
✓ Branch 1 taken 3784644 times.
12201190 if (end - begin == 1)
208 {
209 // Get the bounding box coordinates for the leaf
210 6103006 const std::size_t leafNodeIdx = *begin;
211 6103006 const auto beginCoords = leafBoxes.begin() + 2*dimworld*leafNodeIdx;
212 6103006 const auto endCoords = beginCoords + 2*dimworld;
213
214 // Store the data in the bounding box
215 // leaf nodes are indicated by setting child0 to
216 // the node itself and child1 to the index of the entity in the bounding box.
217 6103006 return addBoundingBox_(BoundingBoxNode{numBoundingBoxes(), leafNodeIdx}, beginCoords, endCoords);
218 }
219
220 // Compute the bounding box of all bounding boxes in the range [begin, end]
221 6098184 const auto bCoords = computeBBoxOfBBoxes_(leafBoxes, begin, end);
222
223 // sort bounding boxes along the longest axis
224 6098184 const auto axis = computeLongestAxis_(bCoords);
225
226 // nth_element sorts the range to make sure that middle points to the coordinate median in axis direction
227 // this is the most expensive part of the algorithm
228 6098184 auto middle = begin + (end - begin)/2;
229 103430506 std::nth_element(begin, middle, end, [&leafBoxes, axis](std::size_t i, std::size_t j)
230 {
231 151565169 const ctype* bi = leafBoxes.data() + 2*dimworld*i;
232 151565169 const ctype* bj = leafBoxes.data() + 2*dimworld*j;
233 151565169 return bi[axis] + bi[axis + dimworld] < bj[axis] + bj[axis + dimworld];
234 });
235
236 // split the bounding boxes into two at the middle iterator and call build recursively, each
237 // call resulting in a new node of this bounding box, i.e. the root will be added at the end of the process.
238 6098184 return addBoundingBox_(BoundingBoxNode{build_(leafBoxes, begin, middle), build_(leafBoxes, middle, end)},
239 12196368 bCoords.begin(), bCoords.end());
240 }
241
242 //! Add a new bounding box to the tree
243 template <class Iterator>
244 15143980 std::size_t addBoundingBox_(BoundingBoxNode&& node,
245 const Iterator& coordBegin,
246 const Iterator& coordEnd)
247 {
248 // Add the bounding box
249 15143980 boundingBoxNodes_.emplace_back(node);
250
251 // Add the bounding box's coordinates
252 15143980 boundingBoxCoordinates_.insert(boundingBoxCoordinates_.end(), coordBegin, coordEnd);
253
254 // return the index of the new node
255 15143980 return boundingBoxNodes_.size() - 1;
256 }
257
258 //! Compute the bounding box of a vector of bounding boxes
259 std::array<ctype, 2*dimworld>
260 6098184 computeBBoxOfBBoxes_(const std::vector<ctype>& leafBoxes,
261 const std::vector<std::size_t>::iterator& begin,
262 const std::vector<std::size_t>::iterator& end)
263 {
264 std::array<ctype, 2*dimworld> bBoxCoords;
265
266 // copy the iterator and get coordinates of first box
267 6098184 auto it = begin;
268 6098184 const auto* bFirst = leafBoxes.data() + 2*dimworld*(*it);
269
270
2/2
✓ Branch 0 taken 17877982 times.
✓ Branch 1 taken 3784644 times.
35817670 for (int coordIdx = 0; coordIdx < 2*dimworld; ++coordIdx)
271 29719486 bBoxCoords[coordIdx] = bFirst[coordIdx];
272
273 // Compute min and max with the remaining boxes
274
2/2
✓ Branch 0 taken 55408969 times.
✓ Branch 1 taken 3784644 times.
96848063 for (; it != end; ++it)
275 {
276 90749879 const auto* b = leafBoxes.data() + 2*dimworld*(*it);
277
2/2
✓ Branch 0 taken 132557576 times.
✓ Branch 1 taken 55408969 times.
314908250 for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
278
2/2
✓ Branch 0 taken 4408799 times.
✓ Branch 1 taken 128148777 times.
224021459 if (b[coordIdx] < bBoxCoords[coordIdx])
279 6940676 bBoxCoords[coordIdx] = b[coordIdx];
280
2/2
✓ Branch 0 taken 132557576 times.
✓ Branch 1 taken 55408969 times.
314771338 for (int coordIdx = dimworld; coordIdx < 2*dimworld; ++coordIdx)
281
2/2
✓ Branch 0 taken 7069096 times.
✓ Branch 1 taken 125488480 times.
224021459 if (b[coordIdx] > bBoxCoords[coordIdx])
282 11249945 bBoxCoords[coordIdx] = b[coordIdx];
283 }
284
285 6098184 return bBoxCoords;
286 }
287
288 //! Compute the bounding box of a vector of bounding boxes
289 5638730 std::size_t computeLongestAxis_(const std::array<ctype, 2*dimworld>& bCoords)
290 {
291 std::array<ctype, dimworld> axisLength;
292
2/2
✓ Branch 0 taken 8002036 times.
✓ Branch 1 taken 3326006 times.
19559904 for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
293 13921174 axisLength[coordIdx] = bCoords[dimworld + coordIdx] - bCoords[coordIdx];
294
295 5638730 return std::distance(axisLength.begin(), std::max_element(axisLength.begin(), axisLength.end()));
296 }
297 };
298
299 /*!
300 * \brief Check whether a point is intersectin a bounding box (dimworld == 3)
301 * \param point The point
302 * \param b Pointer to bounding box coordinates
303 */
304 template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 3, int> = 0>
305 25049136 inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
306 {
307 static constexpr ctype eps_ = 1.0e-7;
308
309 using std::max;
310 25049136 const auto dx = b[3] - b[0];
311 25049136 const auto dy = b[4] - b[1];
312 25049136 const auto dz = b[5] - b[2];
313 25049136 const ctype eps = max({dx, dy, dz})*eps_;
314
6/6
✓ Branch 0 taken 23899873 times.
✓ Branch 1 taken 1149263 times.
✓ Branch 2 taken 1158152 times.
✓ Branch 3 taken 22741721 times.
✓ Branch 4 taken 953988 times.
✓ Branch 5 taken 21787733 times.
25049136 return (b[0] - eps <= point[0] && point[0] <= b[3] + eps &&
315
6/6
✓ Branch 0 taken 953988 times.
✓ Branch 1 taken 21787733 times.
✓ Branch 2 taken 982602 times.
✓ Branch 3 taken 20805131 times.
✓ Branch 4 taken 806265 times.
✓ Branch 5 taken 19998866 times.
22741721 b[1] - eps <= point[1] && point[1] <= b[4] + eps &&
316
6/6
✓ Branch 0 taken 23899873 times.
✓ Branch 1 taken 1149263 times.
✓ Branch 2 taken 806265 times.
✓ Branch 3 taken 19998866 times.
✓ Branch 4 taken 874072 times.
✓ Branch 5 taken 19124794 times.
45854267 b[2] - eps <= point[2] && point[2] <= b[5] + eps);
317 }
318
319 /*!
320 * \brief Check whether a point is intersectin a bounding box (dimworld == 2)
321 * \param point The point
322 * \param b Pointer to bounding box coordinates
323 */
324 template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 2, int> = 0>
325 760440 inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
326 {
327 static constexpr ctype eps_ = 1.0e-7;
328
329 using std::max;
330 760440 const auto dx = b[2] - b[0];
331
2/2
✓ Branch 0 taken 371731 times.
✓ Branch 1 taken 388709 times.
760440 const auto dy = b[3] - b[1];
332 760440 const ctype eps = max(dx, dy)*eps_;
333
6/6
✓ Branch 0 taken 661804 times.
✓ Branch 1 taken 98636 times.
✓ Branch 2 taken 99295 times.
✓ Branch 3 taken 562509 times.
✓ Branch 4 taken 98760 times.
✓ Branch 5 taken 463749 times.
760440 return (b[0] - eps <= point[0] && point[0] <= b[2] + eps &&
334
6/6
✓ Branch 0 taken 661804 times.
✓ Branch 1 taken 98636 times.
✓ Branch 2 taken 98760 times.
✓ Branch 3 taken 463749 times.
✓ Branch 4 taken 105961 times.
✓ Branch 5 taken 357788 times.
1322949 b[1] - eps <= point[1] && point[1] <= b[3] + eps);
335 }
336
337 /*!
338 * \brief Check whether a point is intersectin a bounding box (dimworld == 1)
339 * \param point The point
340 * \param b Pointer to bounding box coordinates
341 */
342 template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 1, int> = 0>
343 214 inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
344 {
345 static constexpr ctype eps_ = 1.0e-7;
346 214 const ctype eps0 = eps_*(b[1] - b[0]);
347
4/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 24 times.
214 return b[0] - eps0 <= point[0] && point[0] <= b[1] + eps0;
348 }
349
350 /*!
351 * \ingroup Geometry
352 * \brief Determine if a point intersects an axis-aligned bounding box
353 * The bounding box is given by the lower left corner (min) and the upper right corner (max)
354 */
355 template<class ctype, int dimworld>
356 12767952 inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point,
357 const Dune::FieldVector<ctype, dimworld>& min,
358 const Dune::FieldVector<ctype, dimworld>& max)
359 {
360 std::array<ctype, 2*dimworld> bBox;
361 12767952 std::copy(min.begin(), min.end(), bBox.begin());
362 12767952 std::copy(max.begin(), max.end(), bBox.begin()+dimworld);
363 12767952 return intersectsPointBoundingBox(point, bBox.data());
364 }
365
366 /*!
367 * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 3)
368 * \param a Pointer to first bounding box coordinates
369 * \param b Pointer to second bounding box coordinates
370 */
371 template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 3, int> = 0>
372 1449824 inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
373 {
374 using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
375 static constexpr ctype eps_ = 1.0e-7;
376
2/2
✓ Branch 0 taken 650791 times.
✓ Branch 1 taken 799033 times.
1449824 const ctype scale0 = std::max(b[3]-b[0], a[3]-a[0]);
377
2/2
✓ Branch 0 taken 648220 times.
✓ Branch 1 taken 801604 times.
1449824 const ctype scale1 = std::max(b[4]-b[1], a[4]-a[1]);
378
4/4
✓ Branch 0 taken 773678 times.
✓ Branch 1 taken 676146 times.
✓ Branch 2 taken 487138 times.
✓ Branch 3 taken 962686 times.
2223502 const ctype scale2 = std::max(b[5]-b[2], a[5]-a[2]);
379
2/2
✓ Branch 0 taken 679820 times.
✓ Branch 1 taken 770004 times.
1449824 const ctype maxScale = std::max(scale0, std::max(scale1, scale2));
380 1449824 const ctype minEps = maxScale*Detail::minimumBaseEpsilon<ctype>;
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1449824 times.
1449824 const ctype eps0 = std::max(eps_*scale0, minEps);
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1449824 times.
1449824 const ctype eps1 = std::max(eps_*scale1, minEps);
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1449824 times.
1449824 const ctype eps2 = std::max(eps_*scale2, minEps);
384
2/2
✓ Branch 0 taken 1169361 times.
✓ Branch 1 taken 131704 times.
1301065 return (b[0] - eps0 <= a[3] && a[0] <= b[3] + eps0 &&
385
4/4
✓ Branch 0 taken 1107750 times.
✓ Branch 1 taken 61611 times.
✓ Branch 2 taken 1044745 times.
✓ Branch 3 taken 63005 times.
1169361 b[1] - eps1 <= a[4] && a[1] <= b[4] + eps1 &&
386
6/6
✓ Branch 0 taken 1301065 times.
✓ Branch 1 taken 148759 times.
✓ Branch 2 taken 991448 times.
✓ Branch 3 taken 53297 times.
✓ Branch 4 taken 58384 times.
✓ Branch 5 taken 933064 times.
2494569 b[2] - eps2 <= a[5] && a[2] <= b[5] + eps2);
387
388 }
389
390 /*!
391 * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 2)
392 * \param a Pointer to first bounding box coordinates
393 * \param b Pointer to second bounding box coordinates
394 */
395 template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 2, int> = 0>
396 2138999 inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
397 {
398 using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
399 static constexpr ctype eps_ = 1.0e-7;
400
2/2
✓ Branch 0 taken 2111540 times.
✓ Branch 1 taken 27459 times.
2138999 const ctype scale0 = std::max(b[2]-b[0], a[2]-a[0]);
401
4/4
✓ Branch 0 taken 2116509 times.
✓ Branch 1 taken 22490 times.
✓ Branch 2 taken 950618 times.
✓ Branch 3 taken 1188381 times.
4255508 const ctype scale1 = std::max(b[3]-b[1], a[3]-a[1]);
402 2138999 const ctype maxScale = std::max(scale0, scale1);
403 2138999 const ctype minEps = maxScale*Detail::minimumBaseEpsilon<ctype>;
404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2138999 times.
2138999 const ctype eps0 = std::max(eps_*scale0, minEps);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2138999 times.
2138999 const ctype eps1 = std::max(eps_*scale1, minEps);
406
2/2
✓ Branch 0 taken 1692032 times.
✓ Branch 1 taken 203997 times.
1896029 return (b[0] - eps0 <= a[2] && a[0] <= b[2] + eps0 &&
407
6/6
✓ Branch 0 taken 1896029 times.
✓ Branch 1 taken 242970 times.
✓ Branch 2 taken 1472810 times.
✓ Branch 3 taken 219222 times.
✓ Branch 4 taken 202478 times.
✓ Branch 5 taken 1270332 times.
3831031 b[1] - eps1 <= a[3] && a[1] <= b[3] + eps1);
408 }
409
410 /*!
411 * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 1)
412 * \param a Pointer to first bounding box coordinates
413 * \param b Pointer to second bounding box coordinates
414 */
415 template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 1, int> = 0>
416 inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
417 {
418 using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
419 static constexpr ctype eps_ = 1.0e-7;
420 const ctype scale0 = std::max(b[1]-b[0], a[1]-a[0]);
421 const ctype eps0 = std::max(eps_*scale0, Detail::minimumBaseEpsilon<ctype>*scale0);
422 return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0;
423 }
424
425 /*!
426 * \brief Compute squared distance between point and bounding box
427 * \param point The point
428 * \param b Pointer to bounding box coordinates
429 */
430 template<int dimworld, class ctype>
431 11105602 inline ctype squaredDistancePointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
432 {
433 11105602 ctype squaredDistance = 0.0;
434
2/2
✓ Branch 0 taken 308444 times.
✓ Branch 1 taken 154222 times.
44255994 for (int d = 0; d < dimworld; ++d)
435 {
436
2/2
✓ Branch 0 taken 26776 times.
✓ Branch 1 taken 281668 times.
33150392 if (point[d] < b[d])
437 7492563 squaredDistance += (point[d] - b[d])*(point[d] - b[d]);
438
2/2
✓ Branch 0 taken 112124 times.
✓ Branch 1 taken 196320 times.
33150392 if (point[d] > b[d+dimworld])
439 18831684 squaredDistance += (point[d] - b[d+dimworld])*(point[d] - b[d+dimworld]);
440 }
441 11105602 return squaredDistance;
442 }
443
444 } // end namespace Dumux
445
446 #endif
447