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-FileCopyrightInfo: 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/20✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 511035 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1535 times.
✓ Branch 10 taken 386514 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 16380 times.
✓ Branch 14 taken 1746 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 11388 times.
✗ Branch 19 not taken.
|
2386305 | 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 | 399648 | explicit IntersectionInfo(std::size_t a, std::size_t b, Corners&& c) | |
46 | : a_(a) | ||
47 | , b_(b) | ||
48 |
26/56✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 686 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 686 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 686 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 686 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 215 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 215 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 215 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 215 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 100 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 100 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 138 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 138 times.
✓ Branch 47 taken 13 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 38 times.
✓ Branch 50 taken 13 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 38 times.
✓ Branch 53 taken 13 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 84 times.
✓ Branch 56 taken 13 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 84 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 84 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 84 times.
✗ Branch 65 not taken.
✓ Branch 73 taken 52 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 52 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 52 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 52 times.
✗ Branch 83 not taken.
|
1598592 | , corners_(c.begin(), c.end()) |
49 | {} | ||
50 | |||
51 | //! Get the index of the intersecting entity belonging to this grid | ||
52 | ✗ | std::size_t first() const | |
53 | ✗ | { return a_; } | |
54 | |||
55 | //! Get the index of the intersecting entity belonging to the other grid | ||
56 | ✗ | std::size_t second() const | |
57 | ✗ | { return b_; } | |
58 | |||
59 | //! Get the corners of the intersection geometry | ||
60 | const std::vector<GlobalPosition>& corners() const | ||
61 |
2/4✓ Branch 1 taken 381299 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2406 times.
✗ Branch 5 not taken.
|
383705 | { 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 | 511368 | bool cornersMatch(const std::vector<GlobalPosition>& otherCorners) const | |
68 | { | ||
69 |
3/6✓ Branch 0 taken 511368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 511368 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 511368 times.
✗ Branch 5 not taken.
|
1534104 | if (otherCorners.size() != corners_.size()) |
70 | return false; | ||
71 | |||
72 | using std::max; | ||
73 | 511368 | ctype eps2 = std::numeric_limits<ctype>::min(); | |
74 |
2/2✓ Branch 0 taken 1017600 times.
✓ Branch 1 taken 511368 times.
|
1528968 | for (int i = 1; i < corners_.size(); ++i) |
75 |
2/2✓ Branch 0 taken 767710 times.
✓ Branch 1 taken 249890 times.
|
3820550 | 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 | 511368 | eps2 *= 1.5e-7*1.5e-7; | |
80 | |||
81 |
4/4✓ Branch 0 taken 573933 times.
✓ Branch 1 taken 1261 times.
✓ Branch 2 taken 573933 times.
✓ Branch 3 taken 1261 times.
|
575194 | 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 3 taken 510107 times.
✓ Branch 4 taken 63826 times.
|
1721799 | if (std::none_of(otherCorners.begin(), |
84 | otherCorners.end(), | ||
85 | 3269988 | [&] (const auto& other) { return (corners_[i] - other).two_norm2() < eps2; })) | |
86 | 510107 | 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 | 351661 | 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 |
1/2✓ Branch 1 taken 342229 times.
✗ Branch 2 not taken.
|
351661 | std::vector<std::size_t> entities; |
108 |
2/4✓ Branch 1 taken 342229 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 342229 times.
✗ Branch 5 not taken.
|
703322 | intersectingEntities(point, tree, tree.numBoundingBoxes() - 1, entities, isCartesianGrid); |
109 | 351661 | 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 | 12394991 | 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 6375744 times.
✓ Branch 1 taken 5941783 times.
|
12394991 | 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 6375744 times.
✓ Branch 1 taken 5941783 times.
✓ Branch 2 taken 6375744 times.
✓ Branch 3 taken 5941783 times.
|
24789982 | 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 383355 times.
✓ Branch 1 taken 5992365 times.
|
6412180 | else if (tree.isLeaf(bBox, node)) |
132 | { | ||
133 | 385799 | 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 383355 times.
|
385799 | if (isCartesianGrid) |
136 | ✗ | entities.push_back(entityIdx); | |
137 | else | ||
138 | { | ||
139 |
1/2✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
|
771609 | 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/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 330202 times.
✓ Branch 2 taken 53153 times.
✗ Branch 3 not taken.
|
385819 | if (intersectsPointGeometry(point, geometry)) |
142 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
332666 | entities.push_back(entityIdx); |
143 | } | ||
144 | } | ||
145 | |||
146 | // No leaf. Check both children nodes. | ||
147 | else | ||
148 | { | ||
149 | 6026381 | intersectingEntities(point, tree, bBox.child0, entities, isCartesianGrid); | |
150 | 6026381 | 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 | 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 4 times.
✗ Branch 2 not taken.
|
8 | 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 | 8 | 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 | 8 | 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 | 8 | ctype* xMin = bBox.data(); ctype* xMax = xMin + Geometry::coorddimension; | |
189 | |||
190 | // Get coordinates of first vertex | ||
191 | 8 | auto corner = geometry.corner(0); | |
192 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 16 times.
|
28 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
193 | 40 | xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx]; | |
194 | |||
195 | // Compute the min and max over the remaining vertices | ||
196 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
|
24 | for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx) |
197 | { | ||
198 | 12 | corner = geometry.corner(cornerIdx); | |
199 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 16 times.
|
44 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
200 | { | ||
201 | using std::max; | ||
202 | using std::min; | ||
203 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]); |
204 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 20 times.
|
76 | xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]); |
205 | } | ||
206 | } | ||
207 | |||
208 | // Call the recursive find function to find candidates | ||
209 | 8 | intersectingEntities(geometry, tree, | |
210 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | bBox, tree.numBoundingBoxes() - 1, |
211 | intersections, intersectionPolicy); | ||
212 | |||
213 | 8 | 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 | 16668 | 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 | 16668 | intersectingEntities(geometry, tree, bBox, nodeIdx, intersections, IP{}); | |
231 | 16668 | } | |
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 | 16676 | 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 |
6/6✓ Branch 0 taken 12712 times.
✓ Branch 1 taken 3964 times.
✓ Branch 2 taken 12712 times.
✓ Branch 3 taken 3964 times.
✓ Branch 4 taken 12712 times.
✓ Branch 5 taken 3964 times.
|
50028 | 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 4378 times.
✓ Branch 1 taken 8334 times.
|
12712 | const auto& bBoxNode = tree.getBoundingBoxNode(nodeIdx); |
253 | |||
254 | // if the box is a leaf do the primitive test. | ||
255 |
2/2✓ Branch 0 taken 4378 times.
✓ Branch 1 taken 8334 times.
|
12712 | if (tree.isLeaf(bBoxNode, nodeIdx)) |
256 | { | ||
257 | // eIdxA is always 0 since we intersect with exactly one geometry | ||
258 | 4378 | const auto eIdxA = 0; | |
259 | 4378 | const auto eIdxB = bBoxNode.child1; | |
260 | |||
261 | 8756 | 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 |
3/6✓ Branch 1 taken 4356 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2244 times.
✓ Branch 4 taken 2112 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
10978 | Intersection intersection; |
266 | |||
267 |
4/4✓ Branch 1 taken 4370 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2244 times.
✓ Branch 4 taken 2112 times.
|
4378 | if (IntersectionAlgorithm::intersection(geometry, geometryTree, intersection)) |
268 | { | ||
269 | static constexpr int dimIntersection = IntersectionPolicy::dimIntersection; | ||
270 | if constexpr (dimIntersection >= 2) | ||
271 | { | ||
272 |
2/6✓ Branch 1 taken 2244 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2244 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6732 | const auto triangulation = triangulate<dimIntersection, dimworld>(intersection); |
273 |
4/4✓ Branch 0 taken 8580 times.
✓ Branch 1 taken 2244 times.
✓ Branch 2 taken 8580 times.
✓ Branch 3 taken 2244 times.
|
13068 | for (unsigned int i = 0; i < triangulation.size(); ++i) |
274 |
2/4✓ Branch 1 taken 8580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8580 times.
✗ Branch 5 not taken.
|
17160 | intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i])); |
275 | } | ||
276 | else | ||
277 | 14 | intersections.emplace_back(eIdxA, eIdxB, intersection); | |
278 | } | ||
279 | } | ||
280 | |||
281 | // No leaf. Check both children nodes. | ||
282 | else | ||
283 | { | ||
284 | 8334 | intersectingEntities(geometry, tree, bBox, bBoxNode.child0, intersections); | |
285 | 8334 | 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 | 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 27 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
143 | 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 | ✗ | 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 | ✗ | std::vector<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>> intersections; | |
318 | |||
319 | // Call the recursive find function to find candidates | ||
320 | ✗ | intersectingEntities(treeA, treeB, | |
321 | ✗ | treeA.numBoundingBoxes() - 1, | |
322 | ✗ | treeB.numBoundingBoxes() - 1, | |
323 | intersections, intersectionPolicy); | ||
324 | |||
325 | ✗ | 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 | 4354764 | 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 | 4354764 | intersectingEntities(treeA, treeB, nodeA, nodeB, intersections, IP{}); | |
342 | 4354764 | } | |
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 | 3536449 | 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 |
2/2✓ Branch 0 taken 1587802 times.
✓ Branch 1 taken 1130111 times.
|
3536449 | const auto& bBoxA = treeA.getBoundingBoxNode(nodeA); |
359 |
2/2✓ Branch 0 taken 1587802 times.
✓ Branch 1 taken 1130111 times.
|
3536449 | 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 |
6/6✓ Branch 0 taken 1587802 times.
✓ Branch 1 taken 1130111 times.
✓ Branch 2 taken 1587802 times.
✓ Branch 3 taken 1130111 times.
✓ Branch 4 taken 1587802 times.
✓ Branch 5 taken 1130111 times.
|
10609347 | 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 |
2/2✓ Branch 0 taken 228878 times.
✓ Branch 1 taken 1358924 times.
|
2168967 | const bool isLeafA = treeA.isLeaf(bBoxA, nodeA); |
369 |
2/2✓ Branch 0 taken 228878 times.
✓ Branch 1 taken 1358924 times.
|
2168967 | const bool isLeafB = treeB.isLeaf(bBoxB, nodeB); |
370 | |||
371 | // If both boxes are leaves do the primitive test | ||
372 |
2/2✓ Branch 0 taken 228878 times.
✓ Branch 1 taken 1358924 times.
|
2168967 | if (isLeafA && isLeafB) |
373 | { | ||
374 | 400814 | const auto eIdxA = bBoxA.child1; | |
375 | 400814 | const auto eIdxB = bBoxB.child1; | |
376 | |||
377 | 1106009 | const auto geometryA = treeA.entitySet().entity(eIdxA).geometry(); | |
378 | 809346 | 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 |
7/10✓ Branch 1 taken 225887 times.
✓ Branch 2 taken 2991 times.
✓ Branch 4 taken 215837 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 88330 times.
✓ Branch 7 taken 127507 times.
✓ Branch 8 taken 88330 times.
✓ Branch 9 taken 127507 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
814934 | 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 |
2/6✓ Branch 1 taken 88330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 88330 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
272316 | const auto triangulation = triangulate<dimIntersection, dimworld>(intersection); |
394 |
4/4✓ Branch 0 taken 345906 times.
✓ Branch 1 taken 88330 times.
✓ Branch 2 taken 345906 times.
✓ Branch 3 taken 88330 times.
|
557381 | for (unsigned int i = 0; i < triangulation.size(); ++i) |
395 |
2/4✓ Branch 1 taken 345906 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 345906 times.
✗ Branch 5 not taken.
|
751674 | intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i])); |
396 | } | ||
397 | else | ||
398 | 15217 | intersections.emplace_back(eIdxA, eIdxB, intersection); | |
399 | } | ||
400 | } | ||
401 | |||
402 | // if we reached the leaf in treeA, just continue in treeB | ||
403 |
2/2✓ Branch 0 taken 268210 times.
✓ Branch 1 taken 1090714 times.
|
1768153 | else if (isLeafA) |
404 | { | ||
405 | 335777 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections); | |
406 | 335777 | 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 981753 times.
✓ Branch 1 taken 108961 times.
|
1432376 | else if (isLeafB) |
411 | { | ||
412 | 1160032 | intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections); | |
413 | 1160032 | 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 29352 times.
✓ Branch 1 taken 79609 times.
|
272344 | else if (nodeA > nodeB) |
419 | { | ||
420 | 41619 | intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections); | |
421 | 41619 | intersectingEntities(treeA, treeB, bBoxA.child1, nodeB, intersections); | |
422 | } | ||
423 | else | ||
424 | { | ||
425 | 230725 | intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections); | |
426 | 230725 | 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 | 12356879 | 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 | 12356879 | std::size_t index = 0; | |
445 |
2/2✓ Branch 0 taken 36986847 times.
✓ Branch 1 taken 12328949 times.
|
49426556 | for (int i = 0; i < dimworld; ++i) |
446 | { | ||
447 | using std::clamp; using std::floor; | ||
448 |
7/14✓ Branch 0 taken 36986847 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36986847 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36986847 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36986847 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36986847 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 36986847 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 36986847 times.
✗ Branch 13 not taken.
|
259487619 | 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 36986847 times.
✓ Branch 1 taken 36986847 times.
|
74138424 | for (int j = 0; j < i; ++j) |
450 | 74137494 | dimOffset *= cells[j]; | |
451 | 37069677 | index += static_cast<std::size_t>(dimOffset); | |
452 | } | ||
453 | 12356879 | return index; | |
454 | } | ||
455 | |||
456 | } // end namespace Dumux | ||
457 | |||
458 | #endif | ||
459 |