MeshLib C++ Docs
Loading...
Searching...
No Matches
MRMesh/MRBox.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMeshFwd.h"
4#include "MRAffineXf3.h"
5#include "MRVectorTraits.h"
6#include <algorithm>
7#include <cassert>
8#include <limits>
9#include <type_traits>
10
11namespace MR
12{
13
17
19template <typename T>
20std::array<Vector3<T>, 8> getCorners( const Box<Vector3<T>> & box );
21
23template <typename V>
24struct Box
25{
26public:
28 using T = typename VTraits::BaseType;
29 static constexpr int elements = VTraits::size;
30 using Vb = typename VTraits::template ChangeBaseType<bool>; //if V is Vector3<T> then Vb is Vector3b
32
33 V min, max;
34
36 const V & operator []( int e ) const { return *( &min + e ); }
37 V & operator []( int e ) { return *( &min + e ); }
38
40 Box() : min{ VTraits::diagonal( std::numeric_limits<T>::max() ) }, max{ VTraits::diagonal( std::numeric_limits<T>::lowest() ) } { }
41 Box( const V& min, const V& max ) : min{ min }, max{ max } { }
42
44 template <typename VV = V, typename std::enable_if_t<VectorTraits<VV>::supportNoInit, int> = 0>
45 explicit Box( NoInit ) : min{ noInit }, max{ noInit } { }
46
47 template <typename VV = V, typename std::enable_if_t<!VectorTraits<VV>::supportNoInit, int> = 0>
48 explicit Box( NoInit ) { }
49
50 template <typename U>
51 explicit Box( const Box<U> & a ) : min{ a.min }, max{ a.max } { }
52
53 static Box fromMinAndSize( const V& min, const V& size ) { return Box{ min, V( min + size ) }; }
54
56 bool valid() const
57 {
58 for ( int i = 0; i < elements; ++i )
59 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, max ) )
60 return false;
61 return true;
62 }
63
65 V center() const { assert( valid() ); return ( min + max ) / T(2); }
66
70 V corner( const Vb& c ) const
71 {
72 V res;
73 for ( int i = 0; i < elements; ++i )
74 VTraits::getElem( i, res ) = VTraits::getElem( i, operator[]( VbTraits::getElem( i, c ) ) );
75 return res;
76 }
77
80 static Vb getMinBoxCorner( const V & n )
81 {
82 Vb res;
83 for ( int i = 0; i < elements; ++i )
84 VbTraits::getElem( i, res ) = VTraits::getElem( i, n ) < 0;
85 return res;
86 }
87
89 V size() const { assert( valid() ); return max - min; }
90
92 T diagonal() const { return std::sqrt( sqr( size() ) ); }
93
95 T volume() const
96 {
97 assert( valid() );
98 T res{ 1 };
99 for ( int i = 0; i < elements; ++i )
100 res *= VTraits::getElem( i, max ) - VTraits::getElem( i, min );
101 return res;
102 }
103
105 void include( const V & pt )
106 {
107 for ( int i = 0; i < elements; ++i )
108 {
109 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, pt );
110 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, pt );
111 }
112 }
113
115 void include( const Box & b )
116 {
117 for ( int i = 0; i < elements; ++i )
118 {
119 if ( VTraits::getElem( i, b.min ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, b.min );
120 if ( VTraits::getElem( i, b.max ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, b.max );
121 }
122 }
123
125 bool contains( const V & pt ) const
126 {
127 for ( int i = 0; i < elements; ++i )
128 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, pt ) || VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
129 return false;
130 return true;
131 }
132
134 V getBoxClosestPointTo( const V & pt ) const
135 {
136 assert( valid() );
137 V res;
138 for ( int i = 0; i < elements; ++i )
139 VTraits::getElem( i, res ) = std::clamp( VTraits::getElem( i, pt ), VTraits::getElem( i, min ), VTraits::getElem( i, max ) );
140 return res;
141 }
142
144 bool intersects( const Box & b ) const
145 {
146 for ( int i = 0; i < elements; ++i )
147 {
148 if ( VTraits::getElem( i, b.max ) < VTraits::getElem( i, min ) || VTraits::getElem( i, b.min ) > VTraits::getElem( i, max ) )
149 return false;
150 }
151 return true;
152 }
153
155 Box intersection( const Box & b ) const
156 {
157 Box res;
158 for ( int i = 0; i < elements; ++i )
159 {
160 VTraits::getElem( i, res.min ) = std::max( VTraits::getElem( i, min ), VTraits::getElem( i, b.min ) );
161 VTraits::getElem( i, res.max ) = std::min( VTraits::getElem( i, max ), VTraits::getElem( i, b.max ) );
162 }
163 return res;
164 }
165 Box & intersect( const Box & b ) { return *this = intersection( b ); }
166
169 T getDistanceSq( const Box & b ) const
170 {
171 auto ibox = intersection( b );
172 T distSq = 0;
173 for ( int i = 0; i < elements; ++i )
174 if ( VTraits::getElem( i, ibox.min ) > VTraits::getElem( i, ibox.max ) )
175 distSq += sqr( VTraits::getElem( i, ibox.min ) - VTraits::getElem( i, ibox.max ) );
176 return distSq;
177 }
178
181 T getDistanceSq( const V & pt ) const
182 {
183 assert( valid() );
184 T res{};
185 for ( int i = 0; i < elements; ++i )
186 {
187 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) )
188 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, min ) );
189 else
190 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
191 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, max ) );
192 }
193 return res;
194 }
195
197 Box expanded( const V & expansion ) const
198 {
199 assert( valid() );
200 return Box( min - expansion, max + expansion );
201 }
202
205 {
206 assert( valid() );
207 Box res;
208 for ( int i = 0; i < elements; ++i )
209 {
210 VTraits::getElem( i, res.min ) = std::nextafter( VTraits::getElem( i, min ), std::numeric_limits<T>::lowest() );
211 VTraits::getElem( i, res.max ) = std::nextafter( VTraits::getElem( i, max ), std::numeric_limits<T>::max() );
212 }
213 return res;
214 }
215
216 bool operator == ( const Box & a ) const
217 { return min == a.min && max == a.max; }
218 bool operator != ( const Box & a ) const
219 { return !( *this == a ); }
220};
221
222template <typename T>
223inline std::array<Vector3<T>, 8> getCorners( const Box<Vector3<T>> & box )
224{
225 assert( box.valid() );
226 return
227 {
228 Vector3<T>{ box.min.x, box.min.y, box.min.z },
229 Vector3<T>{ box.max.x, box.min.y, box.min.z },
230 Vector3<T>{ box.min.x, box.max.y, box.min.z },
231 Vector3<T>{ box.max.x, box.max.y, box.min.z },
232 Vector3<T>{ box.min.x, box.min.y, box.max.z },
233 Vector3<T>{ box.max.x, box.min.y, box.max.z },
234 Vector3<T>{ box.min.x, box.max.y, box.max.z },
235 Vector3<T>{ box.max.x, box.max.y, box.max.z }
236 };
237}
238
239template <typename T>
240inline std::array<Vector2<T>, 4> getCorners( const Box<Vector2<T>> & box )
241{
242 assert( box.valid() );
243 return
244 {
245 Vector2<T>{ box.min.x, box.min.y },
246 Vector2<T>{ box.max.x, box.min.y },
247 Vector2<T>{ box.min.x, box.max.y },
248 Vector2<T>{ box.max.x, box.max.y }
249 };
250}
251
254template <typename V>
255MinMax<typename Box<V>::T> getTouchPlanes( const Box<V> & box, const V & n )
256{
257 auto minCorner = box.getMinBoxCorner( n );
258 auto maxCorner = minCorner;
259 for ( auto & v : maxCorner )
260 v = !v;
261 return
262 {
263 dot( n, box.corner( minCorner ) ),
264 dot( n, box.corner( maxCorner ) )
265 };
266}
267
269template <typename V>
270inline Box<V> transformed( const Box<V> & box, const AffineXf<V> & xf )
271{
272 if ( !box.valid() )
273 return {};
274 Box<V> res;
275 for ( const auto & p : getCorners( box ) )
276 res.include( xf( p ) );
277 return res;
278}
280template <typename V>
281inline Box<V> transformed( const Box<V> & box, const AffineXf<V> * xf )
282{
283 return xf ? transformed( box, *xf ) : box;
284}
285
287template <typename V>
288inline auto width( const Box<V>& box )
289{
290 return box.max.x - box.min.x;
291}
292
294template <typename V>
295inline auto height( const Box<V>& box )
296{
297 return box.max.y - box.min.y;
298}
299
301template <typename V>
302inline auto depth( const Box<V>& box )
303{
304 return box.max.z - box.min.z;
305}
306
308template<size_t I, typename V>
309constexpr const V& get( const Box<V>& box ) noexcept { return box[int( I )]; }
310template<size_t I, typename V>
311constexpr V& get( Box<V>& box ) noexcept { return box[int( I )]; }
312
314
315} // namespace MR
316
317namespace std
318{
319
320template<size_t I, typename V>
321struct tuple_element<I, MR::Box<V>> { using type = V; };
322
323template <typename V>
324struct tuple_size<MR::Box<V>> : integral_constant<size_t, 2> {};
325
326} //namespace std
auto width(const Box< V > &box)
returns size along x axis
Definition MRMesh/MRBox.h:288
constexpr const V & get(const Box< V > &box) noexcept
get<0> returns min, get<1> returns max
Definition MRMesh/MRBox.h:309
std::array< Vector3< T >, 8 > getCorners(const Box< Vector3< T > > &box)
returns all corners of given box
Definition MRMesh/MRBox.h:223
auto height(const Box< V > &box)
returns size along y axis
Definition MRMesh/MRBox.h:295
auto depth(const Box< V > &box)
returns size along z axis
Definition MRMesh/MRBox.h:302
Box< V > transformed(const Box< V > &box, const AffineXf< V > &xf)
find the tightest box enclosing this one after transformation
Definition MRMesh/MRBox.h:270
MinMax< typename Box< V >::T > getTouchPlanes(const Box< V > &box, const V &n)
Definition MRMesh/MRBox.h:255
constexpr T sqr(T x) noexcept
squared value
Definition MRMesh/MRMeshFwd.h:661
Box
Definition MRMesh/MRMeshFwd.h:331
constexpr NoInit noInit
Definition MRMesh/MRMeshFwd.h:90
I
Definition MRMesh/MRMeshFwd.h:121
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:170
Definition MRMesh/MRAffineXf.h:14
Box given by its min- and max- corners.
Definition MRMesh/MRBox.h:25
Box(const V &min, const V &max)
Definition MRMesh/MRBox.h:41
typename VTraits::BaseType T
Definition MRMesh/MRBox.h:28
void include(const V &pt)
minimally increases the box to include given point
Definition MRMesh/MRBox.h:105
typename VTraits::template ChangeBaseType< bool > Vb
Definition MRMesh/MRBox.h:30
V getBoxClosestPointTo(const V &pt) const
returns closest point in the box to given point
Definition MRMesh/MRBox.h:134
T getDistanceSq(const Box &b) const
Definition MRMesh/MRBox.h:169
T diagonal() const
computes length from min to max
Definition MRMesh/MRBox.h:92
void include(const Box &b)
minimally increases the box to include another box
Definition MRMesh/MRBox.h:115
Box expanded(const V &expansion) const
decreases min and increased max on given value
Definition MRMesh/MRBox.h:197
V max
Definition MRMesh/MRBox.h:33
Box insignificantlyExpanded() const
decreases min and increases max to their closest representable value
Definition MRMesh/MRBox.h:204
V corner(const Vb &c) const
Definition MRMesh/MRBox.h:70
V center() const
computes center of the box
Definition MRMesh/MRBox.h:65
T getDistanceSq(const V &pt) const
Definition MRMesh/MRBox.h:181
V size() const
computes size of the box in all dimensions
Definition MRMesh/MRBox.h:89
static Vb getMinBoxCorner(const V &n)
Definition MRMesh/MRBox.h:80
bool intersects(const Box &b) const
checks whether this box intersects or touches given box
Definition MRMesh/MRBox.h:144
static constexpr int elements
Definition MRMesh/MRBox.h:29
T volume() const
computes the volume of this box
Definition MRMesh/MRBox.h:95
static Box fromMinAndSize(const V &min, const V &size)
Definition MRMesh/MRBox.h:53
Box()
create invalid box by default
Definition MRMesh/MRBox.h:40
const V & operator[](int e) const
min/max access by 0/1 index
Definition MRMesh/MRBox.h:36
bool operator!=(const Box &a) const
Definition MRMesh/MRBox.h:218
V min
Definition MRMesh/MRBox.h:33
Box intersection(const Box &b) const
computes intersection between this and other box
Definition MRMesh/MRBox.h:155
bool contains(const V &pt) const
checks whether given point is inside (including the surface) of the box
Definition MRMesh/MRBox.h:125
Box & intersect(const Box &b)
Definition MRMesh/MRBox.h:165
Box(const Box< U > &a)
Definition MRMesh/MRBox.h:51
bool valid() const
true if the box contains at least one point
Definition MRMesh/MRBox.h:56
Box(NoInit)
skip initialization of min/max
Definition MRMesh/MRBox.h:45
bool operator==(const Box &a) const
Definition MRMesh/MRBox.h:216
Definition MRMesh/MRMeshFwd.h:89
Definition MRVector2.h:25
T x
Definition MRVector2.h:31
Definition MRMesh/MRVector3.h:26
T x
Definition MRMesh/MRVector3.h:32
Definition MRMesh/MRVectorTraits.h:15
static constexpr int size
Definition MRMesh/MRVectorTraits.h:19
static constexpr auto && getElem(int i, U &&value)
Definition MRMesh/MRVectorTraits.h:29
T BaseType
Definition MRMesh/MRVectorTraits.h:18