Easy3D 2.5.3
box.h
1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ********************************************************************/
26
27#ifndef EASY3D_CORE_GENERIC_BOX_H
28#define EASY3D_CORE_GENERIC_BOX_H
29
30#include <cassert>
31#include <algorithm>
32#include <limits>
33
34#include <easy3d/core/vec.h>
35
36
37namespace easy3d {
38
46 template<int DIM, typename FT>
47 class GenericBox {
48 public:
49 typedef Vec<DIM, FT> Point;
50 typedef Vec<DIM, FT> Vector;
52
53 public:
56 : min_(std::numeric_limits<FT>::max()) // is_valid to an invalid value
57 , max_(-std::numeric_limits<FT>::max()) {
58 }
59
61 GenericBox(const Point &pmin, const Point &pmax) {
62 // the user might provide wrong order
63 // min_ = pmin;
64 // max_ = pmax;
65 grow(pmin);
66 grow(pmax);
67 }
68
70 GenericBox(const Point &c, FT r) {
71 Vector dir(1.0);
72 dir.normalize();
73 min_ = c - dir * r;
74 max_ = c + dir * r;
75 }
76
78 inline bool is_valid() const {
79 for (int i = 0; i < DIM; ++i) {
80 if (max_[i] >= min_[i] - std::numeric_limits<FT>::epsilon())
81 return true;
82 }
83 return false;
84 }
85
87 inline void clear() {
88 min_ = Point(std::numeric_limits<FT>::max());
89 max_ = Point(-std::numeric_limits<FT>::max());
90 }
91
93 inline const Point& min_point() const { return min_; }
95 inline Point& min_point() { return min_; }
96
98 inline const Point& max_point() const { return max_; }
100 inline Point& max_point() { return max_; }
101
103 inline FT min_coord(unsigned int axis) const {
104 assert(axis >= 0 && axis < DIM);
105 if (is_valid())
106 return min_[axis];
107 else
108 return FT(0.0);
109 }
110
112 inline FT max_coord(unsigned int axis) const {
113 assert(axis >= 0 && axis < DIM);
114 if (is_valid())
115 return max_[axis];
116 else
117 return FT(0.0);
118 }
119
121 inline FT range(unsigned int axis) const {
122 assert(axis >= 0 && axis < DIM);
123 if (is_valid())
124 return max_[axis] - min_[axis];
125 else
126 return FT(0.0);
127 }
128
130 inline FT max_range() const {
131 FT max_value = max_[0] - min_[0];
132 for (int i = 1; i < DIM; ++i)
133 max_value = std::max(max_value, max_[i] - min_[i]);
134 return max_value;
135 }
136
138 inline FT min_range() const {
139 FT min_value = max_[0] - min_[0];
140 for (int i = 1; i < DIM; ++i)
141 min_value = std::min(min_value, max_[i] - min_[i]);
142 return min_value;
143 }
144
146 inline unsigned int max_range_axis() const {
147 unsigned int axis = 0;
148 FT max_value = max_[0] - min_[0];
149 for (int i = 1; i < DIM; ++i) {
150 FT range = max_[i] - min_[i];
151 if (range > max_value) {
152 axis = i;
153 max_value = range;
154 }
155 }
156 return axis;
157 }
158
160 inline unsigned int min_range_axis() const {
161 unsigned int axis = 0;
162 FT min_value = max_[0] - min_[0];
163 for (int i = 1; i < DIM; ++i) {
164 FT range = max_[i] - min_[i];
165 if (range < min_value) {
166 axis = i;
167 min_value = range;
168 }
169 }
170 return axis;
171 }
172
174 inline Point center() const {
175 if (is_valid())
176 return FT(0.5) * (min_ + max_);
177 else
178 return Point(0.0);
179 }
180
182 inline Vector diagonal_vector() const { return max_ - min_; }
183
185 inline FT diagonal_length() const {
186 if (is_valid()) {
187 FT sqr_len(0.0);
188 for (int i = 0; i < DIM; ++i) {
189 FT d = max_[i] - min_[i];
190 sqr_len += d * d;
191 }
192 return std::sqrt(sqr_len);
193 } else
194 return FT(0.0);
195 }
196
198 inline FT radius() const {
199 return diagonal_length() * FT(0.5);
200 }
201
203 inline FT surface_area() const {
204 Vector ext = max_ - min_;
205 if (DIM == 3)
206 return FT(2.0) * (ext[0] * ext[1] + ext[0] * ext[2] + ext[1] * ext[2]);
207 else if (DIM == 2)
208 return ext[0] * ext[1];
209 else {
210 std::cerr << "surface_area() is for 2D and 3D boxes" << std::endl;
211 return FT(0);
212 }
213 }
214
216 inline void grow(const Point &p) {
217 if (is_valid()) {
218 for (int i = 0; i < DIM; ++i) {
219 min_[i] = std::min(min_[i], p[i]);
220 max_[i] = std::max(max_[i], p[i]);
221 }
222 } else {
223 min_ = p;
224 max_ = p;
225 }
226 }
227
229 inline void grow(const thisclass &b) {
230 if (b.is_valid()) {
231 grow(b.min_point());
232 grow(b.max_point());
233 }
234 }
235
237 inline thisclass operator+(const thisclass &b) const {
238 thisclass result = *this;
239 if (b.is_valid())
240 result += b;
241 return result;
242 }
243
245 inline thisclass &operator+=(const thisclass &b) {
246 if (b.is_valid()) {
247 grow(b.min_point());
248 grow(b.max_point());
249 }
250 return *this;
251 }
252
254 inline bool contains(Point const& p) const {
255 for (int i = 0; i < DIM; ++i) {
256 if (p[i] <= min_[i] || p[i] >= max_[i])
257 return false;
258 }
259 return true;
260 }
261
263 inline bool contains(thisclass const& b) const {
264 return contains(b.min_point()) && contains(b.max_point());
265 }
266
268 inline bool intersects(thisclass const& b) const {
269 for (int i = 0; i < DIM; ++i) {
270 if (b.min_coord(i) > max_[i] || b.max_coord(i) < min_[i])
271 return false;
272 }
273 return true;
274 }
275
276 private:
277 Point min_;
278 Point max_;
279 };
280
281
283 template<int DIM, typename FT>
284 inline bool has_nan(const GenericBox<DIM, FT> &box) {
285 return has_nan(box.min_point()) || has_nan(box.max_point());
286 }
287
288
289 namespace geom {
290
291#if 1
292 template<int DIM, typename FT>
293 GenericBox<DIM, FT> box_union(GenericBox<DIM, FT> const& a, GenericBox<DIM, FT> const& b) {
294 return GenericBox<DIM, FT>(comp_min(a.min_point(), b.min_point()), comp_max(a.max_point(), b.max_point()));
295 }
296
297 template<int DIM, typename FT>
298 GenericBox<DIM, FT> box_intersection(GenericBox<DIM, FT> const& a, GenericBox<DIM, FT> const& b)
299 {
300 return GenericBox<DIM, FT>(comp_max(a.min_point(), b.min_point()), comp_min(a.max_point(), b.max_point()));
301 }
302#else
303 template<int DIM, typename FT>
304 GenericBox<DIM, FT> box_union(GenericBox<DIM, FT> const& a, GenericBox<DIM, FT> const& b) { return a + b; }
305
306 template<int DIM, typename FT>
307 GenericBox<DIM, FT> box_intersection(GenericBox<DIM, FT> const& a, GenericBox<DIM, FT> const& b) {
308 if (a.intersects(b))
309 return GenericBox<DIM, FT>(comp_max(a.min_point(), b.min_point()), comp_min(a.max_point(), b.max_point()));
310 else
311 return GenericBox<DIM, FT>();
312 }
313#endif
314
315 }
316
317} // namespace easy3d
318
319
320#endif // EASY3D_CORE_GENERIC_BOX_H
GenericBox represents the bounding box of shapes.
Definition: box.h:47
bool contains(Point const &p) const
Definition: box.h:254
Point center() const
Definition: box.h:174
GenericBox()
Definition: box.h:55
FT max_coord(unsigned int axis) const
Definition: box.h:112
bool contains(thisclass const &b) const
Definition: box.h:263
const Point & min_point() const
Definition: box.h:93
FT range(unsigned int axis) const
Definition: box.h:121
Vector diagonal_vector() const
Definition: box.h:182
FT radius() const
Definition: box.h:198
Point & min_point()
Definition: box.h:95
FT min_coord(unsigned int axis) const
Definition: box.h:103
FT max_range() const
Definition: box.h:130
FT diagonal_length() const
Definition: box.h:185
FT min_range() const
Definition: box.h:138
thisclass & operator+=(const thisclass &b)
Definition: box.h:245
void grow(const thisclass &b)
Definition: box.h:229
unsigned int min_range_axis() const
Definition: box.h:160
const Point & max_point() const
Definition: box.h:98
bool is_valid() const
Definition: box.h:78
FT surface_area() const
Definition: box.h:203
GenericBox(const Point &c, FT r)
Definition: box.h:70
thisclass operator+(const thisclass &b) const
Definition: box.h:237
void clear()
Definition: box.h:87
unsigned int max_range_axis() const
Definition: box.h:146
GenericBox(const Point &pmin, const Point &pmax)
Definition: box.h:61
bool intersects(thisclass const &b) const
Definition: box.h:268
void grow(const Point &p)
Definition: box.h:216
Point & max_point()
Definition: box.h:100
thisclass & normalize()
Normalizes this vector.
Definition: vec.h:135
Definition: collider.cpp:182
FT max()
Function returning maximum representable value for a given type.
bool has_nan(const GenericBox< DIM, FT > &box)
Definition: box.h:284
Vec< N, T > comp_min(const Vec< N, T > &v1, const Vec< N, T > &v2)
Component-wise minimum vector.
Definition: vec.h:801
Vec< N, T > comp_max(const Vec< N, T > &v1, const Vec< N, T > &v2)
Component-wise maximum vector.
Definition: vec.h:810