HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_RTreeBox.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_RTreeBox.h (UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_RTreeBox_H__
12 #define __UT_RTreeBox_H__
13 
14 #include "UT_Vector3.h"
15 #include "UT_BoundingBox.h"
16 #include "UT_Format.h"
17 
18 #include <type_traits>
19 
20 // UT_BoxT represents either an axis-aligned box or the empty set.
21 // UT_BoxT is closed as a set; all operations assume that
22 // the boundary is included.
23 // FT is the number type used to represent the box coordinates,
24 // for example, float or double.
25 
26 // Named constructor tags
27 struct UT_BoxCT
28 {
32 };
33 
34 template< typename FT > class UT_BoxT;
35 
36 // Forward declare friends:
37 template< typename FT > inline void setEmpty( UT_BoxT< FT >& t );
38 
39 template< typename FT >
40 class UT_BoxT
41 {
42 public:
43  using CT = UT_BoxCT;
44  using Scalar = FT;
46 
47  // Default construct: the empty set
48  constexpr UT_BoxT();
49 
50  // Construct box containing a single point position,
51  // which is represented by its array of three coordinates.
52  template< typename U >
53  constexpr explicit UT_BoxT( const U p[3] );
54 
55  template< typename U >
56  constexpr explicit UT_BoxT( const UT_Vector3T< U >& p );
57 
58  constexpr explicit UT_BoxT( const UT_BoundingBox& a );
59 
60  // Construct a bounding box from points in an array-like type 'l_x'
61  // Starting with the empty box,
62  // for each l in [ 0, size ), absorb the point l_x[ l ] in the bounding box.
63  // size == 0 results in the empty set.
64  template< typename POINT_ARRAY >
65  constexpr UT_BoxT( const CT::BoundPointArrayType, POINT_ARRAY&& l_x, const exint size );
66 
67  // Construct a bounding box from points in an array-like type 'l_x'
68  // Starting with the empty box,
69  // for each iterator cit in the half-open range [ begin, end ),
70  // absorb the point l_x[ *cit ] in the bounding box.
71  // end == begin results in the empty set.
72  template< typename CIT, typename POINT_ARRAY >
73  constexpr UT_BoxT( const CT::BoundIndirectRangePointArrayType, POINT_ARRAY&& l_x, const CIT begin, const CIT end );
74 
75  // Construct a bounding box using points given by
76  // a generator function object
77  // Starting with the empty box,
78  // for each l in [ 0, size ), absorb generator( l ) in the bounding box.
79  // size == 0 results in the empty set.
80  template< typename POINT_GENERATOR >
81  constexpr UT_BoxT( const CT::BoundPointGeneratorType, POINT_GENERATOR&& generator, const exint size );
82 
83  UT_BoxT( const UT_BoxT& ) = default;
84  UT_BoxT& operator=( const UT_BoxT& ) = default;
85 
86  // Return whether this represents the empty set
87  constexpr bool isEmpty() const;
88 
89  // Make a box that's a single point
90  template< typename U >
91  void assignPoint(const U p[3]);
92  template< typename U >
93  void assignPoint( const UT_Vector3T<U> p) { assignPoint(p.vec); }
94 
95  // Expand the box just enough so that it contains a point p
96  template< typename U >
97  void absorbPoint(const U p[3]);
98  template< typename U >
99  void absorbPoint( const UT_Vector3T<U> p) { absorbPoint(p.vec); }
100 
101  // Expand the box just enough so that it contains a box b
102  void absorbBox(const UT_BoxT<FT>& b);
103  void absorbBox(const UT_BoundingBox &b);
104 
105  // Expand in the directions of the axes:
106  // In case this is the empty set, the result is still the empty set
107  // This is equivalent to making *this the union of all cubes with
108  // radius l placed at points of the original set.
109  void expandDistance(const FT l);
110 
111  // Get minimum coordinate for given standard axis
112  // Assumes this is not empty!
113  FT getMin(const int c) const;
114 
115  // Get maximum coordinate for given standard axis
116  // Assumes this is not empty!
117  FT getMax(const int c) const;
118 
119  FT3 getSize() const
120  {
121  UT_ASSERT_P( ! isEmpty() );
122 
123  return FT3(
124  (myMax[0]-myMin[0]),
125  (myMax[1]-myMin[1]),
126  (myMax[2]-myMin[2])
127  );
128  }
129 
130  FT getRadius2() const
131  {
132  UT_ASSERT_P( ! isEmpty() );
133 
134  const FT3 h(
135  (myMax[0]-myMin[0]) / 2,
136  (myMax[1]-myMin[1]) / 2,
137  (myMax[2]-myMin[2]) / 2
138  );
139 
140  return h.length2();
141  }
142 
143  FT3 getCenter() const
144  {
145  UT_ASSERT_P( ! isEmpty() );
146 
147  return FT3(
148  (myMin[0]+myMax[0])/2,
149  (myMin[1]+myMax[1])/2,
150  (myMin[2]+myMax[2])/2
151  );
152  }
153 
154  // Return whether a point is contained in the closed set
155  bool contains(const FT p[3]) const;
156 
157  // Return the axis in which the box is the widest.
158  // For the empty set, this always returns axis 0
159  int getLargestAxis() const;
160 
161 private:
162  // This represents set of all points x
163  // with myMin[c] <= x[c] <= myMax[c] for each c = 0, 1, 2
164  FT myMin[ 3 ];
165  FT myMax[ 3 ];
166 
167  friend void setEmpty <>( UT_BoxT< FT >& t );
168 
169  friend bool intersects( const UT_BoxT< float >& a, const UT_BoxT< float >& b );
170  friend bool intersects( const UT_BoxT< double >& a, const UT_BoxT< double >& b );
171 };
172 
173 // Overload for custom formatting of UT_BoxT with UTformat.
174 template< typename FT >
175 inline size_t
176 UTformatBuffer( char* buffer, size_t buffer_size, const UT_BoxT< FT >& a )
177 {
178  UT::Format::Writer writer( buffer, buffer_size );
180  return f.format(
181  writer, "min[{0}, {1}, {2}]], max[{3}, {4}, {5}]",
182  {
183  a.getMin( 0 ),
184  a.getMin( 1 ),
185  a.getMin( 2 ),
186  a.getMax( 0 ),
187  a.getMax( 1 ),
188  a.getMax( 2 )
189  }
190  );
191 }
192 
193 //TODO: Move below code into UT_RTreeBoxImpl.h
194 
195 namespace UT
196 {
197 
198 // TODO: Move definitions of FT_Least and FT_Greatest
199 // to a separate header and include it here:
200 
201 // Primary template defined for built-in floating point types:
202 // Map type 'FT' to the least possible value of that type
203 template< typename FT >
204 struct FT_Least
205 {
206  constexpr auto operator()() { return std::numeric_limits< FT >::lowest(); }
207 };
208 
209 //template< typename FT > constexpr auto FT_Least_v = FT_Least< FT >{}();
210 
211 // Primary template defined for built-in floating point types:
212 // Map type 'FT' to the greatest possible value of that type
213 template< typename FT >
215 {
216  constexpr auto operator()() { return std::numeric_limits< FT >::max(); }
217 };
218 
219 //template< typename FT > constexpr auto FT_Greatest_v = FT_Greatest< FT >{}();
220 
221 //
222 // Use class specialization on AssignCopyFT3
223 // to make copy-assignment work for UT_BoxT
224 // when the underlying type FT has a deleted copy assignment operator
225 // This is the case, types FT used in $SC and $CLO.
226 // Such types must support "setCopy( dest, source )" instead.
227 //
228 
231 
232 template< typename FT >
233 struct AssignCopyFT3< FT, true >
234 {
235  void operator()( FT ts[ 3 ], const FT as[ 3 ] )
236  {
237  ts[ 0 ] = as[ 0 ];
238  ts[ 1 ] = as[ 1 ];
239  ts[ 2 ] = as[ 2 ];
240  }
241 };
242 
243 template< typename FT >
244 struct AssignCopyFT3< FT, false >
245 {
246  void operator()( FT ts[ 3 ], const FT as[ 3 ] )
247  {
248  setCopy( ts[ 0 ], as[ 0 ] );
249  setCopy( ts[ 1 ], as[ 1 ] );
250  setCopy( ts[ 2 ], as[ 2 ] );
251  }
252 };
253 
256 
257 template< typename FT >
258 struct AssignCoordinatesFT3< FT, true >
259 {
260  void operator()( FT ts[ 3 ], const FT a0, const FT a1, const FT a2 )
261  {
262  ts[ 0 ] = a0;
263  ts[ 1 ] = a1;
264  ts[ 2 ] = a2;
265  }
266 };
267 
268 template< typename FT >
269 struct AssignCoordinatesFT3< FT, false >
270 {
271  void operator()( FT ts[ 3 ], const FT a0, const FT a1, const FT a2 )
272  {
273  setCopy( ts[ 0 ], a0 );
274  setCopy( ts[ 1 ], a1 );
275  setCopy( ts[ 2 ], a2 );
276  }
277 };
278 
279 }
280 // namespace UT
281 
282 template< typename FT >
284  myMin{
288  },
289  myMax{
290  UT::FT_Least< FT >{}(),
291  UT::FT_Least< FT >{}(),
293  }
294 {
295 }
296 
297 template< typename FT >
298 template< typename U >
299 constexpr UT_BoxT< FT >::UT_BoxT( const U p[ 3 ] ) :
300  myMin{
301  FT( p[ 0 ] ),
302  FT( p[ 1 ] ),
303  FT( p[ 2 ] )
304  },
305  myMax{
306  FT( p[ 0 ] ),
307  FT( p[ 1 ] ),
308  FT( p[ 2 ] )
309  }
310 {
311 }
312 
313 template< typename FT >
314 template< typename U >
315 constexpr UT_BoxT< FT >::UT_BoxT( const UT_Vector3T< U >& p ) :
316  myMin{
317  FT( p[ 0 ] ),
318  FT( p[ 1 ] ),
319  FT( p[ 2 ] )
320  },
321  myMax{
322  FT( p[ 0 ] ),
323  FT( p[ 1 ] ),
324  FT( p[ 2 ] )
325  }
326 {
327 }
328 
329 template< typename FT >
330 constexpr UT_BoxT< FT >::UT_BoxT( const UT_BoundingBox& a ) :
331  myMin{
332  a.xmin(),
333  a.ymin(),
334  a.zmin()
335  },
336  myMax{
337  a.xmax(),
338  a.ymax(),
339  a.zmax()
340  }
341 {
342 }
343 
344 template< typename FT >
345 template< typename POINT_ARRAY >
346 constexpr UT_BoxT< FT >::UT_BoxT(
348  POINT_ARRAY&& l_x,
349  const exint size
350 ) :
351  myMin{
355  },
356  myMax{
357  UT::FT_Least< FT >{}(),
358  UT::FT_Least< FT >{}(),
360  }
361 {
362  for( int l = 0; l != size; ++l )
363  {
364  absorbPoint( l_x[ l ] );
365  }
366 }
367 
368 template< typename FT >
369 template< typename CIT, typename POINT_ARRAY >
370 constexpr UT_BoxT< FT >::UT_BoxT(
372  POINT_ARRAY&& l_x,
373  const CIT begin, const CIT end
374 ) :
375  myMin{
379  },
380  myMax{
381  UT::FT_Least< FT >{}(),
382  UT::FT_Least< FT >{}(),
384  }
385 {
386  for( auto cit = begin; cit != end; ++cit )
387  {
388  absorbPoint( l_x[ *cit ] );
389  }
390 }
391 
392 template< typename FT >
393 template< typename POINT_GENERATOR >
394 constexpr UT_BoxT< FT >::UT_BoxT( const CT::BoundPointGeneratorType, POINT_GENERATOR&& generator, const exint size ) :
395  myMin{
399  },
400  myMax{
401  UT::FT_Least< FT >{}(),
402  UT::FT_Least< FT >{}(),
404  }
405 {
406  for( int l = 0; l != size; ++l )
407  {
408  absorbPoint( generator( l ) );
409  }
410 }
411 
412 
413 
414 template< typename FT >
415 constexpr bool UT_BoxT< FT >::isEmpty() const
416 {
417  return(
418  ( myMax[ 0 ] < myMin[ 0 ] ) ||
419  ( myMax[ 1 ] < myMin[ 1 ] ) ||
420  ( myMax[ 2 ] < myMin[ 2 ] )
421  );
422 }
423 
424 template< typename T >
425 template< typename U >
426 inline void UT_BoxT<T>::assignPoint(const U p[3])
427 {
428  myMin[0] = p[0];
429  myMin[1] = p[1];
430  myMin[2] = p[2];
431 
432  myMax[0] = p[0];
433  myMax[1] = p[1];
434  myMax[2] = p[2];
435 }
436 
437 template< typename T >
438 template< typename U >
439 inline void UT_BoxT<T>::absorbPoint(const U p[3])
440 {
441  myMin[0] = (myMin[0] > p[0]) ? p[0] : myMin[0];
442  myMin[1] = (myMin[1] > p[1]) ? p[1] : myMin[1];
443  myMin[2] = (myMin[2] > p[2]) ? p[2] : myMin[2];
444 
445  myMax[0] = (myMax[0] < p[0]) ? p[0] : myMax[0];
446  myMax[1] = (myMax[1] < p[1]) ? p[1] : myMax[1];
447  myMax[2] = (myMax[2] < p[2]) ? p[2] : myMax[2];
448 }
449 
450 template< typename T >
451 inline void UT_BoxT<T>::absorbBox(const UT_BoxT<T>& b)
452 {
453  myMin[0] = (myMin[0] > b.myMin[0]) ? b.myMin[0] : myMin[0];
454  myMin[1] = (myMin[1] > b.myMin[1]) ? b.myMin[1] : myMin[1];
455  myMin[2] = (myMin[2] > b.myMin[2]) ? b.myMin[2] : myMin[2];
456 
457  myMax[0] = (myMax[0] < b.myMax[0]) ? b.myMax[0] : myMax[0];
458  myMax[1] = (myMax[1] < b.myMax[1]) ? b.myMax[1] : myMax[1];
459  myMax[2] = (myMax[2] < b.myMax[2]) ? b.myMax[2] : myMax[2];
460 }
461 
462 template< typename T >
463 inline void UT_BoxT<T>::absorbBox(const UT_BoundingBox &b)
464 {
465  myMin[0] = (myMin[0] > b.xmin()) ? b.xmin() : myMin[0];
466  myMin[1] = (myMin[1] > b.ymin()) ? b.ymin() : myMin[1];
467  myMin[2] = (myMin[2] > b.zmin()) ? b.zmin() : myMin[2];
468 
469  myMax[0] = (myMax[0] < b.xmax()) ? b.xmax() : myMax[0];
470  myMax[1] = (myMax[1] < b.ymax()) ? b.ymax() : myMax[1];
471  myMax[2] = (myMax[2] < b.zmax()) ? b.zmax() : myMax[2];
472 }
473 
474 template< typename T >
475 inline void UT_BoxT<T>::expandDistance(const T l)
476 {
477  if( isEmpty() )
478  return;
479 
480  myMin[0] -= l;
481  myMin[1] -= l;
482  myMin[2] -= l;
483 
484  myMax[0] += l;
485  myMax[1] += l;
486  myMax[2] += l;
487 }
488 
489 template< typename T >
490 inline T UT_BoxT<T>::getMin(const int c) const
491 {
492  UT_ASSERT_P( (0 <= c) && (c < 3) );
493  UT_ASSERT_P( !isEmpty() );
494 
495  return myMin[c];
496 }
497 
498 template< typename T >
499 inline T UT_BoxT<T>::getMax(const int c) const
500 {
501  UT_ASSERT_P( (0 <= c) && (c < 3) );
502  UT_ASSERT_P( !isEmpty() );
503 
504  return myMax[c];
505 }
506 
507 
508 template< typename T >
509 inline bool UT_BoxT<T>::contains(const T p[3]) const
510 {
511  return ( (myMin[0] <= p[0]) && (p[0] <= myMax[0]) &&
512  (myMin[1] <= p[1]) && (p[1] <= myMax[1]) &&
513  (myMin[2] <= p[2]) && (p[2] <= myMax[2]) );
514 }
515 
516 template< typename T >
517 inline int UT_BoxT<T>::getLargestAxis() const
518 {
519  if( isEmpty() )
520  {
521  return 0;
522  }
523 
524  int max_axis(0);
525  T max_length(myMax[0] - myMin[0]);
526 
527  T length(0);
528 
529  length = myMax[1] - myMin[1];
530  if( length > max_length )
531  {
532  max_length = length;
533  max_axis = 1;
534  }
535 
536  length = myMax[2] - myMin[2];
537  if( length > max_length )
538  {
539  max_length = length;
540  max_axis = 2;
541  }
542 
543  return max_axis;
544 }
545 
546 template< typename FT >
547 inline void setEmpty( UT_BoxT< FT >& t )
548 {
550  t.myMin,
554  );
555 
557  t.myMax,
558  UT::FT_Least< FT >{}(),
559  UT::FT_Least< FT >{}(),
561  );
562 }
563 
564 inline bool intersects( const UT_BoxT< double >& a, const UT_BoxT< double >& b )
565 {
566  return (
567  ( SYSmax( a.myMin[0], b.myMin[0] ) <= SYSmin( a.myMax[0], b.myMax[0] ) ) &&
568  ( SYSmax( a.myMin[1], b.myMin[1] ) <= SYSmin( a.myMax[1], b.myMax[1] ) ) &&
569  ( SYSmax( a.myMin[2], b.myMin[2] ) <= SYSmin( a.myMax[2], b.myMax[2] ) )
570  );
571 }
572 
573 inline bool intersects( const UT_BoxT< float >& a, const UT_BoxT< float >& b )
574 {
575  // We have to load from the wrong vector & swizzle or
576  // we risk reading past a page boundary, triggering a fault,
577  // even though we don't use the results of the w() component.
578  v4uf tmax( &a.myMin[2] );
579  v4uf tmin( &a.myMin[0] );
580  tmax = tmax.swizzle<1, 2, 3, 0>();
581 
582  v4uf bmax( &b.myMin[2] );
583  v4uf bmin( &b.myMin[0] );
584  bmax = bmax.swizzle<1, 2, 3, 0>();
585 
586  tmin = vmax(tmin, bmin);
587  tmax = vmin(tmax, bmax);
588  v4uu valid = tmin <= tmax;
589 
590  int validmask;
591  validmask = signbits(valid);
592 
593  return ((validmask & 0x7) == 0x7);
594 }
595 
596 // Return
597 // -1 if center(a)[ axis ] > center(b)[ axis ]
598 // 0 if center(a)[ axis ] == center(b)[ axis ]
599 // 1 if center(a)[ axis ] < center(b)[ axis ]
600 template< typename FT >
601 inline int signAxisCenterComparison(
602  const int axis,
603  const UT_BoxT< FT >& a,
604  const UT_BoxT< FT >& b
605 )
606 {
607  return SYSsignum(
608  ( b.getMin( axis ) + b.getMax( axis ) )
609  -
610  ( a.getMin( axis ) + a.getMax( axis ) )
611  );
612 }
613 
614 #endif
615 
void absorbPoint(const U p[3])
constexpr SYS_FORCE_INLINE T length2() const noexcept
Definition: UT_Vector3.h:358
#define SYSmax(a, b)
Definition: SYS_Math.h:1952
BoundPointArrayType
Definition: UT_RTreeBox.h:29
FT getRadius2() const
Definition: UT_RTreeBox.h:130
constexpr auto operator()()
Definition: UT_RTreeBox.h:206
void operator()(FT ts[3], const FT a0, const FT a1, const FT a2)
Definition: UT_RTreeBox.h:271
void assignPoint(const U p[3])
size_t UTformatBuffer(char *buffer, size_t buffer_size, const UT_BoxT< FT > &a)
Definition: UT_RTreeBox.h:176
GLsizei const GLfloat * value
Definition: glcorearb.h:824
constexpr bool isEmpty() const
void absorbPoint(const UT_Vector3T< U > p)
Definition: UT_RTreeBox.h:99
T vec[tuple_size]
Definition: UT_Vector3.h:776
int64 exint
Definition: SYS_Types.h:125
void assignPoint(const UT_Vector3T< U > p)
Definition: UT_RTreeBox.h:93
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
3D Vector class.
GLuint buffer
Definition: glcorearb.h:660
BoundIndirectRangePointArrayType
Definition: UT_RTreeBox.h:30
FT Scalar
Definition: UT_RTreeBox.h:44
constexpr UT_BoxT()
Definition: UT_RTreeBox.h:283
FT3 getCenter() const
Definition: UT_RTreeBox.h:143
GLfloat f
Definition: glcorearb.h:1926
constexpr auto operator()()
Definition: UT_RTreeBox.h:216
FT getMax(const int c) const
UT_BoxT & operator=(const UT_BoxT &)=default
bool contains(const FT p[3]) const
Definition: VM_SIMD.h:48
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:164
GLuint GLuint end
Definition: glcorearb.h:475
void setEmpty(UT_BoxT< FT > &t)
Definition: VM_SIMD.h:188
constexpr int SYSsignum(const F a) noexcept
Definition: SYS_Math.h:234
FT getMin(const int c) const
void expandDistance(const FT l)
void operator()(FT ts[3], const FT a0, const FT a1, const FT a2)
Definition: UT_RTreeBox.h:260
void absorbBox(const UT_BoxT< FT > &b)
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLdouble t
Definition: glad.h:2397
GLsizeiptr size
Definition: glcorearb.h:664
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
friend bool intersects(const UT_BoxT< float > &a, const UT_BoxT< float > &b)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
UT_Vector3T< FT > FT3
Definition: UT_RTreeBox.h:45
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Type-safe formatting, modeled on the Python str.format function.
SYS_FORCE_INLINE v4uf swizzle() const
Definition: VM_SIMD.h:335
void operator()(FT ts[3], const FT as[3])
Definition: UT_RTreeBox.h:246
size_t format(W &writer, const char *format, std::initializer_list< ArgValue > args)
void operator()(FT ts[3], const FT as[3])
Definition: UT_RTreeBox.h:235
#define SYSmin(a, b)
Definition: SYS_Math.h:1953
BoundPointGeneratorType
Definition: UT_RTreeBox.h:31
friend void setEmpty(UT_BoxT< FT > &t)
FT3 getSize() const
Definition: UT_RTreeBox.h:119
int getLargestAxis() const