00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019 ON_BoundingBox::ON_BoundingBox()
00020 : m_min(1.0,0.0,0.0),
00021 m_max(-1.0,0.0,0.0)
00022 {}
00023
00024 const ON_BoundingBox ON_BoundingBox::EmptyBoundingBox;
00025
00026 ON_BoundingBox::ON_BoundingBox( const ON_3dPoint& min_pt, const ON_3dPoint& max_pt )
00027 : m_min( min_pt ),
00028 m_max( max_pt )
00029 {}
00030
00031 ON_BoundingBox::~ON_BoundingBox()
00032 {}
00033
00034 void ON_BoundingBox::Destroy()
00035 {
00036 m_min.Zero();
00037 m_max.Zero();
00038 m_min.x = 1.0;
00039 m_max.x = -1.0;
00040 }
00041
00043
00044
00045
00046
00047 bool ON_BoundingBox::Transform( const ON_Xform& xform )
00048 {
00049 ON_3dPointArray corners;
00050 bool rc = GetCorners( corners );
00051 if (rc) {
00052 rc = corners.Transform(xform);
00053 if (rc)
00054 rc = Set(corners);
00055 }
00056 return rc;
00057 }
00058
00059 double ON_BoundingBox::Tolerance() const
00060 {
00061
00062 return ON_BoundingBoxTolerance( 3, m_min, m_max );
00063 }
00064
00065 ON_3dPoint& ON_BoundingBox::operator[](int i)
00066 {
00067 return (i>0) ? m_max : m_min;
00068 }
00069
00070 const ON_3dPoint& ON_BoundingBox::operator[](int i) const
00071 {
00072 return (i>0) ? m_max : m_min;
00073 }
00074
00075 ON_3dPoint ON_BoundingBox::Min() const
00076 {
00077 return m_min;
00078 }
00079
00080 ON_3dPoint ON_BoundingBox::Max() const
00081 {
00082 return m_max;
00083 }
00084
00085 ON_3dVector ON_BoundingBox::Diagonal() const
00086 {
00087 return m_max - m_min;
00088 }
00089
00090 ON_3dPoint ON_BoundingBox::Center() const
00091 {
00092 return 0.5*(m_max+m_min);
00093 }
00094
00095 ON_3dPoint ON_BoundingBox::Corner( int x_index, int y_index, int z_index ) const
00096 {
00097
00098
00099
00100
00101 ON_3dPoint corner;
00102 corner.x = (x_index>0) ? m_max.x : m_min.x;
00103 corner.y = (y_index>0) ? m_max.y : m_min.y;
00104 corner.z = (z_index>0) ? m_max.z : m_min.z;
00105 return corner;
00106 }
00107
00108 bool
00109 ON_BoundingBox::GetCorners(
00110 ON_3dPoint corners[8]
00111 ) const
00112 {
00113 int n = 0;
00114 if ( IsValid() )
00115 {
00116 ON_3dPoint P;
00117 int i,j,k;
00118 for( i = 0; i < 2; i++ )
00119 {
00120 P.x = (i) ? m_max.x : m_min.x;
00121 for ( j = 0; j < 2; j++ )
00122 {
00123 P.y = (j) ? m_max.y : m_min.y;
00124 for ( k = 0; k < 2; k++ )
00125 {
00126 P.z = (k) ? m_max.z : m_min.z;
00127 corners[n++] = P;
00128 }
00129 }
00130 }
00131 }
00132 return (8==n);
00133 }
00134
00135 bool
00136 ON_BoundingBox::GetCorners(
00137 ON_3dPointArray& corners
00138 ) const
00139 {
00140 ON_3dPoint c[8];
00141 corners.Empty();
00142 bool rc = GetCorners(c);
00143 if ( rc )
00144 corners.Append(8,c);
00145 return rc;
00146 }
00147
00148 ON_ClippingRegion::ON_ClippingRegion()
00149 {
00150 memset(this,0,sizeof(*this));
00151 }
00152
00153 void ON_ClippingRegion::SetClipPlaneTolerance( double clip_plane_tolerance )
00154 {
00155 if ( clip_plane_tolerance > 0.0 && clip_plane_tolerance < 3.402823466e+38 )
00156 m_clip_plane_tolerance = (float)clip_plane_tolerance;
00157 else
00158 m_clip_plane_tolerance = 0.0;
00159 }
00160
00161 double ON_ClippingRegion::ClipPlaneTolerance() const
00162 {
00163 return (float)m_clip_plane_tolerance;
00164 }
00165
00166 int ON_ClippingRegion::InViewFrustum(
00167 ON_3dPoint P
00168 ) const
00169 {
00170 return InViewFrustum(1,&P);
00171 }
00172
00173 int ON_ClippingRegion::InViewFrustum(
00174 const ON_BoundingBox& bbox
00175 ) const
00176 {
00177 if ( !ON_IsValid(bbox.m_min.x)
00178 || !ON_IsValid(bbox.m_max.x)
00179 || bbox.m_min.x > bbox.m_max.x
00180 )
00181 {
00182 return 0;
00183 }
00184
00185 ON_3dPoint P[8];
00186 P[0] = bbox.m_min;
00187 P[1] = bbox.m_max;
00188 P[2].x = bbox.m_min.x; P[2].y = bbox.m_min.y; P[2].z = bbox.m_max.z;
00189 P[3].x = bbox.m_min.x; P[3].y = bbox.m_max.y; P[3].z = bbox.m_min.z;
00190 P[4].x = bbox.m_min.x; P[4].y = bbox.m_max.y; P[4].z = bbox.m_max.z;
00191 P[5].x = bbox.m_max.x; P[5].y = bbox.m_min.y; P[5].z = bbox.m_min.z;
00192 P[6].x = bbox.m_max.x; P[6].y = bbox.m_min.y; P[6].z = bbox.m_max.z;
00193 P[7].x = bbox.m_max.x; P[7].y = bbox.m_max.y; P[7].z = bbox.m_min.z;
00194
00195 return InViewFrustum(8,P);
00196 }
00197
00198 int ON_ClippingRegion::InViewFrustum(
00199 int count,
00200 const ON_3fPoint* p
00201 ) const
00202 {
00203 const double* xform;
00204 const float* cv;
00205 double x, w;
00206 unsigned int out, all_out, some_out;
00207 int i;
00208
00209 some_out = 0;
00210 all_out = 0xFFFFFFFF;
00211 xform = &m_xform.m_xform[0][0];
00212 cv = &p[0].x;
00213 for ( i = count; i--; cv += 3 )
00214 {
00215 out = 0;
00216 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15];
00217 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3];
00218 if (x < -w) out = 0x01; else if (x > w) out = 0x02;
00219 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7];
00220 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00221 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11];
00222 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00223 some_out |= out;
00224 all_out &= out;
00225 if ( some_out && !all_out )
00226 {
00227
00228 break;
00229 }
00230 }
00231
00232 if ( all_out )
00233 i = 0;
00234 else if ( some_out )
00235 i = 1;
00236 else
00237 i = 2;
00238
00239 return i;
00240 }
00241
00242 int ON_ClippingRegion::InViewFrustum(
00243 int count,
00244 const ON_3dPoint* p
00245 ) const
00246 {
00247 const double* xform;
00248 const double* cv;
00249 double x, w;
00250 unsigned int out, all_out, some_out;
00251 int i;
00252
00253 some_out = 0;
00254 all_out = 0xFFFFFFFF;
00255 xform = &m_xform.m_xform[0][0];
00256 cv = &p[0].x;
00257 for ( i = count; i--; cv += 3 )
00258 {
00259 out = 0;
00260 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15];
00261 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3];
00262 if (x < -w) out = 0x01; else if (x > w) out = 0x02;
00263 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7];
00264 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00265 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11];
00266 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00267 some_out |= out;
00268 all_out &= out;
00269 if ( some_out && !all_out )
00270 {
00271
00272 break;
00273 }
00274 }
00275
00276 if ( all_out )
00277 i = 0;
00278 else if ( some_out )
00279 i = 1;
00280 else
00281 i = 2;
00282
00283 return i;
00284 }
00285
00286 int ON_ClippingRegion::InViewFrustum(
00287 int count,
00288 const ON_4dPoint* p
00289 ) const
00290 {
00291 const double* xform;
00292 const double* cv;
00293 double x, w;
00294 unsigned int out, all_out, some_out;
00295 int i;
00296
00297 some_out = 0;
00298 all_out = 0xFFFFFFFF;
00299 xform = &m_xform.m_xform[0][0];
00300 cv = &p[0].x;
00301 for ( i = count; i--; cv += 4 )
00302 {
00303 out = 0;
00304 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
00305 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
00306 if (x < -w) out = 0x01; else if (x > w) out = 0x02;
00307 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
00308 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00309 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
00310 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00311 some_out |= out;
00312 all_out &= out;
00313 if ( some_out && !all_out )
00314 {
00315
00316 break;
00317 }
00318 }
00319
00320 if ( all_out )
00321 i = 0;
00322 else if ( some_out )
00323 i = 1;
00324 else
00325 i = 2;
00326
00327 return i;
00328 }
00329
00330 int ON_ClippingRegion::InClipPlaneRegion(
00331 ON_3dPoint P
00332 ) const
00333 {
00334 return InClipPlaneRegion(1,&P);
00335 }
00336
00337 int ON_ClippingRegion::InClipPlaneRegion(
00338 const ON_BoundingBox& bbox
00339 ) const
00340 {
00341 if ( !ON_IsValid(bbox.m_min.x)
00342 || !ON_IsValid(bbox.m_max.x)
00343 || bbox.m_min.x > bbox.m_max.x
00344 )
00345 {
00346 return 0;
00347 }
00348
00349 if ( m_clip_plane_count <= 0 )
00350 {
00351 return 2;
00352 }
00353
00354 ON_3dPoint P[8];
00355 P[0] = bbox.m_min;
00356 P[1] = bbox.m_max;
00357 P[2].x = bbox.m_min.x; P[2].y = bbox.m_min.y; P[2].z = bbox.m_max.z;
00358 P[3].x = bbox.m_min.x; P[3].y = bbox.m_max.y; P[3].z = bbox.m_min.z;
00359 P[4].x = bbox.m_min.x; P[4].y = bbox.m_max.y; P[4].z = bbox.m_max.z;
00360 P[5].x = bbox.m_max.x; P[5].y = bbox.m_min.y; P[5].z = bbox.m_min.z;
00361 P[6].x = bbox.m_max.x; P[6].y = bbox.m_min.y; P[6].z = bbox.m_max.z;
00362 P[7].x = bbox.m_max.x; P[7].y = bbox.m_max.y; P[7].z = bbox.m_min.z;
00363
00364 return InClipPlaneRegion(8,P);
00365 }
00366
00367 int ON_ClippingRegion::InClipPlaneRegion(
00368 int count,
00369 const ON_3fPoint* p
00370 ) const
00371 {
00372 const ON_PlaneEquation* cpeqn;
00373 const float* cv;
00374 double x;
00375 unsigned int out, all_out, some_out, cpbit;
00376 int i, j;
00377
00378
00379
00380
00381
00382
00383
00384 const double clip_plane_tolerance = ClipPlaneTolerance();
00385
00386 if ( count <= 0 || !p )
00387 return 0;
00388
00389 if ( m_clip_plane_count <= 0 )
00390 return 2;
00391
00392 some_out = 0;
00393 all_out = 0xFFFFFFFF;
00394 cv = &p[0].x;
00395 for ( i = count; i--; cv += 3 )
00396 {
00397 out = 0;
00398
00399 {
00400 cpbit = 0x40;
00401 cpeqn = m_clip_plane;
00402 j = m_clip_plane_count;
00403 while (j--)
00404 {
00405 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d;
00406 if ( x < -clip_plane_tolerance )
00407 out |= cpbit;
00408 cpbit <<= 1;
00409 cpeqn++;;
00410 }
00411 }
00412 some_out |= out;
00413 all_out &= out;
00414 if ( some_out && !all_out )
00415 {
00416
00417 break;
00418 }
00419 }
00420
00421 if ( all_out )
00422 i = 0;
00423 else if ( some_out )
00424 i = 1;
00425 else
00426 i = 2;
00427
00428 return i;
00429 }
00430
00431 int ON_ClippingRegion::InClipPlaneRegion(
00432 int count,
00433 const ON_3dPoint* p
00434 ) const
00435 {
00436 const ON_PlaneEquation* cpeqn;
00437 const double* cv;
00438 double x;
00439 unsigned int out, all_out, some_out, cpbit;
00440 int i, j;
00441
00442 if ( count <= 0 || !p )
00443 return 0;
00444
00445 if ( m_clip_plane_count <= 0 )
00446 return 2;
00447
00448
00449
00450
00451
00452
00453
00454 const double clip_plane_tolerance = ClipPlaneTolerance();
00455
00456 some_out = 0;
00457 all_out = 0xFFFFFFFF;
00458 cv = &p[0].x;
00459 for ( i = count; i--; cv += 3 )
00460 {
00461 out = 0;
00462
00463 {
00464 cpbit = 0x40;
00465 cpeqn = m_clip_plane;
00466 j = m_clip_plane_count;
00467 while (j--)
00468 {
00469 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d;
00470 if ( x < -clip_plane_tolerance )
00471 out |= cpbit;
00472 cpbit <<= 1;
00473 cpeqn++;;
00474 }
00475 }
00476 some_out |= out;
00477 all_out &= out;
00478 if ( some_out && !all_out )
00479 {
00480
00481 break;
00482 }
00483 }
00484
00485 if ( all_out )
00486 i = 0;
00487 else if ( some_out )
00488 i = 1;
00489 else
00490 i = 2;
00491
00492 return i;
00493 }
00494
00495 int ON_ClippingRegion::InClipPlaneRegion(
00496 int count,
00497 const ON_4dPoint* p
00498 ) const
00499 {
00500 const ON_PlaneEquation* cpeqn;
00501 const double* cv;
00502 double x;
00503 unsigned int out, all_out, some_out, cpbit;
00504 int i, j;
00505
00506 if ( count <= 0 || !p )
00507 return 0;
00508
00509 if ( m_clip_plane_count <= 0 )
00510 return 2;
00511
00512
00513
00514
00515
00516
00517
00518 const double clip_plane_tolerance = ClipPlaneTolerance();
00519
00520 some_out = 0;
00521 all_out = 0xFFFFFFFF;
00522 cv = &p[0].x;
00523 for ( i = count; i--; cv += 4 )
00524 {
00525 out = 0;
00526
00527 {
00528 cpbit = 0x40;
00529 cpeqn = m_clip_plane;
00530 j = m_clip_plane_count;
00531 while (j--)
00532 {
00533 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d*cv[3];
00534 if ( x < -clip_plane_tolerance )
00535 out |= cpbit;
00536 cpbit <<= 1;
00537 cpeqn++;;
00538 }
00539 }
00540 some_out |= out;
00541 all_out &= out;
00542 if ( some_out && !all_out )
00543 {
00544
00545 break;
00546 }
00547 }
00548
00549 if ( all_out )
00550 i = 0;
00551 else if ( some_out )
00552 i = 1;
00553 else
00554 i = 2;
00555
00556 return i;
00557 }
00558
00559 int ON_ClippingRegion::IsVisible( ON_3dPoint P ) const
00560 {
00561 return IsVisible(1,&P);
00562 }
00563
00564 int ON_ClippingRegion::IsVisible( const ON_BoundingBox& bbox ) const
00565 {
00566 if ( !ON_IsValid(bbox.m_min.x)
00567 || !ON_IsValid(bbox.m_max.x)
00568 || bbox.m_min.x > bbox.m_max.x
00569 )
00570 {
00571 return 0;
00572 }
00573
00574 ON_3dPoint P[8];
00575 P[0] = bbox.m_min;
00576 P[1] = bbox.m_max;
00577 P[2].x = bbox.m_min.x; P[2].y = bbox.m_min.y; P[2].z = bbox.m_max.z;
00578 P[3].x = bbox.m_min.x; P[3].y = bbox.m_max.y; P[3].z = bbox.m_min.z;
00579 P[4].x = bbox.m_min.x; P[4].y = bbox.m_max.y; P[4].z = bbox.m_max.z;
00580 P[5].x = bbox.m_max.x; P[5].y = bbox.m_min.y; P[5].z = bbox.m_min.z;
00581 P[6].x = bbox.m_max.x; P[6].y = bbox.m_min.y; P[6].z = bbox.m_max.z;
00582 P[7].x = bbox.m_max.x; P[7].y = bbox.m_max.y; P[7].z = bbox.m_min.z;
00583
00584 return IsVisible(8,P);
00585 }
00586
00587
00588 int ON_ClippingRegion::IsVisible( int count, const ON_3fPoint* p ) const
00589 {
00590 const double* xform;
00591 const ON_PlaneEquation* cpeqn;
00592 const float* cv;
00593 double x, w;
00594 unsigned int out, all_out, some_out, cpbit;
00595 int i, j;
00596
00597
00598
00599
00600
00601
00602
00603 const double clip_plane_tolerance = ClipPlaneTolerance();
00604
00605 some_out = 0;
00606 all_out = 0xFFFFFFFF;
00607 xform = &m_xform.m_xform[0][0];
00608 cv = &p[0].x;
00609 for ( i = count; i--; cv += 3 )
00610 {
00611 out = 0;
00612 if ( m_clip_plane_count )
00613 {
00614 cpbit = 0x40;
00615 cpeqn = m_clip_plane;
00616 j = m_clip_plane_count;
00617 while (j--)
00618 {
00619 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d;
00620 if ( x < -clip_plane_tolerance )
00621 out |= cpbit;
00622 cpbit <<= 1;
00623 cpeqn++;;
00624 }
00625 }
00626 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15];
00627 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3];
00628 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00629 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7];
00630 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00631 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11];
00632 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00633 some_out |= out;
00634 all_out &= out;
00635 if ( some_out && !all_out )
00636 {
00637
00638 break;
00639 }
00640 }
00641
00642 if ( all_out )
00643 i = 0;
00644 else if ( some_out )
00645 i = 1;
00646 else
00647 i = 2;
00648
00649 return i;
00650 }
00651
00652 int ON_ClippingRegion::IsVisible( int count, const ON_3dPoint* p ) const
00653 {
00654 const double* xform;
00655 const ON_PlaneEquation* cpeqn;
00656 const double* cv;
00657 double x, w;
00658 unsigned int out, all_out, some_out, cpbit;
00659 int i, j;
00660
00661
00662
00663
00664
00665
00666
00667 const double clip_plane_tolerance = ClipPlaneTolerance();
00668
00669 some_out = 0;
00670 all_out = 0xFFFFFFFF;
00671 xform = &m_xform.m_xform[0][0];
00672 cv = &p[0].x;
00673 for ( i = count; i--; cv += 3 )
00674 {
00675 out = 0;
00676 if ( m_clip_plane_count )
00677 {
00678 cpbit = 0x40;
00679 cpeqn = m_clip_plane;
00680 j = m_clip_plane_count;
00681 while (j--)
00682 {
00683 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d;
00684 if ( x < -clip_plane_tolerance )
00685 out |= cpbit;
00686 cpbit <<= 1;
00687 cpeqn++;;
00688 }
00689 }
00690 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15];
00691 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3];
00692 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00693 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7];
00694 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00695 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11];
00696 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00697 some_out |= out;
00698 all_out &= out;
00699 if ( some_out && !all_out )
00700 {
00701
00702 break;
00703 }
00704 }
00705
00706 if ( all_out )
00707 i = 0;
00708 else if ( some_out )
00709 i = 1;
00710 else
00711 i = 2;
00712
00713 return i;
00714 }
00715
00716
00717 int ON_ClippingRegion::IsVisible( int count, const ON_4dPoint* p ) const
00718 {
00719 const double* xform;
00720 const ON_PlaneEquation* cpeqn;
00721 const double* cv;
00722 double x, w;
00723 unsigned int out, all_out, some_out, cpbit;
00724 int i, j;
00725
00726
00727
00728
00729
00730
00731
00732 const double clip_plane_tolerance = ClipPlaneTolerance();
00733
00734 some_out = 0;
00735 all_out = 0xFFFFFFFF;
00736 xform = &m_xform.m_xform[0][0];
00737 cv = &p[0].x;
00738 for ( i = count; i--; cv += 4 )
00739 {
00740 out = 0;
00741 if ( m_clip_plane_count )
00742 {
00743 cpbit = 0x40;
00744 cpeqn = m_clip_plane;
00745 j = m_clip_plane_count;
00746 while (j--)
00747 {
00748 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d*cv[3];
00749 if ( x < -clip_plane_tolerance )
00750 out |= cpbit;
00751 cpbit <<= 1;
00752 cpeqn++;
00753 }
00754 }
00755 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
00756 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
00757 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00758 x = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
00759 if (x < -w) out |= 0x04; else if (x > w) out |= 0x08;
00760 x = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
00761 if (x < -w) out |= 0x10; else if (x > w) out |= 0x20;
00762 some_out |= out;
00763 all_out &= out;
00764 if ( some_out && !all_out )
00765 {
00766
00767 break;
00768 }
00769 }
00770
00771 if ( all_out )
00772 i = 0;
00773 else if ( some_out )
00774 i = 1;
00775 else
00776 i = 2;
00777
00778 return i;
00779 }
00780
00781 unsigned int ON_ClippingRegion::TransformPoint(
00782 const ON_4dPoint& P,
00783 ON_4dPoint& Q
00784 ) const
00785 {
00786 unsigned int out, cpbit;
00787 const double* xform = &m_xform.m_xform[0][0];
00788 const double cv[4] = {P.x,P.y,P.z,P.w};
00789 const ON_PlaneEquation* cpeqn;
00790 int j;
00791 double x,y,z,w;
00792
00793
00794
00795
00796
00797
00798
00799 const double clip_plane_tolerance = ClipPlaneTolerance();
00800
00801 out = 0;
00802 if ( m_clip_plane_count )
00803 {
00804 cpbit = 0x40;
00805 cpeqn = m_clip_plane;
00806 j = m_clip_plane_count;
00807 while (j--)
00808 {
00809 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d*cv[3];
00810 if ( x < -clip_plane_tolerance )
00811 out |= cpbit;
00812 cpbit <<= 1;
00813 cpeqn++;
00814 }
00815 }
00816 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
00817 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
00818 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00819 y = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
00820 if (y < -w) out |= 0x04; else if (y > w) out |= 0x08;
00821 z = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
00822 if (z < -w) out |= 0x10; else if (z > w) out |= 0x20;
00823 if ( w <= 0.0 )
00824 out = 0x80000000;
00825 Q.x = x; Q.y = y; Q.z = z; Q.w = w;
00826 return out;
00827 }
00828
00829 unsigned int ON_ClippingRegion::TransformPoint(
00830 const ON_3dPoint& P,
00831 ON_3dPoint& Q
00832 ) const
00833 {
00834 unsigned int out, cpbit;
00835 const double* xform = &m_xform.m_xform[0][0];
00836 const double cv[3] = {P.x,P.y,P.z};
00837 const ON_PlaneEquation* cpeqn;
00838 int j;
00839 double x,y,z,w;
00840
00841
00842
00843
00844
00845
00846
00847 const double clip_plane_tolerance = ClipPlaneTolerance();
00848
00849 out = 0;
00850 if ( m_clip_plane_count )
00851 {
00852 cpbit = 0x40;
00853 cpeqn = m_clip_plane;
00854 j = m_clip_plane_count;
00855 while (j--)
00856 {
00857 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d;
00858 if ( x < -clip_plane_tolerance )
00859 out |= cpbit;
00860 cpbit <<= 1;
00861 cpeqn++;
00862 }
00863 }
00864 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15];
00865 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3];
00866 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00867 y = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7];
00868 if (y < -w) out |= 0x04; else if (y > w) out |= 0x08;
00869 z = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11];
00870 if (z < -w) out |= 0x10; else if (z > w) out |= 0x20;
00871 if ( w <= 0.0 )
00872 {
00873 w = (0.0==w) ? 1.0 : 1.0/w;
00874 out |= 0x80000000;
00875 }
00876 else
00877 {
00878 w = 1.0/w;
00879 }
00880 Q.x = x*w; Q.y = y*w; Q.z = z*w;
00881 return out;
00882 }
00883
00884 unsigned int ON_ClippingRegion::TransformPoint(
00885 const ON_3fPoint& P,
00886 ON_3dPoint& Q
00887 ) const
00888 {
00889 ON_3dPoint PP(P.x,P.y,P.z);
00890 return TransformPoint(PP,Q);
00891 }
00892
00893 int ON_ClippingRegion::TransformPoints( int count, ON_4dPoint* p, unsigned int* pflags ) const
00894 {
00895
00896 const double* xform;
00897 const ON_PlaneEquation* cpeqn;
00898 double* cv;
00899 double x, y, z, w;
00900 unsigned int out, all_out, some_out, cpbit;
00901 int i, j;
00902
00903
00904
00905
00906
00907
00908
00909 const double clip_plane_tolerance = ClipPlaneTolerance();
00910
00911 some_out = 0;
00912 all_out = 0xFFFFFFFF;
00913 xform = &m_xform.m_xform[0][0];
00914 cv = &p[0].x;
00915 i = count;
00916 while (i--)
00917 {
00918 out = 0;
00919 if ( m_clip_plane_count )
00920 {
00921 cpbit = 0x40;
00922 cpeqn = m_clip_plane;
00923 j = m_clip_plane_count;
00924 while (j--)
00925 {
00926 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d*cv[3];
00927 if ( x < -clip_plane_tolerance )
00928 out |= cpbit;
00929 cpbit <<= 1;
00930 cpeqn++;;
00931 }
00932 }
00933 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
00934 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
00935 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
00936 y = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
00937 if (y < -w) out |= 0x04; else if (y > w) out |= 0x08;
00938 z = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
00939 if (z < -w) out |= 0x10; else if (z > w) out |= 0x20;
00940 if ( w <= 0.0 )
00941 out |= 0x80000000;
00942 some_out |= out;
00943 all_out &= out;
00944 *pflags++ = out;
00945 *cv++ = x; *cv++ = y; *cv++ = z; *cv++ = w;
00946 }
00947
00948 if ( all_out )
00949 i = 0;
00950 else if ( some_out )
00951 i = 1;
00952 else
00953 i = 2;
00954
00955 return i;
00956 }
00957
00958 int ON_ClippingRegion::TransformPoints( int count, ON_4dPoint* p ) const
00959 {
00960
00961 const double* xform;
00962 const ON_PlaneEquation* cpeqn;
00963 double* cv;
00964 double x, y, z, w;
00965 unsigned int out, all_out, some_out, cpbit;
00966 int i, j;
00967
00968
00969
00970
00971
00972
00973
00974 const double clip_plane_tolerance = ClipPlaneTolerance();
00975
00976 some_out = 0;
00977 all_out = 0xFFFFFFFF;
00978 xform = &m_xform.m_xform[0][0];
00979 cv = &p[0].x;
00980 i = count;
00981 while (i--)
00982 {
00983 out = 0;
00984 if ( m_clip_plane_count )
00985 {
00986 cpbit = 0x40;
00987 cpeqn = m_clip_plane;
00988 j = m_clip_plane_count;
00989 while (j--)
00990 {
00991 x = cpeqn->x*cv[0] + cpeqn->y*cv[1] + cpeqn->z*cv[2] + cpeqn->d*cv[3];
00992 if ( x < -clip_plane_tolerance )
00993 out |= cpbit;
00994 cpbit <<= 1;
00995 cpeqn++;;
00996 }
00997 }
00998 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
00999 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
01000 if (x < -w) out |= 0x01; else if (x > w) out |= 0x02;
01001 y = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
01002 if (y < -w) out |= 0x04; else if (y > w) out |= 0x08;
01003 z = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
01004 if (z < -w) out |= 0x10; else if (z > w) out |= 0x20;
01005 *cv++ = x; *cv++ = y; *cv++ = z; *cv++ = w;
01006 some_out |= out;
01007 all_out &= out;
01008 if ( some_out && !all_out )
01009 {
01010
01011 while (i--)
01012 {
01013 x = xform[0]*cv[0] + xform[1]*cv[1] + xform[2]*cv[2] + xform[3]*cv[3];
01014 y = xform[4]*cv[0] + xform[5]*cv[1] + xform[6]*cv[2] + xform[7]*cv[3];
01015 z = xform[8]*cv[0] + xform[9]*cv[1] + xform[10]*cv[2] + xform[11]*cv[3];
01016 w = xform[12]*cv[0] + xform[13]*cv[1] + xform[14]*cv[2] + xform[15]*cv[3];
01017 *cv++ = x; *cv++ = y; *cv++ = z; *cv++ = w;
01018 }
01019 break;
01020 }
01021 }
01022
01023 if ( all_out )
01024 i = 0;
01025 else if ( some_out )
01026 i = 1;
01027 else
01028 i = 2;
01029
01030 return i;
01031 }
01032
01033
01034 bool ON_ClippingRegion::GetLineClipPlaneParamters(
01035 ON_4dPoint P0,
01036 ON_4dPoint P1,
01037 double* t0,
01038 double* t1
01039 ) const
01040 {
01041 double s0, s1, x0, x1, s;
01042 const ON_PlaneEquation* eqn;
01043 int i;
01044 if ( m_clip_plane_count )
01045 {
01046 s0 = 0.0;
01047 s1 = 1.0;
01048 eqn = m_clip_plane;
01049 const double clip_plane_tolerance = ClipPlaneTolerance();
01050 for ( i = 0; i < m_clip_plane_count; i++, eqn++ )
01051 {
01052 x0 = eqn->x*P0.x + eqn->y*P0.y + eqn->z*P0.z + eqn->d*P0.w;
01053 x1 = eqn->x*P1.x + eqn->y*P1.y + eqn->z*P1.z + eqn->d*P1.w;
01054 if ( x0 < 0.0)
01055 {
01056 if ( x1 <= 0.0 )
01057 {
01058 if ( x0 < -clip_plane_tolerance && x1 <= - clip_plane_tolerance )
01059 return false;
01060 }
01061 if ( x0 != x1 )
01062 {
01063 s = x0/(x0-x1);
01064 if ( s > s0 )
01065 {
01066 s0 = s;
01067 if ( s0 >= s1 )
01068 return false;
01069 }
01070 }
01071 }
01072 else if ( x1 < 0.0 )
01073 {
01074 if ( x0 <= 0.0 )
01075 {
01076 if ( x1 < -clip_plane_tolerance && x0 <= - clip_plane_tolerance )
01077 return false;
01078 }
01079 if ( x0 != x1 )
01080 {
01081 s = x1/(x1-x0);
01082 if ( s < s1 )
01083 {
01084 s1 = s;
01085 if ( s0 >= s1 )
01086 return false;
01087 }
01088 }
01089 }
01090 }
01091 *t0 = s0;
01092 *t1 = s1;
01093 }
01094 else
01095 {
01096 *t0 = 0.0;
01097 *t1 = 1.0;
01098 }
01099 return true;
01100 }
01101
01102
01103 int ON_BoundingBox::IsVisible(
01104 const ON_Xform& bbox2c
01105 ) const
01106 {
01107 int i,j,k,n;
01108 unsigned int all_out, some_out, out;
01109 double bx,by,bz,x,w;
01110 const double* p;
01111
01112 if ( !ON_IsValid(m_min.x) || !ON_IsValid(m_max.x) || m_min.x > m_max.x)
01113 return 0;
01114
01115 some_out = 0;
01116 all_out = 0xFFFFFFFF;
01117 p = &bbox2c.m_xform[0][0];
01118 n = 0;
01119 i = 2; bx = m_min.x;
01120 while(i--)
01121 {
01122 j = 2; by = m_min.y;
01123 while(j--)
01124 {
01125 k = 2; bz = m_min.z;
01126 while(k--)
01127 {
01128 w = bx*p[12] + by*p[13] + bz*p[14] + p[15];
01129 x = bx*p[ 0] + by*p[ 1] + bz*p[ 2] + p[ 3];
01130 if ( x < -w) out = 0x01; else if (x > w) out = 0x02; else out = 0;
01131 x = bx*p[ 4] + by*p[ 5] + bz*p[ 6] + p[ 7];
01132 if ( x < -w) out |= 0x04; else if (x > w) out |= 0x08;
01133 x = bx*p[ 8] + by*p[ 9] + bz*p[10] + p[11];
01134 if ( x < -w) out |= 0x10; else if (x > w) out |= 0x20;
01135 some_out |= out;
01136 all_out &= out;
01137 if ( some_out && !all_out )
01138 {
01139
01140 return 1;
01141 }
01142 bz = m_max.z;
01143 }
01144 by = m_max.y;
01145 }
01146 bx = m_max.x;
01147 }
01148
01149 return ( all_out ? 0 : 2 );
01150 }
01151
01152 bool ON_BoundingBox::IsPointIn( const ON_3dPoint& p, int bStrictlyIn ) const
01153 {
01154 bool bIn = false;
01155 if ( bStrictlyIn ) {
01156 bIn = m_min.x<p.x && p.x<m_max.x &&
01157 m_min.y<p.y && p.y<m_max.y &&
01158 m_min.z<p.z && p.z<m_max.z;
01159 }
01160 else {
01161 bIn = m_min.x<=p.x && p.x<=m_max.x &&
01162 m_min.y<=p.y && p.y<=m_max.y &&
01163 m_min.z<=p.z && p.z<=m_max.z;
01164 }
01165 return bIn;
01166 };
01167
01168 ON_3dPoint ON_BoundingBox::ClosestPoint(
01169 const ON_3dPoint& test_point
01170 ) const
01171 {
01172 ON_3dPoint near_point = test_point;
01173
01174
01175 if ( test_point.x < m_min.x )
01176 near_point.x = m_min.x;
01177 else if ( test_point.x > m_max.x )
01178 near_point.x = m_max.x;
01179 if ( test_point.y < m_min.y )
01180 near_point.y = m_min.y;
01181 else if ( test_point.y > m_max.y )
01182 near_point.y = m_max.y;
01183 if ( test_point.z < m_min.z )
01184 near_point.z = m_min.z;
01185 else if ( test_point.z > m_max.z )
01186 near_point.z = m_max.z;
01187 return near_point;
01188 }
01189
01190
01191
01192 int ON_BoundingBox::GetClosestPoint(
01193 const ON_Line& line, ON_3dPoint& box_point, double* t0, double* t1
01194 ) const
01195 {
01196 if(!IsValid() || !line.IsValid())
01197 return 0;
01198
01199 ON_3dPoint closest;
01200
01201 if(line.Direction().Length()<=ON_SQRT_EPSILON){
01202 ON_3dPoint center = line.PointAt(.5);
01203 if(t0) *t0 = 0.0;
01204 if(t1) *t1 = 1.0;
01205 box_point = ClosestPoint(center);
01206 return IsPointIn( center )? 3 : 1;
01207 }
01208
01209 ON_Interval over[3];
01210
01211 for(int j=0; j<3; j++){
01212 ON_Interval pl( line[0][j], line[1][j]);
01213 if( pl[0]!=pl[1])
01214 over[j]= ON_Interval( pl.NormalizedParameterAt(Min()[j]),
01215 pl.NormalizedParameterAt(Max()[j]) );
01216 else
01217 if( Min()[j]<=pl[0] && pl[0]<=Max()[j] )
01218 over[j]=ON_Interval(-ON_DBL_MAX, ON_DBL_MAX);
01219 else
01220 over[j]=ON_Interval(ON_UNSET_VALUE, ON_UNSET_VALUE);
01221 }
01222
01223
01224
01225
01226 ON_Interval overlap(-ON_DBL_MAX, ON_DBL_MAX);
01227 bool nonempty=true;
01228 int i;
01229 for( i=0;i<3 && nonempty;i++)
01230 nonempty = overlap.Intersection(over[i]);
01231
01232 if(nonempty){
01233 if( overlap.Intersection( ON_Interval(0,1) ) ){
01234
01235 if(t0) *t0 = overlap[0];
01236 if(t1) *t1 = overlap[1];
01237 box_point = line.PointAt(overlap[0]);
01238 return (overlap.Length()>0)? 3 : 2;
01239 }
01240
01241 double EndInd=(overlap[1]<0)? 0.0: 1.0;
01242 if(t0) *t0 = EndInd;
01243 if(t1) *t1 = EndInd;
01244 return 1;
01245 }
01246
01247
01248
01249
01250
01251
01252 int k[3];
01253 for(i=0; i<3; i++)
01254 {
01255
01256
01257 if(!overlap.Intersection( over[(i+1)%3], over[(i+2)%3] )){
01258
01259
01260 ON_3dVector StdUnit(0,0,0);
01261 StdUnit[i]=1.0;
01262 ON_3dVector n = ON_CrossProduct(line.Direction(), StdUnit);
01263 if(n.Length()==0)
01264 continue;
01265 n.Unitize();
01266 int ilo[3]={0,0,0};
01267 int ihi[3]={1,1,1};
01268 int imin[3]={-1,-1,-1};
01269 double amin=0.0;
01270 ihi[i]=ilo[i];
01271 for(k[0]=ilo[0]; k[0]<=ihi[0]; k[0]++)
01272 for(k[1]=ilo[1]; k[1]<=ihi[1]; k[1]++)
01273 for(k[2]=ilo[2]; k[2]<=ihi[2]; k[2]++){
01274 double a = n*(Corner(k[0],k[1],k[2]) - line.from);
01275 if(amin == 0.0 || fabs(a)<fabs(amin))
01276 {
01277 amin= a;
01278 imin[0]=k[0]; imin[1]=k[1]; imin[2]=k[2];
01279 }
01280 }
01281 if ( imin[0] < 0 )
01282 {
01283 return 0;
01284 }
01285 ON_3dPoint vertex = Corner(imin[0],imin[1],imin[2]);
01286 vertex[i] = line.from[i];
01287
01288 ON_3dVector ProjDir = line.Direction();
01289 ProjDir[i]=0.0;
01290 double t = ( vertex - line.from)*ProjDir / ProjDir.LengthSquared();
01291 ON_3dPoint cp = line.PointAt(t);
01292 if( 0<=t && t<=1 && m_min[i]<=cp[i] &&cp[i]<= m_max[i] ){
01293 if(t0) *t0 = t;
01294 if(t1) *t1 = t;
01295 vertex[i] = cp[i];
01296 box_point = vertex;
01297 return 1;
01298 }
01299 }
01300 }
01301
01302
01303 for( k[0]=0; k[0]<2; k[0]++)
01304 for( k[1]=0; k[1]<2; k[1]++)
01305 for( k[2]=0; k[2]<2; k[2]++){
01306 ON_3dPoint corner = Corner(k[0],k[1],k[2]);
01307 double tstar;
01308 line.ClosestPointTo( corner, &tstar );
01309 ON_3dPoint cp = line.PointAt( tstar);
01310 ON_3dVector disp = cp - corner;
01311 bool InNCone=true;
01312 for(int j=0;j<2 && InNCone;j++){
01313 InNCone = InNCone && ( k[j] )? disp[j]>=0 : disp[j]<=0 ;
01314 }
01315 if(InNCone){
01316 if(t0) *t0 = tstar;
01317 if(t1) *t1 = tstar;
01318 box_point = corner;
01319 return 1;
01320 }
01321 }
01322
01323
01324 for(i=0; i<2; i++){
01325 closest = ClosestPoint(line[i]);
01326 double dot = (closest - line[i]) * line.Direction();
01327 if( (i==0 && dot<= 0) || (i==1 && dot>=0) )
01328 {
01329 if(t0) *t0 = i;
01330 if(t1) *t1 = i;
01331 box_point = closest;
01332 return 1;
01333 }
01334 }
01335
01336 ON_ASSERT(false);
01337 return 0;
01338 }
01339
01340
01341
01342 ON_3dPoint ON_BoundingBox::FarPoint(
01343 const ON_3dPoint& test_point
01344 ) const
01345 {
01346 ON_3dPoint far_point = test_point;
01347
01348 far_point.x = ( fabs(m_min.x-test_point.x) >= fabs(m_max.x-test_point.x) )
01349 ? m_min.x : m_max.x;
01350 far_point.y = ( fabs(m_min.y-test_point.y) >= fabs(m_max.y-test_point.y) )
01351 ? m_min.y : m_max.y;
01352 far_point.z = ( fabs(m_min.z-test_point.z) >= fabs(m_max.z-test_point.z) )
01353 ? m_min.z : m_max.z;
01354
01355 return far_point;
01356 }
01357
01358
01359
01360
01361
01362
01363
01364
01365 static bool Intersect( ON_Interval A, ON_Interval B, ON_Interval& AB);
01366
01367 bool Intersect( ON_Interval A, ON_Interval B, ON_Interval& AB){
01368 if(A.IsDecreasing()) A.Swap();
01369 if(B.IsDecreasing()) B.Swap();
01370
01371 bool NotEmpty=true;
01372 if( A.m_t[0] <= B.m_t[0] && B.m_t[0]<=A.m_t[1] && A.m_t[1]<= B.m_t[1]){
01373 AB.Set(B.m_t[0], A.m_t[1]);
01374 } else if( B.m_t[0] <= A.m_t[0] && A.m_t[0]<=B.m_t[1] && B.m_t[1]<=A.m_t[1]){
01375 AB.Set(A.m_t[0], B.m_t[1]);
01376 } else if( A.m_t[0] <= B.m_t[0] && B.m_t[0] <= B.m_t[1] && B.m_t[1]<= A.m_t[1]){
01377 AB.Set(B.m_t[0], B.m_t[1]);
01378 } else if( B.m_t[0] <= A.m_t[0] && A.m_t[0] <= A.m_t[1] && A.m_t[1]<= B.m_t[1]){
01379 AB.Set(A.m_t[0], A.m_t[1]);
01380 } else if( B.m_t[0] <= A.m_t[0] && A.m_t[0] <= A.m_t[1] && A.m_t[1]<= B.m_t[1]){
01381 AB.Set(A.m_t[0], A.m_t[1]);
01382 } else if(A.m_t[1] < B.m_t[0] || B.m_t[1] < A.m_t[0] ){
01383 AB.Destroy();
01384 NotEmpty = false;
01385 }
01386 return NotEmpty;
01387 }
01388
01389 bool ON_BoundingBox::GetClosestPoint(
01390 const ON_BoundingBox& other_box,
01391 ON_3dPoint& this_point,
01392 ON_3dPoint& other_point
01393 ) const
01394 {
01395 ON_BoundingBox b;
01396 if ( !IsValid() || !other_box.IsValid() )
01397 return false;
01398
01399 for (int i=0; i<3; i++ )
01400 {
01401 ON_Interval It(m_min[i],m_max[i]);
01402 ON_Interval Io(other_box.m_min[i],other_box.m_max[i]);
01403 ON_Interval intersect;
01404 bool NotEmpty = Intersect(It,Io,intersect);
01405 if(NotEmpty)
01406 {
01407 this_point[i] = other_point[i] = intersect.Mid();
01408 }
01409 else {
01410 if(m_max[i]< other_box.m_min[i] )
01411 {
01412 this_point[i] = m_max[i];
01413 other_point[i] = other_box.m_min[i];
01414 }
01415 else {
01416 this_point[i] = m_min[i];
01417 other_point[i] = other_box.m_max[i];
01418 }
01419 }
01420 }
01421 return true;
01422 }
01423
01425
01426 bool ON_BoundingBox::GetFarPoint(
01427 const ON_BoundingBox& other_box,
01428 ON_3dPoint& this_point,
01429 ON_3dPoint& other_point
01430 ) const
01431 {
01432 if(!IsValid() || !other_box.IsValid())
01433 return false;
01434 for(int i=0; i<3; i++){
01435 ON_Interval It(m_min[i], m_max[i]);
01436 ON_Interval Io(other_box.m_min[i], other_box.m_max[i]);
01437 if( It.Includes(Io) || Io.Includes(It)){
01438 if( m_max[i] - other_box.m_min[i] > other_box.m_max[i] - m_min[i]){
01439 this_point[i] = m_max[i];
01440 other_point[i] = other_box.m_min[i];
01441 } else {
01442 this_point[i] = m_min[i];
01443 other_point[i] = other_box.m_max[i];
01444 }
01445 } else {
01446 if( m_min[i]< other_box.m_min[i]){
01447 this_point[i]=m_min[i];
01448 } else {
01449 other_point[i] = other_box.m_min[i];
01450 }
01451 if( m_max[i]> other_box.m_max[i]){
01452 this_point[i]=m_max[i];
01453 } else {
01454 other_point[i] = other_box.m_max[i];
01455 }
01456 }
01457 }
01458 return true;
01459 }
01460
01461 bool ON_BoundingBox::SwapCoordinates( int i, int j )
01462 {
01463 bool rc = false;
01464 if ( IsValid() && 0 <= i && i < 3 && 0 <= j && j < 3 ) {
01465 rc = true;
01466 if ( i != j ) {
01467 double t = m_min[i]; m_min[i] = m_min[j]; m_min[j] = t;
01468 t = m_max[i]; m_max[i] = m_max[j]; m_max[j] = t;
01469 }
01470 }
01471 return rc;
01472 }
01473
01474 bool ON_BoundingBox::IsDisjoint( const ON_BoundingBox& other_bbox ) const
01475 {
01476 if ( m_min.x > m_max.x || other_bbox.m_min.x > other_bbox.m_max.x
01477 || m_min.x > other_bbox.m_max.x
01478 || m_max.x < other_bbox.m_min.x )
01479 {
01480 return true;
01481 }
01482 if ( m_min.y > m_max.y || other_bbox.m_min.y > other_bbox.m_max.y
01483 || m_min.y > other_bbox.m_max.y
01484 || m_max.y < other_bbox.m_min.y )
01485 {
01486 return true;
01487 }
01488 if ( m_min.z > m_max.z || other_bbox.m_min.z > other_bbox.m_max.z
01489 || m_min.z > other_bbox.m_max.z
01490 || m_max.z < other_bbox.m_min.z )
01491 {
01492 return true;
01493 }
01494 return false;
01495 }
01496
01497 bool ON_BoundingBox::Intersection(
01498 const ON_BoundingBox& a
01499 )
01500 {
01501 if ( IsValid() && a.IsValid() ) {
01502 if ( a.m_min.x > m_min.x )
01503 m_min.x = a.m_min.x;
01504 if ( a.m_min.y > m_min.y )
01505 m_min.y = a.m_min.y;
01506 if ( a.m_min.z > m_min.z )
01507 m_min.z = a.m_min.z;
01508 if ( a.m_max.x < m_max.x )
01509 m_max.x = a.m_max.x;
01510 if ( a.m_max.y < m_max.y )
01511 m_max.y = a.m_max.y;
01512 if ( a.m_max.z < m_max.z )
01513 m_max.z = a.m_max.z;
01514 }
01515 else {
01516 Destroy();
01517 }
01518 return IsValid();
01519 }
01520
01521 bool ON_BoundingBox::Intersection(
01522 const ON_Line& line,
01523 double* t0 ,
01524 double* t1
01525 ) const
01526 {
01527 ON_Interval t(-ON_DBL_MAX, ON_DBL_MAX), ti, Li;
01528 const double* boxmin = &m_min.x;
01529 const double* boxmax = &m_max.x;
01530 const double* from = &line.from.x;
01531 const double* to = &line.to.x;
01532 for(int i=0; i<3; i++)
01533 {
01534 if( from[i] == to[i] )
01535 {
01536 if( from[i] < boxmin[i] || from[i] > boxmax[i] )
01537 return false;
01538 }
01539 else
01540 {
01541 Li.m_t[0] = from[i];
01542 Li.m_t[1] = to[i];
01543 ti.m_t[0] = Li.NormalizedParameterAt( boxmin[i]);
01544 ti.m_t[1] = Li.NormalizedParameterAt( boxmax[i]);
01545 if ( !t.Intersection(ti) )
01546 return false;
01547 }
01548 }
01549
01550 if(t0)
01551 *t0 = t.Min();
01552 if(t1)
01553 *t1 = t.Max();
01554 return true;
01555 }
01556
01557 bool ON_BoundingBox::Union(
01558 const ON_BoundingBox& a
01559 )
01560 {
01561 if ( IsValid() ) {
01562 if ( a.IsValid() ) {
01563 if ( a.m_min.x < m_min.x )
01564 m_min.x = a.m_min.x;
01565 if ( a.m_min.y < m_min.y )
01566 m_min.y = a.m_min.y;
01567 if ( a.m_min.z < m_min.z )
01568 m_min.z = a.m_min.z;
01569 if ( a.m_max.x > m_max.x )
01570 m_max.x = a.m_max.x;
01571 if ( a.m_max.y > m_max.y )
01572 m_max.y = a.m_max.y;
01573 if ( a.m_max.z > m_max.z )
01574 m_max.z = a.m_max.z;
01575 }
01576 }
01577 else if ( a.IsValid() ) {
01578 *this = a;
01579 }
01580 else {
01581 Destroy();
01582 }
01583 return IsValid();
01584 }
01585
01586 bool ON_BoundingBox::Intersection(
01587 const ON_BoundingBox& a,
01588 const ON_BoundingBox& b
01589 )
01590 {
01591 if ( a.IsValid() && b.IsValid() ) {
01592 m_min.x = (a.m_min.x >= b.m_min.x) ? a.m_min.x : b.m_min.x;
01593 m_min.y = (a.m_min.y >= b.m_min.y) ? a.m_min.y : b.m_min.y;
01594 m_min.z = (a.m_min.z >= b.m_min.z) ? a.m_min.z : b.m_min.z;
01595 m_max.x = (a.m_max.x <= b.m_max.x) ? a.m_max.x : b.m_max.x;
01596 m_max.y = (a.m_max.y <= b.m_max.y) ? a.m_max.y : b.m_max.y;
01597 m_max.z = (a.m_max.z <= b.m_max.z) ? a.m_max.z : b.m_max.z;
01598 }
01599 else {
01600 Destroy();
01601 }
01602 return IsValid();
01603 }
01604
01605 bool ON_BoundingBox::Includes(
01606 const ON_BoundingBox& other,
01607 bool bProperSubSet) const
01608 {
01609 bool rc = true;
01610 bool proper = false;
01611 for(int i=0; i<3 && rc ; i++)
01612 {
01613 ON_Interval thisI( m_min[i], m_max[i]);
01614 ON_Interval otherI( other.m_min[i], other.m_max[i]);
01615 rc = thisI.Includes( otherI );
01616 if(bProperSubSet && !proper)
01617 {
01618 proper = (other.m_min[i] > m_min[i]) || (other.m_max[i] < m_max[i]);
01619 }
01620 }
01621
01622
01623 if(bProperSubSet)
01624 rc = rc && proper;
01625 return rc;
01626 }
01627
01628
01629 bool ON_BoundingBox::Union(
01630 const ON_BoundingBox& a,
01631 const ON_BoundingBox& b
01632 )
01633 {
01634 if ( a.IsValid() ) {
01635 if ( b.IsValid() ) {
01636 m_min.x = (a.m_min.x <= b.m_min.x) ? a.m_min.x : b.m_min.x;
01637 m_min.y = (a.m_min.y <= b.m_min.y) ? a.m_min.y : b.m_min.y;
01638 m_min.z = (a.m_min.z <= b.m_min.z) ? a.m_min.z : b.m_min.z;
01639 m_max.x = (a.m_max.x >= b.m_max.x) ? a.m_max.x : b.m_max.x;
01640 m_max.y = (a.m_max.y >= b.m_max.y) ? a.m_max.y : b.m_max.y;
01641 m_max.z = (a.m_max.z >= b.m_max.z) ? a.m_max.z : b.m_max.z;
01642 }
01643 else {
01644 *this = a;
01645 }
01646 }
01647 else if ( b.IsValid() ) {
01648 *this = b;
01649 }
01650 else {
01651 Destroy();
01652 }
01653 return IsValid();
01654 }
01655
01656 double ON_BoundingBox::Volume() const
01657 {
01658 double dx = m_max.x - m_min.x;
01659 double dy = m_max.y - m_min.y;
01660 double dz = m_max.z - m_min.z;
01661 return (dx > 0.0 && dy > 0.0 && dz > 0.0) ? dx*dy*dz : 0.0;
01662 }
01663
01664 double ON_BoundingBox::Area() const
01665 {
01666 double dx = m_max.x - m_min.x;
01667 double dy = m_max.y - m_min.y;
01668 double dz = m_max.z - m_min.z;
01669 return (dx >= 0.0 && dy >= 0.0 && dz >= 0.0) ? 2.0*(dx*dy + dy*dz + dz*dx) : 0.0;
01670 }
01671
01672 bool ON_BoundingBox::Set(
01673 int dim, int is_rat, int count, int stride,
01674 const double* points,
01675 int bGrowBox
01676 )
01677 {
01678 return ON_GetPointListBoundingBox(dim, is_rat, count, stride, points, *this, bGrowBox!=0, 0 );
01679 }
01680
01681 bool ON_BoundingBox::Set ( const ON_3dPoint& P, int bGrowBox )
01682 {
01683 if ( !bGrowBox || !IsValid() )
01684 {
01685 m_min = P;
01686 m_max = P;
01687 }
01688 else
01689 {
01690 if ( P.x < m_min.x ) m_min.x = P.x; else if ( m_max.x < P.x ) m_max.x = P.x;
01691 if ( P.y < m_min.y ) m_min.y = P.y; else if ( m_max.y < P.y ) m_max.y = P.y;
01692 if ( P.z < m_min.z ) m_min.z = P.z; else if ( m_max.z < P.z ) m_max.z = P.z;
01693 }
01694 return true;
01695 }
01696
01697
01698 bool ON_BoundingBox::Set( const ON_SimpleArray<ON_4dPoint>& a, int bGrowBox )
01699 {
01700 const int count = a.Count();
01701 const double* p = (count>0) ? &a.Array()->x : 0;
01702 return ON_GetPointListBoundingBox(3, 1, count, 4, p, *this, bGrowBox!=0, 0 );
01703 }
01704
01705 bool ON_BoundingBox::Set( const ON_SimpleArray<ON_3dPoint>& a, int bGrowBox )
01706 {
01707 const int count = a.Count();
01708 const double* p = (count>0) ? &a.Array()->x : 0;
01709 return ON_GetPointListBoundingBox(3, 0, count, 3, p, *this, bGrowBox!=0, 0 );
01710 }
01711
01712 bool ON_BoundingBox::Set( const ON_SimpleArray<ON_2dPoint>& a, int bGrowBox )
01713 {
01714 const int count = a.Count();
01715 const double* p = (count>0) ? &a.Array()->x : 0;
01716 return ON_GetPointListBoundingBox(2, 0, count, 2, p, *this, bGrowBox!=0, 0 );
01717 }
01718
01719 ON_BoundingBox ON_PointListBoundingBox(
01720 int dim, int is_rat, int count, int stride, const double* points
01721 )
01722 {
01723 ON_BoundingBox bbox;
01724 ON_GetPointListBoundingBox( dim, is_rat, count, stride, points, bbox, false, 0 );
01725 return bbox;
01726 }
01727
01728 bool ON_GetPointListBoundingBox(
01729 int dim, int is_rat, int count, int stride, const double* points,
01730 ON_BoundingBox& tight_bbox,
01731 int bGrowBox,
01732 const ON_Xform* xform
01733 )
01734 {
01735
01736 bool rc = false;
01737 if ( bGrowBox && !tight_bbox.IsValid() )
01738 {
01739 bGrowBox = false;
01740 }
01741 if ( !bGrowBox )
01742 {
01743 tight_bbox.Destroy();
01744 }
01745 if ( is_rat )
01746 {
01747 is_rat = 1;
01748 }
01749
01750 if ( count > 0 && dim > 0 && points && (count == 1 || stride >= dim+is_rat) )
01751 {
01752 ON_BoundingBox bbox;
01753 ON_3dPoint P(0.0,0.0,0.0);
01754 double w;
01755 int i, wi;
01756
01757 if ( xform && xform->IsIdentity() )
01758 {
01759 xform = 0;
01760 }
01761 wi = dim;
01762 if ( dim > 3 )
01763 {
01764 dim = 3;
01765 }
01766
01767 rc = true;
01768 if ( is_rat )
01769 {
01770
01771 while ( count > 0 && points[wi] == 0.0 )
01772 {
01773 count--;
01774 points += stride;
01775 rc = false;
01776 }
01777 if ( count <= 0 )
01778 return false;
01779 }
01780
01781 memcpy( &bbox.m_min.x, points, dim*sizeof(bbox.m_min.x) );
01782 if ( is_rat )
01783 {
01784 w = 1.0/points[wi];
01785 bbox.m_min.x *= w; bbox.m_min.y *= w; bbox.m_min.z *= w;
01786 }
01787 if ( xform )
01788 {
01789 bbox.m_min.Transform(*xform);
01790 }
01791 bbox.m_max = bbox.m_min;
01792 points += stride;
01793 count--;
01794
01795 if ( count > 0 )
01796 {
01797 if ( is_rat )
01798 {
01799
01800 if ( xform )
01801 {
01802 for ( ; count--; points += stride )
01803 {
01804 if ( 0.0 == (w = points[wi]) )
01805 {
01806 rc = false;
01807 continue;
01808 }
01809 memcpy( &P.x, points, dim*sizeof(P.x) );
01810 w = 1.0/w;
01811 P.x *= w; P.y *= w; P.z *= w;
01812 P.Transform(*xform);
01813 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
01814 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
01815 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
01816 }
01817 if ( dim < 3 )
01818 {
01819 for ( i = dim; i < 3; i++)
01820 {
01821 bbox.m_min[i] = 0.0;
01822 bbox.m_max[i] = 0.0;
01823 }
01824 }
01825 }
01826 else
01827 {
01828 for ( ; count--; points += stride )
01829 {
01830 if ( 0.0 == (w = points[wi]) )
01831 {
01832 rc = false;
01833 continue;
01834 }
01835 memcpy( &P.x, points, dim*sizeof(P.x) );
01836 w = 1.0/w;
01837 P.x *= w; P.y *= w; P.z *= w;
01838 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
01839 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
01840 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
01841 }
01842 }
01843 }
01844 else
01845 {
01846
01847 if ( xform )
01848 {
01849 for ( ; count--; points += stride )
01850 {
01851 memcpy( &P.x, points, dim*sizeof(P.x) );
01852 P.Transform(*xform);
01853 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
01854 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
01855 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
01856 }
01857 if ( dim < 3 )
01858 {
01859 for ( i = dim; i < 3; i++)
01860 {
01861 bbox.m_min[i] = 0.0;
01862 bbox.m_max[i] = 0.0;
01863 }
01864 }
01865 }
01866 else
01867 {
01868 for ( ; count--; points += stride )
01869 {
01870 memcpy( &P.x, points, dim*sizeof(P.x) );
01871 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
01872 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
01873 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
01874 }
01875 }
01876 }
01877 }
01878
01879 tight_bbox.Union(bbox);
01880 }
01881 else if ( bGrowBox )
01882 {
01883
01884 rc = (0 == count);
01885 }
01886
01887 return rc;
01888 }
01889
01890 bool ON_GetPointListBoundingBox(
01891 int dim, int is_rat, int count, int stride, const float* points,
01892 ON_BoundingBox& tight_bbox,
01893 int bGrowBox,
01894 const ON_Xform* xform
01895 )
01896 {
01897
01898 ON_BoundingBox bbox;
01899 ON_3dPoint P(0.0,0.0,0.0);
01900 ON_3fPoint Q(0.0,0.0,0.0);
01901 double w;
01902 int i, wi;
01903 bool rc = false;
01904 if ( bGrowBox && !tight_bbox.IsValid() )
01905 {
01906 bGrowBox = false;
01907 }
01908 if ( !bGrowBox )
01909 {
01910 tight_bbox.Destroy();
01911 }
01912 if ( is_rat )
01913 {
01914 is_rat = 1;
01915 }
01916
01917 if ( count > 0 && dim > 0 && points && (count == 1 || stride >= dim+is_rat) )
01918 {
01919 if ( xform && xform->IsIdentity() )
01920 {
01921 xform = 0;
01922 }
01923 wi = dim;
01924 if ( dim > 3 )
01925 {
01926 dim = 3;
01927 }
01928
01929 rc = true;
01930 if ( is_rat )
01931 {
01932
01933 while ( count > 0 && points[wi] == 0.0f )
01934 {
01935 count--;
01936 points += stride;
01937 rc = false;
01938 }
01939 if ( count <= 0 )
01940 return false;
01941 }
01942
01943 if ( !bGrowBox )
01944 {
01945 memcpy( &Q.x, points, dim*sizeof(Q.x) );
01946 bbox.m_min = Q;
01947 if ( is_rat )
01948 {
01949 w = 1.0/points[wi];
01950 bbox.m_min.x *= w; bbox.m_min.y *= w; bbox.m_min.z *= w;
01951 }
01952 if ( xform )
01953 {
01954 bbox.m_min.Transform(*xform);
01955 }
01956 bbox.m_max = bbox.m_min;
01957 points += stride;
01958 count--;
01959 bGrowBox = true;
01960 }
01961
01962 if ( count > 0 )
01963 {
01964 if ( is_rat )
01965 {
01966
01967 if ( xform )
01968 {
01969 for ( ; count--; points += stride )
01970 {
01971 if ( 0.0 == (w = points[wi]) )
01972 {
01973 rc = false;
01974 continue;
01975 }
01976 memcpy( &Q.x, points, dim*sizeof(Q.x) );
01977 w = 1.0/w;
01978 P.x = w*Q.x; P.y = w*Q.y; P.z = w*Q.z;
01979 P.Transform(*xform);
01980 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
01981 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
01982 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
01983 }
01984 if ( dim < 3 )
01985 {
01986 for ( i = dim; i < 3; i++)
01987 {
01988 bbox.m_min[i] = 0.0;
01989 bbox.m_max[i] = 0.0;
01990 }
01991 }
01992 }
01993 else
01994 {
01995 for ( ; count--; points += stride )
01996 {
01997 if ( 0.0 == (w = points[wi]) )
01998 {
01999 rc = false;
02000 continue;
02001 }
02002 memcpy( &Q.x, points, dim*sizeof(Q.x) );
02003 w = 1.0/w;
02004 P.x = w*Q.x; P.y = w*Q.y; P.z = w*Q.z;
02005 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
02006 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
02007 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
02008 }
02009 }
02010 }
02011 else
02012 {
02013
02014 if ( xform )
02015 {
02016 for ( ; count--; points += stride )
02017 {
02018 memcpy( &Q.x, points, dim*sizeof(Q.x) );
02019 P.x = Q.x; P.y = Q.y; P.z = Q.z;
02020 P.Transform(*xform);
02021 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
02022 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
02023 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
02024 }
02025 if ( dim < 3 )
02026 {
02027 for ( i = dim; i < 3; i++)
02028 {
02029 bbox.m_min[i] = 0.0;
02030 bbox.m_max[i] = 0.0;
02031 }
02032 }
02033 }
02034 else
02035 {
02036 for ( ; count--; points += stride )
02037 {
02038 memcpy( &Q.x, points, dim*sizeof(Q.x) );
02039 P.x = Q.x; P.y = Q.y; P.z = Q.z;
02040 if ( bbox.m_min.x > P.x ) bbox.m_min.x = P.x; else if ( bbox.m_max.x < P.x ) bbox.m_max.x = P.x;
02041 if ( bbox.m_min.y > P.y ) bbox.m_min.y = P.y; else if ( bbox.m_max.y < P.y ) bbox.m_max.y = P.y;
02042 if ( bbox.m_min.z > P.z ) bbox.m_min.z = P.z; else if ( bbox.m_max.z < P.z ) bbox.m_max.z = P.z;
02043 }
02044 }
02045 }
02046 }
02047
02048 tight_bbox.Union(bbox);
02049 }
02050 else if ( bGrowBox )
02051 {
02052
02053 rc = (0 == count);
02054 }
02055
02056 return rc;
02057 }
02058
02059
02060 bool ON_GetPointListBoundingBox(
02061 int dim, int is_rat, int count, int stride, const double* points,
02062 double* boxmin, double* boxmax,
02063 int bGrowBox
02064 )
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082 {
02083
02084
02085 double x, w;
02086 int j;
02087 bool rc = false;
02088 for ( j = 0; j < dim && bGrowBox; j++ )
02089 {
02090 if ( boxmin[j] > boxmax[j] )
02091 bGrowBox = false;
02092 }
02093
02094 if ( count > 0 )
02095 {
02096 if ( is_rat )
02097 {
02098 is_rat = 1;
02099 }
02100 if ( points && dim > 0 && (count == 1 || stride >= dim+is_rat) )
02101 {
02102
02103
02104 if ( is_rat )
02105 {
02106
02107 rc = true;
02108 while ( count > 0 && points[dim] == 0.0 )
02109 {
02110 count--;
02111 points += stride;
02112 rc = false;
02113 }
02114 if ( count > 0 )
02115 {
02116 if ( !bGrowBox )
02117 {
02118 ON_ArrayScale( dim, 1.0/points[dim], points, boxmin );
02119 memcpy( boxmax, boxmin, dim*sizeof(*boxmax) );
02120 points += stride;
02121 count--;
02122 bGrowBox = true;
02123 }
02124 if ( count > 0 )
02125 {
02126 for ( ; count--; points += stride )
02127 {
02128 if ( points[dim] == 0.0 ) {
02129 rc = false;
02130 continue;
02131 }
02132 w = 1.0/points[dim];
02133 for ( j = 0; j < dim; j++ )
02134 {
02135 x = w*points[j];
02136 if (boxmin[j] > x)
02137 boxmin[j] = x;
02138 else if (boxmax[j] < x)
02139 boxmax[j] = x;
02140 }
02141 }
02142 }
02143 }
02144 }
02145 else
02146 {
02147
02148 rc = true;
02149 if ( !bGrowBox )
02150 {
02151
02152 memcpy( boxmin, points, dim*sizeof(*boxmin) );
02153 memcpy( boxmax, boxmin, dim*sizeof(*boxmax) );
02154 points += stride;
02155 count--;
02156 bGrowBox = true;
02157 }
02158 if ( count )
02159 {
02160
02161 for ( ; count--; points += stride )
02162 {
02163 for ( j = 0; j < dim; j++ )
02164 {
02165 x = points[j];
02166 if (boxmin[j] > x)
02167 boxmin[j] = x;
02168 else if (boxmax[j] < x)
02169 boxmax[j] = x;
02170 }
02171 }
02172 }
02173 }
02174 }
02175 }
02176 else if ( bGrowBox )
02177 {
02178
02179 rc = true;
02180 }
02181 return rc;
02182 }
02183
02184
02185 ON_BoundingBox ON_PointListBoundingBox(
02186 int dim, int is_rat, int count, int stride, const float* points
02187 )
02188 {
02189 ON_BoundingBox bbox;
02190 ON_GetPointListBoundingBox( dim, is_rat, count, stride, points, bbox, false, 0 );
02191 return bbox;
02192 }
02193
02194
02195 bool ON_GetPointListBoundingBox(
02196 int dim, int is_rat, int count, int stride, const float* points,
02197 float* boxmin, float* boxmax,
02198 int bGrowBox
02199 )
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216 {
02217
02218
02219 float x;
02220 double w;
02221 int j;
02222 bool rc = false;
02223 for ( j = 0; j < dim && bGrowBox; j++ )
02224 {
02225 if ( boxmin[j] > boxmax[j] )
02226 bGrowBox = false;
02227 }
02228 if ( count > 0 )
02229 {
02230 if ( is_rat )
02231 is_rat = 1;
02232 if ( points && dim > 0 && (count == 1 || stride >= dim+is_rat) )
02233 {
02234 if ( is_rat ) {
02235 rc = true;
02236 while ( count > 0 && points[dim] == 0.0 ) {
02237 count--;
02238 points += stride;
02239 rc = false;
02240 }
02241 if ( count > 0 ) {
02242 if ( !bGrowBox )
02243 {
02244 ON_ArrayScale( dim, 1.0f/points[dim], points, boxmin );
02245 memcpy( boxmax, boxmin, dim*sizeof(*boxmax) );
02246 points += stride;
02247 count--;
02248 bGrowBox = true;
02249 }
02250 for ( ; count--; points += stride )
02251 {
02252 if ( points[dim] == 0.0 )
02253 continue;
02254 w = 1.0/points[dim];
02255 for ( j = 0; j < dim; j++ ) {
02256 x = (float)(w*points[j]);
02257 if (boxmin[j] > x)
02258 boxmin[j] = x;
02259 else if (boxmax[j] < x)
02260 boxmax[j] = x;
02261 }
02262 }
02263 }
02264 }
02265 else
02266 {
02267 rc = true;
02268 if ( !bGrowBox ) {
02269 memcpy( boxmin, points, dim*sizeof(*boxmin) );
02270 memcpy( boxmax, boxmin, dim*sizeof(*boxmax) );
02271 points += stride;
02272 count--;
02273 bGrowBox = true;
02274 }
02275 for ( ; count--; points += stride )
02276 {
02277 for ( j = 0; j < dim; j++ ) {
02278 x = points[j];
02279 if (boxmin[j] > x)
02280 boxmin[j] = x;
02281 else if (boxmax[j] < x)
02282 boxmax[j] = x;
02283 }
02284 }
02285 }
02286 }
02287 }
02288 else if ( bGrowBox )
02289 {
02290 rc = true;
02291 }
02292 return rc;
02293 }
02294
02295
02296 ON_BoundingBox ON_PointGridBoundingBox(
02297 int dim,
02298 ON_BOOL32 is_rat,
02299 int point_count0, int point_count1,
02300 int point_stride0, int point_stride1,
02301 const double* p
02302 )
02303 {
02304 ON_BoundingBox bbox;
02305 if ( dim > 3 )
02306 {
02307
02308 dim = 3;
02309 }
02310 ON_GetPointGridBoundingBox( dim, is_rat,
02311 point_count0, point_count1,
02312 point_stride0, point_stride1, p,
02313 &bbox.m_min.x, &bbox.m_max.x, false );
02314 return bbox;
02315 }
02316
02317
02318 bool ON_GetPointGridBoundingBox(
02319 int dim,
02320 int is_rat,
02321 int point_count0, int point_count1,
02322 int point_stride0, int point_stride1,
02323 const double* p,
02324 double* boxmin, double* boxmax,
02325 int bGrowBox
02326 )
02327 {
02328 int i;
02329 for ( i = 0; i < dim && bGrowBox; i++ )
02330 {
02331 if ( boxmin[i] > boxmax[i] )
02332 bGrowBox = false;
02333 }
02334 bool rc = bGrowBox ? true : false;
02335 for ( i = 0; i < point_count0; i++ )
02336 {
02337 if ( !ON_GetPointListBoundingBox( dim, is_rat, point_count1, point_stride1, p + i*point_stride0, boxmin, boxmax, bGrowBox ) ) {
02338 rc = false;
02339 break;
02340 }
02341 else
02342 {
02343 bGrowBox = true;
02344 if (!i)
02345 rc = true;
02346 }
02347 }
02348 return rc;
02349 }
02350
02351 bool ON_BeyondSinglePrecision( const ON_BoundingBox& bbox, ON_Xform* xform )
02352 {
02353 bool rc = false;
02354
02355 if ( bbox.IsValid() )
02356 {
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 const double too_far = 262144.0;
02373 const double too_big = 1048576.0;
02374 bool bTooFar = ( bbox.m_min.x >= too_far
02375 || bbox.m_min.y >= too_far
02376 || bbox.m_min.x >= too_far
02377 || bbox.m_max.x <= -too_far
02378 || bbox.m_max.y <= -too_far
02379 || bbox.m_max.x <= -too_far
02380 );
02381 bool bTooBig = ( bbox.m_min.x <= -too_big
02382 || bbox.m_min.y <= -too_big
02383 || bbox.m_min.x <= -too_big
02384 || bbox.m_max.x >= too_big
02385 || bbox.m_max.y >= too_big
02386 || bbox.m_max.x >= too_big
02387 );
02388 if ( bTooFar || bTooBig )
02389 {
02390 rc = true;
02391 if ( 0 != xform )
02392 {
02393 ON_3dVector C = bbox.Center();
02394
02395
02396
02397
02398
02399 if ( fabs(C.x) <= 100.0 )
02400 C.x = 0.0;
02401 if ( fabs(C.y) <= 100.0 )
02402 C.y = 0.0;
02403 if ( fabs(C.z) <= 100.0 )
02404 C.z = 0.0;
02405 double r = 0.5*bbox.m_max.DistanceTo(bbox.m_min);
02406
02407 ON_Xform T;
02408 T.Translation(-C);
02409
02410
02411
02412
02413
02414 double s = 1.0;
02415 if ( r > too_big/16.0 )
02416 {
02417
02418
02419 s = too_big;
02420 while ( r > s*1024.0 )
02421 s *= 2.0;
02422 s = 1.0/s;
02423 }
02424 ON_Xform S(s);
02425
02426
02427
02428
02429 *xform = S*T;
02430 }
02431 }
02432 }
02433
02434 if (!rc && 0 != xform )
02435 xform->Identity();
02436
02437 return rc;
02438 }
02439
02440
02441 double ON_BoundingBoxTolerance(
02442 int dim,
02443 const double* bboxmin,
02444 const double* bboxmax
02445 )
02446 {
02447 int i;
02448 double x, tolerance=0.0;
02449
02450 #if defined(ON_COMPILER_MSC)
02451 #pragma warning( push )
02452
02453
02454 #pragma warning( disable : 4127 )
02455 #endif
02456
02457 ON_ASSERT_OR_RETURN( dim > 0 && bboxmin != NULL && bboxmax != NULL,tolerance);
02458 for ( i = 0; i < dim; i++ ) {
02459 ON_ASSERT_OR_RETURN(bboxmin[i] <= bboxmax[i],tolerance);
02460 }
02461
02462 #if defined(ON_COMPILER_MSC)
02463 #pragma warning( pop )
02464 #endif
02465
02466 tolerance = ON_ArrayDistance(dim,bboxmin,bboxmax)*ON_EPSILON;
02467 for ( i = 0; i < dim; i++ ) {
02468 x = (bboxmax[i] - bboxmin[i])*ON_SQRT_EPSILON;
02469 if ( x > tolerance )
02470 tolerance = x;
02471 x = (fabs(bboxmax[i]) - fabs(bboxmin[i]))*ON_EPSILON;
02472 if ( x > tolerance )
02473 tolerance = x;
02474 }
02475 if ( tolerance > 0.0 && tolerance < ON_ZERO_TOLERANCE )
02476 tolerance = ON_ZERO_TOLERANCE;
02477 return tolerance;
02478 }
02479
02480 int ON_BoundingBox::IsDegenerate( double tolerance ) const
02481 {
02482 ON_3dVector diag = Diagonal();
02483 if ( tolerance < 0.0 )
02484 {
02485
02486 tolerance = diag.MaximumCoordinate()*ON_SQRT_EPSILON;
02487 }
02488 int rc = 0;
02489 if ( diag.x < 0.0 )
02490 return 4;
02491 if ( diag.x <= tolerance )
02492 rc++;
02493 if ( diag.y < 0.0 )
02494 return 4;
02495 if ( diag.y <= tolerance )
02496 rc++;
02497 if ( diag.z < 0.0 )
02498 return 4;
02499 if ( diag.z <= tolerance )
02500 rc++;
02501 return rc;
02502 }
02503
02504 double ON_BoundingBox::MinimumDistanceTo( const ON_3dPoint& P ) const
02505 {
02506
02507
02508
02509
02510
02511 ON_3dVector V;
02512
02513 if ( P.x < m_min.x )
02514 V.x = m_min.x - P.x;
02515 else if ( P.x > m_max.x )
02516 V.x = P.x - m_max.x;
02517 else
02518 V.x = 0.0;
02519
02520 if ( P.y < m_min.y )
02521 V.y = m_min.y - P.y;
02522 else if ( P.y > m_max.y )
02523 V.y = P.y - m_max.y;
02524 else
02525 V.y = 0.0;
02526
02527 if ( P.z < m_min.z )
02528 V.z = m_min.z - P.z;
02529 else if ( P.z > m_max.z )
02530 V.z = P.z - m_max.z;
02531 else
02532 V.z = 0.0;
02533
02534 return V.Length();
02535 }
02536
02537 double ON_BoundingBox::MaximumDistanceTo( const ON_3dPoint& P ) const
02538 {
02539
02540
02541
02542 ON_3dVector V;
02543
02544 V.x = ( (P.x < 0.5*(m_min.x+m_max.x)) ? m_max.x : m_min.x) - P.x;
02545 V.y = ( (P.y < 0.5*(m_min.y+m_max.y)) ? m_max.y : m_min.y) - P.y;
02546 V.z = ( (P.z < 0.5*(m_min.z+m_max.z)) ? m_max.z : m_min.z) - P.z;
02547
02548 return V.Length();
02549 }
02550
02551 static double ON_BBoxMinimumDistanceToHelper( const ON_BoundingBox& bbox, ON_Line line )
02552 {
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564 double d, t;
02565 bool bTrimmed;
02566
02567
02568
02569 if ( bbox.m_min.x <= line.from.x && line.from.x <= bbox.m_max.x )
02570 {
02571 if ( bbox.m_min.y <= line.from.y && line.from.y <= bbox.m_max.y )
02572 {
02573 if ( bbox.m_min.z <= line.from.z && line.from.z <= bbox.m_max.z )
02574 {
02575 return 0.0;
02576 }
02577 }
02578 }
02579
02580
02581 if ( bbox.m_min.x <= line.to.x && line.to.x <= bbox.m_max.x )
02582 {
02583 if ( bbox.m_min.y <= line.to.y && line.to.y <= bbox.m_max.y )
02584 {
02585 if ( bbox.m_min.z <= line.to.z && line.to.z <= bbox.m_max.z )
02586 {
02587 return 0.0;
02588 }
02589 }
02590 }
02591
02592 ON_BoundingBox line_bbox;
02593 line_bbox.Set(3,false,2,3,&line.from.x,false);
02594
02595 d = bbox.MinimumDistanceTo(line_bbox);
02596 if ( d > 0.0 )
02597 return d;
02598
02599 if ( bbox.m_min.x <= line_bbox.m_min.x && line_bbox.m_max.x <= bbox.m_max.x )
02600 {
02601 if ( bbox.m_min.y <= line_bbox.m_min.y && line_bbox.m_max.y <= bbox.m_max.y )
02602 {
02603
02604
02605 return 0.0;
02606 }
02607 else if ( bbox.m_min.z <= line_bbox.m_min.z && line_bbox.m_max.z <= bbox.m_max.z )
02608 {
02609
02610
02611 return 0.0;
02612 }
02613 }
02614 else if ( bbox.m_min.y <= line_bbox.m_min.y && line_bbox.m_max.y <= bbox.m_max.y
02615 && bbox.m_min.z <= line_bbox.m_min.z && line_bbox.m_max.z <= bbox.m_max.z )
02616 {
02617
02618
02619 return 0.0;
02620 }
02621
02622 d = line.to.x - line.from.x;
02623 bTrimmed = false;
02624 if ( d != 0.0 )
02625 {
02626 if ( d < 0.0 )
02627 {
02628 line.Reverse();
02629 d = -d;
02630 }
02631 d = 1.0/d;
02632 t = (bbox.m_min.x - line.from.x)*d;
02633 if( 0.0 < t && t < 1.0 )
02634 {
02635 line.from = line.PointAt(t);
02636 line.from.x = bbox.m_min.x;
02637 d = line.to.x - line.from.x;
02638 if ( d != 0.0 )
02639 d = 1.0/d;
02640 bTrimmed = true;
02641 }
02642 t = (bbox.m_max.x - line.from.x)*d;
02643 if( 0.0 < t && t < 1.0 )
02644 {
02645 line.to = line.PointAt(t);
02646 line.to.x = bbox.m_max.x;
02647 bTrimmed = true;
02648 }
02649 }
02650
02651 d = line.to.y - line.from.y;
02652 if ( d < 0.0 )
02653 {
02654 line.Reverse();
02655 d = -d;
02656 }
02657
02658 if ( bTrimmed )
02659 {
02660 if ( line.to.y < bbox.m_min.y || line.from.y > bbox.m_max.y )
02661 return ON_UNSET_VALUE;
02662 if ( line.from.z < bbox.m_min.z && line.to.z < bbox.m_min.z )
02663 return ON_UNSET_VALUE;
02664 if ( line.from.z > bbox.m_max.z && line.to.z > bbox.m_max.z )
02665 return ON_UNSET_VALUE;
02666 }
02667
02668 if ( d > 0.0 )
02669 {
02670 d = 1.0/d;
02671 t = (bbox.m_min.y - line.from.y)*d;
02672 if( 0.0 < t && t < 1.0 )
02673 {
02674 line.from = line.PointAt(t);
02675 line.from.y = bbox.m_min.y;
02676 d = line.to.y - line.from.y;
02677 if ( d != 0.0 )
02678 d = 1.0/d;
02679 }
02680 t = (bbox.m_max.y - line.from.y)*d;
02681 if( 0.0 < t && t < 1.0 )
02682 {
02683 line.to = line.PointAt(t);
02684 line.to.y = bbox.m_max.y;
02685 }
02686 }
02687
02688 if ( line.from.z < bbox.m_min.z && line.to.z < bbox.m_min.z )
02689 return ON_UNSET_VALUE;
02690
02691 if ( line.from.z > bbox.m_max.z && line.to.z > bbox.m_max.z )
02692 return ON_UNSET_VALUE;
02693
02694 return 0.0;
02695 }
02696
02697 double ON_BoundingBox::MinimumDistanceTo( const ON_Plane& plane ) const
02698 {
02699 ON_PlaneEquation e;
02700 e.Create(plane.origin,plane.zaxis);
02701 return MinimumDistanceTo(e);
02702 }
02703
02704 double ON_BoundingBox::MinimumDistanceTo( const ON_PlaneEquation& e ) const
02705 {
02706 double t, t0, t1;
02707 ON_3dPoint P(m_min);
02708 t0 = t1 = e.ValueAt(P);
02709
02710 P.z = m_max.z;
02711 t = e.ValueAt(P);
02712 if (t < t0)
02713 {
02714 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02715 }
02716 else if (t > t1)
02717 {
02718 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02719 }
02720
02721 P.y = m_max.y;
02722 t = e.ValueAt(P);
02723 if (t < t0)
02724 {
02725 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02726 }
02727 else if (t > t1)
02728 {
02729 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02730 }
02731
02732 P.z = m_min.z;
02733 t = e.ValueAt(P);
02734 if (t < t0)
02735 {
02736 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02737 }
02738 else if (t > t1)
02739 {
02740 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02741 }
02742
02743 P.x = m_max.x;
02744 t = e.ValueAt(P);
02745 if (t < t0)
02746 {
02747 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02748 }
02749 else if (t > t1)
02750 {
02751 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02752 }
02753
02754 P.y = m_min.y;
02755 t = e.ValueAt(P);
02756 if (t < t0)
02757 {
02758 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02759 }
02760 else if (t > t1)
02761 {
02762 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02763 }
02764
02765 P.z = m_max.z;
02766 t = e.ValueAt(P);
02767 if (t < t0)
02768 {
02769 t0 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02770 }
02771 else if (t > t1)
02772 {
02773 t1 = t; if ( t0 <= 0.0 && t1 >= 0.0 ) return 0.0;
02774 }
02775
02776 P.y = m_max.y;
02777 t = e.ValueAt(P);
02778 if (t < t0)
02779 {
02780 t0 = t;
02781 }
02782 else if (t > t1)
02783 {
02784 t1 = t;
02785 }
02786
02787 if ( t0 >= 0.0 ) return t0;
02788 if ( t1 <= 0.0 ) return -t1;
02789 return 0.0;
02790 }
02791
02792
02793 double ON_BoundingBox::MaximumDistanceTo( const ON_Plane& plane ) const
02794 {
02795 ON_PlaneEquation e;
02796 e.Create(plane.origin,plane.zaxis);
02797 return MinimumDistanceTo(e);
02798 }
02799
02800 double ON_BoundingBox::MaximumDistanceTo( const ON_PlaneEquation& e ) const
02801 {
02802 double t, t0;
02803 ON_3dPoint P(m_min);
02804 t0 = fabs(e.ValueAt(P));
02805
02806 P.z = m_max.z;
02807 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02808
02809 P.y = m_max.y;
02810 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02811
02812 P.z = m_min.z;
02813 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02814
02815 P.x = m_max.x;
02816 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02817
02818 P.y = m_min.y;
02819 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02820
02821 P.z = m_max.z;
02822 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02823
02824 P.y = m_max.y;
02825 t = fabs(e.ValueAt(P)); if (t > t0) t0 = t;
02826
02827 return t0;
02828 }
02829
02830
02831 bool ON_BoundingBox::IsFartherThan( double d, const ON_Plane& plane ) const
02832 {
02833 ON_PlaneEquation e;
02834 e.Create(plane.origin,plane.zaxis);
02835 return IsFartherThan(d,e);
02836 }
02837
02838 bool ON_BoundingBox::IsFartherThan( double d, const ON_PlaneEquation& e ) const
02839 {
02840 double t, t0, t1;
02841 ON_3dPoint P(m_min);
02842 t0 = t1 = e.ValueAt(P);
02843 if ( t0 <= d && t1 >= -d ) return false;
02844
02845 P.z = m_max.z;
02846 t = e.ValueAt(P);
02847 if (t < t0)
02848 {
02849 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02850 }
02851 else if (t > t1)
02852 {
02853 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02854 }
02855
02856 P.y = m_max.y;
02857 t = e.ValueAt(P);
02858 if (t < t0)
02859 {
02860 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02861 }
02862 else if (t > t1)
02863 {
02864 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02865 }
02866
02867 P.z = m_min.z;
02868 t = e.ValueAt(P);
02869 if (t < t0)
02870 {
02871 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02872 }
02873 else if (t > t1)
02874 {
02875 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02876 }
02877
02878 P.x = m_max.x;
02879 t = e.ValueAt(P);
02880 if (t < t0)
02881 {
02882 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02883 }
02884 else if (t > t1)
02885 {
02886 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02887 }
02888
02889 P.y = m_min.y;
02890 t = e.ValueAt(P);
02891 if (t < t0)
02892 {
02893 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02894 }
02895 else if (t > t1)
02896 {
02897 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02898 }
02899
02900 P.z = m_max.z;
02901 if (t < t0)
02902 {
02903 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02904 }
02905 else if (t > t1)
02906 {
02907 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02908 }
02909
02910 P.y = m_max.y;
02911 if (t < t0)
02912 {
02913 t0 = t; if ( t0 <= d && t1 >= -d ) return false;
02914 }
02915 else if (t > t1)
02916 {
02917 t1 = t; if ( t0 <= d && t1 >= -d ) return false;
02918 }
02919
02920 return true;
02921 }
02922
02923
02924 double ON_BoundingBox::MinimumDistanceTo( const ON_Line& line ) const
02925 {
02926 double d = ON_BBoxMinimumDistanceToHelper( *this, line );
02927 if ( d < 0.0 )
02928 {
02929
02930
02931
02932
02933
02934 const ON_BoundingBox line_bbox(line.BoundingBox());
02935 ON_Line edge;
02936 double e,t;
02937 int i,j;
02938
02939 edge.from.z = m_min.z;
02940 edge.to.z = m_max.z;
02941 for ( i = 0; i < 2; i++ )
02942 {
02943 edge.from.x = i?m_min.x:m_max.x;
02944 if ( d > 0.0 )
02945 {
02946 if ( line_bbox.m_min.x - edge.from.x > d )
02947 continue;
02948 if ( edge.from.x - line_bbox.m_max.x > d )
02949 continue;
02950 }
02951 edge.to.x = edge.from.x;
02952 for ( j = 0; j < 2; j++ )
02953 {
02954 edge.from.y = j?m_min.y:m_max.y;
02955 if ( d > 0.0 )
02956 {
02957 if ( line_bbox.m_min.y - edge.from.y > d )
02958 continue;
02959 if ( edge.from.y - line_bbox.m_max.y > d )
02960 continue;
02961 }
02962 edge.to.y = edge.from.y;
02963 if ( ON_Intersect(edge,line,&e,&t) )
02964 {
02965 if ( e < 0.0 ) e = 0.0; else if (e > 1.0) e = 1.0;
02966 if ( t < 0.0 ) t = 0.0; else if (t > 1.0) t = 1.0;
02967 e = edge.PointAt(e).DistanceTo(line.PointAt(t));
02968 if ( d < 0.0 || e < d )
02969 d = e;
02970 }
02971 }
02972 }
02973
02974 edge.from.y = m_min.y;
02975 edge.to.y = m_max.y;
02976 for ( i = 0; i < 2; i++ )
02977 {
02978 edge.from.z = i?m_min.z:m_max.z;
02979 edge.to.z = edge.from.z;
02980 if ( d > 0.0 )
02981 {
02982 if ( line_bbox.m_min.z - edge.from.z > d )
02983 continue;
02984 if ( edge.from.z - line_bbox.m_max.z > d )
02985 continue;
02986 }
02987 for ( j = 0; j < 2; j++ )
02988 {
02989 edge.from.x = j?m_min.x:m_max.x;
02990 if ( d > 0.0 )
02991 {
02992 if ( line_bbox.m_min.x - edge.from.x > d )
02993 continue;
02994 if ( edge.from.x - line_bbox.m_max.x > d )
02995 continue;
02996 }
02997 edge.to.x = edge.from.x;
02998 if ( ON_Intersect(edge,line,&e,&t) )
02999 {
03000 if ( e < 0.0 ) e = 0.0; else if (e > 1.0) e = 1.0;
03001 if ( t < 0.0 ) t = 0.0; else if (t > 1.0) t = 1.0;
03002 e = edge.PointAt(e).DistanceTo(line.PointAt(t));
03003 if ( d < 0.0 || e < d )
03004 d = e;
03005 }
03006 }
03007 }
03008
03009 edge.from.x = m_min.x;
03010 edge.to.x = m_max.x;
03011 for ( i = 0; i < 2; i++ )
03012 {
03013 edge.from.y = i?m_min.y:m_max.y;
03014 edge.to.y = edge.from.y;
03015 if ( d > 0.0 )
03016 {
03017 if ( line_bbox.m_min.y - edge.from.y > d )
03018 continue;
03019 if ( edge.from.y - line_bbox.m_max.y > d )
03020 continue;
03021 }
03022 for ( j = 0; j < 2; j++ )
03023 {
03024 edge.from.z = j?m_min.z:m_max.z;
03025 edge.to.z = edge.from.z;
03026 if ( d > 0.0 )
03027 {
03028 if ( line_bbox.m_min.z - edge.from.z > d )
03029 continue;
03030 if ( edge.from.z - line_bbox.m_max.z > d )
03031 continue;
03032 }
03033 if ( ON_Intersect(edge,line,&e,&t) )
03034 {
03035 if ( e < 0.0 ) e = 0.0; else if (e > 1.0) e = 1.0;
03036 if ( t < 0.0 ) t = 0.0; else if (t > 1.0) t = 1.0;
03037 e = edge.PointAt(e).DistanceTo(line.PointAt(t));
03038 if ( d < 0.0 || e < d )
03039 d = e;
03040 }
03041 }
03042 }
03043
03044 if ( d < 0.0 )
03045 d = 0.0;
03046
03047 }
03048
03049 return d;
03050 }
03051
03052 double ON_BoundingBox::MaximumDistanceTo( const ON_Line& line ) const
03053 {
03054
03055
03056
03057
03058
03059
03060
03061 double d,dx,dy,dz;
03062 const double* a;
03063 int i,j,k;
03064
03065 d = 0.0;
03066 a = &line.from.x;
03067 for ( i = 0; i < 2; i++ )
03068 {
03069 dx = fabs(a[0] - (i?m_max.x:m_min.x));
03070 dx = dx*dx;
03071 if ( dx <= d )
03072 continue;
03073 for ( j = 0; j < 2; j++ )
03074 {
03075 dy = fabs(a[1] - (j?m_max.y:m_min.y));
03076 dy = dx + dy*dy;
03077 if ( dy <= d )
03078 continue;
03079 for ( k = 0; k < 2; k++ )
03080 {
03081 dz = fabs(a[2] - (k?m_max.z:m_min.z));
03082 dz = dz*dz + dy;
03083 if ( dz > d )
03084 d = dz;
03085 }
03086 }
03087 }
03088
03089 a = &line.to.x;
03090 for ( i = 0; i < 2; i++ )
03091 {
03092 dx = fabs(a[0] - (i?m_max.x:m_min.x));
03093 dx = dx*dx;
03094 if ( dx <= d )
03095 continue;
03096 for ( j = 0; j < 2; j++ )
03097 {
03098 dy = fabs(a[1] - (j?m_max.y:m_min.y));
03099 dy = dx + dy*dy;
03100 if ( dy <= d )
03101 continue;
03102 for ( k = 0; k < 2; k++ )
03103 {
03104 dz = fabs(a[2] - (k?m_max.z:m_min.z));
03105 dz = dz*dz + dy;
03106 if ( dz > d )
03107 d = dz;
03108 }
03109 }
03110 }
03111
03112 return sqrt(d);
03113 }
03114
03115 double ON_BoundingBox::MinimumDistanceTo( const ON_BoundingBox& other ) const
03116 {
03117
03118 ON_3dVector V;
03119
03120 if ( m_min.x > other.m_max.x )
03121 V.x = m_min.x - other.m_max.x;
03122 else if ( m_max.x < other.m_min.x )
03123 V.x = other.m_min.x - m_max.x;
03124 else
03125 V.x = 0.0;
03126
03127 if ( m_min.y > other.m_max.y )
03128 V.y = m_min.y - other.m_max.y;
03129 else if ( m_max.y < other.m_min.y )
03130 V.y = other.m_min.y - m_max.y;
03131 else
03132 V.y = 0.0;
03133
03134 if ( m_min.z > other.m_max.z )
03135 V.z = m_min.z - other.m_max.z;
03136 else if ( m_max.z < other.m_min.z )
03137 V.z = other.m_min.z - m_max.z;
03138 else
03139 V.z = 0.0;
03140
03141 return V.Length();
03142 }
03143
03144
03145 double ON_BoundingBox::MaximumDistanceTo( const ON_BoundingBox& other ) const
03146 {
03147
03148 ON_3dVector V;
03149 double d;
03150
03151 V.x = fabs(m_min.x - other.m_max.x);
03152 d = fabs(m_max.x - other.m_min.x);
03153 if ( d > V.x )
03154 V.x = d;
03155
03156 V.y = fabs(m_min.y - other.m_max.y);
03157 d = fabs(m_max.y - other.m_min.y);
03158 if ( d > V.y )
03159 V.y = d;
03160
03161 V.z = fabs(m_min.z - other.m_max.z);
03162 d = fabs(m_max.z - other.m_min.z);
03163 if ( d > V.z )
03164 V.z = d;
03165
03166 return V.Length();
03167 }
03168
03169
03170 bool ON_BoundingBox::IsFartherThan( double d, const ON_3dPoint& P ) const
03171 {
03172 return (d < MinimumDistanceTo(P));
03173 }
03174
03175 bool ON_BoundingBox::IsFartherThan( double d, const ON_Line& line ) const
03176 {
03177 ON_BoundingBox bbox = *this;
03178 bbox.m_min.x -= d;
03179 bbox.m_min.y -= d;
03180 bbox.m_min.z -= d;
03181 bbox.m_max.x += d;
03182 bbox.m_max.y += d;
03183 bbox.m_max.z += d;
03184 d = ON_BBoxMinimumDistanceToHelper( bbox, line );
03185
03186 return (d != 0.0);
03187 }
03188
03189 bool ON_BoundingBox::IsFartherThan( double d, const ON_BoundingBox& other ) const
03190 {
03191 return (d < MinimumDistanceTo(other));
03192 }
03193
03194
03195