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