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 Algorithms that finds which geometric entities intersect | ||
11 | */ | ||
12 | #ifndef DUMUX_GEOMETRY_INTERSECTING_ENTITIES_HH | ||
13 | #define DUMUX_GEOMETRY_INTERSECTING_ENTITIES_HH | ||
14 | |||
15 | #include <cmath> | ||
16 | #include <type_traits> | ||
17 | #include <vector> | ||
18 | #include <algorithm> | ||
19 | #include <limits> | ||
20 | |||
21 | #include <dune/common/fvector.hh> | ||
22 | |||
23 | #include <dumux/common/math.hh> | ||
24 | #include <dumux/geometry/boundingboxtree.hh> | ||
25 | #include <dumux/geometry/intersectspointgeometry.hh> | ||
26 | #include <dumux/geometry/geometryintersection.hh> | ||
27 | #include <dumux/geometry/triangulation.hh> | ||
28 | |||
29 | namespace Dumux { | ||
30 | |||
31 | /*! | ||
32 | * \ingroup Geometry | ||
33 | * \brief An intersection object resulting from the intersection of two primitives in an entity set | ||
34 | * \note this is used as return type for some of the intersectingEntities overloads below | ||
35 | */ | ||
36 | template<int dimworld, class CoordTypeA, class CoordTypeB = CoordTypeA> | ||
37 |
7/18✗ Branch 0 not taken.
✓ Branch 1 taken 598313 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 877 times.
✓ Branch 4 taken 388341 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 48302 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11388 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 628 times.
✗ Branch 17 not taken.
|
1496619 | class IntersectionInfo |
38 | { | ||
39 | public: | ||
40 | using ctype = typename Dune::PromotionTraits<CoordTypeA, CoordTypeB>::PromotedType; | ||
41 | static constexpr int dimensionworld = dimworld; | ||
42 | using GlobalPosition = Dune::FieldVector<ctype, dimworld>; | ||
43 | |||
44 | template<class Corners> | ||
45 | 448705 | explicit IntersectionInfo(std::size_t a, std::size_t b, Corners&& c) | |
46 | 448705 | : a_(a) | |
47 | 448705 | , b_(b) | |
48 |
6/9✓ Branch 3 taken 2 times.
✓ Branch 4 taken 32 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 1 taken 831 times.
✓ Branch 2 taken 160 times.
✓ Branch 5 taken 52 times.
|
448705 | , corners_(c.begin(), c.end()) |
49 | {} | ||
50 | |||
51 | //! Get the index of the intersecting entity belonging to this grid | ||
52 | 421198 | std::size_t first() const | |
53 |
21/42✓ Branch 1 taken 7464 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1568 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1568 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1568 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1568 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1568 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1568 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 224 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 224 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 224 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 224 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 224 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 224 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 224 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 320 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 320 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 320 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 320 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 320 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 320 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 320 times.
✗ Branch 62 not taken.
|
412750 | { return a_; } |
54 | |||
55 | //! Get the index of the intersecting entity belonging to the other grid | ||
56 | 437667 | std::size_t second() const | |
57 |
3/6✓ Branch 1 taken 1596 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 224 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 320 times.
✗ Branch 8 not taken.
|
437667 | { return b_; } |
58 | |||
59 | //! Get the corners of the intersection geometry | ||
60 | 430828 | const std::vector<GlobalPosition>& corners() const | |
61 |
3/6✓ Branch 1 taken 428112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2398 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 318 times.
✗ Branch 8 not taken.
|
430828 | { return corners_; } |
62 | |||
63 | /*! | ||
64 | * \brief Check if the corners of this intersection match with the given corners | ||
65 | * \note This is useful to check if the intersection geometry of two intersections coincide. | ||
66 | */ | ||
67 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 511537 times.
|
511537 | bool cornersMatch(const std::vector<GlobalPosition>& otherCorners) const |
68 | { | ||
69 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 511537 times.
|
511537 | if (otherCorners.size() != corners_.size()) |
70 | return false; | ||
71 | |||
72 | using std::max; | ||
73 | 511537 | ctype eps2 = std::numeric_limits<ctype>::min(); | |
74 |
2/2✓ Branch 0 taken 1017769 times.
✓ Branch 1 taken 511537 times.
|
1529306 | for (int i = 1; i < corners_.size(); ++i) |
75 |
2/2✓ Branch 0 taken 767879 times.
✓ Branch 1 taken 249890 times.
|
3821186 | eps2 = max(eps2, (corners_[i] - corners_[0]).two_norm2()); |
76 | |||
77 | // We use a base epsilon of 1.5e-7 for comparisons of lengths. | ||
78 | // Since here we compare squared lengths, we multiply by its square. | ||
79 | 511537 | eps2 *= 1.5e-7*1.5e-7; | |
80 | |||
81 |
2/2✓ Branch 0 taken 574164 times.
✓ Branch 1 taken 1261 times.
|
575425 | for (int i = 0; i < corners_.size(); ++i) |
82 | // early return if none of the other corners are equal to this corner | ||
83 |
2/2✓ Branch 0 taken 510276 times.
✓ Branch 1 taken 63888 times.
|
574164 | if (std::none_of(otherCorners.begin(), |
84 | otherCorners.end(), | ||
85 | 3270774 | [&] (const auto& other) { return (corners_[i] - other).two_norm2() < eps2; })) | |
86 | 510276 | return false; | |
87 | |||
88 | 1261 | return true; | |
89 | } | ||
90 | |||
91 | private: | ||
92 | std::size_t a_, b_; //!< Indices of the intersection elements | ||
93 | std::vector<GlobalPosition> corners_; //!< the corner points of the intersection geometry | ||
94 | }; | ||
95 | |||
96 | /*! | ||
97 | * \ingroup Geometry | ||
98 | * \brief Compute all intersections between entities and a point | ||
99 | */ | ||
100 | template<class EntitySet, class ctype, int dimworld> | ||
101 | inline std::vector<std::size_t> | ||
102 | 352010 | intersectingEntities(const Dune::FieldVector<ctype, dimworld>& point, | |
103 | const BoundingBoxTree<EntitySet>& tree, | ||
104 | bool isCartesianGrid = false) | ||
105 | { | ||
106 | // Call the recursive find function to find candidates | ||
107 | 352010 | std::vector<std::size_t> entities; | |
108 |
1/2✓ Branch 1 taken 342416 times.
✗ Branch 2 not taken.
|
352010 | intersectingEntities(point, tree, tree.numBoundingBoxes() - 1, entities, isCartesianGrid); |
109 | 352010 | return entities; | |
110 | ✗ | } | |
111 | |||
112 | /*! | ||
113 | * \ingroup Geometry | ||
114 | * \brief Compute intersections with point for all nodes of the bounding box tree recursively | ||
115 | */ | ||
116 | template<class EntitySet, class ctype, int dimworld> | ||
117 |
2/2✓ Branch 0 taken 6376182 times.
✓ Branch 1 taken 5942174 times.
|
12396746 | void intersectingEntities(const Dune::FieldVector<ctype, dimworld>& point, |
118 | const BoundingBoxTree<EntitySet>& tree, | ||
119 | std::size_t node, | ||
120 | std::vector<std::size_t>& entities, | ||
121 | bool isCartesianGrid = false) | ||
122 | { | ||
123 | // Get the bounding box for the current node | ||
124 |
2/2✓ Branch 0 taken 6376182 times.
✓ Branch 1 taken 5942174 times.
|
12396746 | const auto& bBox = tree.getBoundingBoxNode(node); |
125 | |||
126 | // if the point is not in the bounding box we can stop | ||
127 |
4/4✓ Branch 0 taken 6376182 times.
✓ Branch 1 taken 5942174 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 84 times.
|
12396850 | if (!intersectsPointBoundingBox(point, tree.getBoundingBoxCoordinates(node))) return; |
128 | |||
129 | // now we know it's inside | ||
130 | // if the box is a leaf do the primitive test. | ||
131 |
2/2✓ Branch 0 taken 383391 times.
✓ Branch 1 taken 5992767 times.
|
6413040 | else if (tree.isLeaf(bBox, node)) |
132 | { | ||
133 | 385875 | const std::size_t entityIdx = bBox.child1; | |
134 | // for structured cube grids skip the primitive test | ||
135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 383391 times.
|
385875 | if (isCartesianGrid) |
136 | ✗ | entities.push_back(entityIdx); | |
137 | else | ||
138 | { | ||
139 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
385906 | const auto geometry = tree.entitySet().entity(entityIdx).geometry(); |
140 | // if the primitive is positive it intersects the actual geometry, add the entity to the list | ||
141 |
3/3✓ Branch 1 taken 329114 times.
✓ Branch 2 taken 53133 times.
✓ Branch 0 taken 1144 times.
|
385875 | if (intersectsPointGeometry(point, geometry)) |
142 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
332742 | entities.push_back(entityIdx); |
143 | 11 | } | |
144 | } | ||
145 | |||
146 | // No leaf. Check both children nodes. | ||
147 | else | ||
148 | { | ||
149 | 6027165 | intersectingEntities(point, tree, bBox.child0, entities, isCartesianGrid); | |
150 | 6027165 | intersectingEntities(point, tree, bBox.child1, entities, isCartesianGrid); | |
151 | } | ||
152 | } | ||
153 | |||
154 | /*! | ||
155 | * \ingroup Geometry | ||
156 | * \brief Compute all intersections between a geometry and a bounding box tree | ||
157 | */ | ||
158 | template<class Geometry, class EntitySet> | ||
159 | inline std::vector<IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>> | ||
160 | 51 | intersectingEntities(const Geometry& geometry, | |
161 | const BoundingBoxTree<EntitySet>& tree) | ||
162 | { | ||
163 | using IP = typename IntersectionPolicy::DefaultPolicy<Geometry, typename EntitySet::Entity::Geometry>; | ||
164 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
51 | return intersectingEntities(geometry, tree, IP{}); |
165 | } | ||
166 | |||
167 | /*! | ||
168 | * \ingroup Geometry | ||
169 | * \brief Compute all intersections between a geometry and a bounding box tree | ||
170 | */ | ||
171 | template<class Geometry, class EntitySet, class IntersectionPolicy> | ||
172 | inline std::vector<IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>> | ||
173 | 52 | intersectingEntities(const Geometry& geometry, | |
174 | const BoundingBoxTree<EntitySet>& tree, | ||
175 | IntersectionPolicy intersectionPolicy) | ||
176 | { | ||
177 | // check if the world dimensions match | ||
178 | static_assert(int(Geometry::coorddimension) == int(EntitySet::dimensionworld), | ||
179 | "Can only intersect geometry and bounding box tree of same world dimension"); | ||
180 | |||
181 | // Create data structure for return type | ||
182 | 52 | std::vector<IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>> intersections; | |
183 | using ctype = typename IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>::ctype; | ||
184 | static constexpr int dimworld = Geometry::coorddimension; | ||
185 | |||
186 | // compute the bounding box of the given geometry | ||
187 | std::array<ctype, 2*Geometry::coorddimension> bBox; | ||
188 | 52 | ctype* xMin = bBox.data(); ctype* xMax = xMin + Geometry::coorddimension; | |
189 | |||
190 | // Get coordinates of first vertex | ||
191 | 52 | auto corner = geometry.corner(0); | |
192 |
3/3✓ Branch 0 taken 102 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 2 times.
|
162 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
193 | 110 | xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx]; | |
194 | |||
195 | // Compute the min and max over the remaining vertices | ||
196 |
3/3✓ Branch 1 taken 67 times.
✓ Branch 2 taken 7 times.
✓ Branch 0 taken 116 times.
|
192 | for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx) |
197 | { | ||
198 | 140 | corner = geometry.corner(cornerIdx); | |
199 |
3/3✓ Branch 0 taken 258 times.
✓ Branch 1 taken 167 times.
✓ Branch 2 taken 14 times.
|
442 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
200 | { | ||
201 | using std::max; | ||
202 | using std::min; | ||
203 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 204 times.
|
302 | xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]); |
204 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 204 times.
|
400 | xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]); |
205 | } | ||
206 | } | ||
207 | |||
208 | // Call the recursive find function to find candidates | ||
209 | 52 | intersectingEntities(geometry, tree, | |
210 |
1/2✓ Branch 1 taken 51 times.
✗ Branch 2 not taken.
|
52 | bBox, tree.numBoundingBoxes() - 1, |
211 | intersections, intersectionPolicy); | ||
212 | |||
213 | 52 | return intersections; | |
214 | ✗ | } | |
215 | |||
216 | /*! | ||
217 | * \ingroup Geometry | ||
218 | * \brief Compute intersections with point for all nodes of the bounding box tree recursively | ||
219 | */ | ||
220 | template<class Geometry, class EntitySet> | ||
221 | 21552 | void intersectingEntities(const Geometry& geometry, | |
222 | const BoundingBoxTree<EntitySet>& tree, | ||
223 | const std::array<typename Geometry::ctype, 2*Geometry::coorddimension>& bBox, | ||
224 | std::size_t nodeIdx, | ||
225 | std::vector<IntersectionInfo<Geometry::coorddimension, | ||
226 | typename Geometry::ctype, | ||
227 | typename EntitySet::ctype>>& intersections) | ||
228 | { | ||
229 | using IP = typename IntersectionPolicy::DefaultPolicy<Geometry, typename EntitySet::Entity::Geometry>; | ||
230 | 21552 | intersectingEntities(geometry, tree, bBox, nodeIdx, intersections, IP{}); | |
231 | 21552 | } | |
232 | /*! | ||
233 | * \ingroup Geometry | ||
234 | * \brief Compute intersections with point for all nodes of the bounding box tree recursively | ||
235 | */ | ||
236 | template<class Geometry, class EntitySet, class IntersectionPolicy> | ||
237 |
2/2✓ Branch 0 taken 17219 times.
✓ Branch 1 taken 4382 times.
|
21604 | void intersectingEntities(const Geometry& geometry, |
238 | const BoundingBoxTree<EntitySet>& tree, | ||
239 | const std::array<typename Geometry::ctype, 2*Geometry::coorddimension>& bBox, | ||
240 | std::size_t nodeIdx, | ||
241 | std::vector<IntersectionInfo<Geometry::coorddimension, | ||
242 | typename Geometry::ctype, | ||
243 | typename EntitySet::ctype>>& intersections, | ||
244 | IntersectionPolicy intersectionPolicy) | ||
245 | { | ||
246 | // if the two bounding boxes don't intersect we can stop searching | ||
247 | static constexpr int dimworld = Geometry::coorddimension; | ||
248 |
2/2✓ Branch 0 taken 17219 times.
✓ Branch 1 taken 4382 times.
|
21604 | if (!intersectsBoundingBoxBoundingBox<dimworld>(bBox.data(), tree.getBoundingBoxCoordinates(nodeIdx))) |
249 | return; | ||
250 | |||
251 | // get node info for current bounding box node | ||
252 |
2/2✓ Branch 0 taken 6444 times.
✓ Branch 1 taken 10775 times.
|
17222 | const auto& bBoxNode = tree.getBoundingBoxNode(nodeIdx); |
253 | |||
254 | // if the box is a leaf do the primitive test. | ||
255 |
2/2✓ Branch 0 taken 6444 times.
✓ Branch 1 taken 10775 times.
|
17222 | if (tree.isLeaf(bBoxNode, nodeIdx)) |
256 | { | ||
257 | // eIdxA is always 0 since we intersect with exactly one geometry | ||
258 | 6446 | const auto eIdxA = 0; | |
259 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
6446 | const auto eIdxB = bBoxNode.child1; |
260 | |||
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
6446 | const auto geometryTree = tree.entitySet().entity(eIdxB).geometry(); |
262 | using GeometryTree = std::decay_t<decltype(geometryTree)>; | ||
263 | using IntersectionAlgorithm = GeometryIntersection<Geometry, GeometryTree, IntersectionPolicy>; | ||
264 | using Intersection = typename IntersectionAlgorithm::Intersection; | ||
265 |
1/2✓ Branch 1 taken 4356 times.
✗ Branch 2 not taken.
|
6446 | Intersection intersection; |
266 | |||
267 |
4/5✓ Branch 1 taken 4172 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2018 times.
✓ Branch 4 taken 24 times.
✓ Branch 0 taken 2272 times.
|
6446 | if (IntersectionAlgorithm::intersection(geometry, geometryTree, intersection)) |
268 | { | ||
269 | static constexpr int dimIntersection = IntersectionPolicy::dimIntersection; | ||
270 | if constexpr (dimIntersection >= 2) | ||
271 | { | ||
272 |
1/2✓ Branch 1 taken 4262 times.
✗ Branch 2 not taken.
|
4262 | const auto triangulation = triangulate<dimIntersection, dimworld>(intersection); |
273 |
2/2✓ Branch 0 taken 54372 times.
✓ Branch 1 taken 4262 times.
|
58634 | for (unsigned int i = 0; i < triangulation.size(); ++i) |
274 |
1/2✓ Branch 1 taken 54372 times.
✗ Branch 2 not taken.
|
54372 | intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i])); |
275 | 4262 | } | |
276 | else | ||
277 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
32 | intersections.emplace_back(eIdxA, eIdxB, intersection); |
278 | } | ||
279 | 6398 | } | |
280 | |||
281 | // No leaf. Check both children nodes. | ||
282 | else | ||
283 | { | ||
284 | 10776 | intersectingEntities(geometry, tree, bBox, bBoxNode.child0, intersections); | |
285 | 10776 | intersectingEntities(geometry, tree, bBox, bBoxNode.child1, intersections); | |
286 | } | ||
287 | } | ||
288 | |||
289 | /*! | ||
290 | * \ingroup Geometry | ||
291 | * \brief Compute all intersections between two bounding box trees | ||
292 | */ | ||
293 | template<class EntitySet0, class EntitySet1> | ||
294 | inline std::vector<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>> | ||
295 | 148 | intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA, | |
296 | const BoundingBoxTree<EntitySet1>& treeB) | ||
297 | { | ||
298 | using IP = typename IntersectionPolicy::DefaultPolicy<typename EntitySet0::Entity::Geometry, typename EntitySet1::Entity::Geometry>; | ||
299 |
2/4✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
148 | return intersectingEntities(treeA, treeB, IP{}); |
300 | } | ||
301 | |||
302 | /*! | ||
303 | * \ingroup Geometry | ||
304 | * \brief Compute all intersections between two bounding box trees | ||
305 | */ | ||
306 | template<class EntitySet0, class EntitySet1, class IntersectionPolicy> | ||
307 | inline std::vector<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>> | ||
308 | 226 | intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA, | |
309 | const BoundingBoxTree<EntitySet1>& treeB, | ||
310 | IntersectionPolicy intersectionPolicy) | ||
311 | { | ||
312 | // check if the world dimensions match | ||
313 | static_assert(int(EntitySet0::dimensionworld) == int(EntitySet1::dimensionworld), | ||
314 | "Can only intersect bounding box trees of same world dimension"); | ||
315 | |||
316 | // Create data structure for return type | ||
317 |
1/2✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
|
226 | std::vector<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>> intersections; |
318 | |||
319 | // Call the recursive find function to find candidates | ||
320 | 226 | intersectingEntities(treeA, treeB, | |
321 | 226 | treeA.numBoundingBoxes() - 1, | |
322 |
1/2✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
|
226 | treeB.numBoundingBoxes() - 1, |
323 | intersections, intersectionPolicy); | ||
324 | |||
325 | 226 | return intersections; | |
326 | ✗ | } | |
327 | |||
328 | /*! | ||
329 | * \ingroup Geometry | ||
330 | * \brief Compute all intersections between two all bounding box tree nodes recursively | ||
331 | */ | ||
332 | template<class EntitySet0, class EntitySet1> | ||
333 | 4385532 | void intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA, | |
334 | const BoundingBoxTree<EntitySet1>& treeB, | ||
335 | std::size_t nodeA, std::size_t nodeB, | ||
336 | std::vector<IntersectionInfo<EntitySet0::dimensionworld, | ||
337 | typename EntitySet0::ctype, | ||
338 | typename EntitySet1::ctype>>& intersections) | ||
339 | { | ||
340 | using IP = typename IntersectionPolicy::DefaultPolicy<typename EntitySet0::Entity::Geometry, typename EntitySet1::Entity::Geometry>; | ||
341 | 4385532 | intersectingEntities(treeA, treeB, nodeA, nodeB, intersections, IP{}); | |
342 | 4385532 | } | |
343 | |||
344 | /*! | ||
345 | * \ingroup Geometry | ||
346 | * \brief Compute all intersections between two all bounding box tree nodes recursively | ||
347 | */ | ||
348 | template<class EntitySet0, class EntitySet1, class IntersectionPolicy> | ||
349 |
2/2✓ Branch 0 taken 1605012 times.
✓ Branch 1 taken 1143674 times.
|
3567222 | void intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA, |
350 | const BoundingBoxTree<EntitySet1>& treeB, | ||
351 | std::size_t nodeA, std::size_t nodeB, | ||
352 | std::vector<IntersectionInfo<EntitySet0::dimensionworld, | ||
353 | typename EntitySet0::ctype, | ||
354 | typename EntitySet1::ctype>>& intersections, | ||
355 | IntersectionPolicy intersectionPolicy) | ||
356 | { | ||
357 | // Get the bounding box for the current node | ||
358 | 3567222 | const auto& bBoxA = treeA.getBoundingBoxNode(nodeA); | |
359 |
2/2✓ Branch 0 taken 1605012 times.
✓ Branch 1 taken 1143674 times.
|
3567222 | const auto& bBoxB = treeB.getBoundingBoxNode(nodeB); |
360 | |||
361 | // if the two bounding boxes of the current nodes don't intersect we can stop searching | ||
362 | static constexpr int dimworld = EntitySet0::dimensionworld; | ||
363 |
2/2✓ Branch 0 taken 1605012 times.
✓ Branch 1 taken 1143674 times.
|
3567222 | if (!intersectsBoundingBoxBoundingBox<dimworld>(treeA.getBoundingBoxCoordinates(nodeA), |
364 | treeB.getBoundingBoxCoordinates(nodeB))) | ||
365 | return; | ||
366 | |||
367 | // Check if we have a leaf in treeA or treeB | ||
368 | 2186177 | const bool isLeafA = treeA.isLeaf(bBoxA, nodeA); | |
369 | 2186177 | const bool isLeafB = treeB.isLeaf(bBoxB, nodeB); | |
370 | |||
371 | // If both boxes are leaves do the primitive test | ||
372 |
2/2✓ Branch 0 taken 230704 times.
✓ Branch 1 taken 1374308 times.
|
2186177 | if (isLeafA && isLeafB) |
373 | { | ||
374 | 402640 | const auto eIdxA = bBoxA.child1; | |
375 | 402640 | const auto eIdxB = bBoxB.child1; | |
376 | |||
377 | 409971 | const auto geometryA = treeA.entitySet().entity(eIdxA).geometry(); | |
378 | 402640 | const auto geometryB = treeB.entitySet().entity(eIdxB).geometry(); | |
379 | |||
380 | using GeometryA = std::decay_t<decltype(geometryA)>; | ||
381 | using GeometryB = std::decay_t<decltype(geometryB)>; | ||
382 | using IntersectionAlgorithm = GeometryIntersection<GeometryA, GeometryB, IntersectionPolicy>; | ||
383 | using Intersection = typename IntersectionAlgorithm::Intersection; | ||
384 | |||
385 |
4/4✓ Branch 1 taken 227696 times.
✓ Branch 2 taken 3008 times.
✓ Branch 3 taken 88810 times.
✓ Branch 4 taken 127507 times.
|
635696 | if (Intersection intersection; IntersectionAlgorithm::intersection(geometryA, geometryB, intersection)) |
386 | { | ||
387 | static constexpr int dimIntersection = IntersectionPolicy::dimIntersection; | ||
388 | |||
389 | // intersection is returned as a point cloud for dim >= 2 | ||
390 | // so we have to triangulate first | ||
391 | if constexpr (dimIntersection >= 2) | ||
392 | { | ||
393 |
1/2✓ Branch 1 taken 88810 times.
✗ Branch 2 not taken.
|
91252 | const auto triangulation = triangulate<dimIntersection, dimworld>(intersection); |
394 |
2/2✓ Branch 0 taken 347826 times.
✓ Branch 1 taken 88810 times.
|
469009 | for (unsigned int i = 0; i < triangulation.size(); ++i) |
395 |
1/2✓ Branch 1 taken 347826 times.
✗ Branch 2 not taken.
|
377757 | intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i])); |
396 | 91252 | } | |
397 | else | ||
398 | 16546 | intersections.emplace_back(eIdxA, eIdxB, intersection); | |
399 | } | ||
400 | 156631 | } | |
401 | |||
402 | // if we reached the leaf in treeA, just continue in treeB | ||
403 |
2/2✓ Branch 0 taken 279772 times.
✓ Branch 1 taken 1094536 times.
|
1783537 | else if (isLeafA) |
404 | { | ||
405 | 347339 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections); | |
406 | 347339 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child1, intersections); | |
407 | } | ||
408 | |||
409 | // if we reached the leaf in treeB, just continue in treeA | ||
410 |
2/2✓ Branch 0 taken 982485 times.
✓ Branch 1 taken 112051 times.
|
1436198 | else if (isLeafB) |
411 | { | ||
412 | 1160764 | intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections); | |
413 | 1160764 | intersectingEntities(treeA, treeB, bBoxA.child1, nodeB, intersections); | |
414 | } | ||
415 | |||
416 | // we know now that both trees didn't reach the leaf yet so | ||
417 | // we continue with the larger tree first (bigger node number) | ||
418 |
2/2✓ Branch 0 taken 32441 times.
✓ Branch 1 taken 79610 times.
|
275434 | else if (nodeA > nodeB) |
419 | { | ||
420 | 44708 | intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections); | |
421 | 44708 | intersectingEntities(treeA, treeB, bBoxA.child1, nodeB, intersections); | |
422 | } | ||
423 | else | ||
424 | { | ||
425 | 230726 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections); | |
426 | 230726 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child1, intersections); | |
427 | } | ||
428 | } | ||
429 | |||
430 | /*! | ||
431 | * \ingroup Geometry | ||
432 | * \brief Compute the index of the intersecting element of a Cartesian grid with a point | ||
433 | * The grid is given by the lower left corner (min), the upper right corner (max) | ||
434 | * and the number of cells in each direction (cells). | ||
435 | * \note If there are several options the lowest matching cell index will be returned | ||
436 | * \note Returns the index i + I*j + I*J*k for the intersecting element i,j,k of a grid with I,J,K cells | ||
437 | */ | ||
438 | template<class ctype, int dimworld> | ||
439 | 13253168 | inline std::size_t intersectingEntityCartesianGrid(const Dune::FieldVector<ctype, dimworld>& point, | |
440 | const Dune::FieldVector<ctype, dimworld>& min, | ||
441 | const Dune::FieldVector<ctype, dimworld>& max, | ||
442 | const std::array<int, std::size_t(dimworld)>& cells) | ||
443 | { | ||
444 | 13253168 | std::size_t index = 0; | |
445 |
2/2✓ Branch 0 taken 39189674 times.
✓ Branch 1 taken 13225238 times.
|
52525672 | for (int i = 0; i < dimworld; ++i) |
446 | { | ||
447 | using std::clamp; using std::floor; | ||
448 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39189674 times.
|
39272504 | ctype dimOffset = clamp<ctype>(floor((point[i]-min[i])*cells[i]/(max[i]-min[i])), 0.0, cells[i]-1); |
449 |
2/2✓ Branch 0 taken 38703634 times.
✓ Branch 1 taken 39189674 times.
|
78058038 | for (int j = 0; j < i; ++j) |
450 | 38785534 | dimOffset *= cells[j]; | |
451 | 39272504 | index += static_cast<std::size_t>(dimOffset); | |
452 | } | ||
453 | 13253168 | return index; | |
454 | } | ||
455 | |||
456 | } // end namespace Dumux | ||
457 | |||
458 | #endif | ||
459 |