Blender V4.3
BLI_bounds.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
13#include <optional>
14
15#include "BLI_bounds_types.hh"
16#include "BLI_index_mask.hh"
17#include "BLI_math_vector.hh"
18#include "BLI_task.hh"
19
20namespace blender {
21
22namespace bounds {
23
24template<typename T> [[nodiscard]] inline Bounds<T> merge(const Bounds<T> &a, const Bounds<T> &b)
25{
26 return {math::min(a.min, b.min), math::max(a.max, b.max)};
27}
28
29template<typename T>
30[[nodiscard]] inline std::optional<Bounds<T>> merge(const std::optional<Bounds<T>> &a,
31 const std::optional<Bounds<T>> &b)
32{
33 if (a.has_value() && b.has_value()) {
34 return merge(*a, *b);
35 }
36 if (a.has_value()) {
37 return a;
38 }
39 if (b.has_value()) {
40 return b;
41 }
42 return std::nullopt;
43}
44
45template<typename T>
46[[nodiscard]] inline std::optional<Bounds<T>> min_max(const std::optional<Bounds<T>> &a,
47 const T &b)
48{
49 if (a.has_value()) {
50 return merge(*a, {b, b});
51 }
52 return Bounds<T>{b, b};
54
58template<typename T> [[nodiscard]] inline std::optional<Bounds<T>> min_max(const Span<T> values)
59{
60 if (values.is_empty()) {
61 return std::nullopt;
62 }
63 const Bounds<T> init{values.first(), values.first()};
65 values.index_range(),
66 1024,
67 init,
68 [&](const IndexRange range, const Bounds<T> &init) {
69 Bounds<T> result = init;
70 for (const int i : range) {
71 math::min_max(values[i], result.min, result.max);
72 }
73 return result;
74 },
75 [](const Bounds<T> &a, const Bounds<T> &b) { return merge(a, b); });
76}
77
78template<typename T>
79[[nodiscard]] inline std::optional<Bounds<T>> min_max(const IndexMask &mask, const Span<T> values)
80{
81 if (values.is_empty() || mask.is_empty()) {
82 return std::nullopt;
83 }
84 if (mask.size() == values.size()) {
85 /* To avoid mask slice/lookup. */
86 return min_max(values);
87 }
88 const Bounds<T> init{values.first(), values.first()};
90 mask.index_range(),
91 1024,
92 init,
93 [&](const IndexRange range, const Bounds<T> &init) {
94 Bounds<T> result = init;
95 mask.slice(range).foreach_index_optimized<int64_t>(
96 [&](const int i) { math::min_max(values[i], result.min, result.max); });
97 return result;
98 },
99 [](const Bounds<T> &a, const Bounds<T> &b) { return merge(a, b); });
100}
101
106template<typename T, typename RadiusT>
107[[nodiscard]] inline std::optional<Bounds<T>> min_max_with_radii(const Span<T> values,
108 const Span<RadiusT> radii)
109{
110 BLI_assert(values.size() == radii.size());
111 if (values.is_empty()) {
112 return std::nullopt;
113 }
114 const Bounds<T> init{values.first(), values.first()};
115 return threading::parallel_reduce(
116 values.index_range(),
117 1024,
118 init,
119 [&](const IndexRange range, const Bounds<T> &init) {
120 Bounds<T> result = init;
121 for (const int i : range) {
122 result.min = math::min(values[i] - radii[i], result.min);
123 result.max = math::max(values[i] + radii[i], result.max);
124 }
125 return result;
126 },
127 [](const Bounds<T> &a, const Bounds<T> &b) { return merge(a, b); });
128}
129
134template<typename T>
135[[nodiscard]] inline std::optional<Bounds<T>> intersect(const std::optional<Bounds<T>> &a,
136 const std::optional<Bounds<T>> &b)
137{
138 if (!a.has_value() || !b.has_value()) {
139 return std::nullopt;
140 }
141 const Bounds<T> result{math::max(a.value().min, b.value().min),
142 math::min(a.value().max, b.value().max)};
143 if (result.is_empty()) {
144 return std::nullopt;
145 }
146 return result;
147}
148
149} // namespace bounds
150
151namespace detail {
152
153template<typename T, int Size>
154[[nodiscard]] inline bool any_less_or_equal_than(const VecBase<T, Size> &a,
155 const VecBase<T, Size> &b)
156{
157 for (int i = 0; i < Size; i++) {
158 if (a[i] <= b[i]) {
159 return true;
160 }
161 }
162 return false;
163}
164
165} // namespace detail
166
167template<typename T> inline bool Bounds<T>::is_empty() const
168{
169 if constexpr (std::is_integral<T>::value || std::is_floating_point<T>::value) {
170 return this->max <= this->min;
171 }
172 else {
173 return detail::any_less_or_equal_than(this->max, this->min);
174 }
175}
176
177template<typename T> inline T Bounds<T>::center() const
178{
179 return math::midpoint(this->min, this->max);
180}
181
182template<typename T> inline T Bounds<T>::size() const
183{
184 return math::abs(max - min);
185}
186
187template<typename T> inline void Bounds<T>::translate(const T &offset)
188{
189 this->min += offset;
190 this->max += offset;
191}
192
193template<typename T> inline void Bounds<T>::scale_from_center(const T &scale)
194{
195 const T center = this->center();
196 const T new_half_size = this->size() / T(2) * scale;
197 this->min = center - new_half_size;
198 this->max = center + new_half_size;
199}
200
201template<typename T> inline void Bounds<T>::resize(const T &new_size)
202{
203 this->min = this->center() - (new_size / T(2));
204 this->max = this->min + new_size;
205}
206
207template<typename T> inline void Bounds<T>::recenter(const T &new_center)
208{
209 const T offset = new_center - this->center();
210 this->translate(offset);
211}
212
213template<typename T>
214template<typename PaddingT>
215inline void Bounds<T>::pad(const PaddingT &padding)
216{
217 this->min = this->min - padding;
218 this->max = this->max + padding;
219}
220
221} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:50
__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
Definition boundbox.h:178
void init()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
local_group_size(16, 16) .push_constant(Type b
uint padding(uint offset, uint alignment)
OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds &cone_b)
#define T
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:24
std::optional< Bounds< T > > min_max_with_radii(const Span< T > values, const Span< RadiusT > radii)
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
Definition BLI_bounds.hh:46
bool any_less_or_equal_than(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T min(const T &a, const T &b)
T midpoint(const T &a, const T &b)
T max(const T &a, const T &b)
T abs(const T &a)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:153
#define min(a, b)
Definition sort.c:32