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 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 <type_traits> | ||
28 | #include <iostream> | ||
29 | |||
30 | #include <dune/common/promotiontraits.hh> | ||
31 | #include <dune/common/timer.hh> | ||
32 | #include <dune/common/fvector.hh> | ||
33 | |||
34 | namespace Dumux { | ||
35 | |||
36 | /*! | ||
37 | * \ingroup Geometry | ||
38 | * \brief An axis-aligned bounding box volume tree implementation | ||
39 | * | ||
40 | * The class constructs a hierarchical structure of bounding box volumes around | ||
41 | * grid entities. This class can be used to efficiently compute intersections | ||
42 | * between a grid and other geometrical object. It only implements the intersection | ||
43 | * of two of such bounding box trees, so that two independent grids can be intersected. | ||
44 | * \tparam GeometricEntitySet has the following requirements | ||
45 | * * export dimensionworld, ctype | ||
46 | * * a size() member function returning the number of entities | ||
47 | * * begin() and end() member function returning at least forward iterators to entities | ||
48 | * * an index() method returning a consecutive index given an entity | ||
49 | * * an entity() method returning an entity given the consecutive index | ||
50 | * * entities have the following requirements: | ||
51 | * * a member function geometry() returning a geometry with the member functions | ||
52 | * * corner() and corners() returning global coordinates and number of corners | ||
53 | */ | ||
54 | template <class GeometricEntitySet> | ||
55 | class BoundingBoxTree | ||
56 | { | ||
57 | enum { dimworld = GeometricEntitySet::dimensionworld }; | ||
58 | using ctype = typename GeometricEntitySet::ctype; | ||
59 | |||
60 | /*! | ||
61 | * \brief Bounding box node data structure | ||
62 | * leaf nodes are indicated by setting child0 to | ||
63 | * the node itself and child1 to the index of the entity in the bounding box. | ||
64 | */ | ||
65 | struct BoundingBoxNode | ||
66 | { | ||
67 | std::size_t child0; | ||
68 | std::size_t child1; | ||
69 | }; | ||
70 | |||
71 | public: | ||
72 | //! the type of entity set this tree was built with | ||
73 | using EntitySet = GeometricEntitySet; | ||
74 | |||
75 | //! Default Constructor | ||
76 |
8/16✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
|
72 | BoundingBoxTree() = default; |
77 | |||
78 | //! Constructor with gridView | ||
79 | 4517 | BoundingBoxTree(std::shared_ptr<const GeometricEntitySet> set) | |
80 |
2/12✓ Branch 5 taken 2508 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2508 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
22585 | { build(set); } |
81 | |||
82 | //! Build up bounding box tree for a grid with leafGridView | ||
83 | 4589 | void build(std::shared_ptr<const GeometricEntitySet> set) | |
84 | { | ||
85 | // set the pointer to the entity set | ||
86 | 4589 | entitySet_ = set; | |
87 | |||
88 | // clear all internal data | ||
89 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2542 times.
|
4589 | boundingBoxNodes_.clear(); |
90 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2542 times.
|
4589 | boundingBoxCoordinates_.clear(); |
91 | |||
92 | // start the timer | ||
93 | 4589 | Dune::Timer timer; | |
94 | |||
95 | // Create bounding boxes for all elements | ||
96 | 9178 | const auto numLeaves = set->size(); | |
97 | |||
98 | // reserve enough space for the nodes and the coordinates | ||
99 | 4589 | const auto numNodes = 2*numLeaves - 1; | |
100 | 4589 | boundingBoxNodes_.reserve(numNodes); | |
101 | 4589 | boundingBoxCoordinates_.reserve(numNodes*2*dimworld); | |
102 | |||
103 | // create a vector for leaf boxes (min and max for all dims) | ||
104 | 9178 | std::vector<ctype> leafBoxes(2*dimworld*numLeaves); | |
105 | |||
106 |
16/18✓ Branch 0 taken 56039 times.
✓ Branch 1 taken 2381 times.
✓ Branch 2 taken 56039 times.
✓ Branch 3 taken 124184 times.
✓ Branch 4 taken 877 times.
✓ Branch 5 taken 122515 times.
✓ Branch 6 taken 165 times.
✓ Branch 7 taken 721 times.
✓ Branch 8 taken 3751 times.
✓ Branch 9 taken 3155947 times.
✓ Branch 10 taken 220 times.
✓ Branch 11 taken 648659 times.
✓ Branch 12 taken 220 times.
✓ Branch 13 taken 11160 times.
✓ Branch 14 taken 648659 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 648659 times.
✗ Branch 18 not taken.
|
9689156 | for (const auto& geometricEntity : *set) |
107 |
4/8✓ Branch 1 taken 665748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 743894 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 665748 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 654588 times.
✗ Branch 11 not taken.
|
16102447 | computeEntityBoundingBox_(leafBoxes.data() + 2*dimworld*set->index(geometricEntity), geometricEntity); |
108 | |||
109 | // create the leaf partition, the set of available indices (to be sorted) | ||
110 |
3/8✓ Branch 1 taken 2546 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2546 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2546 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
13767 | std::vector<std::size_t> leafPartition(numLeaves); |
111 | 13767 | std::iota(leafPartition.begin(), leafPartition.end(), 0); | |
112 | |||
113 | // Recursively build the bounding box tree | ||
114 |
3/8✓ Branch 1 taken 2546 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2546 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2546 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
13767 | build_(leafBoxes, leafPartition.begin(), leafPartition.end()); |
115 | |||
116 | // We are done, log output | ||
117 |
1/2✓ Branch 2 taken 2546 times.
✗ Branch 3 not taken.
|
9178 | std::cout << "Computed bounding box tree with " << numBoundingBoxes() |
118 |
1/2✓ Branch 2 taken 2546 times.
✗ Branch 3 not taken.
|
9178 | << " nodes for " << numLeaves << " grid entities in " |
119 |
3/6✓ Branch 2 taken 2546 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2546 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2546 times.
✗ Branch 9 not taken.
|
9178 | << timer.stop() << " seconds." << std::endl; |
120 | 4589 | } | |
121 | |||
122 | //! the entity set this tree was built with | ||
123 | const EntitySet& entitySet() const | ||
124 |
30/43✓ Branch 1 taken 16404 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 453 times.
✓ Branch 4 taken 16404 times.
✓ Branch 5 taken 314256 times.
✓ Branch 6 taken 453 times.
✓ Branch 7 taken 11396 times.
✓ Branch 8 taken 314256 times.
✓ Branch 9 taken 24502 times.
✓ Branch 10 taken 11396 times.
✓ Branch 11 taken 316422 times.
✓ Branch 12 taken 24502 times.
✓ Branch 13 taken 11408 times.
✓ Branch 14 taken 316422 times.
✓ Branch 15 taken 4640 times.
✓ Branch 16 taken 11408 times.
✓ Branch 17 taken 314662 times.
✓ Branch 18 taken 4640 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 314662 times.
✓ Branch 21 taken 1968 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 779344 times.
✓ Branch 24 taken 1968 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 779344 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 7056 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 7056 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 7056 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 7056 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 7056 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 7056 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 28224 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 28224 times.
✗ Branch 51 not taken.
|
13167644 | { return *entitySet_; } |
125 | |||
126 | ///////////////////////////////////////////////////// | ||
127 | //! Interface to be used by other bounding box trees | ||
128 | ///////////////////////////////////////////////////// | ||
129 | |||
130 | //! Get an existing bounding box for a given node | ||
131 | const BoundingBoxNode& getBoundingBoxNode(std::size_t nodeIdx) const | ||
132 |
48/48✓ Branch 0 taken 2764020 times.
✓ Branch 1 taken 2154111 times.
✓ Branch 2 taken 2764020 times.
✓ Branch 3 taken 2154111 times.
✓ Branch 4 taken 1687539 times.
✓ Branch 5 taken 1214453 times.
✓ Branch 6 taken 1687539 times.
✓ Branch 7 taken 1214453 times.
✓ Branch 8 taken 5640342 times.
✓ Branch 9 taken 5541430 times.
✓ Branch 10 taken 5640342 times.
✓ Branch 11 taken 5541430 times.
✓ Branch 12 taken 198631 times.
✓ Branch 13 taken 265226 times.
✓ Branch 14 taken 198631 times.
✓ Branch 15 taken 265226 times.
✓ Branch 16 taken 1807786 times.
✓ Branch 17 taken 4359807 times.
✓ Branch 18 taken 1807786 times.
✓ Branch 19 taken 4359807 times.
✓ Branch 20 taken 926876 times.
✓ Branch 21 taken 2381898 times.
✓ Branch 22 taken 926876 times.
✓ Branch 23 taken 2381898 times.
✓ Branch 24 taken 2892 times.
✓ Branch 25 taken 1325 times.
✓ Branch 26 taken 2892 times.
✓ Branch 27 taken 1325 times.
✓ Branch 28 taken 2136 times.
✓ Branch 29 taken 1091 times.
✓ Branch 30 taken 2136 times.
✓ Branch 31 taken 1091 times.
✓ Branch 32 taken 517677 times.
✓ Branch 33 taken 204664 times.
✓ Branch 34 taken 517677 times.
✓ Branch 35 taken 204664 times.
✓ Branch 36 taken 496492 times.
✓ Branch 37 taken 191807 times.
✓ Branch 38 taken 496492 times.
✓ Branch 39 taken 191807 times.
✓ Branch 40 taken 1259897 times.
✓ Branch 41 taken 692793 times.
✓ Branch 42 taken 1259897 times.
✓ Branch 43 taken 692793 times.
✓ Branch 44 taken 893741 times.
✓ Branch 45 taken 477679 times.
✓ Branch 46 taken 893741 times.
✓ Branch 47 taken 477679 times.
|
67368626 | { return boundingBoxNodes_[nodeIdx]; } |
133 | |||
134 | //! Get an existing bounding box for a given node | ||
135 | const ctype* getBoundingBoxCoordinates(std::size_t nodeIdx) const | ||
136 |
48/48✓ Branch 0 taken 2767915 times.
✓ Branch 1 taken 2074690 times.
✓ Branch 2 taken 2767915 times.
✓ Branch 3 taken 2074690 times.
✓ Branch 4 taken 1687787 times.
✓ Branch 5 taken 1212459 times.
✓ Branch 6 taken 1687787 times.
✓ Branch 7 taken 1212459 times.
✓ Branch 8 taken 5743241 times.
✓ Branch 9 taken 5203175 times.
✓ Branch 10 taken 5743241 times.
✓ Branch 11 taken 5203175 times.
✓ Branch 12 taken 247696 times.
✓ Branch 13 taken 107380 times.
✓ Branch 14 taken 247696 times.
✓ Branch 15 taken 107380 times.
✓ Branch 16 taken 3085030 times.
✓ Branch 17 taken 1311211 times.
✓ Branch 18 taken 3085030 times.
✓ Branch 19 taken 1311211 times.
✓ Branch 20 taken 1653644 times.
✓ Branch 21 taken 742169 times.
✓ Branch 22 taken 1653644 times.
✓ Branch 23 taken 742169 times.
✓ Branch 24 taken 2892 times.
✓ Branch 25 taken 1325 times.
✓ Branch 26 taken 2892 times.
✓ Branch 27 taken 1325 times.
✓ Branch 28 taken 2136 times.
✓ Branch 29 taken 1091 times.
✓ Branch 30 taken 2136 times.
✓ Branch 31 taken 1091 times.
✓ Branch 32 taken 517677 times.
✓ Branch 33 taken 204664 times.
✓ Branch 34 taken 517677 times.
✓ Branch 35 taken 204664 times.
✓ Branch 36 taken 496492 times.
✓ Branch 37 taken 191807 times.
✓ Branch 38 taken 496492 times.
✓ Branch 39 taken 191807 times.
✓ Branch 40 taken 1268157 times.
✓ Branch 41 taken 688441 times.
✓ Branch 42 taken 1268157 times.
✓ Branch 43 taken 688441 times.
✓ Branch 44 taken 893741 times.
✓ Branch 45 taken 477679 times.
✓ Branch 46 taken 893741 times.
✓ Branch 47 taken 477679 times.
|
61164998 | { return boundingBoxCoordinates_.data() + 2*dimworld*nodeIdx; } |
137 | |||
138 | //! Get the number of bounding boxes currently in the tree | ||
139 | std::size_t numBoundingBoxes() const | ||
140 |
35/50✓ Branch 1 taken 765 times.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 910 times.
✓ Branch 5 taken 149 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 59308 times.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 120 times.
✓ Branch 10 taken 4789 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 120 times.
✓ Branch 13 taken 277359 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 124 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 142 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✓ Branch 22 taken 4 times.
✓ Branch 23 taken 120 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 10 times.
✓ Branch 26 taken 120 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 22 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 120 times.
✓ Branch 31 taken 8 times.
✓ Branch 32 taken 6 times.
✓ Branch 33 taken 120 times.
✓ Branch 34 taken 4 times.
✓ Branch 35 taken 6 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 124 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 2 times.
✓ Branch 40 taken 124 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✓ Branch 43 taken 16 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 18 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 6 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 8 times.
✗ Branch 53 not taken.
|
412959 | { return boundingBoxNodes_.size(); } |
141 | |||
142 | //! Check whether a bounding box node is a leaf node | ||
143 | //! Leaf nodes have itself as child0 | ||
144 | ✗ | bool isLeaf(const BoundingBoxNode& node, std::size_t nodeIdx) const | |
145 |
20/20✓ Branch 0 taken 234935 times.
✓ Branch 1 taken 1398482 times.
✓ Branch 2 taken 234935 times.
✓ Branch 3 taken 1398482 times.
✓ Branch 4 taken 17267 times.
✓ Branch 5 taken 72536 times.
✓ Branch 6 taken 17267 times.
✓ Branch 7 taken 72536 times.
✓ Branch 8 taken 4580 times.
✓ Branch 9 taken 9335 times.
✓ Branch 10 taken 4580 times.
✓ Branch 11 taken 9335 times.
✓ Branch 12 taken 256 times.
✓ Branch 13 taken 308 times.
✓ Branch 14 taken 256 times.
✓ Branch 15 taken 308 times.
✓ Branch 16 taken 143776 times.
✓ Branch 17 taken 287492 times.
✓ Branch 18 taken 143776 times.
✓ Branch 19 taken 287492 times.
|
4337934 | { return node.child0 == nodeIdx; } |
146 | |||
147 | private: | ||
148 | |||
149 | //! vector of bounding box nodes | ||
150 | std::vector<BoundingBoxNode> boundingBoxNodes_; | ||
151 | |||
152 | //! vector of bounding box coordinates | ||
153 | std::vector<ctype> boundingBoxCoordinates_; | ||
154 | |||
155 | //! a pointer to the entity set | ||
156 | std::shared_ptr<const EntitySet> entitySet_; | ||
157 | |||
158 | //! Compute the bounding box of a grid entity | ||
159 | template <class Entity> | ||
160 | 5291449 | void computeEntityBoundingBox_(ctype* b, const Entity& entity) const | |
161 | { | ||
162 | // get the bounding box coordinates | ||
163 | 5319083 | ctype* xMin = b; | |
164 | 5319083 | ctype* xMax = b + dimworld; | |
165 | |||
166 | // get mesh entity data | ||
167 |
1/2✓ Branch 2 taken 2178 times.
✗ Branch 3 not taken.
|
5862445 | auto geometry = entity.geometry(); |
168 | |||
169 | // Get coordinates of first vertex | ||
170 | 5319083 | auto corner = geometry.corner(0); | |
171 |
12/12✓ Branch 0 taken 3512814 times.
✓ Branch 1 taken 7525616 times.
✓ Branch 2 taken 216546 times.
✓ Branch 3 taken 528 times.
✓ Branch 4 taken 24000 times.
✓ Branch 5 taken 8160 times.
✓ Branch 6 taken 7200 times.
✓ Branch 7 taken 2400 times.
✓ Branch 8 taken 34020 times.
✓ Branch 9 taken 11340 times.
✓ Branch 10 taken 11820 times.
✓ Branch 11 taken 4100 times.
|
18568208 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
172 | 26483638 | xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx]; | |
173 | |||
174 | // Compute the min and max over the remaining vertices | ||
175 |
4/4✓ Branch 0 taken 14160371 times.
✓ Branch 1 taken 3306366 times.
✓ Branch 2 taken 14160304 times.
✓ Branch 3 taken 3306333 times.
|
35230086 | for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx) |
176 | { | ||
177 | 24605008 | corner = geometry.corner(cornerIdx); | |
178 |
3/3✓ Branch 0 taken 36530644 times.
✓ Branch 1 taken 14288673 times.
✓ Branch 2 taken 125558 times.
|
90552823 | for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx) |
179 | { | ||
180 | using std::max; | ||
181 | using std::min; | ||
182 |
4/4✓ Branch 0 taken 1026621 times.
✓ Branch 1 taken 35757883 times.
✓ Branch 2 taken 1026621 times.
✓ Branch 3 taken 35743291 times.
|
131881018 | xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]); |
183 |
4/4✓ Branch 0 taken 7876033 times.
✓ Branch 1 taken 28908471 times.
✓ Branch 2 taken 7861441 times.
✓ Branch 3 taken 28908471 times.
|
145042463 | xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]); |
184 | } | ||
185 | } | ||
186 | 5291449 | } | |
187 | |||
188 | //! Build bounding box tree for all entities recursively | ||
189 | 10688845 | 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) | ||
192 | { | ||
193 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 6665454 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6665454 times.
|
21377690 | assert(begin < end); |
194 | |||
195 | // If we reached the end of the recursion, i.e. only a leaf box is left | ||
196 |
4/4✓ Branch 0 taken 3334000 times.
✓ Branch 1 taken 3331454 times.
✓ Branch 2 taken 3334000 times.
✓ Branch 3 taken 3331454 times.
|
21377690 | if (end - begin == 1) |
197 | { | ||
198 | // Get the bounding box coordinates for the leaf | ||
199 | 5346717 | const std::size_t leafNodeIdx = *begin; | |
200 | 10693434 | const auto beginCoords = leafBoxes.begin() + 2*dimworld*leafNodeIdx; | |
201 | 5346717 | const auto endCoords = beginCoords + 2*dimworld; | |
202 | |||
203 | // Store the data in the bounding box | ||
204 | // leaf nodes are indicated by setting child0 to | ||
205 | // the node itself and child1 to the index of the entity in the bounding box. | ||
206 | 10693434 | return addBoundingBox_(BoundingBoxNode{numBoundingBoxes(), leafNodeIdx}, beginCoords, endCoords); | |
207 | } | ||
208 | |||
209 | // Compute the bounding box of all bounding boxes in the range [begin, end] | ||
210 | 5342128 | const auto bCoords = computeBBoxOfBBoxes_(leafBoxes, begin, end); | |
211 | |||
212 | // sort bounding boxes along the longest axis | ||
213 | 5356694 | const auto axis = computeLongestAxis_(bCoords); | |
214 | |||
215 | // nth_element sorts the range to make sure that middle points to the coordinate median in axis direction | ||
216 | // this is the most expensive part of the algorithm | ||
217 | 5342128 | auto middle = begin + (end - begin)/2; | |
218 | 173759594 | std::nth_element(begin, middle, end, [&leafBoxes, axis](std::size_t i, std::size_t j) | |
219 | { | ||
220 | 265475454 | const ctype* bi = leafBoxes.data() + 2*dimworld*i; | |
221 | 265475454 | const ctype* bj = leafBoxes.data() + 2*dimworld*j; | |
222 | 132737727 | return bi[axis] + bi[axis + dimworld] < bj[axis] + bj[axis + dimworld]; | |
223 | }); | ||
224 | |||
225 | // split the bounding boxes into two at the middle iterator and call build recursively, each | ||
226 | // call resulting in a new node of this bounding box, i.e. the root will be added at the end of the process. | ||
227 | return addBoundingBox_(BoundingBoxNode{build_(leafBoxes, begin, middle), build_(leafBoxes, middle, end)}, | ||
228 |
5/10✓ Branch 1 taken 3331454 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3331454 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3331454 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3331454 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 3331454 times.
✗ Branch 14 not taken.
|
16026384 | bCoords.begin(), bCoords.end()); |
229 | } | ||
230 | |||
231 | //! Add a new bounding box to the tree | ||
232 | template <class Iterator> | ||
233 | 6662908 | std::size_t addBoundingBox_(BoundingBoxNode&& node, | |
234 | const Iterator& coordBegin, | ||
235 | const Iterator& coordEnd) | ||
236 | { | ||
237 | // Add the bounding box | ||
238 | 6662908 | boundingBoxNodes_.emplace_back(node); | |
239 | |||
240 | // Add the bounding box's coordinates | ||
241 |
0/6✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
19988724 | boundingBoxCoordinates_.insert(boundingBoxCoordinates_.end(), coordBegin, coordEnd); |
242 | |||
243 | // return the index of the new node | ||
244 | 13325816 | return boundingBoxNodes_.size() - 1; | |
245 | } | ||
246 | |||
247 | //! Compute the bounding box of a vector of bounding boxes | ||
248 | std::array<ctype, 2*dimworld> | ||
249 | 5342128 | computeBBoxOfBBoxes_(const std::vector<ctype>& leafBoxes, | |
250 | const std::vector<std::size_t>::iterator& begin, | ||
251 | const std::vector<std::size_t>::iterator& end) | ||
252 | { | ||
253 | std::array<ctype, 2*dimworld> bBoxCoords; | ||
254 | |||
255 | // copy the iterator and get coordinates of first box | ||
256 | 5342128 | auto it = begin; | |
257 | 5342128 | const auto* bFirst = leafBoxes.data() + 2*dimworld*(*it); | |
258 | |||
259 |
2/2✓ Branch 0 taken 3331454 times.
✓ Branch 1 taken 16036380 times.
|
31979548 | for (int coordIdx = 0; coordIdx < 2*dimworld; ++coordIdx) |
260 | 53274840 | bBoxCoords[coordIdx] = bFirst[coordIdx]; | |
261 | |||
262 | // Compute min and max with the remaining boxes | ||
263 |
4/4✓ Branch 0 taken 48452029 times.
✓ Branch 1 taken 3331454 times.
✓ Branch 2 taken 48452029 times.
✓ Branch 3 taken 3331454 times.
|
89642595 | for (; it != end; ++it) |
264 | { | ||
265 | 78958339 | const auto* b = leafBoxes.data() + 2*dimworld*(*it); | |
266 |
2/2✓ Branch 0 taken 48452029 times.
✓ Branch 1 taken 118476794 times.
|
279198802 | for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx) |
267 |
4/4✓ Branch 0 taken 3895068 times.
✓ Branch 1 taken 114581726 times.
✓ Branch 2 taken 3895068 times.
✓ Branch 3 taken 114581726 times.
|
400208126 | if (b[coordIdx] < bBoxCoords[coordIdx]) |
268 | 12214160 | bBoxCoords[coordIdx] = b[coordIdx]; | |
269 |
2/2✓ Branch 0 taken 118476794 times.
✓ Branch 1 taken 48452029 times.
|
279062402 | for (int coordIdx = dimworld; coordIdx < 2*dimworld; ++coordIdx) |
270 |
4/4✓ Branch 0 taken 6188268 times.
✓ Branch 1 taken 112288526 times.
✓ Branch 2 taken 6188268 times.
✓ Branch 3 taken 112288526 times.
|
400208126 | if (b[coordIdx] > bBoxCoords[coordIdx]) |
271 | 19644202 | bBoxCoords[coordIdx] = b[coordIdx]; | |
272 | } | ||
273 | |||
274 | 5342128 | return bBoxCoords; | |
275 | } | ||
276 | |||
277 | //! Compute the bounding box of a vector of bounding boxes | ||
278 | ✗ | std::size_t computeLongestAxis_(const std::array<ctype, 2*dimworld>& bCoords) | |
279 | { | ||
280 | std::array<ctype, dimworld> axisLength; | ||
281 |
30/30✓ Branch 0 taken 422208 times.
✓ Branch 1 taken 901512 times.
✓ Branch 2 taken 2662093 times.
✓ Branch 3 taken 6410892 times.
✓ Branch 4 taken 20781 times.
✓ Branch 5 taken 61838 times.
✓ Branch 6 taken 160538 times.
✓ Branch 7 taken 477168 times.
✓ Branch 8 taken 498 times.
✓ Branch 9 taken 1040 times.
✓ Branch 10 taken 454 times.
✓ Branch 11 taken 956 times.
✓ Branch 12 taken 406 times.
✓ Branch 13 taken 1172 times.
✓ Branch 14 taken 8034 times.
✓ Branch 15 taken 24102 times.
✓ Branch 16 taken 8034 times.
✓ Branch 17 taken 24102 times.
✓ Branch 18 taken 2274 times.
✓ Branch 19 taken 6822 times.
✓ Branch 20 taken 2274 times.
✓ Branch 21 taken 6462 times.
✓ Branch 22 taken 11218 times.
✓ Branch 23 taken 33294 times.
✓ Branch 24 taken 10858 times.
✓ Branch 25 taken 32574 times.
✓ Branch 26 taken 3618 times.
✓ Branch 27 taken 10854 times.
✓ Branch 28 taken 3618 times.
✓ Branch 29 taken 10854 times.
|
11335096 | for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx) |
282 | 32014568 | axisLength[coordIdx] = bCoords[dimworld + coordIdx] - bCoords[coordIdx]; | |
283 | |||
284 | 9950718 | return std::distance(axisLength.begin(), std::max_element(axisLength.begin(), axisLength.end())); | |
285 | } | ||
286 | }; | ||
287 | |||
288 | /*! | ||
289 | * \brief Check whether a point is intersectin a bounding box (dimworld == 3) | ||
290 | * \param point The point | ||
291 | * \param b Pointer to bounding box coordinates | ||
292 | */ | ||
293 | template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 3, int> = 0> | ||
294 | 24638475 | inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b) | |
295 | { | ||
296 | static constexpr ctype eps_ = 1.0e-7; | ||
297 | |||
298 | using std::max; | ||
299 | 24638475 | const auto dx = b[3] - b[0]; | |
300 | 24638475 | const auto dy = b[4] - b[1]; | |
301 | 24638475 | const auto dz = b[5] - b[2]; | |
302 | 24638475 | const ctype eps = max({dx, dy, dz})*eps_; | |
303 |
6/6✓ Branch 0 taken 23489212 times.
✓ Branch 1 taken 1149263 times.
✓ Branch 2 taken 22331060 times.
✓ Branch 3 taken 1158152 times.
✓ Branch 4 taken 22331060 times.
✓ Branch 5 taken 1158152 times.
|
24638475 | return (b[0] - eps <= point[0] && point[0] <= b[3] + eps && |
304 |
8/8✓ Branch 0 taken 21377072 times.
✓ Branch 1 taken 953988 times.
✓ Branch 2 taken 21377072 times.
✓ Branch 3 taken 953988 times.
✓ Branch 4 taken 20394470 times.
✓ Branch 5 taken 982602 times.
✓ Branch 6 taken 20394470 times.
✓ Branch 7 taken 982602 times.
|
44662120 | b[1] - eps <= point[1] && point[1] <= b[4] + eps && |
305 |
10/10✓ Branch 0 taken 23489212 times.
✓ Branch 1 taken 1149263 times.
✓ Branch 2 taken 19588205 times.
✓ Branch 3 taken 806265 times.
✓ Branch 4 taken 19588205 times.
✓ Branch 5 taken 806265 times.
✓ Branch 6 taken 873660 times.
✓ Branch 7 taken 18714545 times.
✓ Branch 8 taken 873660 times.
✓ Branch 9 taken 18714545 times.
|
65427415 | b[2] - eps <= point[2] && point[2] <= b[5] + eps); |
306 | } | ||
307 | |||
308 | /*! | ||
309 | * \brief Check whether a point is intersectin a bounding box (dimworld == 2) | ||
310 | * \param point The point | ||
311 | * \param b Pointer to bounding box coordinates | ||
312 | */ | ||
313 | template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 2, int> = 0> | ||
314 | 757997 | inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b) | |
315 | { | ||
316 | static constexpr ctype eps_ = 1.0e-7; | ||
317 | |||
318 | using std::max; | ||
319 | 757997 | const auto dx = b[2] - b[0]; | |
320 | 757997 | const auto dy = b[3] - b[1]; | |
321 |
2/2✓ Branch 0 taken 370536 times.
✓ Branch 1 taken 387461 times.
|
757997 | const ctype eps = max(dx, dy)*eps_; |
322 |
6/6✓ Branch 0 taken 659671 times.
✓ Branch 1 taken 98326 times.
✓ Branch 2 taken 560653 times.
✓ Branch 3 taken 99018 times.
✓ Branch 4 taken 560653 times.
✓ Branch 5 taken 99018 times.
|
757997 | return (b[0] - eps <= point[0] && point[0] <= b[2] + eps && |
323 |
10/10✓ Branch 0 taken 659671 times.
✓ Branch 1 taken 98326 times.
✓ Branch 2 taken 462236 times.
✓ Branch 3 taken 98417 times.
✓ Branch 4 taken 462236 times.
✓ Branch 5 taken 98417 times.
✓ Branch 6 taken 105636 times.
✓ Branch 7 taken 356600 times.
✓ Branch 8 taken 105636 times.
✓ Branch 9 taken 356600 times.
|
1879303 | b[1] - eps <= point[1] && point[1] <= b[3] + eps); |
324 | } | ||
325 | |||
326 | /*! | ||
327 | * \brief Check whether a point is intersectin a bounding box (dimworld == 1) | ||
328 | * \param point The point | ||
329 | * \param b Pointer to bounding box coordinates | ||
330 | */ | ||
331 | template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 1, int> = 0> | ||
332 | inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b) | ||
333 | { | ||
334 | static constexpr ctype eps_ = 1.0e-7; | ||
335 | 214 | const ctype eps0 = eps_*(b[1] - b[0]); | |
336 |
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; |
337 | } | ||
338 | |||
339 | /*! | ||
340 | * \ingroup Geometry | ||
341 | * \brief Determine if a point intersects an axis-aligned bounding box | ||
342 | * The bounding box is given by the lower left corner (min) and the upper right corner (max) | ||
343 | */ | ||
344 | template<class ctype, int dimworld> | ||
345 | 12357291 | inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, | |
346 | const Dune::FieldVector<ctype, dimworld>& min, | ||
347 | const Dune::FieldVector<ctype, dimworld>& max) | ||
348 | { | ||
349 | std::array<ctype, 2*dimworld> bBox; | ||
350 | 49429164 | std::copy(min.begin(), min.end(), bBox.begin()); | |
351 | 49429164 | std::copy(max.begin(), max.end(), bBox.begin()+dimworld); | |
352 | 24714582 | return intersectsPointBoundingBox(point, bBox.data()); | |
353 | } | ||
354 | |||
355 | /*! | ||
356 | * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 3) | ||
357 | * \param a Pointer to first bounding box coordinates | ||
358 | * \param b Pointer to second bounding box coordinates | ||
359 | */ | ||
360 | template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 3, int> = 0> | ||
361 | 1415281 | inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b) | |
362 | { | ||
363 | using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType; | ||
364 | static constexpr ctype eps_ = 1.0e-7; | ||
365 |
2/2✓ Branch 0 taken 639414 times.
✓ Branch 1 taken 775867 times.
|
1415281 | const ctype eps0 = eps_*std::max(b[3]-b[0], a[3]-a[0]); |
366 |
2/2✓ Branch 0 taken 637925 times.
✓ Branch 1 taken 777356 times.
|
1415281 | const ctype eps1 = eps_*std::max(b[4]-b[1], a[4]-a[1]); |
367 |
2/2✓ Branch 0 taken 764277 times.
✓ Branch 1 taken 651004 times.
|
1415281 | const ctype eps2 = eps_*std::max(b[5]-b[2], a[5]-a[2]); |
368 |
2/2✓ Branch 0 taken 1140100 times.
✓ Branch 1 taken 128838 times.
|
1268938 | return (b[0] - eps0 <= a[3] && a[0] <= b[3] + eps0 && |
369 |
4/4✓ Branch 0 taken 1080269 times.
✓ Branch 1 taken 59831 times.
✓ Branch 2 taken 1019371 times.
✓ Branch 3 taken 60898 times.
|
1140100 | b[1] - eps1 <= a[4] && a[1] <= b[4] + eps1 && |
370 |
6/6✓ Branch 0 taken 1268938 times.
✓ Branch 1 taken 146343 times.
✓ Branch 2 taken 968029 times.
✓ Branch 3 taken 51342 times.
✓ Branch 4 taken 55945 times.
✓ Branch 5 taken 912084 times.
|
2434652 | b[2] - eps2 <= a[5] && a[2] <= b[5] + eps2); |
371 | |||
372 | } | ||
373 | |||
374 | /*! | ||
375 | * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 2) | ||
376 | * \param a Pointer to first bounding box coordinates | ||
377 | * \param b Pointer to second bounding box coordinates | ||
378 | */ | ||
379 | template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 2, int> = 0> | ||
380 | 2137844 | inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b) | |
381 | { | ||
382 | using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType; | ||
383 | static constexpr ctype eps_ = 1.0e-7; | ||
384 |
2/2✓ Branch 0 taken 2111163 times.
✓ Branch 1 taken 26681 times.
|
2137844 | const ctype eps0 = eps_*std::max(b[2]-b[0], a[2]-a[0]); |
385 |
2/2✓ Branch 0 taken 2116201 times.
✓ Branch 1 taken 21643 times.
|
2137844 | const ctype eps1 = eps_*std::max(b[3]-b[1], a[3]-a[1]); |
386 |
2/2✓ Branch 0 taken 1691074 times.
✓ Branch 1 taken 203897 times.
|
1894971 | return (b[0] - eps0 <= a[2] && a[0] <= b[2] + eps0 && |
387 |
6/6✓ Branch 0 taken 1894971 times.
✓ Branch 1 taken 242873 times.
✓ Branch 2 taken 1471988 times.
✓ Branch 3 taken 219086 times.
✓ Branch 4 taken 202393 times.
✓ Branch 5 taken 1269595 times.
|
3828918 | b[1] - eps1 <= a[3] && a[1] <= b[3] + eps1); |
388 | } | ||
389 | |||
390 | /*! | ||
391 | * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 1) | ||
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 == 1, int> = 0> | ||
396 | 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 | const ctype eps0 = eps_*std::max(b[1]-b[0], a[1]-a[0]); | ||
401 | return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0; | ||
402 | } | ||
403 | |||
404 | /*! | ||
405 | * \brief Compute squared distance between point and bounding box | ||
406 | * \param point The point | ||
407 | * \param b Pointer to bounding box coordinates | ||
408 | */ | ||
409 | template<int dimworld, class ctype> | ||
410 | 11097934 | inline ctype squaredDistancePointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b) | |
411 | { | ||
412 | 11097934 | ctype squaredDistance = 0.0; | |
413 |
2/2✓ Branch 0 taken 293084 times.
✓ Branch 1 taken 146542 times.
|
44232996 | for (int d = 0; d < dimworld; ++d) |
414 | { | ||
415 |
4/4✓ Branch 0 taken 25456 times.
✓ Branch 1 taken 267628 times.
✓ Branch 2 taken 25456 times.
✓ Branch 3 taken 267628 times.
|
66270124 | if (point[d] < b[d]) |
416 | 22474146 | squaredDistance += (point[d] - b[d])*(point[d] - b[d]); | |
417 |
4/4✓ Branch 0 taken 103484 times.
✓ Branch 1 taken 189600 times.
✓ Branch 2 taken 103484 times.
✓ Branch 3 taken 189600 times.
|
66270124 | if (point[d] > b[d+dimworld]) |
418 | 56468778 | squaredDistance += (point[d] - b[d+dimworld])*(point[d] - b[d+dimworld]); | |
419 | } | ||
420 | 11097934 | return squaredDistance; | |
421 | } | ||
422 | |||
423 | } // end namespace Dumux | ||
424 | |||
425 | #endif | ||
426 |