1 /* $NoKeywords: $ */ 2 /* 3 // 4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. 5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert 6 // McNeel & Associates. 7 // 8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF 10 // MERCHANTABILITY ARE HEREBY DISCLAIMED. 11 // 12 // For complete openNURBS copyright information see <http://www.opennurbs.org>. 13 // 14 //////////////////////////////////////////////////////////////// 15 */ 16 17 #if !defined(ON_BOUNDING_BOX_INC_) 18 #define ON_BOUNDING_BOX_INC_ 19 20 //////////////////////////////////////////////////////////////// 21 // 22 // ON_BoundingBox - axis aligned bounding box 23 // 24 25 class ON_CLASS ON_BoundingBox 26 { 27 public: 28 static const ON_BoundingBox EmptyBoundingBox; // ((1.0,0,0,0,0),(-1.0,0.0,0.0)) 29 30 ON_BoundingBox(); // creates EmptyBox 31 32 ON_BoundingBox( 33 const ON_3dPoint&, // min corner of axis aligned bounding box 34 const ON_3dPoint& // max corner of axis aligned bounding box 35 ); 36 ~ON_BoundingBox(); 37 38 39 // temporary - use ON_ClippingRegion - this function will be removed soon. 40 int IsVisible( 41 const ON_Xform& bbox2c 42 ) const; 43 44 void Destroy(); // invalidates bounding box 45 46 // operator[] returns min if index <= 0 and max if indes >= 1 47 ON_3dPoint& operator[](int); 48 const ON_3dPoint& operator[](int) const; 49 50 ON_3dPoint Min() const; 51 ON_3dPoint Max() const; 52 ON_3dVector Diagonal() const; // max corner - min corner 53 ON_3dPoint Center() const; 54 ON_3dPoint Corner( // 8 corners of box 55 int, // x_index 0 = Min().x, 1 = Max().x 56 int, // y_index 0 = Min().y, 1 = Max().y 57 int // z_index 0 = Min().z, 1 = Max().z 58 ) const; 59 bool GetCorners( 60 ON_3dPointArray& box_corners // returns list of 8 corner points 61 ) const; 62 bool GetCorners( 63 ON_3dPoint box_corners[8] // returns list of 8 corner points 64 ) const; 65 66 /* 67 Parameters: 68 edges[] - out 69 12 edge lines. If the bounding box has no height, width or depth, 70 then the corresponding edges will have the same "from" and "to" 71 points. 72 Returns: 73 If the bounding box is valid, then true is returned and 74 12 line segments, some possibly a single point, are returned. 75 Otherwise false is returned and 12 line segments with "from" 76 and "to" points set to ON_3dPoint::UnsetPoint are returned. 77 */ 78 bool GetEdges( 79 ON_Line edges[12] // returns list of 12 edge segments 80 ) const; 81 82 bool IsValid() const; // empty boxes are not valid 83 84 void Dump(class ON_TextLog&) const; 85 86 /* 87 Description: 88 Test a bounding box to see if it is degenerate (flat) 89 in one or more directions. 90 Parameters: 91 tolerance - [in] Distances <= tolerance will be considered 92 to be zero. If tolerance is negative (default), then 93 a scale invarient tolerance is used. 94 Returns: 95 @untitled table 96 0 box is not degenerate 97 1 box is a rectangle (degenerate in one direction) 98 2 box is a line (degenerate in two directions) 99 3 box is a point (degenerate in three directions) 100 4 box is not valid 101 */ 102 int IsDegenerate( 103 double tolerance = ON_UNSET_VALUE 104 ) const; 105 106 107 ////////// 108 // ON_BoundingBox::Transform() updates the bounding box 109 // to be the smallest axis aligned bounding box that contains 110 // the transform of the eight corner points of the input 111 // bounding box. 112 bool Transform( const ON_Xform& ); 113 114 double Tolerance() const; // rough guess at a tolerance to use for comparing 115 // objects in this bounding box 116 117 118 // All of these Set() functions set or expand a box to enclose the points in the arguments 119 // If bGrowBox is true, the existing box is expanded, otherwise it is only set to the current point list 120 bool Set( 121 int dim, 122 int is_rat, 123 int count, 124 int stride, 125 const double* point_array, 126 int bGrowBox = false 127 ); 128 129 bool Set( 130 const ON_3dPoint& point, 131 int bGrowBox = false 132 ); 133 134 bool Set( 135 const ON_2dPoint& point, 136 int bGrowBox = false 137 ); 138 139 bool Set( 140 const ON_SimpleArray<ON_4dPoint>& point_array, 141 int bGrowBox = false 142 ); 143 144 bool Set( 145 const ON_SimpleArray<ON_3dPoint>& point_array, 146 int bGrowBox = false 147 ); 148 149 bool Set( 150 const ON_SimpleArray<ON_2dPoint>& point_array, 151 int bGrowBox = false 152 ); 153 154 bool Set( 155 int dim, 156 int is_rat, 157 int count, 158 int stride, 159 const float* point_array, 160 int bGrowBox = false 161 ); 162 163 bool Set( 164 const ON_3fPoint& point, 165 int bGrowBox = false 166 ); 167 168 bool Set( 169 const ON_2fPoint& point, 170 int bGrowBox = false 171 ); 172 173 bool Set( 174 const ON_SimpleArray<ON_4fPoint>& point_array, 175 int bGrowBox = false 176 ); 177 178 bool Set( 179 const ON_SimpleArray<ON_3fPoint>& point_array, 180 int bGrowBox = false 181 ); 182 183 bool Set( 184 const ON_SimpleArray<ON_2fPoint>& point_array, 185 int bGrowBox = false 186 ); 187 188 bool IsPointIn( 189 const ON_3dPoint& test_point, // point to test 190 int bStrictlyIn = false 191 // true to test for strict ( min < point < max ) 192 // false to test for (min <= point <= max) 193 // 194 ) const; 195 196 ////////// 197 // Point on or in the box that is closest to test_point. 198 // If test_point is in or on the box, the test_point is returned. 199 ON_3dPoint ClosestPoint( 200 const ON_3dPoint& test_point 201 ) const; 202 203 204 /* 205 Description: 206 Quickly find a lower bound on the distance 207 between the point and this bounding box. 208 Parameters: 209 P - [in] 210 Returns: 211 A distance that is less than or equal to the shortest 212 distance from the line to this bounding box. 213 Put another way, if Q is any point in this bounding box, 214 then P.DistanceTo(Q) >= MinimumDistanceTo(bbox). 215 */ 216 double MinimumDistanceTo( const ON_3dPoint& P ) const; 217 218 /* 219 Description: 220 Quickly find an upper bound on the distance 221 between the point and this bounding box. 222 Parameters: 223 P - [in] 224 Returns: 225 A distance that is greater than or equal to the 226 longest distance from the point P to this bounding box. 227 Put another way, if Q is any point in this bounding box, 228 then P.DistanceTo(Q) <= MaximumDistanceTo(bbox). 229 */ 230 double MaximumDistanceTo( const ON_3dPoint& P ) const; 231 232 233 /* 234 Description: 235 Quickly find a lower bound on the distance 236 between this and the other bounding box. 237 Parameters: 238 other - [in] 239 Returns: 240 A distance that is less than or equal to the shortest 241 distance between the bounding boxes. 242 Put another way, if Q is any point in this bounding box 243 and P is any point in the other bounding box, 244 then P.DistanceTo(Q) >= MinimumDistanceTo(bbox). 245 */ 246 double MinimumDistanceTo( const ON_BoundingBox& other ) const; 247 248 /* 249 Description: 250 Quickly find an upper bound on the distance 251 between this and the other bounding box. 252 Parameters: 253 other - [in] 254 Returns: 255 A distance that is greater than or equal to the longest 256 distance between the bounding boxes. 257 Put another way, if Q is any point in this bounding box 258 and P is any point in the other bounding box, 259 then P.DistanceTo(Q) <= MaximumDistanceTo(bbox). 260 */ 261 double MaximumDistanceTo( const ON_BoundingBox& other ) const; 262 263 /* 264 Description: 265 Quickly find a lower bound on the distance 266 between the line segment and this bounding box. 267 Parameters: 268 line - [in] 269 Returns: 270 A distance that is less than or equal to the shortest 271 distance from the line to this bounding box. 272 Put another way, if Q is any point on line 273 and P is any point in this bounding box, then 274 P.DistanceTo(Q) >= MinimumDistanceTo(bbox). 275 */ 276 double MinimumDistanceTo( const ON_Line& line ) const; 277 278 /* 279 Description: 280 Quickly find a tight lower bound on the distance 281 between the plane and this bounding box. 282 Parameters: 283 plane - [in] 284 Returns: 285 The minimum distance between a point on the plane 286 and a point on the bounding box. 287 See Also: 288 ON_PlaneEquation::MimimumValueAt 289 ON_PlaneEquation::MaximumValueAt 290 */ 291 double MinimumDistanceTo( const ON_Plane& plane ) const; 292 double MinimumDistanceTo( const ON_PlaneEquation& plane_equation ) const; 293 294 /* 295 Description: 296 Quickly find an upper bound on the distance 297 between the line segment and this bounding box. 298 Parameters: 299 line - [in] 300 Returns: 301 A distance that is greater than or equal to the 302 longest distance from the line to this bounding box. 303 Put another way, if Q is any point on the line 304 and P is any point in this bounding box, then 305 P.DistanceTo(Q) <= MaximumDistanceTo(bbox). 306 */ 307 double MaximumDistanceTo( const ON_Line& line ) const; 308 309 /* 310 Description: 311 Quickly find a tight upper bound on the distance 312 between the plane and this bounding box. 313 Parameters: 314 plane - [in] 315 Returns: 316 A distance that is equal to the longest distance from 317 the plane to this bounding box. Put another way, 318 if Q is any point on the plane and P is any point 319 in this bounding box, then 320 P.DistanceTo(Q) <= MaximumDistanceTo(bbox) and there 321 is at least one point on the bounding box where the 322 distance is equal to the returned value. 323 See Also: 324 ON_PlaneEquation::MaximumValueAt 325 */ 326 double MaximumDistanceTo( const ON_Plane& plane ) const; 327 double MaximumDistanceTo( const ON_PlaneEquation& plane_equation ) const; 328 329 330 /* 331 Description: 332 Quickly determine if the shortest distance from 333 the point P to the bounding box is greater than d. 334 Parameters: 335 d - [in] distance (> 0.0) 336 P - [in] 337 Returns: 338 True if if the shortest distance from the point P 339 to the bounding box is greater than d. 340 */ 341 bool IsFartherThan( double d, const ON_3dPoint& P ) const; 342 343 /* 344 Description: 345 Quickly determine if the shortest distance from the line 346 to the bounding box is greater than d. 347 Parameters: 348 d - [in] distance (> 0.0) 349 line - [in] 350 Returns: 351 True if the shortest distance from the line 352 to the bounding box is greater than d. It is not the 353 case that false means that the shortest distance 354 is less than or equal to d. 355 */ 356 bool IsFartherThan( double d, const ON_Line& line ) const; 357 358 /* 359 Description: 360 Quickly determine if the shortest distance from the plane 361 to the bounding box is greater than d. 362 Parameters: 363 d - [in] distance (> 0.0) 364 plane - [in] 365 Returns: 366 True if the shortest distance from the plane 367 to the bounding box is greater than d, and false 368 if the shortest distance is less than or equal to d. 369 */ 370 bool IsFartherThan( double d, const ON_Plane& plane ) const; 371 372 /* 373 Description: 374 Quickly determine if the shortest distance from the plane 375 to the bounding box is greater than d. 376 Parameters: 377 d - [in] distance (> 0.0) 378 plane_equation - [in] (the first three coefficients 379 are assumed to be a unit vector. 380 If not, adjust your d accordingly.) 381 Returns: 382 True if the shortest distance from the plane 383 to the bounding box is greater than d, and false 384 if the shortest distance is less than or equal to d. 385 */ 386 bool IsFartherThan( double d, const ON_PlaneEquation& plane_equation ) const; 387 388 /* 389 Description: 390 Quickly determine if the shortest distance this bounding 391 box to another bounding box is greater than d. 392 Parameters: 393 d - [in] distance (> 0.0) 394 other - [in] other bounding box 395 Returns: 396 True if if the shortest distance from this bounding 397 box to the other bounding box is greater than d. 398 */ 399 bool IsFartherThan( double d, const ON_BoundingBox& other ) const; 400 401 402 // Description: 403 // Get point in a bounding box that is closest to a line 404 // segment. 405 // Parameters: 406 // line - [in] line segment 407 // box_point - [out] point in box that is closest to line 408 // segment point at t0. 409 // t0 - [out] parameter of point on line that is closest to 410 // the box. 411 // t1 - [out] parameter of point on line that is closest to 412 // the box. 413 // Returns: 414 // 3 success - line segments intersects box in a segment 415 // from line(t0) to line(t1) (t0 < t1) 416 // 2 success - line segments intersects box in a single point 417 // at line(t0) (t0==t1) 418 // 1 success - line segment does not intersect box. Closest 419 // point on the line is at line(t0) (t0==t1) 420 // 0 failure - box is invalid. 421 // Remarks: 422 // The box is treated as a solid box. If the intersection 423 // of the line segment, then 3 is returned. 424 int GetClosestPoint( 425 const ON_Line&, // line 426 ON_3dPoint&, // box_point 427 double*, // t0 428 double* // t1 429 ) const; 430 431 ////////// 432 // Get points on bounding boxes that are closest to each other. 433 // If the boxes intersect, then the point at the centroid of the 434 // intersection is returned for both points. 435 bool GetClosestPoint( 436 const ON_BoundingBox&, // "other" bounding box 437 ON_3dPoint&, // point on "this" box that is closest to "other" box 438 ON_3dPoint& // point on "other" box that is closest to "this" box 439 ) const; 440 441 ////////// 442 // Point on the box that is farthest from the test_point. 443 ON_3dPoint FarPoint( 444 const ON_3dPoint& // test_point 445 ) const; 446 447 ////////// 448 // Get points on bounding boxes that are farthest from each other. 449 bool GetFarPoint( 450 const ON_BoundingBox&, // "other" bounding box 451 ON_3dPoint&, // point on "this" box that is farthest from "other" box 452 ON_3dPoint& // point on "other" box that is farthest from "this" box 453 ) const; 454 455 /* 456 Description: 457 Intersect this with other_bbox and save intersection in this. 458 Parameters: 459 other_bbox - [in] 460 Returns: 461 True if this-intesect-other_bbox is a non-empty valid bounding box 462 and this is set. False if the intersection is empty, in which case 463 "this" is set to an invalid bounding box. 464 Remarks: 465 If "this" or other_bbox is invalid, they are treated as 466 the empty set, and false is returned. 467 */ 468 bool Intersection( 469 const ON_BoundingBox& other_bbox 470 ); 471 472 /* 473 Description: 474 Set "this" to the intersection of bbox_A and bbox_B. 475 Parameters: 476 bbox_A - [in] 477 bbox_B - [in] 478 Returns: 479 True if the "this" is a non-empty valid bounding box. 480 False if the intersection is empty, in which case 481 "this" is set to an invalid bounding box. 482 Remarks: 483 If bbox_A or bbox_B is invalid, they are treated as 484 the empty set, and false is returned. 485 */ 486 bool Intersection( // this = intersection of two args 487 const ON_BoundingBox& bbox_A, 488 const ON_BoundingBox& bbox_B 489 ); 490 491 bool Intersection( //Returns true when intersect is non-empty. 492 const ON_Line&, //Infinite Line segment to intersect with 493 double* =NULL , // t0 parameter of first intersection point 494 double* =NULL // t1 parameter of last intersection point (t0<=t1) 495 ) const; 496 497 /* 498 Description: 499 Test a box to see if it is contained in this box. 500 Parameters: 501 other - [in] box to test 502 bProperSubSet - [in] if true, then the test is for a proper inclusion. 503 Returns: 504 If bProperSubSet is false, then the result is true when 505 this->m_min[i] <= other.m_min[i] and other.m_max[i] <= this->m_max[i]. 506 for i=0,1 and 2. 507 If bProperSubSet is true, then the result is true when 508 the above condition is true and at least one of the inequalities is strict. 509 */ 510 bool Includes( 511 const ON_BoundingBox& other, 512 bool bProperSubSet = false 513 ) const; 514 515 double Volume() const; 516 517 double Area() const; 518 519 // Union() returns true if union is not empty. 520 // Invalid boxes are treated as the empty set. 521 bool Union( // this = this union arg 522 const ON_BoundingBox& 523 ); 524 525 bool Union( // this = union of two args 526 const ON_BoundingBox&, 527 const ON_BoundingBox& 528 ); 529 530 /* 531 Description: 532 Test to see if "this" and other_bbox are disjoint (do not intersect). 533 Parameters: 534 other_bbox - [in] 535 Returns: 536 True if "this" and other_bbox are disjoint. 537 Remarks: 538 If "this" or other_bbox is invalid, then true is returned. 539 */ 540 bool IsDisjoint( 541 const ON_BoundingBox& other_bbox 542 ) const; 543 544 bool SwapCoordinates( int, int ); 545 546 ON_3dPoint m_min; 547 ON_3dPoint m_max; 548 }; 549 550 #if defined(ON_DLL_TEMPLATE) 551 552 // This stuff is here because of a limitation in the way Microsoft 553 // handles templates and DLLs. See Microsoft's knowledge base 554 // article ID Q168958 for details. 555 #pragma warning( push ) 556 #pragma warning( disable : 4231 ) 557 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_BoundingBox>; 558 #pragma warning( pop ) 559 560 #endif 561 562 /* 563 Description: 564 Get a tight bounding box that contains the points. 565 Parameters: 566 dim - [in] (>=1) 567 is_rat - [in] true if points are rational 568 count - [in] number of points 569 stride - [in] stride between points 570 point_list - [in] 571 bbox - [in/out] 572 bGrowBox - [in] (default = false) 573 If the input bbox is valid and bGrowBox is true, 574 then the output bbox is the union of the input 575 bbox and the bounding box of the point list. 576 xform - [in] (default = NULL) 577 If not null, the bounding box of the transformed 578 points is calculated. The points are not modified. 579 Returns: 580 True if the output bbox is valid. 581 */ 582 ON_DECL 583 bool ON_GetPointListBoundingBox( 584 int dim, 585 int is_rat, 586 int count, 587 int stride, 588 const double* point_list, 589 ON_BoundingBox& bbox, 590 int bGrowBox = false, 591 const ON_Xform* xform = 0 592 ); 593 594 ON_DECL 595 bool ON_GetPointListBoundingBox( 596 int dim, 597 int is_rat, 598 int count, 599 int stride, 600 const float* point_list, 601 ON_BoundingBox& bbox, 602 int bGrowBox = false, 603 const ON_Xform* xform = 0 604 ); 605 606 ON_DECL 607 bool ON_GetPointListBoundingBox( 608 int dim, 609 int is_rat, 610 int count, 611 int stride, 612 const double* point_list, 613 double* boxmin, // min[dim] 614 double* boxmax, // max[dim] 615 int bGrowBox 616 ); 617 618 ON_DECL 619 ON_BoundingBox ON_PointListBoundingBox( 620 int dim, 621 int is_rat, 622 int count, 623 int stride, 624 const double* point_list 625 ); 626 627 ON_DECL 628 bool ON_GetPointListBoundingBox( 629 int dim, 630 int is_rat, 631 int count, 632 int stride, 633 const float* point_list, 634 float* boxmin, // min[dim] 635 float* boxmax, // max[dim] 636 int bGrowBox 637 ); 638 639 ON_DECL 640 ON_BoundingBox ON_PointListBoundingBox( // low level workhorse function 641 int dim, 642 int is_rat, 643 int count, 644 int stride, 645 const float* point_list 646 ); 647 648 ON_DECL 649 bool ON_GetPointGridBoundingBox( 650 int dim, 651 int is_rat, 652 int point_count0, int point_count1, 653 int point_stride0, int point_stride1, 654 const double* point_grid, 655 double* boxmin, // min[dim] 656 double* boxmax, // max[dim] 657 int bGrowBox 658 ); 659 660 ON_DECL 661 ON_BoundingBox ON_PointGridBoundingBox( 662 int dim, 663 int is_rat, 664 int point_count0, int point_count1, 665 int point_stride0, int point_stride1, 666 const double* point_grid 667 ); 668 669 ON_DECL 670 double ON_BoundingBoxTolerance( 671 int dim, 672 const double* bboxmin, 673 const double* bboxmax 674 ); 675 676 /* 677 Description: 678 Determine if an object is too large or too far 679 from the origin for single precision coordinates 680 to be useful. 681 Parameters: 682 bbox - [in] 683 Bounding box of an object with single precision 684 coordinates. An ON_Mesh is an example of an 685 object with single precision coordinates. 686 xform - [out] 687 If this function returns false and xform is not 688 null, then the identity transform is returned. 689 If this function returns true and xform is not 690 null, then the transform moves the region 691 contained in bbox to a location where single 692 precision coordinates will have enough 693 information for the object to be useful. 694 Returns: 695 true: 696 The region contained in bbox is too large 697 or too far from the origin for single 698 precision coordinates to be useful. 699 false: 700 A single precision object contained in bbox 701 will be satisfactory for common calculations. 702 */ 703 ON_DECL 704 bool ON_BeyondSinglePrecision( const ON_BoundingBox& bbox, ON_Xform* xform ); 705 706 ON_DECL 707 bool ON_WorldBBoxIsInTightBBox( 708 const ON_BoundingBox& tight_bbox, 709 const ON_BoundingBox& world_bbox, 710 const ON_Xform* xform 711 ); 712 713 #endif 714