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