1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34
35
36 #ifndef INCLUDED_IMATHBOX_H
37 #define INCLUDED_IMATHBOX_H
38
39 //-------------------------------------------------------------------
40 //
41 // class Imath::Box<class T>
42 // --------------------------------
43 //
44 // This class imposes the following requirements on its
45 // parameter class:
46 //
47 // 1) The class T must implement these operators:
48 // + - < > <= >= =
49 // with the signature (T,T) and the expected
50 // return values for a numeric type.
51 //
52 // 2) The class T must implement operator=
53 // with the signature (T,float and/or double)
54 //
55 // 3) The class T must have a constructor which takes
56 // a float (and/or double) for use in initializing the box.
57 //
58 // 4) The class T must have a function T::dimensions()
59 // which returns the number of dimensions in the class
60 // (since its assumed its a vector) -- preferably, this
61 // returns a constant expression.
62 //
63 //-------------------------------------------------------------------
64
65 #include "ImathVec.h"
66 #include "ImathNamespace.h"
67
68 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
69
70
71 template <class T>
72 class Box
73 {
74 public:
75
76 //-------------------------
77 // Data Members are public
78 //-------------------------
79
80 T min;
81 T max;
82
83 //-----------------------------------------------------
84 // Constructors - an "empty" box is created by default
85 //-----------------------------------------------------
86
87 Box ();
88 Box (const T &point);
89 Box (const T &minT, const T &maxT);
90
91 //--------------------
92 // Operators: ==, !=
93 //--------------------
94
95 bool operator == (const Box<T> &src) const;
96 bool operator != (const Box<T> &src) const;
97
98 //------------------
99 // Box manipulation
100 //------------------
101
102 void makeEmpty ();
103 void extendBy (const T &point);
104 void extendBy (const Box<T> &box);
105 void makeInfinite ();
106
107 //---------------------------------------------------
108 // Query functions - these compute results each time
109 //---------------------------------------------------
110
111 T size () const;
112 T center () const;
113 bool intersects (const T &point) const;
114 bool intersects (const Box<T> &box) const;
115
116 unsigned int majorAxis () const;
117
118 //----------------
119 // Classification
120 //----------------
121
122 bool isEmpty () const;
123 bool hasVolume () const;
124 bool isInfinite () const;
125 };
126
127
128 //--------------------
129 // Convenient typedefs
130 //--------------------
131
132 typedef Box <V2s> Box2s;
133 typedef Box <V2i> Box2i;
134 typedef Box <V2f> Box2f;
135 typedef Box <V2d> Box2d;
136 typedef Box <V3s> Box3s;
137 typedef Box <V3i> Box3i;
138 typedef Box <V3f> Box3f;
139 typedef Box <V3d> Box3d;
140
141
142 //----------------
143 // Implementation
144
145
146 template <class T>
Box()147 inline Box<T>::Box()
148 {
149 makeEmpty();
150 }
151
152
153 template <class T>
Box(const T & point)154 inline Box<T>::Box (const T &point)
155 {
156 min = point;
157 max = point;
158 }
159
160
161 template <class T>
Box(const T & minT,const T & maxT)162 inline Box<T>::Box (const T &minT, const T &maxT)
163 {
164 min = minT;
165 max = maxT;
166 }
167
168
169 template <class T>
170 inline bool
171 Box<T>::operator == (const Box<T> &src) const
172 {
173 return (min == src.min && max == src.max);
174 }
175
176
177 template <class T>
178 inline bool
179 Box<T>::operator != (const Box<T> &src) const
180 {
181 return (min != src.min || max != src.max);
182 }
183
184
185 template <class T>
makeEmpty()186 inline void Box<T>::makeEmpty()
187 {
188 min = T(T::baseTypeMax());
189 max = T(T::baseTypeMin());
190 }
191
192 template <class T>
makeInfinite()193 inline void Box<T>::makeInfinite()
194 {
195 min = T(T::baseTypeMin());
196 max = T(T::baseTypeMax());
197 }
198
199
200 template <class T>
201 inline void
extendBy(const T & point)202 Box<T>::extendBy(const T &point)
203 {
204 for (unsigned int i = 0; i < min.dimensions(); i++)
205 {
206 if (point[i] < min[i])
207 min[i] = point[i];
208
209 if (point[i] > max[i])
210 max[i] = point[i];
211 }
212 }
213
214
215 template <class T>
216 inline void
extendBy(const Box<T> & box)217 Box<T>::extendBy(const Box<T> &box)
218 {
219 for (unsigned int i = 0; i < min.dimensions(); i++)
220 {
221 if (box.min[i] < min[i])
222 min[i] = box.min[i];
223
224 if (box.max[i] > max[i])
225 max[i] = box.max[i];
226 }
227 }
228
229
230 template <class T>
231 inline bool
intersects(const T & point)232 Box<T>::intersects(const T &point) const
233 {
234 for (unsigned int i = 0; i < min.dimensions(); i++)
235 {
236 if (point[i] < min[i] || point[i] > max[i])
237 return false;
238 }
239
240 return true;
241 }
242
243
244 template <class T>
245 inline bool
intersects(const Box<T> & box)246 Box<T>::intersects(const Box<T> &box) const
247 {
248 for (unsigned int i = 0; i < min.dimensions(); i++)
249 {
250 if (box.max[i] < min[i] || box.min[i] > max[i])
251 return false;
252 }
253
254 return true;
255 }
256
257
258 template <class T>
259 inline T
size()260 Box<T>::size() const
261 {
262 if (isEmpty())
263 return T (0);
264
265 return max - min;
266 }
267
268
269 template <class T>
270 inline T
center()271 Box<T>::center() const
272 {
273 return (max + min) / 2;
274 }
275
276
277 template <class T>
278 inline bool
isEmpty()279 Box<T>::isEmpty() const
280 {
281 for (unsigned int i = 0; i < min.dimensions(); i++)
282 {
283 if (max[i] < min[i])
284 return true;
285 }
286
287 return false;
288 }
289
290 template <class T>
291 inline bool
isInfinite()292 Box<T>::isInfinite() const
293 {
294 for (unsigned int i = 0; i < min.dimensions(); i++)
295 {
296 if (min[i] != T::baseTypeMin() || max[i] != T::baseTypeMax())
297 return false;
298 }
299
300 return true;
301 }
302
303
304 template <class T>
305 inline bool
hasVolume()306 Box<T>::hasVolume() const
307 {
308 for (unsigned int i = 0; i < min.dimensions(); i++)
309 {
310 if (max[i] <= min[i])
311 return false;
312 }
313
314 return true;
315 }
316
317
318 template<class T>
319 inline unsigned int
majorAxis()320 Box<T>::majorAxis() const
321 {
322 unsigned int major = 0;
323 T s = size();
324
325 for (unsigned int i = 1; i < min.dimensions(); i++)
326 {
327 if (s[i] > s[major])
328 major = i;
329 }
330
331 return major;
332 }
333
334 //-------------------------------------------------------------------
335 //
336 // Partial class specializations for Imath::Vec2<T> and Imath::Vec3<T>
337 //
338 //-------------------------------------------------------------------
339
340 template <typename T> class Box;
341
342 template <class T>
343 class Box<Vec2<T> >
344 {
345 public:
346
347 //-------------------------
348 // Data Members are public
349 //-------------------------
350
351 Vec2<T> min;
352 Vec2<T> max;
353
354 //-----------------------------------------------------
355 // Constructors - an "empty" box is created by default
356 //-----------------------------------------------------
357
358 Box();
359 Box (const Vec2<T> &point);
360 Box (const Vec2<T> &minT, const Vec2<T> &maxT);
361
362 //--------------------
363 // Operators: ==, !=
364 //--------------------
365
366 bool operator == (const Box<Vec2<T> > &src) const;
367 bool operator != (const Box<Vec2<T> > &src) const;
368
369 //------------------
370 // Box manipulation
371 //------------------
372
373 void makeEmpty();
374 void extendBy (const Vec2<T> &point);
375 void extendBy (const Box<Vec2<T> > &box);
376 void makeInfinite();
377
378 //---------------------------------------------------
379 // Query functions - these compute results each time
380 //---------------------------------------------------
381
382 Vec2<T> size() const;
383 Vec2<T> center() const;
384 bool intersects (const Vec2<T> &point) const;
385 bool intersects (const Box<Vec2<T> > &box) const;
386
387 unsigned int majorAxis() const;
388
389 //----------------
390 // Classification
391 //----------------
392
393 bool isEmpty() const;
394 bool hasVolume() const;
395 bool isInfinite() const;
396 };
397
398
399 //----------------
400 // Implementation
401
402 template <class T>
Box()403 inline Box<Vec2<T> >::Box()
404 {
405 makeEmpty();
406 }
407
408
409 template <class T>
Box(const Vec2<T> & point)410 inline Box<Vec2<T> >::Box (const Vec2<T> &point)
411 {
412 min = point;
413 max = point;
414 }
415
416
417 template <class T>
Box(const Vec2<T> & minT,const Vec2<T> & maxT)418 inline Box<Vec2<T> >::Box (const Vec2<T> &minT, const Vec2<T> &maxT)
419 {
420 min = minT;
421 max = maxT;
422 }
423
424
425 template <class T>
426 inline bool
427 Box<Vec2<T> >::operator == (const Box<Vec2<T> > &src) const
428 {
429 return (min == src.min && max == src.max);
430 }
431
432
433 template <class T>
434 inline bool
435 Box<Vec2<T> >::operator != (const Box<Vec2<T> > &src) const
436 {
437 return (min != src.min || max != src.max);
438 }
439
440
441 template <class T>
makeEmpty()442 inline void Box<Vec2<T> >::makeEmpty()
443 {
444 min = Vec2<T>(Vec2<T>::baseTypeMax());
445 max = Vec2<T>(Vec2<T>::baseTypeMin());
446 }
447
448 template <class T>
makeInfinite()449 inline void Box<Vec2<T> >::makeInfinite()
450 {
451 min = Vec2<T>(Vec2<T>::baseTypeMin());
452 max = Vec2<T>(Vec2<T>::baseTypeMax());
453 }
454
455
456 template <class T>
457 inline void
extendBy(const Vec2<T> & point)458 Box<Vec2<T> >::extendBy (const Vec2<T> &point)
459 {
460 if (point[0] < min[0])
461 min[0] = point[0];
462
463 if (point[0] > max[0])
464 max[0] = point[0];
465
466 if (point[1] < min[1])
467 min[1] = point[1];
468
469 if (point[1] > max[1])
470 max[1] = point[1];
471 }
472
473
474 template <class T>
475 inline void
extendBy(const Box<Vec2<T>> & box)476 Box<Vec2<T> >::extendBy (const Box<Vec2<T> > &box)
477 {
478 if (box.min[0] < min[0])
479 min[0] = box.min[0];
480
481 if (box.max[0] > max[0])
482 max[0] = box.max[0];
483
484 if (box.min[1] < min[1])
485 min[1] = box.min[1];
486
487 if (box.max[1] > max[1])
488 max[1] = box.max[1];
489 }
490
491
492 template <class T>
493 inline bool
intersects(const Vec2<T> & point)494 Box<Vec2<T> >::intersects (const Vec2<T> &point) const
495 {
496 if (point[0] < min[0] || point[0] > max[0] ||
497 point[1] < min[1] || point[1] > max[1])
498 return false;
499
500 return true;
501 }
502
503
504 template <class T>
505 inline bool
intersects(const Box<Vec2<T>> & box)506 Box<Vec2<T> >::intersects (const Box<Vec2<T> > &box) const
507 {
508 if (box.max[0] < min[0] || box.min[0] > max[0] ||
509 box.max[1] < min[1] || box.min[1] > max[1])
510 return false;
511
512 return true;
513 }
514
515
516 template <class T>
517 inline Vec2<T>
size()518 Box<Vec2<T> >::size() const
519 {
520 if (isEmpty())
521 return Vec2<T> (0);
522
523 return max - min;
524 }
525
526
527 template <class T>
528 inline Vec2<T>
center()529 Box<Vec2<T> >::center() const
530 {
531 return (max + min) / 2;
532 }
533
534
535 template <class T>
536 inline bool
isEmpty()537 Box<Vec2<T> >::isEmpty() const
538 {
539 if (max[0] < min[0] ||
540 max[1] < min[1])
541 return true;
542
543 return false;
544 }
545
546 template <class T>
547 inline bool
isInfinite()548 Box<Vec2<T> > ::isInfinite() const
549 {
550 if (min[0] != limits<T>::min() || max[0] != limits<T>::max() ||
551 min[1] != limits<T>::min() || max[1] != limits<T>::max())
552 return false;
553
554 return true;
555 }
556
557
558 template <class T>
559 inline bool
hasVolume()560 Box<Vec2<T> >::hasVolume() const
561 {
562 if (max[0] <= min[0] ||
563 max[1] <= min[1])
564 return false;
565
566 return true;
567 }
568
569
570 template <class T>
571 inline unsigned int
majorAxis()572 Box<Vec2<T> >::majorAxis() const
573 {
574 unsigned int major = 0;
575 Vec2<T> s = size();
576
577 if (s[1] > s[major])
578 major = 1;
579
580 return major;
581 }
582
583
584 template <class T>
585 class Box<Vec3<T> >
586 {
587 public:
588
589 //-------------------------
590 // Data Members are public
591 //-------------------------
592
593 Vec3<T> min;
594 Vec3<T> max;
595
596 //-----------------------------------------------------
597 // Constructors - an "empty" box is created by default
598 //-----------------------------------------------------
599
600 Box();
601 Box (const Vec3<T> &point);
602 Box (const Vec3<T> &minT, const Vec3<T> &maxT);
603
604 //--------------------
605 // Operators: ==, !=
606 //--------------------
607
608 bool operator == (const Box<Vec3<T> > &src) const;
609 bool operator != (const Box<Vec3<T> > &src) const;
610
611 //------------------
612 // Box manipulation
613 //------------------
614
615 void makeEmpty();
616 void extendBy (const Vec3<T> &point);
617 void extendBy (const Box<Vec3<T> > &box);
618 void makeInfinite ();
619
620 //---------------------------------------------------
621 // Query functions - these compute results each time
622 //---------------------------------------------------
623
624 Vec3<T> size() const;
625 Vec3<T> center() const;
626 bool intersects (const Vec3<T> &point) const;
627 bool intersects (const Box<Vec3<T> > &box) const;
628
629 unsigned int majorAxis() const;
630
631 //----------------
632 // Classification
633 //----------------
634
635 bool isEmpty() const;
636 bool hasVolume() const;
637 bool isInfinite() const;
638 };
639
640
641 //----------------
642 // Implementation
643
644
645 template <class T>
Box()646 inline Box<Vec3<T> >::Box()
647 {
648 makeEmpty();
649 }
650
651
652 template <class T>
Box(const Vec3<T> & point)653 inline Box<Vec3<T> >::Box (const Vec3<T> &point)
654 {
655 min = point;
656 max = point;
657 }
658
659
660 template <class T>
Box(const Vec3<T> & minT,const Vec3<T> & maxT)661 inline Box<Vec3<T> >::Box (const Vec3<T> &minT, const Vec3<T> &maxT)
662 {
663 min = minT;
664 max = maxT;
665 }
666
667
668 template <class T>
669 inline bool
670 Box<Vec3<T> >::operator == (const Box<Vec3<T> > &src) const
671 {
672 return (min == src.min && max == src.max);
673 }
674
675
676 template <class T>
677 inline bool
678 Box<Vec3<T> >::operator != (const Box<Vec3<T> > &src) const
679 {
680 return (min != src.min || max != src.max);
681 }
682
683
684 template <class T>
makeEmpty()685 inline void Box<Vec3<T> >::makeEmpty()
686 {
687 min = Vec3<T>(Vec3<T>::baseTypeMax());
688 max = Vec3<T>(Vec3<T>::baseTypeMin());
689 }
690
691 template <class T>
makeInfinite()692 inline void Box<Vec3<T> >::makeInfinite()
693 {
694 min = Vec3<T>(Vec3<T>::baseTypeMin());
695 max = Vec3<T>(Vec3<T>::baseTypeMax());
696 }
697
698
699 template <class T>
700 inline void
extendBy(const Vec3<T> & point)701 Box<Vec3<T> >::extendBy (const Vec3<T> &point)
702 {
703 if (point[0] < min[0])
704 min[0] = point[0];
705
706 if (point[0] > max[0])
707 max[0] = point[0];
708
709 if (point[1] < min[1])
710 min[1] = point[1];
711
712 if (point[1] > max[1])
713 max[1] = point[1];
714
715 if (point[2] < min[2])
716 min[2] = point[2];
717
718 if (point[2] > max[2])
719 max[2] = point[2];
720 }
721
722
723 template <class T>
724 inline void
extendBy(const Box<Vec3<T>> & box)725 Box<Vec3<T> >::extendBy (const Box<Vec3<T> > &box)
726 {
727 if (box.min[0] < min[0])
728 min[0] = box.min[0];
729
730 if (box.max[0] > max[0])
731 max[0] = box.max[0];
732
733 if (box.min[1] < min[1])
734 min[1] = box.min[1];
735
736 if (box.max[1] > max[1])
737 max[1] = box.max[1];
738
739 if (box.min[2] < min[2])
740 min[2] = box.min[2];
741
742 if (box.max[2] > max[2])
743 max[2] = box.max[2];
744 }
745
746
747 template <class T>
748 inline bool
intersects(const Vec3<T> & point)749 Box<Vec3<T> >::intersects (const Vec3<T> &point) const
750 {
751 if (point[0] < min[0] || point[0] > max[0] ||
752 point[1] < min[1] || point[1] > max[1] ||
753 point[2] < min[2] || point[2] > max[2])
754 return false;
755
756 return true;
757 }
758
759
760 template <class T>
761 inline bool
intersects(const Box<Vec3<T>> & box)762 Box<Vec3<T> >::intersects (const Box<Vec3<T> > &box) const
763 {
764 if (box.max[0] < min[0] || box.min[0] > max[0] ||
765 box.max[1] < min[1] || box.min[1] > max[1] ||
766 box.max[2] < min[2] || box.min[2] > max[2])
767 return false;
768
769 return true;
770 }
771
772
773 template <class T>
774 inline Vec3<T>
size()775 Box<Vec3<T> >::size() const
776 {
777 if (isEmpty())
778 return Vec3<T> (0);
779
780 return max - min;
781 }
782
783
784 template <class T>
785 inline Vec3<T>
center()786 Box<Vec3<T> >::center() const
787 {
788 return (max + min) / 2;
789 }
790
791
792 template <class T>
793 inline bool
isEmpty()794 Box<Vec3<T> >::isEmpty() const
795 {
796 if (max[0] < min[0] ||
797 max[1] < min[1] ||
798 max[2] < min[2])
799 return true;
800
801 return false;
802 }
803
804 template <class T>
805 inline bool
isInfinite()806 Box<Vec3<T> >::isInfinite() const
807 {
808 if (min[0] != limits<T>::min() || max[0] != limits<T>::max() ||
809 min[1] != limits<T>::min() || max[1] != limits<T>::max() ||
810 min[2] != limits<T>::min() || max[2] != limits<T>::max())
811 return false;
812
813 return true;
814 }
815
816
817 template <class T>
818 inline bool
hasVolume()819 Box<Vec3<T> >::hasVolume() const
820 {
821 if (max[0] <= min[0] ||
822 max[1] <= min[1] ||
823 max[2] <= min[2])
824 return false;
825
826 return true;
827 }
828
829
830 template <class T>
831 inline unsigned int
majorAxis()832 Box<Vec3<T> >::majorAxis() const
833 {
834 unsigned int major = 0;
835 Vec3<T> s = size();
836
837 if (s[1] > s[major])
838 major = 1;
839
840 if (s[2] > s[major])
841 major = 2;
842
843 return major;
844 }
845
846
847 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
848
849 #endif // INCLUDED_IMATHBOX_H
850