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
90 static Vb getMaxBoxCorner( const V & n )
91 {
92 return getMinBoxCorner( -n );
93 }
94
96 V size() const { assert( valid() ); return max - min; }
97
99 T diagonal() const { return std::sqrt( sqr( size() ) ); }
100
102 T volume() const
103 {
104 assert( valid() );
105 T res{ 1 };
106 for ( int i = 0; i < elements; ++i )
107 res *= VTraits::getElem( i, max ) - VTraits::getElem( i, min );
108 return res;
109 }
110
112 void include( const V & pt )
113 {
114 for ( int i = 0; i < elements; ++i )
115 {
116 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, pt );
117 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, pt );
118 }
119 }
120
122 void include( const Box & b )
123 {
124 for ( int i = 0; i < elements; ++i )
125 {
126 if ( VTraits::getElem( i, b.min ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, b.min );
127 if ( VTraits::getElem( i, b.max ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, b.max );
128 }
129 }
130
132 bool contains( const V & pt ) const
133 {
134 for ( int i = 0; i < elements; ++i )
135 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, pt ) || VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
136 return false;
137 return true;
138 }
139
141 bool contains( const Box& otherbox ) const
142 {
143 for ( int i = 0; i < elements; ++i )
144 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, otherbox.min ) || VTraits::getElem( i, otherbox.max ) > VTraits::getElem( i, max ) )
145 return false;
146 return true;
147 }
148
150 V getBoxClosestPointTo( const V & pt ) const
151 {
152 assert( valid() );
153 V res;
154 for ( int i = 0; i < elements; ++i )
155 VTraits::getElem( i, res ) = std::clamp( VTraits::getElem( i, pt ), VTraits::getElem( i, min ), VTraits::getElem( i, max ) );
156 return res;
157 }
158
160 bool intersects( const Box & b ) const
161 {
162 for ( int i = 0; i < elements; ++i )
163 {
164 if ( VTraits::getElem( i, b.max ) < VTraits::getElem( i, min ) || VTraits::getElem( i, b.min ) > VTraits::getElem( i, max ) )
165 return false;
166 }
167 return true;
168 }
169
171 Box intersection( const Box & b ) const
172 {
173 Box res;
174 for ( int i = 0; i < elements; ++i )
175 {
176 VTraits::getElem( i, res.min ) = std::max( VTraits::getElem( i, min ), VTraits::getElem( i, b.min ) );
177 VTraits::getElem( i, res.max ) = std::min( VTraits::getElem( i, max ), VTraits::getElem( i, b.max ) );
178 }
179 return res;
180 }
181 Box & intersect( const Box & b ) { return *this = intersection( b ); }
182
185 T getDistanceSq( const Box & b ) const
186 {
187 auto ibox = intersection( b );
188 T distSq = 0;
189 for ( int i = 0; i < elements; ++i )
190 if ( VTraits::getElem( i, ibox.min ) > VTraits::getElem( i, ibox.max ) )
191 distSq += sqr( VTraits::getElem( i, ibox.min ) - VTraits::getElem( i, ibox.max ) );
192 return distSq;
193 }
194
197 T getDistanceSq( const V & pt ) const
198 {
199 assert( valid() );
200 T res{};
201 for ( int i = 0; i < elements; ++i )
202 {
203 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) )
204 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, min ) );
205 else
206 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
207 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, max ) );
208 }
209 return res;
210 }
211
213 Box expanded( const V & expansion ) const
214 {
215 assert( valid() );
216 return Box( min - expansion, max + expansion );
217 }
218
221 {
222 assert( valid() );
223 Box res;
224 for ( int i = 0; i < elements; ++i )
225 {
226 VTraits::getElem( i, res.min ) = std::nextafter( VTraits::getElem( i, min ), std::numeric_limits<T>::lowest() );
227 VTraits::getElem( i, res.max ) = std::nextafter( VTraits::getElem( i, max ), std::numeric_limits<T>::max() );
228 }
229 return res;
230 }
231
232 bool operator == ( const Box & a ) const
233 { return min == a.min && max == a.max; }
234 bool operator != ( const Box & a ) const
235 { return !( *this == a ); }
236};
237
238template <typename T>
239inline std::array<Vector3<T>, 8> getCorners( const Box<Vector3<T>> & box )
240{
241 assert( box.valid() );
242 return
243 {
244 Vector3<T>{ box.min.x, box.min.y, box.min.z },
245 Vector3<T>{ box.max.x, box.min.y, box.min.z },
246 Vector3<T>{ box.min.x, box.max.y, box.min.z },
247 Vector3<T>{ box.max.x, box.max.y, box.min.z },
248 Vector3<T>{ box.min.x, box.min.y, box.max.z },
249 Vector3<T>{ box.max.x, box.min.y, box.max.z },
250 Vector3<T>{ box.min.x, box.max.y, box.max.z },
251 Vector3<T>{ box.max.x, box.max.y, box.max.z }
252 };
253}
254
255template <typename T>
256inline std::array<Vector2<T>, 4> getCorners( const Box<Vector2<T>> & box )
257{
258 assert( box.valid() );
259 return
260 {
261 Vector2<T>{ box.min.x, box.min.y },
262 Vector2<T>{ box.max.x, box.min.y },
263 Vector2<T>{ box.min.x, box.max.y },
264 Vector2<T>{ box.max.x, box.max.y }
265 };
266}
267
270template <typename V>
271MinMax<typename Box<V>::T> getTouchPlanes( const Box<V> & box, const V & n )
272{
273 auto minCorner = box.getMinBoxCorner( n );
274 auto maxCorner = minCorner;
275 for ( auto & v : maxCorner )
276 v = !v;
277 return
278 {
279 dot( n, box.corner( minCorner ) ),
280 dot( n, box.corner( maxCorner ) )
281 };
282}
283
285template <typename V>
286inline Box<V> transformed( const Box<V> & box, const AffineXf<V> & xf )
287{
288 if ( !box.valid() )
289 return {};
290 Box<V> res;
291 for ( const auto & p : getCorners( box ) )
292 res.include( xf( p ) );
293 return res;
294}
296template <typename V>
297inline Box<V> transformed( const Box<V> & box, const AffineXf<V> * xf )
298{
299 return xf ? transformed( box, *xf ) : box;
300}
301
303template <typename V>
304inline auto width( const Box<V>& box )
305{
306 return box.max.x - box.min.x;
307}
308
310template <typename V>
311inline auto height( const Box<V>& box )
312{
313 return box.max.y - box.min.y;
314}
315
317template <typename V>
318inline auto depth( const Box<V>& box )
319{
320 return box.max.z - box.min.z;
321}
322
324template<size_t I, typename V>
325constexpr const V& get( const Box<V>& box ) noexcept { return box[int( I )]; }
326template<size_t I, typename V>
327constexpr V& get( Box<V>& box ) noexcept { return box[int( I )]; }
328
330
331} // namespace MR
332
333namespace std
334{
335
336template<size_t I, typename V>
337struct tuple_element<I, MR::Box<V>> { using type = V; };
338
339template <typename V>
340struct tuple_size<MR::Box<V>> : integral_constant<size_t, 2> {};
341
342} //namespace std
auto width(const Box< V > &box)
returns size along x axis
Definition MRMesh/MRBox.h:304
constexpr const V & get(const Box< V > &box) noexcept
get<0> returns min, get<1> returns max
Definition MRMesh/MRBox.h:325
std::array< Vector3< T >, 8 > getCorners(const Box< Vector3< T > > &box)
returns all corners of given box
Definition MRMesh/MRBox.h:239
auto height(const Box< V > &box)
returns size along y axis
Definition MRMesh/MRBox.h:311
auto depth(const Box< V > &box)
returns size along z axis
Definition MRMesh/MRBox.h:318
Box< V > transformed(const Box< V > &box, const AffineXf< V > &xf)
find the tightest box enclosing this one after transformation
Definition MRMesh/MRBox.h:286
MinMax< typename Box< V >::T > getTouchPlanes(const Box< V > &box, const V &n)
Definition MRMesh/MRBox.h:271
constexpr T sqr(T x) noexcept
squared value
Definition MRMesh/MRMeshFwd.h:666
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:112
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:150
T getDistanceSq(const Box &b) const
Definition MRMesh/MRBox.h:185
T diagonal() const
computes length from min to max
Definition MRMesh/MRBox.h:99
void include(const Box &b)
minimally increases the box to include another box
Definition MRMesh/MRBox.h:122
Box expanded(const V &expansion) const
decreases min and increased max on given value
Definition MRMesh/MRBox.h:213
V max
Definition MRMesh/MRBox.h:33
Box insignificantlyExpanded() const
decreases min and increases max to their closest representable value
Definition MRMesh/MRBox.h:220
static Vb getMaxBoxCorner(const V &n)
Definition MRMesh/MRBox.h:90
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:197
V size() const
computes size of the box in all dimensions
Definition MRMesh/MRBox.h:96
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:160
static constexpr int elements
Definition MRMesh/MRBox.h:29
T volume() const
computes the volume of this box
Definition MRMesh/MRBox.h:102
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:234
V min
Definition MRMesh/MRBox.h:33
Box intersection(const Box &b) const
computes intersection between this and other box
Definition MRMesh/MRBox.h:171
bool contains(const Box &otherbox) const
checks whether given box is fully inside (the surfaces may touch) of this box
Definition MRMesh/MRBox.h:141
bool contains(const V &pt) const
checks whether given point is inside (including the surface) of this box
Definition MRMesh/MRBox.h:132
Box & intersect(const Box &b)
Definition MRMesh/MRBox.h:181
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:232
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