00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "treeBoundBox.H"
00027 #include <OpenFOAM/ListOps.H>
00028
00029
00030
00031 const Foam::scalar Foam::treeBoundBox::great(GREAT);
00032
00033 const Foam::treeBoundBox Foam::treeBoundBox::greatBox
00034 (
00035 vector(-GREAT, -GREAT, -GREAT),
00036 vector(GREAT, GREAT, GREAT)
00037 );
00038
00039
00040 const Foam::treeBoundBox Foam::treeBoundBox::invertedBox
00041 (
00042 vector(GREAT, GREAT, GREAT),
00043 vector(-GREAT, -GREAT, -GREAT)
00044 );
00045
00046
00048 const Foam::label facesArray[6][4] =
00049 {
00050 {0, 4, 6, 2},
00051 {1, 3, 7, 5},
00052 {0, 1, 5, 4},
00053 {2, 6, 7, 3},
00054 {0, 2, 3, 1},
00055 {4, 5, 7, 6}
00056 };
00058
00059
00060 const Foam::faceList Foam::treeBoundBox::faces
00061 (
00062 initListList<face, label, 6, 4>(facesArray)
00063 );
00064
00065
00067 const Foam::label edgesArray[12][2] =
00068 {
00069 {0, 1},
00070 {1, 3},
00071 {2, 3},
00072 {0, 2},
00073 {4, 5},
00074 {5, 7},
00075 {6, 7},
00076 {4, 6},
00077 {0, 4},
00078 {1, 5},
00079 {3, 7},
00080 {2, 6}
00081 };
00083
00084
00085 const Foam::edgeList Foam::treeBoundBox::edges
00086 (
00087 initListList<edge, label, 12, 2>(edgesArray)
00088 );
00089
00090
00091 const Foam::FixedList<Foam::vector, 6> Foam::treeBoundBox::faceNormals
00092 (
00093 calcFaceNormals()
00094 );
00095
00096
00097
00098
00099 Foam::FixedList<Foam::vector, 6> Foam::treeBoundBox::calcFaceNormals()
00100 {
00101 FixedList<vector, 6> normals;
00102 normals[LEFT] = vector(-1, 0, 0);
00103 normals[RIGHT] = vector( 1, 0, 0);
00104 normals[BOTTOM] = vector( 0, -1, 0);
00105 normals[TOP] = vector( 0, 1, 0);
00106 normals[BACK] = vector( 0, 0, -1);
00107 normals[FRONT] = vector( 0, 0, 1);
00108 return normals;
00109 }
00110
00111
00112
00113
00114
00115 Foam::treeBoundBox::treeBoundBox(const UList<point>& points)
00116 :
00117 boundBox()
00118 {
00119 if (points.empty())
00120 {
00121 WarningIn
00122 (
00123 "treeBoundBox::treeBoundBox(const UList<point>&)"
00124 ) << "cannot find bounding box for zero-sized pointField"
00125 << "returning zero" << endl;
00126
00127 return;
00128 }
00129
00130 min() = points[0];
00131 max() = points[0];
00132
00133 for (label i = 1; i < points.size(); i++)
00134 {
00135 min() = ::Foam::min(min(), points[i]);
00136 max() = ::Foam::max(max(), points[i]);
00137 }
00138 }
00139
00140
00141
00142 Foam::treeBoundBox::treeBoundBox
00143 (
00144 const UList<point>& points,
00145 const UList<label>& meshPoints
00146 )
00147 :
00148 boundBox()
00149 {
00150 if (points.empty() || meshPoints.empty())
00151 {
00152 WarningIn
00153 (
00154 "treeBoundBox::treeBoundBox"
00155 "(const UList<point>&, const UList<label>&)"
00156 ) << "cannot find bounding box for zero-sized pointField"
00157 << "returning zero" << endl;
00158
00159 return;
00160 }
00161
00162 min() = points[meshPoints[0]];
00163 max() = points[meshPoints[0]];
00164
00165 for (label i = 1; i < meshPoints.size(); i++)
00166 {
00167 min() = ::Foam::min(min(), points[meshPoints[i]]);
00168 max() = ::Foam::max(max(), points[meshPoints[i]]);
00169 }
00170 }
00171
00172
00173
00174 Foam::treeBoundBox::treeBoundBox(Istream& is)
00175 :
00176 boundBox(is)
00177 {}
00178
00179
00180
00181
00182 Foam::pointField Foam::treeBoundBox::points() const
00183 {
00184 pointField points(8);
00185 forAll(points, octant)
00186 {
00187 points[octant] = corner(octant);
00188
00189 }
00190 return points;
00191 }
00192
00193
00194 Foam::treeBoundBox Foam::treeBoundBox::subBbox(const direction octant) const
00195 {
00196 return subBbox(midpoint(), octant);
00197 }
00198
00199
00200
00201 Foam::treeBoundBox Foam::treeBoundBox::subBbox
00202 (
00203 const point& mid,
00204 const direction octant
00205 ) const
00206 {
00207 if (octant > 7)
00208 {
00209 FatalErrorIn
00210 (
00211 "treeBoundBox::subBbox(const point&, const direction)"
00212 ) << "octant should be [0..7]"
00213 << abort(FatalError);
00214 }
00215
00216
00217 treeBoundBox subBb(*this);
00218 point& bbMin = subBb.min();
00219 point& bbMax = subBb.max();
00220
00221 if (octant & treeBoundBox::RIGHTHALF)
00222 {
00223 bbMin.x() = mid.x();
00224 }
00225 else
00226 {
00227 bbMax.x() = mid.x();
00228 }
00229
00230 if (octant & treeBoundBox::TOPHALF)
00231 {
00232 bbMin.y() = mid.y();
00233 }
00234 else
00235 {
00236 bbMax.y() = mid.y();
00237 }
00238
00239 if (octant & treeBoundBox::FRONTHALF)
00240 {
00241 bbMin.z() = mid.z();
00242 }
00243 else
00244 {
00245 bbMax.z() = mid.z();
00246 }
00247
00248 return subBb;
00249 }
00250
00251
00252 bool Foam::treeBoundBox::overlaps
00253 (
00254 const point& centre,
00255 const scalar radiusSqr
00256 ) const
00257 {
00258
00259
00260 scalar distSqr = 0;
00261
00262 for (direction dir = 0; dir < vector::nComponents; dir++)
00263 {
00264 scalar d0 = min()[dir] - centre[dir];
00265 scalar d1 = max()[dir] - centre[dir];
00266
00267 if ((d0 > 0) != (d1 > 0))
00268 {
00269
00270
00271 }
00272 else if (Foam::mag(d0) < Foam::mag(d1))
00273 {
00274 distSqr += d0*d0;
00275 }
00276 else
00277 {
00278 distSqr += d1*d1;
00279 }
00280
00281 if (distSqr > radiusSqr)
00282 {
00283 return false;
00284 }
00285 }
00286
00287 return true;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 bool Foam::treeBoundBox::intersects
00310 (
00311 const point& overallStart,
00312 const vector& overallVec,
00313 const point& start,
00314 const point& end,
00315 point& pt,
00316 direction& ptOnFaces
00317 ) const
00318 {
00319 const direction endBits = posBits(end);
00320 pt = start;
00321
00322 while (true)
00323 {
00324 direction ptBits = posBits(pt);
00325
00326 if (ptBits == 0)
00327 {
00328
00329 ptOnFaces = faceBits(pt);
00330 return true;
00331 }
00332
00333 if ((ptBits & endBits) != 0)
00334 {
00335
00336 ptOnFaces = faceBits(pt);
00337 return false;
00338 }
00339
00340 if (ptBits & LEFTBIT)
00341 {
00342
00343 if (Foam::mag(overallVec.x()) > VSMALL)
00344 {
00345 scalar s = (min().x() - overallStart.x())/overallVec.x();
00346 pt.x() = min().x();
00347 pt.y() = overallStart.y() + overallVec.y()*s;
00348 pt.z() = overallStart.z() + overallVec.z()*s;
00349 }
00350 else
00351 {
00352
00353
00354 pt.x() = min().x();
00355 }
00356 }
00357 else if (ptBits & RIGHTBIT)
00358 {
00359
00360 if (Foam::mag(overallVec.x()) > VSMALL)
00361 {
00362 scalar s = (max().x() - overallStart.x())/overallVec.x();
00363 pt.x() = max().x();
00364 pt.y() = overallStart.y() + overallVec.y()*s;
00365 pt.z() = overallStart.z() + overallVec.z()*s;
00366 }
00367 else
00368 {
00369 pt.x() = max().x();
00370 }
00371 }
00372 else if (ptBits & BOTTOMBIT)
00373 {
00374
00375 if (Foam::mag(overallVec.y()) > VSMALL)
00376 {
00377 scalar s = (min().y() - overallStart.y())/overallVec.y();
00378 pt.x() = overallStart.x() + overallVec.x()*s;
00379 pt.y() = min().y();
00380 pt.z() = overallStart.z() + overallVec.z()*s;
00381 }
00382 else
00383 {
00384 pt.x() = min().y();
00385 }
00386 }
00387 else if (ptBits & TOPBIT)
00388 {
00389
00390 if (Foam::mag(overallVec.y()) > VSMALL)
00391 {
00392 scalar s = (max().y() - overallStart.y())/overallVec.y();
00393 pt.x() = overallStart.x() + overallVec.x()*s;
00394 pt.y() = max().y();
00395 pt.z() = overallStart.z() + overallVec.z()*s;
00396 }
00397 else
00398 {
00399 pt.y() = max().y();
00400 }
00401 }
00402 else if (ptBits & BACKBIT)
00403 {
00404
00405 if (Foam::mag(overallVec.z()) > VSMALL)
00406 {
00407 scalar s = (min().z() - overallStart.z())/overallVec.z();
00408 pt.x() = overallStart.x() + overallVec.x()*s;
00409 pt.y() = overallStart.y() + overallVec.y()*s;
00410 pt.z() = min().z();
00411 }
00412 else
00413 {
00414 pt.z() = min().z();
00415 }
00416 }
00417 else if (ptBits & FRONTBIT)
00418 {
00419
00420 if (Foam::mag(overallVec.z()) > VSMALL)
00421 {
00422 scalar s = (max().z() - overallStart.z())/overallVec.z();
00423 pt.x() = overallStart.x() + overallVec.x()*s;
00424 pt.y() = overallStart.y() + overallVec.y()*s;
00425 pt.z() = max().z();
00426 }
00427 else
00428 {
00429 pt.z() = max().z();
00430 }
00431 }
00432 }
00433 }
00434
00435
00436 bool Foam::treeBoundBox::intersects
00437 (
00438 const point& start,
00439 const point& end,
00440 point& pt
00441 ) const
00442 {
00443 direction ptBits;
00444 return intersects(start, end-start, start, end, pt, ptBits);
00445 }
00446
00447
00448
00449 bool Foam::treeBoundBox::contains(const treeBoundBox& bb) const
00450 {
00451 return contains(bb.min()) && contains(bb.max());
00452 }
00453
00454
00455 bool Foam::treeBoundBox::contains(const vector& dir, const point& pt) const
00456 {
00457
00458
00459
00460 for (direction cmpt=0; cmpt<3; cmpt++)
00461 {
00462 if (pt[cmpt] < min()[cmpt])
00463 {
00464 return false;
00465 }
00466 else if (pt[cmpt] == min()[cmpt])
00467 {
00468
00469 if (dir[cmpt] < 0)
00470 {
00471 return false;
00472 }
00473 }
00474
00475 if (pt[cmpt] > max()[cmpt])
00476 {
00477 return false;
00478 }
00479 else if (pt[cmpt] == max()[cmpt])
00480 {
00481
00482 if (dir[cmpt] > 0)
00483 {
00484 return false;
00485 }
00486 }
00487 }
00488
00489
00490 return true;
00491 }
00492
00493
00494
00495 Foam::direction Foam::treeBoundBox::faceBits(const point& pt) const
00496 {
00497 direction faceBits = 0;
00498 if (pt.x() == min().x())
00499 {
00500 faceBits |= LEFTBIT;
00501 }
00502 else if (pt.x() == max().x())
00503 {
00504 faceBits |= RIGHTBIT;
00505 }
00506
00507 if (pt.y() == min().y())
00508 {
00509 faceBits |= BOTTOMBIT;
00510 }
00511 else if (pt.y() == max().y())
00512 {
00513 faceBits |= TOPBIT;
00514 }
00515
00516 if (pt.z() == min().z())
00517 {
00518 faceBits |= BACKBIT;
00519 }
00520 else if (pt.z() == max().z())
00521 {
00522 faceBits |= FRONTBIT;
00523 }
00524 return faceBits;
00525 }
00526
00527
00528
00529 Foam::direction Foam::treeBoundBox::posBits(const point& pt) const
00530 {
00531 direction posBits = 0;
00532
00533 if (pt.x() < min().x())
00534 {
00535 posBits |= LEFTBIT;
00536 }
00537 else if (pt.x() > max().x())
00538 {
00539 posBits |= RIGHTBIT;
00540 }
00541
00542 if (pt.y() < min().y())
00543 {
00544 posBits |= BOTTOMBIT;
00545 }
00546 else if (pt.y() > max().y())
00547 {
00548 posBits |= TOPBIT;
00549 }
00550
00551 if (pt.z() < min().z())
00552 {
00553 posBits |= BACKBIT;
00554 }
00555 else if (pt.z() > max().z())
00556 {
00557 posBits |= FRONTBIT;
00558 }
00559 return posBits;
00560 }
00561
00562
00563
00564
00565 void Foam::treeBoundBox::calcExtremities
00566 (
00567 const point& pt,
00568 point& nearest,
00569 point& furthest
00570 ) const
00571 {
00572 scalar nearX, nearY, nearZ;
00573 scalar farX, farY, farZ;
00574
00575 if (Foam::mag(min().x() - pt.x()) < Foam::mag(max().x() - pt.x()))
00576 {
00577 nearX = min().x();
00578 farX = max().x();
00579 }
00580 else
00581 {
00582 nearX = max().x();
00583 farX = min().x();
00584 }
00585
00586 if (Foam::mag(min().y() - pt.y()) < Foam::mag(max().y() - pt.y()))
00587 {
00588 nearY = min().y();
00589 farY = max().y();
00590 }
00591 else
00592 {
00593 nearY = max().y();
00594 farY = min().y();
00595 }
00596
00597 if (Foam::mag(min().z() - pt.z()) < Foam::mag(max().z() - pt.z()))
00598 {
00599 nearZ = min().z();
00600 farZ = max().z();
00601 }
00602 else
00603 {
00604 nearZ = max().z();
00605 farZ = min().z();
00606 }
00607
00608 nearest = point(nearX, nearY, nearZ);
00609 furthest = point(farX, farY, farZ);
00610 }
00611
00612
00613 Foam::scalar Foam::treeBoundBox::maxDist(const point& pt) const
00614 {
00615 point near, far;
00616 calcExtremities(pt, near, far);
00617
00618 return Foam::mag(far - pt);
00619 }
00620
00621
00622
00623
00624
00625 Foam::label Foam::treeBoundBox::distanceCmp
00626 (
00627 const point& pt,
00628 const treeBoundBox& other
00629 ) const
00630 {
00631
00632
00633
00634
00635 point nearThis, farThis;
00636
00637
00638 calcExtremities(pt, nearThis, farThis);
00639
00640 const scalar minDistThis =
00641 sqr(nearThis.x() - pt.x())
00642 + sqr(nearThis.y() - pt.y())
00643 + sqr(nearThis.z() - pt.z());
00644 const scalar maxDistThis =
00645 sqr(farThis.x() - pt.x())
00646 + sqr(farThis.y() - pt.y())
00647 + sqr(farThis.z() - pt.z());
00648
00649
00650
00651
00652
00653 point nearOther, farOther;
00654
00655
00656 other.calcExtremities(pt, nearOther, farOther);
00657
00658 const scalar minDistOther =
00659 sqr(nearOther.x() - pt.x())
00660 + sqr(nearOther.y() - pt.y())
00661 + sqr(nearOther.z() - pt.z());
00662 const scalar maxDistOther =
00663 sqr(farOther.x() - pt.x())
00664 + sqr(farOther.y() - pt.y())
00665 + sqr(farOther.z() - pt.z());
00666
00667
00668
00669
00670 if (maxDistThis < minDistOther)
00671 {
00672
00673 return -1;
00674 }
00675 else if (minDistThis > maxDistOther)
00676 {
00677
00678 return 1;
00679 }
00680 else
00681 {
00682
00683 return 0;
00684 }
00685 }
00686
00687
00688
00689
00690 bool Foam::operator==(const treeBoundBox& a, const treeBoundBox& b)
00691 {
00692 return operator==
00693 (
00694 static_cast<const boundBox&>(a),
00695 static_cast<const boundBox&>(b)
00696 );
00697 }
00698
00699
00700 bool Foam::operator!=(const treeBoundBox& a, const treeBoundBox& b)
00701 {
00702 return !(a == b);
00703 }
00704
00705
00706
00707
00708 Foam::Ostream& Foam::operator<<(Ostream& os, const treeBoundBox& bb)
00709 {
00710 return os << static_cast<const boundBox&>(bb);
00711 }
00712
00713
00714 Foam::Istream& Foam::operator>>(Istream& is, treeBoundBox& bb)
00715 {
00716 return is >> static_cast<boundBox&>(bb);
00717 }
00718
00719
00720