GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/math/BBox.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 35 41 85.4%
Functions: 8 11 72.7%
Branches: 101 188 53.7%

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