Home | History | Annotate | Download | only in Imath
      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>
    146 inline Box<T>::Box()
    147 {
    148     makeEmpty();
    149 }
    150 
    151 
    152 template <class T>
    153 inline Box<T>::Box (const T &point)
    154 {
    155     min = point;
    156     max = point;
    157 }
    158 
    159 
    160 template <class T>
    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>
    185 inline void Box<T>::makeEmpty()
    186 {
    187     min = T(T::baseTypeMax());
    188     max = T(T::baseTypeMin());
    189 }
    190 
    191 template <class T>
    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
    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
    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
    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
    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
    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
    270 Box<T>::center() const
    271 {
    272     return (max + min) / 2;
    273 }
    274 
    275 
    276 template <class T>
    277 inline bool
    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
    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
    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
    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>
    402 inline Box<Vec2<T> >::Box()
    403 {
    404     makeEmpty();
    405 }
    406 
    407 
    408 template <class T>
    409 inline Box<Vec2<T> >::Box (const Vec2<T> &point)
    410 {
    411     min = point;
    412     max = point;
    413 }
    414 
    415 
    416 template <class T>
    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>
    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>
    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
    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
    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
    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
    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>
    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>
    528 Box<Vec2<T> >::center() const
    529 {
    530     return (max + min) / 2;
    531 }
    532 
    533 
    534 template <class T>
    535 inline bool
    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
    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
    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
    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>
    645 inline Box<Vec3<T> >::Box()
    646 {
    647     makeEmpty();
    648 }
    649 
    650 
    651 template <class T>
    652 inline Box<Vec3<T> >::Box (const Vec3<T> &point)
    653 {
    654     min = point;
    655     max = point;
    656 }
    657 
    658 
    659 template <class T>
    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>
    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>
    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
    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
    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
    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
    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>
    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>
    785 Box<Vec3<T> >::center() const
    786 {
    787     return (max + min) / 2;
    788 }
    789 
    790 
    791 template <class T>
    792 inline bool
    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
    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
    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
    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