Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | #ifndef OPENVDB_MATH_BBOX_HAS_BEEN_INCLUDED | ||
5 | #define OPENVDB_MATH_BBOX_HAS_BEEN_INCLUDED | ||
6 | |||
7 | #include "Math.h" // for math::isApproxEqual() and math::Tolerance() | ||
8 | #include "Vec3.h" | ||
9 | #include <algorithm> // for std::min(), std::max() | ||
10 | #include <cmath> // for std::abs() | ||
11 | #include <iostream> | ||
12 | #include <limits> | ||
13 | #include <type_traits> | ||
14 | |||
15 | |||
16 | namespace openvdb { | ||
17 | OPENVDB_USE_VERSION_NAMESPACE | ||
18 | namespace OPENVDB_VERSION_NAME { | ||
19 | namespace math { | ||
20 | |||
21 | /// @brief Axis-aligned bounding box | ||
22 | template<typename Vec3T> | ||
23 | class BBox | ||
24 | { | ||
25 | public: | ||
26 | using Vec3Type = Vec3T; | ||
27 | using ValueType = Vec3T; | ||
28 | using VectorType = Vec3T; | ||
29 | using ElementType = typename Vec3Type::ValueType; | ||
30 | |||
31 | /// @brief The default constructor creates an invalid bounding box. | ||
32 | BBox(); | ||
33 | /// @brief Construct a bounding box that exactly encloses the given | ||
34 | /// minimum and maximum points. | ||
35 | BBox(const Vec3T& xyzMin, const Vec3T& xyzMax); | ||
36 | /// @brief Construct a bounding box that exactly encloses the given | ||
37 | /// minimum and maximum points. | ||
38 | /// @details If @a sorted is false, sort the points by their | ||
39 | /// @e x, @e y and @e z components. | ||
40 | BBox(const Vec3T& xyzMin, const Vec3T& xyzMax, bool sorted); | ||
41 | /// @brief Contruct a cubical bounding box from a minimum coordinate | ||
42 | /// and an edge length. | ||
43 | /// @note Inclusive for integral <b>ElementType</b>s | ||
44 | BBox(const Vec3T& xyzMin, const ElementType& length); | ||
45 | |||
46 | /// @brief Construct a bounding box that exactly encloses two points, | ||
47 | /// whose coordinates are given by an array of six values, | ||
48 | /// <i>x<sub>1</sub></i>, <i>y<sub>1</sub></i>, <i>z<sub>1</sub></i>, | ||
49 | /// <i>x<sub>2</sub></i>, <i>y<sub>2</sub></i> and <i>z<sub>2</sub></i>. | ||
50 | /// @details If @a sorted is false, sort the points by their | ||
51 | /// @e x, @e y and @e z components. | ||
52 | explicit BBox(const ElementType* xyz, bool sorted = true); | ||
53 | |||
54 | BBox(const BBox&) = default; | ||
55 | BBox& operator=(const BBox&) = default; | ||
56 | |||
57 | /// @brief Sort the mininum and maximum points of this bounding box | ||
58 | /// by their @e x, @e y and @e z components. | ||
59 | void sort(); | ||
60 | |||
61 | /// @brief Return a const reference to the minimum point of this bounding box. | ||
62 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2649 | const Vec3T& min() const { return mMin; } |
63 | /// @brief Return a const reference to the maximum point of this bounding box. | ||
64 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2649 | const Vec3T& max() const { return mMax; } |
65 | /// @brief Return a non-const reference to the minimum point of this bounding box. | ||
66 | ✗ | Vec3T& min() { return mMin; } | |
67 | /// @brief Return a non-const reference to the maximum point of this bounding box. | ||
68 | Vec3T& max() { return mMax; } | ||
69 | |||
70 | /// @brief Return @c true if this bounding box is identical to the given bounding box. | ||
71 | bool operator==(const BBox& rhs) const; | ||
72 | /// @brief Return @c true if this bounding box differs from the given bounding box. | ||
73 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | bool operator!=(const BBox& rhs) const { return !(*this == rhs); } |
74 | |||
75 | /// @brief Return @c true if this bounding box is empty, i.e., it has no (positive) volume. | ||
76 | bool empty() const; | ||
77 | /// @brief Return @c true if this bounding box has (positive) volume. | ||
78 | bool hasVolume() const { return !this->empty(); } | ||
79 | /// @brief Return @c true if this bounding box has (positive) volume. | ||
80 | operator bool() const { return !this->empty(); } | ||
81 | |||
82 | /// @brief Return @c true if all components of the minimum point are less than | ||
83 | /// or equal to the corresponding components of the maximum point. | ||
84 | /// @details This is equivalent to testing whether this bounding box has nonnegative volume. | ||
85 | /// @note For floating-point <b>ElementType</b>s a tolerance is used for this test. | ||
86 | bool isSorted() const; | ||
87 | |||
88 | /// @brief Return the center point of this bounding box. | ||
89 | Vec3d getCenter() const; | ||
90 | |||
91 | /// @brief Return the extents of this bounding box, i.e., the length along each axis. | ||
92 | /// @note Inclusive for integral <b>ElementType</b>s | ||
93 | Vec3T extents() const; | ||
94 | /// @brief Return the index (0, 1 or 2) of the longest axis. | ||
95 | 3 | size_t maxExtent() const { return MaxIndex(mMax - mMin); } | |
96 | /// @brief Return the index (0, 1 or 2) of the shortest axis. | ||
97 | 3 | size_t minExtent() const { return MinIndex(mMax - mMin); } | |
98 | |||
99 | /// @brief Return the volume enclosed by this bounding box. | ||
100 |
5/8✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 17 times.
|
32 | ElementType volume() const { Vec3T e = this->extents(); return e[0] * e[1] * e[2]; } |
101 | |||
102 | /// @brief Return @c true if the given point is inside this bounding box. | ||
103 | bool isInside(const Vec3T& xyz) const; | ||
104 | /// @brief Return @c true if the given bounding box is inside this bounding box. | ||
105 | bool isInside(const BBox&) const; | ||
106 | /// @brief Return @c true if the given bounding box overlaps with this bounding box. | ||
107 | bool hasOverlap(const BBox&) const; | ||
108 | /// @brief Return @c true if the given bounding box overlaps with this bounding box. | ||
109 | bool intersects(const BBox& other) const { return hasOverlap(other); } | ||
110 | |||
111 | /// @brief Pad this bounding box. | ||
112 | void expand(ElementType padding); | ||
113 | /// @brief Expand this bounding box to enclose the given point. | ||
114 | void expand(const Vec3T& xyz); | ||
115 | /// @brief Union this bounding box with the given bounding box. | ||
116 | void expand(const BBox&); | ||
117 | /// @brief Union this bounding box with the cubical bounding box with | ||
118 | /// minimum point @a xyzMin and the given edge length. | ||
119 | /// @note Inclusive for integral <b>ElementType</b>s | ||
120 | void expand(const Vec3T& xyzMin, const ElementType& length); | ||
121 | |||
122 | /// @brief Translate this bounding box by | ||
123 | /// (<i>t<sub>x</sub></i>, <i>t<sub>y</sub></i>, <i>t<sub>z</sub></i>). | ||
124 | void translate(const Vec3T& t); | ||
125 | |||
126 | /// @brief Apply a map to this bounding box. | ||
127 | template<typename MapType> | ||
128 | BBox applyMap(const MapType& map) const; | ||
129 | /// @brief Apply the inverse of a map to this bounding box | ||
130 | template<typename MapType> | ||
131 | BBox applyInverseMap(const MapType& map) const; | ||
132 | |||
133 | /// @brief Unserialize this bounding box from the given stream. | ||
134 | ✗ | void read(std::istream& is) { mMin.read(is); mMax.read(is); } | |
135 | /// @brief Serialize this bounding box to the given stream. | ||
136 | ✗ | void write(std::ostream& os) const { mMin.write(os); mMax.write(os); } | |
137 | |||
138 | private: | ||
139 | Vec3T mMin, mMax; | ||
140 | }; // class BBox | ||
141 | |||
142 | |||
143 | //////////////////////////////////////// | ||
144 | |||
145 | |||
146 | template<typename Vec3T> | ||
147 | inline | ||
148 | 7 | BBox<Vec3T>::BBox(): | |
149 | mMin( std::numeric_limits<ElementType>::max()), | ||
150 | mMax(-std::numeric_limits<ElementType>::max()) | ||
151 | { | ||
152 | } | ||
153 | |||
154 | template<typename Vec3T> | ||
155 | inline | ||
156 | 9743793 | BBox<Vec3T>::BBox(const Vec3T& xyzMin, const Vec3T& xyzMax): | |
157 |
16/22✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 29 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
|
9743779 | mMin(xyzMin), mMax(xyzMax) |
158 | { | ||
159 | } | ||
160 | |||
161 | template<typename Vec3T> | ||
162 | inline | ||
163 | BBox<Vec3T>::BBox(const Vec3T& xyzMin, const Vec3T& xyzMax, bool sorted): | ||
164 | mMin(xyzMin), mMax(xyzMax) | ||
165 | { | ||
166 | if (!sorted) this->sort(); | ||
167 | } | ||
168 | |||
169 | template<typename Vec3T> | ||
170 | inline | ||
171 | BBox<Vec3T>::BBox(const Vec3T& xyzMin, const ElementType& length): | ||
172 | mMin(xyzMin), mMax(xyzMin) | ||
173 | { | ||
174 | // min and max are inclusive for integral ElementType | ||
175 | const ElementType size = std::is_integral<ElementType>::value ? length-1 : length; | ||
176 | mMax[0] += size; | ||
177 | mMax[1] += size; | ||
178 | mMax[2] += size; | ||
179 | } | ||
180 | |||
181 | template<typename Vec3T> | ||
182 | inline | ||
183 | BBox<Vec3T>::BBox(const ElementType* xyz, bool sorted): | ||
184 | mMin(xyz[0], xyz[1], xyz[2]), | ||
185 | mMax(xyz[3], xyz[4], xyz[5]) | ||
186 | { | ||
187 | if (!sorted) this->sort(); | ||
188 | } | ||
189 | |||
190 | |||
191 | //////////////////////////////////////// | ||
192 | |||
193 | |||
194 | template<typename Vec3T> | ||
195 | inline bool | ||
196 | BBox<Vec3T>::empty() const | ||
197 | { | ||
198 | if (std::is_integral<ElementType>::value) { | ||
199 | // min and max are inclusive for integral ElementType | ||
200 | return (mMin[0] > mMax[0] || mMin[1] > mMax[1] || mMin[2] > mMax[2]); | ||
201 | } | ||
202 |
21/90✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
✓ Branch 18 taken 8 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 8 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 8 times.
✓ Branch 24 taken 8 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 8 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 8 times.
✓ Branch 30 taken 8 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 8 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 8 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
|
64 | return mMin[0] >= mMax[0] || mMin[1] >= mMax[1] || mMin[2] >= mMax[2]; |
203 | } | ||
204 | |||
205 | |||
206 | template<typename Vec3T> | ||
207 | inline bool | ||
208 | 3 | BBox<Vec3T>::operator==(const BBox& rhs) const | |
209 | { | ||
210 | if (std::is_integral<ElementType>::value) { | ||
211 | return mMin == rhs.min() && mMax == rhs.max(); | ||
212 | } else { | ||
213 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | return math::isApproxEqual(mMin, rhs.min()) && math::isApproxEqual(mMax, rhs.max()); |
214 | } | ||
215 | } | ||
216 | |||
217 | |||
218 | template<typename Vec3T> | ||
219 | inline void | ||
220 | BBox<Vec3T>::sort() | ||
221 | { | ||
222 | Vec3T tMin(mMin), tMax(mMax); | ||
223 | for (int i = 0; i < 3; ++i) { | ||
224 | mMin[i] = std::min(tMin[i], tMax[i]); | ||
225 | mMax[i] = std::max(tMin[i], tMax[i]); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | |||
230 | template<typename Vec3T> | ||
231 | inline bool | ||
232 | BBox<Vec3T>::isSorted() const | ||
233 | { | ||
234 | if (std::is_integral<ElementType>::value) { | ||
235 | return (mMin[0] <= mMax[0] && mMin[1] <= mMax[1] && mMin[2] <= mMax[2]); | ||
236 | } else { | ||
237 | ElementType t = math::Tolerance<ElementType>::value(); | ||
238 |
4/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
|
48 | return (mMin[0] < (mMax[0] + t) && mMin[1] < (mMax[1] + t) && mMin[2] < (mMax[2] + t)); |
239 | } | ||
240 | } | ||
241 | |||
242 | |||
243 | template<typename Vec3T> | ||
244 | inline Vec3d | ||
245 | BBox<Vec3T>::getCenter() const | ||
246 | { | ||
247 | return (Vec3d(mMin.asPointer()) + Vec3d(mMax.asPointer())) * 0.5; | ||
248 | } | ||
249 | |||
250 | |||
251 | template<typename Vec3T> | ||
252 | inline Vec3T | ||
253 | BBox<Vec3T>::extents() const | ||
254 | { | ||
255 | if (std::is_integral<ElementType>::value) { | ||
256 | return (mMax - mMin) + Vec3T(1, 1, 1); | ||
257 | } else { | ||
258 | return (mMax - mMin); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | //////////////////////////////////////// | ||
263 | |||
264 | |||
265 | template<typename Vec3T> | ||
266 | inline bool | ||
267 |
2/2✓ Branch 0 taken 15398762 times.
✓ Branch 1 taken 1558396 times.
|
16957158 | BBox<Vec3T>::isInside(const Vec3T& xyz) const |
268 | { | ||
269 | if (std::is_integral<ElementType>::value) { | ||
270 | return xyz[0] >= mMin[0] && xyz[0] <= mMax[0] && | ||
271 | xyz[1] >= mMin[1] && xyz[1] <= mMax[1] && | ||
272 | xyz[2] >= mMin[2] && xyz[2] <= mMax[2]; | ||
273 | } else { | ||
274 | ElementType t = math::Tolerance<ElementType>::value(); | ||
275 |
2/2✓ Branch 0 taken 12877618 times.
✓ Branch 1 taken 2521144 times.
|
15398762 | return xyz[0] > (mMin[0]-t) && xyz[0] < (mMax[0]+t) && |
276 |
4/4✓ Branch 0 taken 10014829 times.
✓ Branch 1 taken 2862789 times.
✓ Branch 2 taken 6648940 times.
✓ Branch 3 taken 3365889 times.
|
12877618 | xyz[1] > (mMin[1]-t) && xyz[1] < (mMax[1]+t) && |
277 |
6/6✓ Branch 0 taken 15398762 times.
✓ Branch 1 taken 1558396 times.
✓ Branch 2 taken 5855243 times.
✓ Branch 3 taken 793697 times.
✓ Branch 4 taken 1063960 times.
✓ Branch 5 taken 4791283 times.
|
23606098 | xyz[2] > (mMin[2]-t) && xyz[2] < (mMax[2]+t); |
278 | } | ||
279 | } | ||
280 | |||
281 | |||
282 | template<typename Vec3T> | ||
283 | inline bool | ||
284 |
2/2✓ Branch 0 taken 19652 times.
✓ Branch 1 taken 13126 times.
|
32778 | BBox<Vec3T>::isInside(const BBox& b) const |
285 | { | ||
286 | if (std::is_integral<ElementType>::value) { | ||
287 | return b.min()[0] >= mMin[0] && b.max()[0] <= mMax[0] && | ||
288 | b.min()[1] >= mMin[1] && b.max()[1] <= mMax[1] && | ||
289 | b.min()[2] >= mMin[2] && b.max()[2] <= mMax[2]; | ||
290 | } else { | ||
291 | ElementType t = math::Tolerance<ElementType>::value(); | ||
292 |
2/2✓ Branch 0 taken 768 times.
✓ Branch 1 taken 18884 times.
|
19652 | return (b.min()[0]-t) > mMin[0] && (b.max()[0]+t) < mMax[0] && |
293 |
4/4✓ Branch 0 taken 220 times.
✓ Branch 1 taken 548 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 186 times.
|
768 | (b.min()[1]-t) > mMin[1] && (b.max()[1]+t) < mMax[1] && |
294 |
5/6✓ Branch 0 taken 19652 times.
✓ Branch 1 taken 13126 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
32812 | (b.min()[2]-t) > mMin[2] && (b.max()[2]+t) < mMax[2]; |
295 | } | ||
296 | } | ||
297 | |||
298 | |||
299 | template<typename Vec3T> | ||
300 | inline bool | ||
301 |
2/2✓ Branch 0 taken 14514 times.
✓ Branch 1 taken 18384 times.
|
32898 | BBox<Vec3T>::hasOverlap(const BBox& b) const |
302 | { | ||
303 | if (std::is_integral<ElementType>::value) { | ||
304 | return mMax[0] >= b.min()[0] && mMin[0] <= b.max()[0] && | ||
305 | mMax[1] >= b.min()[1] && mMin[1] <= b.max()[1] && | ||
306 | mMax[2] >= b.min()[2] && mMin[2] <= b.max()[2]; | ||
307 | } else { | ||
308 | ElementType t = math::Tolerance<ElementType>::value(); | ||
309 |
2/2✓ Branch 0 taken 2758 times.
✓ Branch 1 taken 11756 times.
|
14514 | return mMax[0] > (b.min()[0]-t) && mMin[0] < (b.max()[0]+t) && |
310 |
4/4✓ Branch 0 taken 2235 times.
✓ Branch 1 taken 523 times.
✓ Branch 2 taken 1208 times.
✓ Branch 3 taken 1027 times.
|
2758 | mMax[1] > (b.min()[1]-t) && mMin[1] < (b.max()[1]+t) && |
311 |
5/6✓ Branch 0 taken 14514 times.
✓ Branch 1 taken 18384 times.
✓ Branch 2 taken 1208 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1109 times.
✓ Branch 5 taken 99 times.
|
34106 | mMax[2] > (b.min()[2]-t) && mMin[2] < (b.max()[2]+t); |
312 | } | ||
313 | } | ||
314 | |||
315 | |||
316 | //////////////////////////////////////// | ||
317 | |||
318 | |||
319 | template<typename Vec3T> | ||
320 | inline void | ||
321 | 49 | BBox<Vec3T>::expand(ElementType dx) | |
322 | { | ||
323 | dx = std::abs(dx); | ||
324 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 49 times.
|
196 | for (int i = 0; i < 3; ++i) { |
325 | 147 | mMin[i] -= dx; | |
326 | 147 | mMax[i] += dx; | |
327 | } | ||
328 | 49 | } | |
329 | |||
330 | |||
331 | template<typename Vec3T> | ||
332 | inline void | ||
333 | 545330 | BBox<Vec3T>::expand(const Vec3T& xyz) | |
334 | { | ||
335 |
2/2✓ Branch 0 taken 1635990 times.
✓ Branch 1 taken 545330 times.
|
2181320 | for (int i = 0; i < 3; ++i) { |
336 |
4/4✓ Branch 0 taken 414873 times.
✓ Branch 1 taken 1221117 times.
✓ Branch 2 taken 349117 times.
✓ Branch 3 taken 1286873 times.
|
2050863 | mMin[i] = std::min(mMin[i], xyz[i]); |
337 |
2/2✓ Branch 0 taken 349117 times.
✓ Branch 1 taken 1286873 times.
|
1985107 | mMax[i] = std::max(mMax[i], xyz[i]); |
338 | } | ||
339 | 545330 | } | |
340 | |||
341 | |||
342 | template<typename Vec3T> | ||
343 | inline void | ||
344 | BBox<Vec3T>::expand(const BBox& b) | ||
345 | { | ||
346 | for (int i = 0; i < 3; ++i) { | ||
347 | mMin[i] = std::min(mMin[i], b.min()[i]); | ||
348 | mMax[i] = std::max(mMax[i], b.max()[i]); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | template<typename Vec3T> | ||
353 | inline void | ||
354 | BBox<Vec3T>::expand(const Vec3T& xyzMin, const ElementType& length) | ||
355 | { | ||
356 | const ElementType size = std::is_integral<ElementType>::value ? length-1 : length; | ||
357 | for (int i = 0; i < 3; ++i) { | ||
358 | mMin[i] = std::min(mMin[i], xyzMin[i]); | ||
359 | mMax[i] = std::max(mMax[i], xyzMin[i] + size); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | |||
364 | template<typename Vec3T> | ||
365 | inline void | ||
366 | BBox<Vec3T>::translate(const Vec3T& dx) | ||
367 | { | ||
368 | mMin += dx; | ||
369 | mMax += dx; | ||
370 | } | ||
371 | |||
372 | template<typename Vec3T> | ||
373 | template<typename MapType> | ||
374 | inline BBox<Vec3T> | ||
375 | BBox<Vec3T>::applyMap(const MapType& map) const | ||
376 | { | ||
377 | using Vec3R = Vec3<double>; | ||
378 | BBox<Vec3T> bbox; | ||
379 | bbox.expand(map.applyMap(Vec3R(mMin[0], mMin[1], mMin[2]))); | ||
380 | bbox.expand(map.applyMap(Vec3R(mMin[0], mMin[1], mMax[2]))); | ||
381 | bbox.expand(map.applyMap(Vec3R(mMin[0], mMax[1], mMin[2]))); | ||
382 | bbox.expand(map.applyMap(Vec3R(mMax[0], mMin[1], mMin[2]))); | ||
383 | bbox.expand(map.applyMap(Vec3R(mMax[0], mMax[1], mMin[2]))); | ||
384 | bbox.expand(map.applyMap(Vec3R(mMax[0], mMin[1], mMax[2]))); | ||
385 | bbox.expand(map.applyMap(Vec3R(mMin[0], mMax[1], mMax[2]))); | ||
386 | bbox.expand(map.applyMap(Vec3R(mMax[0], mMax[1], mMax[2]))); | ||
387 | return bbox; | ||
388 | } | ||
389 | |||
390 | template<typename Vec3T> | ||
391 | template<typename MapType> | ||
392 | inline BBox<Vec3T> | ||
393 | BBox<Vec3T>::applyInverseMap(const MapType& map) const | ||
394 | { | ||
395 | using Vec3R = Vec3<double>; | ||
396 | BBox<Vec3T> bbox; | ||
397 | bbox.expand(map.applyInverseMap(Vec3R(mMin[0], mMin[1], mMin[2]))); | ||
398 | bbox.expand(map.applyInverseMap(Vec3R(mMin[0], mMin[1], mMax[2]))); | ||
399 | bbox.expand(map.applyInverseMap(Vec3R(mMin[0], mMax[1], mMin[2]))); | ||
400 | bbox.expand(map.applyInverseMap(Vec3R(mMax[0], mMin[1], mMin[2]))); | ||
401 | bbox.expand(map.applyInverseMap(Vec3R(mMax[0], mMax[1], mMin[2]))); | ||
402 | bbox.expand(map.applyInverseMap(Vec3R(mMax[0], mMin[1], mMax[2]))); | ||
403 | bbox.expand(map.applyInverseMap(Vec3R(mMin[0], mMax[1], mMax[2]))); | ||
404 | bbox.expand(map.applyInverseMap(Vec3R(mMax[0], mMax[1], mMax[2]))); | ||
405 | return bbox; | ||
406 | } | ||
407 | |||
408 | //////////////////////////////////////// | ||
409 | |||
410 | |||
411 | template<typename Vec3T> | ||
412 | inline std::ostream& | ||
413 | ✗ | operator<<(std::ostream& os, const BBox<Vec3T>& b) | |
414 | { | ||
415 | ✗ | os << b.min() << " -> " << b.max(); | |
416 | ✗ | return os; | |
417 | } | ||
418 | |||
419 | } // namespace math | ||
420 | } // namespace OPENVDB_VERSION_NAME | ||
421 | } // namespace openvdb | ||
422 | |||
423 | #endif // OPENVDB_MATH_BBOX_HAS_BEEN_INCLUDED | ||
424 |