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
68IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
69
70
71template <class T>
72class 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
132typedef Box <V2s> Box2s;
133typedef Box <V2i> Box2i;
134typedef Box <V2f> Box2f;
135typedef Box <V2d> Box2d;
136typedef Box <V3s> Box3s;
137typedef Box <V3i> Box3i;
138typedef Box <V3f> Box3f;
139typedef Box <V3d> Box3d;
140
141
142//----------------
143// Implementation
144
145
146template <class T>
147inline Box<T>::Box()
148{
149 makeEmpty();
150}
151
152
153template <class T>
154inline Box<T>::Box (const T &point)
155{
156 min = point;
157 max = point;
158}
159
160
161template <class T>
162inline Box<T>::Box (const T &minT, const T &maxT)
163{
164 min = minT;
165 max = maxT;
166}
167
168
169template <class T>
170inline bool
171Box<T>::operator == (const Box<T> &src) const
172{
173 return (min == src.min && max == src.max);
174}
175
176
177template <class T>
178inline bool
179Box<T>::operator != (const Box<T> &src) const
180{
181 return (min != src.min || max != src.max);
182}
183
184
185template <class T>
186inline void Box<T>::makeEmpty()
187{
188 min = T(T::baseTypeMax());
189 max = T(T::baseTypeMin());
190}
191
192template <class T>
193inline void Box<T>::makeInfinite()
194{
195 min = T(T::baseTypeMin());
196 max = T(T::baseTypeMax());
197}
198
199
200template <class T>
201inline void
202Box<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
215template <class T>
216inline void
217Box<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
230template <class T>
231inline bool
232Box<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
244template <class T>
245inline bool
246Box<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
258template <class T>
259inline T
260Box<T>::size() const
261{
262 if (isEmpty())
263 return T (0);
264
265 return max - min;
266}
267
268
269template <class T>
270inline T
271Box<T>::center() const
272{
273 return (max + min) / 2;
274}
275
276
277template <class T>
278inline bool
279Box<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
290template <class T>
291inline bool
292Box<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
304template <class T>
305inline bool
306Box<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
318template<class T>
319inline unsigned int
320Box<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
340template <typename T> class Box;
341
342template <class T>
343class 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
402template <class T>
403inline Box<Vec2<T> >::Box()
404{
405 makeEmpty();
406}
407
408
409template <class T>
410inline Box<Vec2<T> >::Box (const Vec2<T> &point)
411{
412 min = point;
413 max = point;
414}
415
416
417template <class T>
418inline Box<Vec2<T> >::Box (const Vec2<T> &minT, const Vec2<T> &maxT)
419{
420 min = minT;
421 max = maxT;
422}
423
424
425template <class T>
426inline bool
427Box<Vec2<T> >::operator == (const Box<Vec2<T> > &src) const
428{
429 return (min == src.min && max == src.max);
430}
431
432
433template <class T>
434inline bool
435Box<Vec2<T> >::operator != (const Box<Vec2<T> > &src) const
436{
437 return (min != src.min || max != src.max);
438}
439
440
441template <class T>
442inline void Box<Vec2<T> >::makeEmpty()
443{
444 min = Vec2<T>(Vec2<T>::baseTypeMax());
445 max = Vec2<T>(Vec2<T>::baseTypeMin());
446}
447
448template <class T>
449inline void Box<Vec2<T> >::makeInfinite()
450{
451 min = Vec2<T>(Vec2<T>::baseTypeMin());
452 max = Vec2<T>(Vec2<T>::baseTypeMax());
453}
454
455
456template <class T>
457inline void
458Box<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
474template <class T>
475inline void
476Box<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
492template <class T>
493inline bool
494Box<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
504template <class T>
505inline bool
506Box<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
516template <class T>
517inline Vec2<T>
518Box<Vec2<T> >::size() const
519{
520 if (isEmpty())
521 return Vec2<T> (0);
522
523 return max - min;
524}
525
526
527template <class T>
528inline Vec2<T>
529Box<Vec2<T> >::center() const
530{
531 return (max + min) / 2;
532}
533
534
535template <class T>
536inline bool
537Box<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
546template <class T>
547inline bool
548Box<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
558template <class T>
559inline bool
560Box<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
570template <class T>
571inline unsigned int
572Box<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
584template <class T>
585class 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
645template <class T>
646inline Box<Vec3<T> >::Box()
647{
648 makeEmpty();
649}
650
651
652template <class T>
653inline Box<Vec3<T> >::Box (const Vec3<T> &point)
654{
655 min = point;
656 max = point;
657}
658
659
660template <class T>
661inline Box<Vec3<T> >::Box (const Vec3<T> &minT, const Vec3<T> &maxT)
662{
663 min = minT;
664 max = maxT;
665}
666
667
668template <class T>
669inline bool
670Box<Vec3<T> >::operator == (const Box<Vec3<T> > &src) const
671{
672 return (min == src.min && max == src.max);
673}
674
675
676template <class T>
677inline bool
678Box<Vec3<T> >::operator != (const Box<Vec3<T> > &src) const
679{
680 return (min != src.min || max != src.max);
681}
682
683
684template <class T>
685inline void Box<Vec3<T> >::makeEmpty()
686{
687 min = Vec3<T>(Vec3<T>::baseTypeMax());
688 max = Vec3<T>(Vec3<T>::baseTypeMin());
689}
690
691template <class T>
692inline void Box<Vec3<T> >::makeInfinite()
693{
694 min = Vec3<T>(Vec3<T>::baseTypeMin());
695 max = Vec3<T>(Vec3<T>::baseTypeMax());
696}
697
698
699template <class T>
700inline void
701Box<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
723template <class T>
724inline void
725Box<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
747template <class T>
748inline bool
749Box<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
760template <class T>
761inline bool
762Box<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
773template <class T>
774inline Vec3<T>
775Box<Vec3<T> >::size() const
776{
777 if (isEmpty())
778 return Vec3<T> (0);
779
780 return max - min;
781}
782
783
784template <class T>
785inline Vec3<T>
786Box<Vec3<T> >::center() const
787{
788 return (max + min) / 2;
789}
790
791
792template <class T>
793inline bool
794Box<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
804template <class T>
805inline bool
806Box<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
817template <class T>
818inline bool
819Box<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
830template <class T>
831inline unsigned int
832Box<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
847IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
848
849#endif // INCLUDED_IMATHBOX_H
850