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