1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004, 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
67 namespace Imath {
68
69
70 template <class T>
71 class Box
72 {
73 public:
74
75 //-------------------------
76 // Data Members are public
77 //-------------------------
78
79 T min;
80 T max;
81
82 //-----------------------------------------------------
83 // Constructors - an "empty" box is created by default
84 //-----------------------------------------------------
85
86 Box ();
87 Box (const T &point);
88 Box (const T &minT, const T &maxT);
89
90 //--------------------
91 // Operators: ==, !=
92 //--------------------
93
94 bool operator == (const Box<T> &src) const;
95 bool operator != (const Box<T> &src) const;
96
97 //------------------
98 // Box manipulation
99 //------------------
100
101 void makeEmpty ();
102 void extendBy (const T &point);
103 void extendBy (const Box<T> &box);
104 void makeInfinite ();
105
106 //---------------------------------------------------
107 // Query functions - these compute results each time
108 //---------------------------------------------------
109
110 T size () const;
111 T center () const;
112 bool intersects (const T &point) const;
113 bool intersects (const Box<T> &box) const;
114
115 unsigned int majorAxis () const;
116
117 //----------------
118 // Classification
119 //----------------
120
121 bool isEmpty () const;
122 bool hasVolume () const;
123 bool isInfinite () const;
124 };
125
126
127 //--------------------
128 // Convenient typedefs
129 //--------------------
130
131 typedef Box <V2s> Box2s;
132 typedef Box <V2i> Box2i;
133 typedef Box <V2f> Box2f;
134 typedef Box <V2d> Box2d;
135 typedef Box <V3s> Box3s;
136 typedef Box <V3i> Box3i;
137 typedef Box <V3f> Box3f;
138 typedef Box <V3d> Box3d;
139
140
141 //----------------
142 // Implementation
143
144
145 template <class T>
Box()146 inline Box<T>::Box()
147 {
148 makeEmpty();
149 }
150
151
152 template <class T>
Box(const T & point)153 inline Box<T>::Box (const T &point)
154 {
155 min = point;
156 max = point;
157 }
158
159
160 template <class T>
Box(const T & minT,const T & maxT)161 inline Box<T>::Box (const T &minT, const T &maxT)
162 {
163 min = minT;
164 max = maxT;
165 }
166
167
168 template <class T>
169 inline bool
170 Box<T>::operator == (const Box<T> &src) const
171 {
172 return (min == src.min && max == src.max);
173 }
174
175
176 template <class T>
177 inline bool
178 Box<T>::operator != (const Box<T> &src) const
179 {
180 return (min != src.min || max != src.max);
181 }
182
183
184 template <class T>
makeEmpty()185 inline void Box<T>::makeEmpty()
186 {
187 min = T(T::baseTypeMax());
188 max = T(T::baseTypeMin());
189 }
190
191 template <class T>
makeInfinite()192 inline void Box<T>::makeInfinite()
193 {
194 min = T(T::baseTypeMin());
195 max = T(T::baseTypeMax());
196 }
197
198
199 template <class T>
200 inline void
extendBy(const T & point)201 Box<T>::extendBy(const T &point)
202 {
203 for (unsigned int i = 0; i < min.dimensions(); i++)
204 {
205 if (point[i] < min[i])
206 min[i] = point[i];
207
208 if (point[i] > max[i])
209 max[i] = point[i];
210 }
211 }
212
213
214 template <class T>
215 inline void
extendBy(const Box<T> & box)216 Box<T>::extendBy(const Box<T> &box)
217 {
218 for (unsigned int i = 0; i < min.dimensions(); i++)
219 {
220 if (box.min[i] < min[i])
221 min[i] = box.min[i];
222
223 if (box.max[i] > max[i])
224 max[i] = box.max[i];
225 }
226 }
227
228
229 template <class T>
230 inline bool
intersects(const T & point)231 Box<T>::intersects(const T &point) const
232 {
233 for (unsigned int i = 0; i < min.dimensions(); i++)
234 {
235 if (point[i] < min[i] || point[i] > max[i])
236 return false;
237 }
238
239 return true;
240 }
241
242
243 template <class T>
244 inline bool
intersects(const Box<T> & box)245 Box<T>::intersects(const Box<T> &box) const
246 {
247 for (unsigned int i = 0; i < min.dimensions(); i++)
248 {
249 if (box.max[i] < min[i] || box.min[i] > max[i])
250 return false;
251 }
252
253 return true;
254 }
255
256
257 template <class T>
258 inline T
size()259 Box<T>::size() const
260 {
261 if (isEmpty())
262 return T (0);
263
264 return max - min;
265 }
266
267
268 template <class T>
269 inline T
center()270 Box<T>::center() const
271 {
272 return (max + min) / 2;
273 }
274
275
276 template <class T>
277 inline bool
isEmpty()278 Box<T>::isEmpty() const
279 {
280 for (unsigned int i = 0; i < min.dimensions(); i++)
281 {
282 if (max[i] < min[i])
283 return true;
284 }
285
286 return false;
287 }
288
289 template <class T>
290 inline bool
isInfinite()291 Box<T>::isInfinite() const
292 {
293 for (unsigned int i = 0; i < min.dimensions(); i++)
294 {
295 if (min[i] != T::baseTypeMin() || max[i] != T::baseTypeMax())
296 return false;
297 }
298
299 return true;
300 }
301
302
303 template <class T>
304 inline bool
hasVolume()305 Box<T>::hasVolume() const
306 {
307 for (unsigned int i = 0; i < min.dimensions(); i++)
308 {
309 if (max[i] <= min[i])
310 return false;
311 }
312
313 return true;
314 }
315
316
317 template<class T>
318 inline unsigned int
majorAxis()319 Box<T>::majorAxis() const
320 {
321 unsigned int major = 0;
322 T s = size();
323
324 for (unsigned int i = 1; i < min.dimensions(); i++)
325 {
326 if (s[i] > s[major])
327 major = i;
328 }
329
330 return major;
331 }
332
333 //-------------------------------------------------------------------
334 //
335 // Partial class specializations for Imath::Vec2<T> and Imath::Vec3<T>
336 //
337 //-------------------------------------------------------------------
338
339 template <typename T> class Box;
340
341 template <class T>
342 class Box<Vec2<T> >
343 {
344 public:
345
346 //-------------------------
347 // Data Members are public
348 //-------------------------
349
350 Vec2<T> min;
351 Vec2<T> max;
352
353 //-----------------------------------------------------
354 // Constructors - an "empty" box is created by default
355 //-----------------------------------------------------
356
357 Box();
358 Box (const Vec2<T> &point);
359 Box (const Vec2<T> &minT, const Vec2<T> &maxT);
360
361 //--------------------
362 // Operators: ==, !=
363 //--------------------
364
365 bool operator == (const Box<Vec2<T> > &src) const;
366 bool operator != (const Box<Vec2<T> > &src) const;
367
368 //------------------
369 // Box manipulation
370 //------------------
371
372 void makeEmpty();
373 void extendBy (const Vec2<T> &point);
374 void extendBy (const Box<Vec2<T> > &box);
375 void makeInfinite();
376
377 //---------------------------------------------------
378 // Query functions - these compute results each time
379 //---------------------------------------------------
380
381 Vec2<T> size() const;
382 Vec2<T> center() const;
383 bool intersects (const Vec2<T> &point) const;
384 bool intersects (const Box<Vec2<T> > &box) const;
385
386 unsigned int majorAxis() const;
387
388 //----------------
389 // Classification
390 //----------------
391
392 bool isEmpty() const;
393 bool hasVolume() const;
394 bool isInfinite() const;
395 };
396
397
398 //----------------
399 // Implementation
400
401 template <class T>
Box()402 inline Box<Vec2<T> >::Box()
403 {
404 makeEmpty();
405 }
406
407
408 template <class T>
Box(const Vec2<T> & point)409 inline Box<Vec2<T> >::Box (const Vec2<T> &point)
410 {
411 min = point;
412 max = point;
413 }
414
415
416 template <class T>
Box(const Vec2<T> & minT,const Vec2<T> & maxT)417 inline Box<Vec2<T> >::Box (const Vec2<T> &minT, const Vec2<T> &maxT)
418 {
419 min = minT;
420 max = maxT;
421 }
422
423
424 template <class T>
425 inline bool
426 Box<Vec2<T> >::operator == (const Box<Vec2<T> > &src) const
427 {
428 return (min == src.min && max == src.max);
429 }
430
431
432 template <class T>
433 inline bool
434 Box<Vec2<T> >::operator != (const Box<Vec2<T> > &src) const
435 {
436 return (min != src.min || max != src.max);
437 }
438
439
440 template <class T>
makeEmpty()441 inline void Box<Vec2<T> >::makeEmpty()
442 {
443 min = Vec2<T>(Vec2<T>::baseTypeMax());
444 max = Vec2<T>(Vec2<T>::baseTypeMin());
445 }
446
447 template <class T>
makeInfinite()448 inline void Box<Vec2<T> >::makeInfinite()
449 {
450 min = Vec2<T>(Vec2<T>::baseTypeMin());
451 max = Vec2<T>(Vec2<T>::baseTypeMax());
452 }
453
454
455 template <class T>
456 inline void
extendBy(const Vec2<T> & point)457 Box<Vec2<T> >::extendBy (const Vec2<T> &point)
458 {
459 if (point[0] < min[0])
460 min[0] = point[0];
461
462 if (point[0] > max[0])
463 max[0] = point[0];
464
465 if (point[1] < min[1])
466 min[1] = point[1];
467
468 if (point[1] > max[1])
469 max[1] = point[1];
470 }
471
472
473 template <class T>
474 inline void
extendBy(const Box<Vec2<T>> & box)475 Box<Vec2<T> >::extendBy (const Box<Vec2<T> > &box)
476 {
477 if (box.min[0] < min[0])
478 min[0] = box.min[0];
479
480 if (box.max[0] > max[0])
481 max[0] = box.max[0];
482
483 if (box.min[1] < min[1])
484 min[1] = box.min[1];
485
486 if (box.max[1] > max[1])
487 max[1] = box.max[1];
488 }
489
490
491 template <class T>
492 inline bool
intersects(const Vec2<T> & point)493 Box<Vec2<T> >::intersects (const Vec2<T> &point) const
494 {
495 if (point[0] < min[0] || point[0] > max[0] ||
496 point[1] < min[1] || point[1] > max[1])
497 return false;
498
499 return true;
500 }
501
502
503 template <class T>
504 inline bool
intersects(const Box<Vec2<T>> & box)505 Box<Vec2<T> >::intersects (const Box<Vec2<T> > &box) const
506 {
507 if (box.max[0] < min[0] || box.min[0] > max[0] ||
508 box.max[1] < min[1] || box.min[1] > max[1])
509 return false;
510
511 return true;
512 }
513
514
515 template <class T>
516 inline Vec2<T>
size()517 Box<Vec2<T> >::size() const
518 {
519 if (isEmpty())
520 return Vec2<T> (0);
521
522 return max - min;
523 }
524
525
526 template <class T>
527 inline Vec2<T>
center()528 Box<Vec2<T> >::center() const
529 {
530 return (max + min) / 2;
531 }
532
533
534 template <class T>
535 inline bool
isEmpty()536 Box<Vec2<T> >::isEmpty() const
537 {
538 if (max[0] < min[0] ||
539 max[1] < min[1])
540 return true;
541
542 return false;
543 }
544
545 template <class T>
546 inline bool
isInfinite()547 Box<Vec2<T> > ::isInfinite() const
548 {
549 if (min[0] != limits<T>::min() || max[0] != limits<T>::max() ||
550 min[1] != limits<T>::min() || max[1] != limits<T>::max())
551 return false;
552
553 return true;
554 }
555
556
557 template <class T>
558 inline bool
hasVolume()559 Box<Vec2<T> >::hasVolume() const
560 {
561 if (max[0] <= min[0] ||
562 max[1] <= min[1])
563 return false;
564
565 return true;
566 }
567
568
569 template <class T>
570 inline unsigned int
majorAxis()571 Box<Vec2<T> >::majorAxis() const
572 {
573 unsigned int major = 0;
574 Vec2<T> s = size();
575
576 if (s[1] > s[major])
577 major = 1;
578
579 return major;
580 }
581
582
583 template <class T>
584 class Box<Vec3<T> >
585 {
586 public:
587
588 //-------------------------
589 // Data Members are public
590 //-------------------------
591
592 Vec3<T> min;
593 Vec3<T> max;
594
595 //-----------------------------------------------------
596 // Constructors - an "empty" box is created by default
597 //-----------------------------------------------------
598
599 Box();
600 Box (const Vec3<T> &point);
601 Box (const Vec3<T> &minT, const Vec3<T> &maxT);
602
603 //--------------------
604 // Operators: ==, !=
605 //--------------------
606
607 bool operator == (const Box<Vec3<T> > &src) const;
608 bool operator != (const Box<Vec3<T> > &src) const;
609
610 //------------------
611 // Box manipulation
612 //------------------
613
614 void makeEmpty();
615 void extendBy (const Vec3<T> &point);
616 void extendBy (const Box<Vec3<T> > &box);
617 void makeInfinite ();
618
619 //---------------------------------------------------
620 // Query functions - these compute results each time
621 //---------------------------------------------------
622
623 Vec3<T> size() const;
624 Vec3<T> center() const;
625 bool intersects (const Vec3<T> &point) const;
626 bool intersects (const Box<Vec3<T> > &box) const;
627
628 unsigned int majorAxis() const;
629
630 //----------------
631 // Classification
632 //----------------
633
634 bool isEmpty() const;
635 bool hasVolume() const;
636 bool isInfinite() const;
637 };
638
639
640 //----------------
641 // Implementation
642
643
644 template <class T>
Box()645 inline Box<Vec3<T> >::Box()
646 {
647 makeEmpty();
648 }
649
650
651 template <class T>
Box(const Vec3<T> & point)652 inline Box<Vec3<T> >::Box (const Vec3<T> &point)
653 {
654 min = point;
655 max = point;
656 }
657
658
659 template <class T>
Box(const Vec3<T> & minT,const Vec3<T> & maxT)660 inline Box<Vec3<T> >::Box (const Vec3<T> &minT, const Vec3<T> &maxT)
661 {
662 min = minT;
663 max = maxT;
664 }
665
666
667 template <class T>
668 inline bool
669 Box<Vec3<T> >::operator == (const Box<Vec3<T> > &src) const
670 {
671 return (min == src.min && max == src.max);
672 }
673
674
675 template <class T>
676 inline bool
677 Box<Vec3<T> >::operator != (const Box<Vec3<T> > &src) const
678 {
679 return (min != src.min || max != src.max);
680 }
681
682
683 template <class T>
makeEmpty()684 inline void Box<Vec3<T> >::makeEmpty()
685 {
686 min = Vec3<T>(Vec3<T>::baseTypeMax());
687 max = Vec3<T>(Vec3<T>::baseTypeMin());
688 }
689
690 template <class T>
makeInfinite()691 inline void Box<Vec3<T> >::makeInfinite()
692 {
693 min = Vec3<T>(Vec3<T>::baseTypeMin());
694 max = Vec3<T>(Vec3<T>::baseTypeMax());
695 }
696
697
698 template <class T>
699 inline void
extendBy(const Vec3<T> & point)700 Box<Vec3<T> >::extendBy (const Vec3<T> &point)
701 {
702 if (point[0] < min[0])
703 min[0] = point[0];
704
705 if (point[0] > max[0])
706 max[0] = point[0];
707
708 if (point[1] < min[1])
709 min[1] = point[1];
710
711 if (point[1] > max[1])
712 max[1] = point[1];
713
714 if (point[2] < min[2])
715 min[2] = point[2];
716
717 if (point[2] > max[2])
718 max[2] = point[2];
719 }
720
721
722 template <class T>
723 inline void
extendBy(const Box<Vec3<T>> & box)724 Box<Vec3<T> >::extendBy (const Box<Vec3<T> > &box)
725 {
726 if (box.min[0] < min[0])
727 min[0] = box.min[0];
728
729 if (box.max[0] > max[0])
730 max[0] = box.max[0];
731
732 if (box.min[1] < min[1])
733 min[1] = box.min[1];
734
735 if (box.max[1] > max[1])
736 max[1] = box.max[1];
737
738 if (box.min[2] < min[2])
739 min[2] = box.min[2];
740
741 if (box.max[2] > max[2])
742 max[2] = box.max[2];
743 }
744
745
746 template <class T>
747 inline bool
intersects(const Vec3<T> & point)748 Box<Vec3<T> >::intersects (const Vec3<T> &point) const
749 {
750 if (point[0] < min[0] || point[0] > max[0] ||
751 point[1] < min[1] || point[1] > max[1] ||
752 point[2] < min[2] || point[2] > max[2])
753 return false;
754
755 return true;
756 }
757
758
759 template <class T>
760 inline bool
intersects(const Box<Vec3<T>> & box)761 Box<Vec3<T> >::intersects (const Box<Vec3<T> > &box) const
762 {
763 if (box.max[0] < min[0] || box.min[0] > max[0] ||
764 box.max[1] < min[1] || box.min[1] > max[1] ||
765 box.max[2] < min[2] || box.min[2] > max[2])
766 return false;
767
768 return true;
769 }
770
771
772 template <class T>
773 inline Vec3<T>
size()774 Box<Vec3<T> >::size() const
775 {
776 if (isEmpty())
777 return Vec3<T> (0);
778
779 return max - min;
780 }
781
782
783 template <class T>
784 inline Vec3<T>
center()785 Box<Vec3<T> >::center() const
786 {
787 return (max + min) / 2;
788 }
789
790
791 template <class T>
792 inline bool
isEmpty()793 Box<Vec3<T> >::isEmpty() const
794 {
795 if (max[0] < min[0] ||
796 max[1] < min[1] ||
797 max[2] < min[2])
798 return true;
799
800 return false;
801 }
802
803 template <class T>
804 inline bool
isInfinite()805 Box<Vec3<T> >::isInfinite() const
806 {
807 if (min[0] != limits<T>::min() || max[0] != limits<T>::max() ||
808 min[1] != limits<T>::min() || max[1] != limits<T>::max() ||
809 min[2] != limits<T>::min() || max[2] != limits<T>::max())
810 return false;
811
812 return true;
813 }
814
815
816 template <class T>
817 inline bool
hasVolume()818 Box<Vec3<T> >::hasVolume() const
819 {
820 if (max[0] <= min[0] ||
821 max[1] <= min[1] ||
822 max[2] <= min[2])
823 return false;
824
825 return true;
826 }
827
828
829 template <class T>
830 inline unsigned int
majorAxis()831 Box<Vec3<T> >::majorAxis() const
832 {
833 unsigned int major = 0;
834 Vec3<T> s = size();
835
836 if (s[1] > s[major])
837 major = 1;
838
839 if (s[2] > s[major])
840 major = 2;
841
842 return major;
843 }
844
845
846
847
848 } // namespace Imath
849
850 #endif
851