MeshLib Documentation
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
31 V min, max;
32
34 const V & operator []( int e ) const { return *( &min + e ); }
35 V & operator []( int e ) { return *( &min + e ); }
36
38 Box() : min{ VTraits::diagonal( std::numeric_limits<T>::max() ) }, max{ VTraits::diagonal( std::numeric_limits<T>::lowest() ) } { }
39 Box( const V& min, const V& max ) : min{ min }, max{ max } { }
40
42 template <typename VV = V, typename std::enable_if_t<VectorTraits<VV>::supportNoInit, int> = 0>
43 explicit Box( NoInit ) : min{ noInit }, max{ noInit } { }
44
45 template <typename VV = V, typename std::enable_if_t<!VectorTraits<VV>::supportNoInit, int> = 0>
46 explicit Box( NoInit ) { }
47
48 template <typename U>
49 explicit Box( const Box<U> & a ) : min{ a.min }, max{ a.max } { }
50
51 static Box fromMinAndSize( const V& min, const V& size ) { return Box{ min, V( min + size ) }; }
52
54 bool valid() const
55 {
56 for ( int i = 0; i < elements; ++i )
57 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, max ) )
58 return false;
59 return true;
60 }
61
63 V center() const { assert( valid() ); return ( min + max ) / T(2); }
64
66 V size() const { assert( valid() ); return max - min; }
67
69 T diagonal() const { return std::sqrt( sqr( size() ) ); }
70
72 T volume() const
73 {
74 assert( valid() );
75 T res{ 1 };
76 for ( int i = 0; i < elements; ++i )
77 res *= VTraits::getElem( i, max ) - VTraits::getElem( i, min );
78 return res;
79 }
80
82 void include( const V & pt )
83 {
84 for ( int i = 0; i < elements; ++i )
85 {
86 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, pt );
87 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, pt );
88 }
89 }
90
92 void include( const Box & b )
93 {
94 for ( int i = 0; i < elements; ++i )
95 {
96 if ( VTraits::getElem( i, b.min ) < VTraits::getElem( i, min ) ) VTraits::getElem( i, min ) = VTraits::getElem( i, b.min );
97 if ( VTraits::getElem( i, b.max ) > VTraits::getElem( i, max ) ) VTraits::getElem( i, max ) = VTraits::getElem( i, b.max );
98 }
99 }
100
102 bool contains( const V & pt ) const
103 {
104 for ( int i = 0; i < elements; ++i )
105 if ( VTraits::getElem( i, min ) > VTraits::getElem( i, pt ) || VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
106 return false;
107 return true;
108 }
109
111 V getBoxClosestPointTo( const V & pt ) const
112 {
113 assert( valid() );
114 V res;
115 for ( int i = 0; i < elements; ++i )
116 VTraits::getElem( i, res ) = std::clamp( VTraits::getElem( i, pt ), VTraits::getElem( i, min ), VTraits::getElem( i, max ) );
117 return res;
118 }
119
121 bool intersects( const Box & b ) const
122 {
123 for ( int i = 0; i < elements; ++i )
124 {
125 if ( VTraits::getElem( i, b.max ) < VTraits::getElem( i, min ) || VTraits::getElem( i, b.min ) > VTraits::getElem( i, max ) )
126 return false;
127 }
128 return true;
129 }
130
132 Box intersection( const Box & b ) const
133 {
134 Box res;
135 for ( int i = 0; i < elements; ++i )
136 {
137 VTraits::getElem( i, res.min ) = std::max( VTraits::getElem( i, min ), VTraits::getElem( i, b.min ) );
138 VTraits::getElem( i, res.max ) = std::min( VTraits::getElem( i, max ), VTraits::getElem( i, b.max ) );
139 }
140 return res;
141 }
142 Box & intersect( const Box & b ) { return *this = intersection( b ); }
143
146 T getDistanceSq( const Box & b ) const
147 {
148 auto ibox = intersection( b );
149 T distSq = 0;
150 for ( int i = 0; i < elements; ++i )
151 if ( VTraits::getElem( i, ibox.min ) > VTraits::getElem( i, ibox.max ) )
152 distSq += sqr( VTraits::getElem( i, ibox.min ) - VTraits::getElem( i, ibox.max ) );
153 return distSq;
154 }
155
158 T getDistanceSq( const V & pt ) const
159 {
160 assert( valid() );
161 T res{};
162 for ( int i = 0; i < elements; ++i )
163 {
164 if ( VTraits::getElem( i, pt ) < VTraits::getElem( i, min ) )
165 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, min ) );
166 else
167 if ( VTraits::getElem( i, pt ) > VTraits::getElem( i, max ) )
168 res += sqr( VTraits::getElem( i, pt ) - VTraits::getElem( i, max ) );
169 }
170 return res;
171 }
172
174 Box expanded( const V & expansion ) const
175 {
176 assert( valid() );
177 return Box( min - expansion, max + expansion );
178 }
179
182 {
183 assert( valid() );
184 Box res;
185 for ( int i = 0; i < elements; ++i )
186 {
187 VTraits::getElem( i, res.min ) = std::nextafter( VTraits::getElem( i, min ), std::numeric_limits<T>::lowest() );
188 VTraits::getElem( i, res.max ) = std::nextafter( VTraits::getElem( i, max ), std::numeric_limits<T>::max() );
189 }
190 return res;
191 }
192
193 bool operator == ( const Box & a ) const
194 { return min == a.min && max == a.max; }
195 bool operator != ( const Box & a ) const
196 { return !( *this == a ); }
197};
198
199template <typename T>
200inline std::array<Vector3<T>, 8> getCorners( const Box<Vector3<T>> & box )
201{
202 return
203 {
204 Vector3<T>{ box.min.x, box.min.y, box.min.z },
205 Vector3<T>{ box.max.x, box.min.y, box.min.z },
206 Vector3<T>{ box.min.x, box.max.y, box.min.z },
207 Vector3<T>{ box.max.x, box.max.y, box.min.z },
208 Vector3<T>{ box.min.x, box.min.y, box.max.z },
209 Vector3<T>{ box.max.x, box.min.y, box.max.z },
210 Vector3<T>{ box.min.x, box.max.y, box.max.z },
211 Vector3<T>{ box.max.x, box.max.y, box.max.z }
212 };
213}
214
215template <typename T>
216inline std::array<Vector2<T>, 4> getCorners( const Box<Vector2<T>> & box )
217{
218 return
219 {
220 Vector2<T>{ box.min.x, box.min.y },
221 Vector2<T>{ box.max.x, box.min.y },
222 Vector2<T>{ box.min.x, box.max.y },
223 Vector2<T>{ box.max.x, box.max.y }
224 };
225}
226
228template <typename V>
229inline Box<V> transformed( const Box<V> & box, const AffineXf<V> & xf )
230{
231 if ( !box.valid() )
232 return {};
233 Box<V> res;
234 for ( const auto & p : getCorners( box ) )
235 res.include( xf( p ) );
236 return res;
237}
239template <typename V>
240inline Box<V> transformed( const Box<V> & box, const AffineXf<V> * xf )
241{
242 return xf ? transformed( box, *xf ) : box;
243}
244
246template <typename V>
247inline auto width( const Box<V>& box )
248{
249 return box.max.x - box.min.x;
250}
251
253template <typename V>
254inline auto height( const Box<V>& box )
255{
256 return box.max.y - box.min.y;
257}
258
260template <typename V>
261inline auto depth( const Box<V>& box )
262{
263 return box.max.z - box.min.z;
264}
265
267template<size_t I, typename V>
268constexpr const V& get( const Box<V>& box ) noexcept { return box[int( I )]; }
269template<size_t I, typename V>
270constexpr V& get( Box<V>& box ) noexcept { return box[int( I )]; }
271
273
274} // namespace MR
275
276namespace std
277{
278
279template<size_t I, typename V>
280struct tuple_element<I, MR::Box<V>> { using type = V; };
281
282template <typename V>
283struct tuple_size<MR::Box<V>> : integral_constant<size_t, 2> {};
284
285} //namespace std
auto width(const Box< V > &box)
returns size along x axis
Definition MRMesh/MRBox.h:247
constexpr const V & get(const Box< V > &box) noexcept
get<0> returns min, get<1> returns max
Definition MRMesh/MRBox.h:268
std::array< Vector3< T >, 8 > getCorners(const Box< Vector3< T > > &box)
returns all corners of given box
Definition MRMesh/MRBox.h:200
auto height(const Box< V > &box)
returns size along y axis
Definition MRMesh/MRBox.h:254
auto depth(const Box< V > &box)
returns size along z axis
Definition MRMesh/MRBox.h:261
Box< V > transformed(const Box< V > &box, const AffineXf< V > &xf)
find the tightest box enclosing this one after transformation
Definition MRMesh/MRBox.h:229
Definition MRCameraOrientationPlugin.h:8
constexpr T sqr(T x) noexcept
Definition MRMesh/MRMeshFwd.h:600
Box
Definition MRMesh/MRMeshFwd.h:298
constexpr NoInit noInit
Definition MRMesh/MRMeshFwd.h:57
I
Definition MRMesh/MRMeshFwd.h:88
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:137
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:39
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:82
V getBoxClosestPointTo(const V &pt) const
returns closest point in the box to given point
Definition MRMesh/MRBox.h:111
T getDistanceSq(const Box &b) const
Definition MRMesh/MRBox.h:146
T diagonal() const
computes length from min to max
Definition MRMesh/MRBox.h:69
void include(const Box &b)
minimally increases the box to include another box
Definition MRMesh/MRBox.h:92
Box expanded(const V &expansion) const
decreases min and increased max on given value
Definition MRMesh/MRBox.h:174
V max
Definition MRMesh/MRBox.h:31
Box insignificantlyExpanded() const
decreases min and increases max to their closest representable value
Definition MRMesh/MRBox.h:181
V center() const
computes center of the box
Definition MRMesh/MRBox.h:63
T getDistanceSq(const V &pt) const
Definition MRMesh/MRBox.h:158
V size() const
computes size of the box in all dimensions
Definition MRMesh/MRBox.h:66
bool intersects(const Box &b) const
checks whether this box intersects or touches given box
Definition MRMesh/MRBox.h:121
static constexpr int elements
Definition MRMesh/MRBox.h:29
T volume() const
computes the volume of this box
Definition MRMesh/MRBox.h:72
static Box fromMinAndSize(const V &min, const V &size)
Definition MRMesh/MRBox.h:51
Box()
create invalid box by default
Definition MRMesh/MRBox.h:38
const V & operator[](int e) const
min/max access by 0/1 index
Definition MRMesh/MRBox.h:34
bool operator!=(const Box &a) const
Definition MRMesh/MRBox.h:195
V min
Definition MRMesh/MRBox.h:31
Box intersection(const Box &b) const
computes intersection between this and other box
Definition MRMesh/MRBox.h:132
bool contains(const V &pt) const
checks whether given point is inside (including the surface) of the box
Definition MRMesh/MRBox.h:102
Box & intersect(const Box &b)
Definition MRMesh/MRBox.h:142
Box(const Box< U > &a)
Definition MRMesh/MRBox.h:49
bool valid() const
true if the box contains at least one point
Definition MRMesh/MRBox.h:54
Box(NoInit)
skip initialization of min/max
Definition MRMesh/MRBox.h:43
bool operator==(const Box &a) const
Definition MRMesh/MRBox.h:193
Definition MRMesh/MRMeshFwd.h:56
Definition MRVector2.h:18
T x
Definition MRVector2.h:24
Definition MRMesh/MRVector3.h:19
T x
Definition MRMesh/MRVector3.h:25
Definition MRMesh/MRVectorTraits.h:14
static constexpr int size
Definition MRMesh/MRVectorTraits.h:18
static constexpr auto && getElem(int i, U &&value)
Definition MRMesh/MRVectorTraits.h:28
T BaseType
Definition MRMesh/MRVectorTraits.h:17