Visual Computing Library  devel
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
28namespace vcl {
29
44template<PointConcept PointT>
45class Box
46{
47 PointT mMin;
48 PointT mMax;
49
50public:
54 using PointType = PointT;
55
59 static const uint DIM = PointT::DIM;
60
65 Box() { setNull(); }
66
73 Box(const PointT& p) : mMin(p), mMax(p) {}
74
83 Box(const PointT& min, const PointT& max) : mMin(min), mMax(max) {}
84
90 PointT& min() { return mMin; }
91
97 const PointT& min() const { return mMin; }
98
104 PointT& max() { return mMax; }
105
111 const PointT& max() const { return mMax; }
112
113 template<typename Scalar>
114 auto cast() const
115 {
116 if constexpr (std::is_same_v<typename PointT::ScalarType, Scalar>) {
117 return *this;
118 }
119 else {
121 mMin.template cast<Scalar>(), mMax.template cast<Scalar>());
122 }
123 }
124
133 bool isNull() const
134 {
135 for (uint i = 0; i < PointT::DIM; ++i) {
136 if (mMin[i] > mMax[i])
137 return true;
138 }
139 return false;
140 }
141
150 bool isEmpty() const { return mMin == mMax; }
151
163 bool isInside(const PointT& p) const
164 {
165 for (uint i = 0; i < PointT::DIM; ++i) {
166 if (p[i] < mMin[i] || p[i] > mMax[i])
167 return false;
168 }
169 return true;
170 }
171
183 bool isInsideStrict(const PointT& p) const
184 {
185 for (uint i = 0; i < PointT::DIM; ++i) {
186 if (p[i] <= mMin[i] || p[i] >= mMax[i])
187 return false;
188 }
189 return true;
190 }
191
199 bool isInsideOpenBox(const PointT& p) const
200 {
201 for (uint i = 0; i < PointT::DIM; ++i) {
202 if (p[i] < mMin[i] || p[i] >= mMax[i])
203 return false;
204 }
205 return true;
206 }
207
214 bool overlap(const Box<PointT>& b) const
215 {
216 // Check if any dimension of the boxes does not overlap.
217 for (uint i = 0; i < PointT::DIM; ++i) {
218 if (b.mMin[i] >= mMax[i] || b.mMax[i] <= mMin[i])
219 return false;
220 }
221 // All dimensions overlap, the boxes collide.
222 return true;
223 }
224
231 bool collide(const Box<PointT>& b) const { return overlap(b); }
232
239 bool intersects(const Box<PointT>& b) const { return overlap(b); }
240
246 auto diagonal() const { return mMin.dist(mMax); }
247
252 auto squaredDiagonal() const { return mMin.squaredDist(mMax); }
253
259 PointT center() const { return (mMax + mMin) / 2; }
260
267 PointT size() const { return mMax - mMin; }
268
274 auto volume() const
275 {
276 // Initialize volume as the width of the first dimension.
277 auto vol = mMax[0] - mMin[0];
278 // Multiply by the width of each dimension.
279 for (uint i = 1; i < PointT::DIM; ++i) {
280 vol *= mMax[i] - mMin[i];
281 }
282 return vol;
283 }
284
292 auto dim(uint i) const
293 {
294 assert(i < PointT::DIM);
295 return mMax[i] - mMin[i];
296 }
297
305 auto minDim() const
306 {
307 auto m = mMax[0] - mMin[0];
308 for (uint i = 1; i < PointT::DIM; ++i) {
309 if (mMax[i] - mMin[i] < m)
310 m = mMax[i] - mMin[i];
311 }
312 return m;
313 }
314
322 auto maxDim() const
323 {
324 auto m = mMax[0] - mMin[0];
325 for (uint i = 1; i < PointT::DIM; ++i) {
326 if (mMax[i] - mMin[i] > m)
327 m = mMax[i] - mMin[i];
328 }
329 return m;
330 }
331
340 {
341 Box<PointT> res = *this;
342 for (uint i = 0; i < PointT::DIM; ++i) {
343 if (mMin[i] < b.mMin[i]) {
344 // set the minimum point to the larger value
345 res.mMin[i] = b.mMin[i];
346 }
347 if (mMax[i] > b.mMax[i]) {
348 // set the maximum point to the smaller value
349 res.mMax[i] = b.mMax[i];
350 }
351 if (res.mMin[i] > res.mMax[i]) {
352 // if the minimum point is larger than the maximum point, the
353 // box is null
354 res.setNull();
355 return res;
356 }
357 }
358 return res;
359 }
360
368 void setNull()
369 {
370 mMin.setConstant(
371 std::numeric_limits<typename PointT::ScalarType>::max());
372 mMax.setConstant(
373 std::numeric_limits<typename PointT::ScalarType>::lowest());
374 }
375
385 void add(const PointT& p)
386 {
387 if (isNull()) {
388 // If the box was null, set both the minimum and maximum points to
389 // the given point
390 *this = Box(p);
391 }
392 else {
393 // Expand the current box to include the added point
394 mMin = vcl::min(mMin, p);
395 mMax = vcl::max(mMax, p);
396 }
397 }
398
411 template<typename Scalar>
412 void add(const PointT& p, Scalar radius)
413 {
414 if (isNull()) {
415 // If the box was null, initialize it with the minimum and maximum
416 // points obtained by subtracting and adding the radius to the given
417 // point
418 *this = Box(p - radius, p + radius);
419 }
420 else {
421 // Expand the current box to include the added point and all points
422 // within the radius around it
423 mMin = vcl::min(mMin, p - radius);
424 mMax = vcl::max(mMax, p + radius);
425 }
426 }
427
436 void add(const Box<PointT>& b)
437 {
438 // Adding a null box should do nothing
439 if (!b.isNull()) {
440 if (isNull()) {
441 *this = b; // if the current box is null, set it equal to b
442 }
443 else {
444 // expand this box to contain the minimum and maximum point of b
445 add(b.mMin);
446 add(b.mMax);
447 }
448 }
449 }
450
456 void translate(const PointT& p)
457 {
458 mMin += p; // translate the minimum point by p
459 mMax += p; // translate the maximum point by p
460 }
461
466 void serialize(std::ostream& os) const
467 {
468 mMin.serialize(os);
469 mMax.serialize(os);
470 }
471
476 void deserialize(std::istream& is)
477 {
478 mMin.deserialize(is);
479 mMax.deserialize(is);
480 }
481
488 bool operator==(const Box<PointT>& b) const
489 {
490 return mMin == b.mMin && mMax == b.mMax;
491 }
492
499 bool operator!=(const Box<PointT>& b) const { return !(*this == b); }
500};
501
502/* Specialization Aliases */
503
504template<typename S>
505using Box2 = Box<Point2<S>>;
506
507using Box2i = Box<Point2i>;
508using Box2f = Box<Point2f>;
509using Box2d = Box<Point2d>;
510
511template<typename S>
512using Box3 = Box<Point3<S>>;
513
514using Box3i = Box<Point3i>;
515using Box3f = Box<Point3f>;
516using Box3d = Box<Point3d>;
517
518/* Concepts */
519
530template<typename T>
531concept BoxConcept = std::derived_from< // same type or derived type
532 std::remove_cvref_t<T>,
533 Box<typename RemoveRef<T>::PointType>>;
534
545template<typename T>
546concept Box2Concept = BoxConcept<T> && RemoveRef<T>::DIM == 2;
547
558template<typename T>
559concept Box3Concept = BoxConcept<T> && RemoveRef<T>::DIM == 3;
560
561} // namespace vcl
562
563#endif // VCL_SPACE_CORE_BOX_H
A class representing a box in N-dimensional space.
Definition box.h:46
auto diagonal() const
Calculates the diagonal length of the box.
Definition box.h:246
const PointT & max() const
Returns a const reference to the maximum point of the box.
Definition box.h:111
PointT PointType
The type of point used to represent the corners of the box.
Definition box.h:54
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:73
const PointT & min() const
Returns a const reference to the minimum point of the box.
Definition box.h:97
auto squaredDiagonal() const
Calculates the squared length of the diagonal of the box.
Definition box.h:252
bool intersects(const Box< PointT > &b) const
Same as Box::overlap.
Definition box.h:239
Box(const PointT &min, const PointT &max)
Initializes the box with the given minimum and maximum points.
Definition box.h:83
bool isInsideStrict(const PointT &p) const
Checks whether a given point is inside the box or not, bounds excluded.
Definition box.h:183
void deserialize(std::istream &is)
Deserializes the box from the given input stream.
Definition box.h:476
void translate(const PointT &p)
Translates the box by summing the values of p.
Definition box.h:456
PointT & max()
Returns a reference to the maximum point of the box.
Definition box.h:104
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:199
PointT & min()
Returns a reference to the minimum point of the box.
Definition box.h:90
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:412
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:436
bool overlap(const Box< PointT > &b) const
Check if two boxes overlap.
Definition box.h:214
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:385
bool operator!=(const Box< PointT > &b) const
Compares the current box to another box for inequality.
Definition box.h:499
Box()
The Empty constructor of a box, initializes a null box.
Definition box.h:65
static const uint DIM
The dimensionality of the box.
Definition box.h:59
auto minDim() const
Calculates the minimum dimension of the box, which is defined as the smallest difference between the ...
Definition box.h:305
bool isInside(const PointT &p) const
Checks whether a given point is inside the box or not, bounds included.
Definition box.h:163
bool collide(const Box< PointT > &b) const
Same as Box::overlap.
Definition box.h:231
PointT center() const
Calculates the center point of the box.
Definition box.h:259
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:339
auto maxDim() const
Computes the maximum dimension of the box, which is defined as the greater difference between the max...
Definition box.h:322
bool isEmpty() const
Checks whether the box is empty or not.
Definition box.h:150
void serialize(std::ostream &os) const
Serializes the box to the given output stream.
Definition box.h:466
auto dim(uint i) const
Get the length of the box along a given dimension.
Definition box.h:292
auto volume() const
Computes the volume of the box.
Definition box.h:274
PointT size() const
Computes the size of the box.
Definition box.h:267
bool operator==(const Box< PointT > &b) const
Compares the current box to another box for equality.
Definition box.h:488
bool isNull() const
Checks whether the box is null or not.
Definition box.h:133
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:368
A concept representing a 2D Box.
Definition box.h:546
A concept representing a 3D Box.
Definition box.h:559
A concept representing a Box.
Definition box.h:531
constexpr auto max(const T &p1, const T &p2)
Returns the maximum between the two parameters.
Definition min_max.h:81
constexpr auto min(const T &p1, const T &p2)
Returns the minimum between the two parameters.
Definition min_max.h:40