pbpt
Loading...
Searching...
No Matches
bounding_box.hpp
1#pragma once
2
3#include "global.hpp"
4#include "math/vector.hpp"
5#include "point.hpp"
6#include <type_traits>
7#include <vector>
8
9namespace pbpt::math {
10
11template<typename T, int N>
12requires (N > 0) && (std::is_floating_point_v<T>)
13class BoundingBox {
14private:
15 Point<T, N> m_min;
16 Point<T, N> m_max;
17
18public:
19
20 constexpr BoundingBox() noexcept :
21 m_min(Point<T, N>::filled(std::numeric_limits<T>::max())),
22 m_max(Point<T, N>::filled(std::numeric_limits<T>::lowest())) {}
23
24 template<typename ...Args>
25 requires (std::is_same_v<Point<T, N>, Args> && ...) && (sizeof...(Args) > 0)
26 constexpr explicit BoundingBox(const Args&... args) noexcept {
27 // 将点解包到数组中以访问第一个元素
28 const Point<T, N> points[] = {args...};
29 m_min = points[0];
30 m_max = points[0];
31 // 从第二个元素开始合并
32 for (size_t i = 1; i < sizeof...(args); ++i) {
33 unite(points[i]);
34 }
35 }
36
37 constexpr BoundingBox& unite(const Point<T, N>& point) noexcept {
38 for (int i = 0; i < N; ++i) {
39 m_min[i] = std::min(m_min[i], point[i]);
40 m_max[i] = std::max(m_max[i], point[i]);
41 }
42 return *this;
43 }
44
45 constexpr BoundingBox& unite(const BoundingBox& box) noexcept {
46 unite(box.min());
47 unite(box.max());
48 return *this;
49 }
50
51 constexpr BoundingBox& unite(const std::vector<Point<T, N>>& points) noexcept {
52 for (const auto& p : points) {
53 unite(p);
54 }
55 return *this;
56 }
57
58 constexpr BoundingBox& unite(const std::vector<BoundingBox>& boxes) noexcept {
59 for (const auto& box : boxes) {
60 unite(box);
61 }
62 return *this;
63 }
64
65 constexpr BoundingBox united(const Point<T, N>& point) const noexcept {
66 BoundingBox<T, N> box(*this);
67 box.unite(point);
68 return box;
69 }
70
71 constexpr BoundingBox& united(const BoundingBox& box) noexcept {
72 BoundingBox<T, N> box_united(*this);
73 box_united.unite(box.min());
74 box_united.unite(box.max());
75 return box_united;
76 }
77
78 constexpr BoundingBox united(const std::vector<Point<T, N>>& points) const noexcept {
79 BoundingBox<T, N> box(*this);
80 box.unite(points);
81 return box;
82 }
83
84
85 constexpr BoundingBox united(const std::vector<BoundingBox>& boxes) const noexcept {
86 BoundingBox<T, N> box(*this);
87 box.unite(boxes);
88 return box;
89 }
90
97 constexpr bool is_overlapped(const BoundingBox& box) const noexcept {
98 return contains(box.min()) || contains(box.max());
99 }
100
106 constexpr BoundingBox overlapped_box(const BoundingBox& box) const noexcept {
107 BoundingBox<T, N> overlapped_box(*this);
108 for (int i = 0; i < N; ++i) {
109 overlapped_box.m_min[i] = std::max(overlapped_box.m_min[i], box.m_min[i]);
110 overlapped_box.m_max[i] = std::min(overlapped_box.m_max[i], box.m_max[i]);
111 }
112 return overlapped_box;
113 }
114
120 constexpr bool contains(const Point<T, N>& point) const noexcept {
121 for (int i = 0; i < N; ++i) {
122 if (point[i] < m_min[i] || point[i] > m_max[i]) {
123 return false;
124 }
125 }
126 return true;
127 }
128
133 constexpr int max_extent() const noexcept {
134 int max_extent = 0;
135 T max_diff = m_max[0] - m_min[0];
136 for (int i = 1; i < N; ++i) {
137 T diff = m_max[i] - m_min[i];
138 if (diff > max_diff) {
139 max_diff = diff;
140 max_extent = i;
141 }
142 }
143 return max_extent;
144 }
145
151 constexpr Vector<T, N> offset(const Point<T, N>& p) const noexcept {
153 for (int i = 0; i < N; ++i) {
154 offset[i] = (p[i] - m_min[i]) / (m_max[i] - m_min[i]);
155 }
156 return offset;
157 }
158
163 constexpr const Point<T, N>& min() const noexcept { return m_min; }
164
169 constexpr const Point<T, N>& max() const noexcept { return m_max; }
170
175 constexpr Point<T, N> center() const noexcept {
176 return m_min.mid(m_max);
177 }
178
183 constexpr Vector<T, N> diagonal() const noexcept {
184 return m_max - m_min;
185 }
186
191 constexpr T volume() const noexcept {
192 return diagonal().product();
193 }
194
199 constexpr T surface_area() const noexcept requires (N == 3) {
200 auto diag = diagonal();
201 return 2 * (diag.x() * diag.y() + diag.y() * diag.z() + diag.z() * diag.x());
202 }
203
210 friend std::ostream& operator<<(std::ostream& os, const BoundingBox& box) {
211 os << "BoundingBox(" << box.m_min << ", " << box.m_max << ")";
212 return os;
213 }
214
215};
216
227
228}
229
Definition bounding_box.hpp:13
constexpr bool contains(const Point< T, N > &point) const noexcept
Check if the bounding box contains the point.
Definition bounding_box.hpp:120
constexpr T surface_area() const noexcept
Get the surface area of the bounding box.
Definition bounding_box.hpp:199
constexpr BoundingBox overlapped_box(const BoundingBox &box) const noexcept
Get the overlapped box.
Definition bounding_box.hpp:106
constexpr const Point< T, N > & max() const noexcept
Get the maximum point of the bounding box.
Definition bounding_box.hpp:169
constexpr Point< T, N > center() const noexcept
Get the center point of the bounding box.
Definition bounding_box.hpp:175
constexpr const Point< T, N > & min() const noexcept
Get the minimum point of the bounding box.
Definition bounding_box.hpp:163
constexpr Vector< T, N > offset(const Point< T, N > &p) const noexcept
Get the offset of the point relative to the bounding box.
Definition bounding_box.hpp:151
constexpr bool is_overlapped(const BoundingBox &box) const noexcept
is_overlapped
Definition bounding_box.hpp:97
constexpr Vector< T, N > diagonal() const noexcept
Get the diagonal of the bounding box.
Definition bounding_box.hpp:183
constexpr int max_extent() const noexcept
Get the maximum extent of the bounding box.
Definition bounding_box.hpp:133
friend std::ostream & operator<<(std::ostream &os, const BoundingBox &box)
stream output
Definition bounding_box.hpp:210
constexpr T volume() const noexcept
Get the volume of the bounding box.
Definition bounding_box.hpp:191
A template class for an N-dimensional point in space.
Definition point.hpp:37
static constexpr Point filled(T value) noexcept
Creates a point filled with a specified value.
Definition point.hpp:52
A template class for N-dimensional mathematical vectors.
Definition vector.hpp:35
Defines the primary floating-point type alias for the math library.
The namespace for math library implementation.
Definition bounding_box.hpp:9
BoundingBox< Float, 3 > Bound3
3D bounding box
Definition bounding_box.hpp:221
BoundingBox< Float, 2 > Bound2
2D bounding box
Definition bounding_box.hpp:226
Defines a generic, N-dimensional Point class and its geometric operations.
Defines a generic, N-dimensional, constexpr-friendly vector class.