Visual Computing Library
Loading...
Searching...
No Matches
box.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_SPACE_CORE_BOX_H
24#define VCL_SPACE_CORE_BOX_H
25
26#include "point.h"
27
28#include <vclib/concepts/space/box.h>
29#include <vclib/math/min_max.h>
30
31namespace vcl {
32
47template<PointConcept PointT>
48class Box
49{
50 PointT mMin;
51 PointT mMax;
52
53public:
57 using PointType = PointT;
58
62 static const uint DIM = PointT::DIM;
63
68 Box() { setNull(); }
69
76 Box(const PointT& p) : mMin(p), mMax(p) {}
77
86 Box(const PointT& min, const PointT& max) : mMin(min), mMax(max) {}
87
93 PointT& min() { return mMin; }
94
100 const PointT& min() const { return mMin; }
101
107 PointT& max() { return mMax; }
108
114 const PointT& max() const { return mMax; }
115
116 template<typename Scalar>
117 auto cast() const
118 {
119 if constexpr (std::is_same_v<typename PointT::ScalarType, Scalar>) {
120 return *this;
121 }
122 else {
123 return Box<Point<Scalar, PointT::DIM>>(
124 mMin.template cast<Scalar>(), mMax.template cast<Scalar>());
125 }
126 }
127
136 bool isNull() const
137 {
138 for (uint i = 0; i < PointT::DIM; ++i) {
139 if (mMin[i] > mMax[i])
140 return true;
141 }
142 return false;
143 }
144
153 bool isEmpty() const { return mMin == mMax; }
154
166 bool isInside(const PointT& p) const
167 {
168 for (uint i = 0; i < PointT::DIM; ++i) {
169 if (p[i] < mMin[i] || p[i] > mMax[i])
170 return false;
171 }
172 return true;
173 }
174
186 bool isInsideStrict(const PointT& p) const
187 {
188 for (uint i = 0; i < PointT::DIM; ++i) {
189 if (p[i] <= mMin[i] || p[i] >= mMax[i])
190 return false;
191 }
192 return true;
193 }
194
202 bool isInsideOpenBox(const PointT& p) const
203 {
204 for (uint i = 0; i < PointT::DIM; ++i) {
205 if (p[i] < mMin[i] || p[i] >= mMax[i])
206 return false;
207 }
208 return true;
209 }
210
217 bool overlap(const Box<PointT>& b) const
218 {
219 // Check if any dimension of the boxes does not overlap.
220 for (uint i = 0; i < PointT::DIM; ++i) {
221 if (b.mMin[i] >= mMax[i] || b.mMax[i] <= mMin[i])
222 return false;
223 }
224 // All dimensions overlap, the boxes collide.
225 return true;
226 }
227
234 bool collide(const Box<PointT>& b) const { return overlap(b); }
235
242 bool intersects(const Box<PointT>& b) const { return overlap(b); }
243
249 auto diagonal() const { return mMin.dist(mMax); }
250
255 auto squaredDiagonal() const { return mMin.squaredDist(mMax); }
256
262 PointT center() const { return (mMax + mMin) / 2; }
263
270 PointT size() const { return mMax - mMin; }
271
277 auto volume() const
278 {
279 // Initialize volume as the width of the first dimension.
280 auto vol = mMax[0] - mMin[0];
281 // Multiply by the width of each dimension.
282 for (uint i = 1; i < PointT::DIM; ++i) {
283 vol *= mMax[i] - mMin[i];
284 }
285 return vol;
286 }
287
295 auto dim(uint i) const
296 {
297 assert(i < PointT::DIM);
298 return mMax[i] - mMin[i];
299 }
300
308 auto minDim() const
309 {
310 auto m = mMax[0] - mMin[0];
311 for (uint i = 1; i < PointT::DIM; ++i) {
312 if (mMax[i] - mMin[i] < m)
313 m = mMax[i] - mMin[i];
314 }
315 return m;
316 }
317
325 auto maxDim() const
326 {
327 auto m = mMax[0] - mMin[0];
328 for (uint i = 1; i < PointT::DIM; ++i) {
329 if (mMax[i] - mMin[i] > m)
330 m = mMax[i] - mMin[i];
331 }
332 return m;
333 }
334
343 {
344 Box<PointT> res = *this;
345 for (uint i = 0; i < PointT::DIM; ++i) {
346 if (mMin[i] < b.mMin[i]) {
347 // set the minimum point to the larger value
348 res.mMin[i] = b.mMin[i];
349 }
350 if (mMax[i] > b.mMax[i]) {
351 // set the maximum point to the smaller value
352 res.mMax[i] = b.mMax[i];
353 }
354 if (res.mMin[i] > res.mMax[i]) {
355 // if the minimum point is larger than the maximum point, the
356 // box is null
357 res.setNull();
358 return res;
359 }
360 }
361 return res;
362 }
363
371 void setNull()
372 {
373 mMin.setConstant(
374 std::numeric_limits<typename PointT::ScalarType>::max());
375 mMax.setConstant(
376 std::numeric_limits<typename PointT::ScalarType>::lowest());
377 }
378
388 void add(const PointT& p)
389 {
390 if (isNull()) {
391 // If the box was null, set both the minimum and maximum points to
392 // the given point
393 *this = Box(p);
394 }
395 else {
396 // Expand the current box to include the added point
397 mMin = vcl::min(mMin, p);
398 mMax = vcl::max(mMax, p);
399 }
400 }
401
414 template<typename Scalar>
415 void add(const PointT& p, Scalar radius)
416 {
417 if (isNull()) {
418 // If the box was null, initialize it with the minimum and maximum
419 // points obtained by subtracting and adding the radius to the given
420 // point
421 *this = Box(p - radius, p + radius);
422 }
423 else {
424 // Expand the current box to include the added point and all points
425 // within the radius around it
426 mMin = vcl::min(mMin, p - radius);
427 mMax = vcl::max(mMax, p + radius);
428 }
429 }
430
439 void add(const Box<PointT>& b)
440 {
441 // Adding a null box should do nothing
442 if (!b.isNull()) {
443 if (isNull()) {
444 *this = b; // if the current box is null, set it equal to b
445 }
446 else {
447 // expand this box to contain the minimum and maximum point of b
448 add(b.mMin);
449 add(b.mMax);
450 }
451 }
452 }
453
459 void translate(const PointT& p)
460 {
461 mMin += p; // translate the minimum point by p
462 mMax += p; // translate the maximum point by p
463 }
464
469 void serialize(std::ostream& os) const
470 {
471 mMin.serialize(os);
472 mMax.serialize(os);
473 }
474
479 void deserialize(std::istream& is)
480 {
481 mMin.deserialize(is);
482 mMax.deserialize(is);
483 }
484
491 bool operator==(const Box<PointT>& b) const
492 {
493 return mMin == b.mMin && mMax == b.mMax;
494 }
495
502 bool operator!=(const Box<PointT>& b) const { return !(*this == b); }
503};
504
505/* Specialization Aliases */
506
507template<typename S>
508using Box2 = Box<Point2<S>>;
509
510using Box2i = Box<Point2i>;
511using Box2f = Box<Point2f>;
512using Box2d = Box<Point2d>;
513
514template<typename S>
515using Box3 = Box<Point3<S>>;
516
517using Box3i = Box<Point3i>;
518using Box3f = Box<Point3f>;
519using Box3d = Box<Point3d>;
520
521} // namespace vcl
522
523#endif // VCL_SPACE_CORE_BOX_H
A class representing a box in N-dimensional space.
Definition box.h:49
auto diagonal() const
Calculates the diagonal length of the box.
Definition box.h:249
const PointT & max() const
Returns a const reference to the maximum point of the box.
Definition box.h:114
PointT PointType
The type of point used to represent the corners of the box.
Definition box.h:57
Box(const PointT &p)
Initializes the box with the given point. The box is a valid empty box (meaning that the minimum and ...
Definition box.h:76
const PointT & min() const
Returns a const reference to the minimum point of the box.
Definition box.h:100
auto squaredDiagonal() const
Calculates the squared length of the diagonal of the box.
Definition box.h:255
bool intersects(const Box< PointT > &b) const
Same as Box::overlap.
Definition box.h:242
Box(const PointT &min, const PointT &max)
Initializes the box with the given minimum and maximum points.
Definition box.h:86
bool isInsideStrict(const PointT &p) const
Checks whether a given point is inside the box or not, bounds excluded.
Definition box.h:186
void deserialize(std::istream &is)
Deserializes the box from the given input stream.
Definition box.h:479
void translate(const PointT &p)
Translates the box by summing the values of p.
Definition box.h:459
PointT & max()
Returns a reference to the maximum point of the box.
Definition box.h:107
bool isInsideOpenBox(const PointT &p) const
Checks if a point is inside the open box (max bound excluded); e.g. p in [min, max).
Definition box.h:202
PointT & min()
Returns a reference to the minimum point of the box.
Definition box.h:93
void add(const PointT &p, Scalar radius)
Adds the given point to the current box, expanding this box by a radius around the point,...
Definition box.h:415
void add(const Box< PointT > &b)
Adds the given box to the current box, expanding this box in order that will contain also the b value...
Definition box.h:439
bool overlap(const Box< PointT > &b) const
Check if two boxes overlap.
Definition box.h:217
void add(const PointT &p)
Adds the given point to the current box, expanding this box in order to contain also the values of th...
Definition box.h:388
bool operator!=(const Box< PointT > &b) const
Compares the current box to another box for inequality.
Definition box.h:502
Box()
The Empty constructor of a box, initializes a null box.
Definition box.h:68
static const uint DIM
The dimensionality of the box.
Definition box.h:62
auto minDim() const
Calculates the minimum dimension of the box, which is defined as the smallest difference between the ...
Definition box.h:308
bool isInside(const PointT &p) const
Checks whether a given point is inside the box or not, bounds included.
Definition box.h:166
bool collide(const Box< PointT > &b) const
Same as Box::overlap.
Definition box.h:234
PointT center() const
Calculates the center point of the box.
Definition box.h:262
Box< PointT > intersection(const Box< PointT > &b) const
Computes and returns the intersection between the current box and the given box b.
Definition box.h:342
auto maxDim() const
Computes the maximum dimension of the box, which is defined as the greater difference between the max...
Definition box.h:325
bool isEmpty() const
Checks whether the box is empty or not.
Definition box.h:153
void serialize(std::ostream &os) const
Serializes the box to the given output stream.
Definition box.h:469
auto dim(uint i) const
Get the length of the box along a given dimension.
Definition box.h:295
auto volume() const
Computes the volume of the box.
Definition box.h:277
PointT size() const
Computes the size of the box.
Definition box.h:270
bool operator==(const Box< PointT > &b) const
Compares the current box to another box for equality.
Definition box.h:491
bool isNull() const
Checks whether the box is null or not.
Definition box.h:136
void setNull()
Sets the Box to null. A box is considered null if at least one min component is greater than the corr...
Definition box.h:371
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
constexpr auto max(const T &p1, const T &p2)
Returns the maximum between the two parameters.
Definition min_max.h:83
constexpr auto min(const T &p1, const T &p2)
Returns the minimum between the two parameters.
Definition min_max.h:42