TGLBoundingBox.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLBoundingBox.cxx 37397 2010-12-08 13:54:23Z matevz $
00002 // Author:  Richard Maunder  25/05/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "Riostream.h"
00013 #include "TGLBoundingBox.h"
00014 #include "TGLIncludes.h"
00015 #include "TMathBase.h"
00016 
00017 //////////////////////////////////////////////////////////////////////////
00018 //                                                                      //
00019 // TGLBoundingBox                                                       //
00020 //                                                                      //
00021 // Concrete class describing an orientated (free) or axis aligned box   //
00022 // of 8 verticies. Supports methods for setting aligned or orientated   //
00023 // boxes, find volume, axes, extents, centers, face planes etc.         //
00024 // Also tests for overlap testing of planes and other bounding boxes,   //
00025 // with fast sphere approximation.                                      //
00026 //////////////////////////////////////////////////////////////////////////
00027 
00028 ClassImp(TGLBoundingBox)
00029 
00030 //______________________________________________________________________________
00031 TGLBoundingBox::TGLBoundingBox()
00032 {
00033    // Construct an empty bounding box
00034    SetEmpty();
00035 }
00036 
00037 //______________________________________________________________________________
00038 TGLBoundingBox::TGLBoundingBox(const TGLVertex3 vertex[8])
00039 {
00040    // Construct a bounding box from provided 8 vertices
00041    Set(vertex);
00042 }
00043 
00044 //______________________________________________________________________________
00045 TGLBoundingBox::TGLBoundingBox(const Double_t vertex[8][3])
00046 {
00047    // Construct a bounding box from provided 8 vertices
00048    Set(vertex);
00049 }
00050 
00051 //______________________________________________________________________________
00052 TGLBoundingBox::TGLBoundingBox(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
00053 {
00054    // Construct an global axis ALIGNED bounding box from provided low/high vertex pair
00055    SetAligned(lowVertex, highVertex);
00056 }
00057 
00058 //______________________________________________________________________________
00059 TGLBoundingBox::TGLBoundingBox(const TGLBoundingBox & other)
00060 {
00061    // Construct a bounding box as copy of existing one
00062    Set(other);
00063 }
00064 
00065 //______________________________________________________________________________
00066 TGLBoundingBox::~TGLBoundingBox()
00067 {
00068   // Destroy bounding box
00069 }
00070 
00071 //______________________________________________________________________________
00072 void TGLBoundingBox::UpdateCache()
00073 {
00074    // Update the internally cached volume and axes vectors - these are retained
00075    // for efficiency - many more reads than modifications
00076 
00077    //    y
00078    //    |
00079    //    |
00080    //    |________x
00081    //   /  3-------2
00082    //  /  /|      /|
00083    // z  7-------6 |
00084    //    | 0-----|-1
00085    //    |/      |/
00086    //    4-------5
00087    //
00088 
00089    // Do axes first so Extents() is correct
00090    fAxes[0].Set(fVertex[1] - fVertex[0]);
00091    fAxes[1].Set(fVertex[3] - fVertex[0]);
00092    fAxes[2].Set(fVertex[4] - fVertex[0]);
00093 
00094    // Sometimes have zero volume BB due to single zero magnitude
00095    // axis record and try to fix below
00096    Bool_t fixZeroMagAxis = kFALSE;
00097    Int_t zeroMagAxisInd = -1;
00098    for (UInt_t i = 0; i<3; i++) {
00099       fAxesNorm[i] = fAxes[i];
00100       Double_t mag = fAxesNorm[i].Mag();
00101       if (mag > 0.0) {
00102          fAxesNorm[i] /= mag;
00103       } else {
00104          if (!fixZeroMagAxis && zeroMagAxisInd == -1) {
00105             zeroMagAxisInd = i;
00106             fixZeroMagAxis = kTRUE;
00107          } else if (fixZeroMagAxis) {
00108             fixZeroMagAxis = kFALSE;
00109          }
00110       }
00111    }
00112 
00113    // Try to cope with a zero volume bounding box where one
00114    // axis is zero by using cross product of other two
00115    if (fixZeroMagAxis) {
00116       fAxesNorm[zeroMagAxisInd] = Cross(fAxesNorm[(zeroMagAxisInd+1)%3],
00117                                         fAxesNorm[(zeroMagAxisInd+2)%3]);
00118    }
00119 
00120    TGLVector3 extents = Extents();
00121    fVolume   = TMath::Abs(extents.X() * extents.Y() * extents.Z());
00122    fDiagonal = extents.Mag();
00123 }
00124 
00125 //______________________________________________________________________________
00126 void TGLBoundingBox::Set(const TGLVertex3 vertex[8])
00127 {
00128    // Set a bounding box from provided 8 vertices
00129    for (UInt_t v = 0; v < 8; v++) {
00130       fVertex[v] = vertex[v];
00131    }
00132    // Could change cached volume/axes
00133    UpdateCache();
00134 }
00135 
00136 //______________________________________________________________________________
00137 void TGLBoundingBox::Set(const Double_t vertex[8][3])
00138 {
00139    // Set a bounding box from provided 8 vertices
00140    for (UInt_t v = 0; v < 8; v++) {
00141       for (UInt_t a = 0; a < 3; a++) {
00142          fVertex[v][a] = vertex[v][a];
00143       }
00144    }
00145    // Could change cached volume/axes
00146    UpdateCache();
00147 }
00148 
00149 //______________________________________________________________________________
00150 void TGLBoundingBox::Set(const TGLBoundingBox & other)
00151 {
00152    // Set a bounding box from vertices of other
00153    for (UInt_t v = 0; v < 8; v++) {
00154       fVertex[v].Set(other.fVertex[v]);
00155    }
00156    // Could change cached volume/axes
00157    UpdateCache();
00158 }
00159 
00160 //______________________________________________________________________________
00161 void TGLBoundingBox::SetEmpty()
00162 {
00163    // Set bounding box empty - all vertices at (0,0,0)
00164    for (UInt_t v = 0; v < 8; v++) {
00165       fVertex[v].Fill(0.0);
00166    }
00167    // Could change cached volume/axes
00168    UpdateCache();
00169 }
00170 
00171 //______________________________________________________________________________
00172 void TGLBoundingBox::SetAligned(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
00173 {
00174    // Set ALIGNED box from two low/high vertices. Box axes are aligned with
00175    // global frame axes that vertices are specified in.
00176 
00177    // lowVertex = vertex[0]
00178    // highVertex = vertex[6]
00179    //
00180    //    y
00181    //    |
00182    //    |
00183    //    |________x
00184    //   /  3-------2
00185    //  /  /|      /|
00186    // z  7-------6 |
00187    //    | 0-----|-1
00188    //    |/      |/
00189    //    4-------5
00190    //
00191 
00192    TGLVector3 diff = highVertex - lowVertex;
00193    if (diff.X() < 0.0 || diff.Y() < 0.0 || diff.Z() < 0.0) {
00194       Error("TGLBoundingBox::SetAligned", "low/high vertex range error");
00195    }
00196    fVertex[0] = lowVertex;
00197    fVertex[1] = lowVertex;  fVertex[1].X() += diff.X();
00198    fVertex[2] = lowVertex;  fVertex[2].X() += diff.X(); fVertex[2].Y() += diff.Y();
00199    fVertex[3] = lowVertex;  fVertex[3].Y() += diff.Y();
00200    fVertex[4] = highVertex; fVertex[4].X() -= diff.X(); fVertex[4].Y() -= diff.Y();
00201    fVertex[5] = highVertex; fVertex[5].Y() -= diff.Y();
00202    fVertex[6] = highVertex;
00203    fVertex[7] = highVertex; fVertex[7].X() -= diff.X();
00204    // Could change cached volume/axes
00205    UpdateCache();
00206 }
00207 
00208 //______________________________________________________________________________
00209 void TGLBoundingBox::SetAligned(UInt_t nbPnts, const Double_t * pnts)
00210 {
00211    // Set ALIGNED box from one or more points. Box axes are aligned with
00212    // global frame axes that points are specified in.
00213    if (nbPnts < 1 || !pnts) {
00214       assert(false);
00215       return;
00216    }
00217 
00218    // Single point gives a zero volume BB
00219    TGLVertex3 low(pnts[0], pnts[1], pnts[2]);
00220    TGLVertex3 high(pnts[0], pnts[1], pnts[2]);
00221 
00222    for (UInt_t p = 1; p < nbPnts; p++) {
00223       for (UInt_t i = 0; i < 3; i++) {
00224          if (pnts[3*p + i] < low[i]) {
00225             low[i] = pnts[3*p + i] ;
00226          }
00227          if (pnts[3*p + i] > high[i]) {
00228             high[i] = pnts[3*p + i] ;
00229          }
00230       }
00231    }
00232 
00233    SetAligned(low, high);
00234 }
00235 
00236 //______________________________________________________________________________
00237 void TGLBoundingBox::MergeAligned(const TGLBoundingBox & other)
00238 {
00239    // Expand current bbox so that it includes other's bbox.
00240    // This make the bbox axis-aligned.
00241 
00242    if (other.IsEmpty()) return;
00243    if (IsEmpty())
00244    {
00245       Set(other);
00246    }
00247    else
00248    {
00249       TGLVertex3 low (other.MinAAVertex());
00250       TGLVertex3 high(other.MaxAAVertex());
00251 
00252       low .Minimum(MinAAVertex());
00253       high.Maximum(MaxAAVertex());
00254       SetAligned(low, high);
00255    }
00256 }
00257 
00258 //______________________________________________________________________________
00259 void TGLBoundingBox::ExpandAligned(const TGLVertex3 & point)
00260 {
00261    // Expand current bbox so that it includes the point.
00262    // This make the bbox axis-aligned.
00263 
00264    TGLVertex3 low (MinAAVertex());
00265    TGLVertex3 high(MaxAAVertex());
00266 
00267    low .Minimum(point);
00268    high.Maximum(point);
00269 
00270    SetAligned(low, high);
00271 }
00272 
00273 //______________________________________________________________________________
00274 void TGLBoundingBox::Scale(Double_t factor)
00275 {
00276    // Isotropically scale bounding box along it's LOCAL axes, preserving center
00277    Scale(factor, factor, factor);
00278    // Could change cached volume/axes
00279    UpdateCache();
00280 }
00281 
00282 //______________________________________________________________________________
00283 void TGLBoundingBox::Scale(Double_t xFactor, Double_t yFactor, Double_t zFactor)
00284 {
00285    // Asymetrically scale box along it's LOCAL x,y,z axes, preserving center
00286 
00287    // Get x,y,z edges (non-normalised axis) and scale
00288    // them by factors
00289    const TGLVector3 xOffset = Axis(0, kFALSE)*(xFactor - 1.0) / 2.0;
00290    const TGLVector3 yOffset = Axis(1, kFALSE)*(yFactor - 1.0) / 2.0;
00291    const TGLVector3 zOffset = Axis(2, kFALSE)*(zFactor - 1.0) / 2.0;
00292 
00293    //    y
00294    //    |
00295    //    |
00296    //    |________x
00297    //   /  3-------2
00298    //  /  /|      /|
00299    // z  7-------6 |
00300    //    | 0-----|-1
00301    //    |/      |/
00302    //    4-------5
00303    //
00304    fVertex[0] += -xOffset - yOffset - zOffset;
00305    fVertex[1] +=  xOffset - yOffset - zOffset;
00306    fVertex[2] +=  xOffset + yOffset - zOffset;
00307    fVertex[3] += -xOffset + yOffset - zOffset;
00308 
00309    fVertex[4] += -xOffset - yOffset + zOffset;
00310    fVertex[5] +=  xOffset - yOffset + zOffset;
00311    fVertex[6] +=  xOffset + yOffset + zOffset;
00312    fVertex[7] += -xOffset + yOffset + zOffset;
00313 
00314    // Could change cached volume/axes
00315    UpdateCache();
00316 }
00317 
00318 //______________________________________________________________________________
00319 void TGLBoundingBox::Translate(const TGLVector3 & offset)
00320 {
00321    // Translate all vertices by offset
00322    for (UInt_t v = 0; v < 8; v++) {
00323       fVertex[v] = fVertex[v] + offset;
00324    }
00325 
00326    // No cache change - volume and axes vectors remain same
00327 }
00328 
00329 //______________________________________________________________________________
00330 void TGLBoundingBox::Transform(const TGLMatrix & matrix)
00331 {
00332    // Transform all vertices with matrix.
00333 
00334    for (UInt_t v = 0; v < 8; v++) {
00335       matrix.TransformVertex(fVertex[v]);
00336    }
00337 
00338    // Could change cached volume/axes
00339    UpdateCache();
00340 }
00341 
00342 //______________________________________________________________________________
00343 const std::vector<UInt_t> & TGLBoundingBox::FaceVertices(EFace face) const
00344 {
00345    //return a vector of face vertices
00346    //    y
00347    //    |
00348    //    |
00349    //    |________x
00350    //   /  3-------2
00351    //  /  /|      /|
00352    // z  7-------6 |
00353    //    | 0-----|-1
00354    //    |/      |/
00355    //    4-------5
00356    //
00357    static Bool_t init = kFALSE;
00358    static std::vector<UInt_t> faceIndexes[kFaceCount];
00359    if (!init) {
00360       // Low X - 7403
00361       faceIndexes[kFaceLowX].push_back(7);
00362       faceIndexes[kFaceLowX].push_back(4);
00363       faceIndexes[kFaceLowX].push_back(0);
00364       faceIndexes[kFaceLowX].push_back(3);
00365       // High X - 2156
00366       faceIndexes[kFaceHighX].push_back(2);
00367       faceIndexes[kFaceHighX].push_back(1);
00368       faceIndexes[kFaceHighX].push_back(5);
00369       faceIndexes[kFaceHighX].push_back(6);
00370       // Low Y - 5104
00371       faceIndexes[kFaceLowY].push_back(5);
00372       faceIndexes[kFaceLowY].push_back(1);
00373       faceIndexes[kFaceLowY].push_back(0);
00374       faceIndexes[kFaceLowY].push_back(4);
00375       // High Y - 2673
00376       faceIndexes[kFaceHighY].push_back(2);
00377       faceIndexes[kFaceHighY].push_back(6);
00378       faceIndexes[kFaceHighY].push_back(7);
00379       faceIndexes[kFaceHighY].push_back(3);
00380       // Low Z - 3012
00381       faceIndexes[kFaceLowZ].push_back(3);
00382       faceIndexes[kFaceLowZ].push_back(0);
00383       faceIndexes[kFaceLowZ].push_back(1);
00384       faceIndexes[kFaceLowZ].push_back(2);
00385       // High Z - 6547
00386       faceIndexes[kFaceHighZ].push_back(6);
00387       faceIndexes[kFaceHighZ].push_back(5);
00388       faceIndexes[kFaceHighZ].push_back(4);
00389       faceIndexes[kFaceHighZ].push_back(7);
00390       init= kTRUE;
00391    }
00392    return faceIndexes[face];
00393 }
00394 
00395 //______________________________________________________________________________
00396 void TGLBoundingBox::PlaneSet(TGLPlaneSet_t & planeSet) const
00397 {
00398    // Fill out supplied plane set vector with TGLPlane objects
00399    // representing six faces of box
00400    assert(planeSet.empty());
00401 
00402    //    y
00403    //    |
00404    //    |
00405    //    |________x
00406    //   /  3-------2
00407    //  /  /|      /|
00408    // z  7-------6 |
00409    //    | 0-----|-1
00410    //    |/      |/
00411    //    4-------5
00412    //
00413    // Construct plane set using axis + vertices
00414    planeSet.push_back(TGLPlane( fAxesNorm[2], fVertex[4])); // Near
00415    planeSet.push_back(TGLPlane(-fAxesNorm[2], fVertex[0])); // Far
00416    planeSet.push_back(TGLPlane(-fAxesNorm[0], fVertex[0])); // Left
00417    planeSet.push_back(TGLPlane( fAxesNorm[0], fVertex[1])); // Right
00418    planeSet.push_back(TGLPlane(-fAxesNorm[1], fVertex[0])); // Bottom
00419    planeSet.push_back(TGLPlane( fAxesNorm[1], fVertex[3])); // Top
00420 }
00421 
00422 //______________________________________________________________________________
00423 TGLPlane TGLBoundingBox::GetNearPlane() const
00424 {
00425    // Return the near-plane.
00426 
00427    return TGLPlane(fAxesNorm[2], fVertex[4]);
00428 }
00429 
00430 //______________________________________________________________________________
00431 EOverlap TGLBoundingBox::Overlap(const TGLPlane & plane) const
00432 {
00433    // Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
00434 
00435    // First : cheap square approxiamtion test. If distance of our
00436    // center to plane > our half extent length we are outside plane
00437    if (plane.DistanceTo(Center()) + (Extents().Mag()/2.0) < 0.0) {
00438       return kOutside;
00439    }
00440 
00441    // Second : test all 8 box vertices against plane
00442    Int_t verticesInsidePlane = 8;
00443    for (UInt_t v = 0; v < 8; v++) {
00444       if (plane.DistanceTo(fVertex[v]) < 0.0) {
00445          verticesInsidePlane--;
00446       }
00447    }
00448 
00449    if ( verticesInsidePlane == 0 ) {
00450       return kOutside;
00451    } else if ( verticesInsidePlane == 8 ) {
00452       return kInside;
00453    } else {
00454       return kPartial;
00455    }
00456 }
00457 
00458 //______________________________________________________________________________
00459 EOverlap TGLBoundingBox::Overlap(const TGLBoundingBox & other) const
00460 {
00461    // Find overlap (Inside, Outside, Partial) of other bounding box c.f. us.
00462 
00463    // Simplify code with refs
00464    const TGLBoundingBox & a = *this;
00465    const TGLBoundingBox & b = other;
00466 
00467    TGLVector3 aHL = a.Extents() / 2.0; // Half length extents
00468    TGLVector3 bHL = b.Extents() / 2.0; // Half length extents
00469 
00470    // Following tests are greatly simplified
00471    // if we convert into our local frame
00472 
00473    // Find translation in parent frame
00474    TGLVector3 parentT = b.Center() - a.Center();
00475 
00476    // First: Do a simple & cheap sphere approximation containment test.
00477    // In many uses b will be completely contained by a and very much smaller
00478    // these cases short circuited here
00479 
00480    // We need the inner sphere for the container (box a) - radius = shortest box half length
00481    Double_t aSphereRadius = aHL[0] < aHL[1] ? aHL[0] : aHL[1];
00482    if (aHL[2] < aSphereRadius) {
00483       aSphereRadius = aHL[2];
00484    }
00485    // and the outer sphere for containee (box b) - radius = box diagonal
00486    Double_t bSphereRadius = bHL.Mag();
00487 
00488    // If b sphere radius + translation mag is smaller than b sphere radius
00489    // b is complete contained by a
00490    if (bSphereRadius + parentT.Mag() < aSphereRadius) {
00491       return kInside;
00492    }
00493 
00494    // Second: Perform more expensive 15 seperating axes test
00495 
00496    // Find translation in A's frame
00497    TGLVector3 aT(Dot(parentT, a.Axis(0)), Dot(parentT, a.Axis(1)), Dot(parentT, a.Axis(2)));
00498 
00499    // Find B's basis with respect to A's local frame
00500    // Get rotation matrix
00501    Double_t   roaT[3][3];
00502    UInt_t     i, k;
00503    for (i=0 ; i<3 ; i++) {
00504       for (k=0; k<3; k++) {
00505          roaT[i][k] = Dot(a.Axis(i), b.Axis(k));
00506          // Force very small components to zero to avoid rounding errors
00507          if (fabs(roaT[i][k]) < 1e-14) {
00508             roaT[i][k] = 0.0;
00509          }
00510       }
00511       // Normalise columns to avoid rounding errors
00512       Double_t norm = sqrt(roaT[i][0]*roaT[i][0] + roaT[i][1]*roaT[i][1] + roaT[i][2]*roaT[i][2]);
00513       roaT[i][0] /= norm; roaT[i][1] /= norm; roaT[i][2] /= norm;
00514    }
00515 
00516    // Perform separating axis test for all 15 potential
00517    // axes. If no separating axes found, the two boxes overlap.
00518    Double_t ra, rb, t;
00519 
00520    // A's 3 basis vectors
00521    for (i=0; i<3; i++) {
00522       ra = aHL[i];
00523       rb = bHL[0]*fabs(roaT[i][0]) + bHL[1]*fabs(roaT[i][1]) + bHL[2]*fabs(roaT[i][2]);
00524       t = fabs(aT[i]);
00525       if (t > ra + rb)
00526          return kOutside;
00527       else if (ra < t + rb)
00528          return kPartial;
00529    }
00530 
00531    // B's 3 basis vectors
00532    for (k=0; k<3; k++) {
00533       ra = aHL[0]*fabs(roaT[0][k]) + aHL[1]*fabs(roaT[1][k]) + aHL[2]*fabs(roaT[2][k]);
00534       rb = bHL[k];
00535       t = fabs(aT[0]*roaT[0][k] + aT[1]*roaT[1][k] + aT[2]*roaT[2][k]);
00536       if (t > ra + rb)
00537          return kOutside;
00538       else if (ra < t + rb)
00539          return kPartial;
00540    }
00541 
00542    // Now the 9 cross products
00543 
00544    // A0 x B0
00545    ra = aHL[1]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[1][0]);
00546    rb = bHL[1]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][1]);
00547    t = fabs(aT[2]*roaT[1][0] - aT[1]*roaT[2][0]);
00548    if (t > ra + rb)
00549       return kOutside;
00550    else if (ra < t + rb)
00551       return kPartial;
00552 
00553    // A0 x B1
00554    ra = aHL[1]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[1][1]);
00555    rb = bHL[0]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][0]);
00556    t = fabs(aT[2]*roaT[1][1] - aT[1]*roaT[2][1]);
00557    if (t > ra + rb)
00558       return kOutside;
00559    else if (ra < t + rb)
00560       return kPartial;
00561 
00562    // A0 x B2
00563    ra = aHL[1]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[1][2]);
00564    rb = bHL[0]*fabs(roaT[0][1]) + bHL[1]*fabs(roaT[0][0]);
00565    t = fabs(aT[2]*roaT[1][2] - aT[1]*roaT[2][2]);
00566    if (t > ra + rb)
00567       return kOutside;
00568    else if (ra < t + rb)
00569       return kPartial;
00570 
00571    // A1 x B0
00572    ra = aHL[0]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[0][0]);
00573    rb = bHL[1]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][1]);
00574    t = fabs(aT[0]*roaT[2][0] - aT[2]*roaT[0][0]);
00575    if (t > ra + rb)
00576       return kOutside;
00577    else if (ra < t + rb)
00578       return kPartial;
00579 
00580    // A1 x B1
00581    ra = aHL[0]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[0][1]);
00582    rb = bHL[0]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][0]);
00583    t = fabs(aT[0]*roaT[2][1] - aT[2]*roaT[0][1]);
00584    if (t > ra + rb)
00585       return kOutside;
00586    else if (ra < t + rb)
00587       return kPartial;
00588 
00589    // A1 x B2
00590    ra = aHL[0]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[0][2]);
00591    rb = bHL[0]*fabs(roaT[1][1]) + bHL[1]*fabs(roaT[1][0]);
00592    t = fabs(aT[0]*roaT[2][2] - aT[2]*roaT[0][2]);
00593    if (t > ra + rb)
00594       return kOutside;
00595    else if (ra < t + rb)
00596       return kPartial;
00597 
00598    // A2 x B0
00599    ra = aHL[0]*fabs(roaT[1][0]) + aHL[1]*fabs(roaT[0][0]);
00600    rb = bHL[1]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][1]);
00601    t = fabs(aT[1]*roaT[0][0] - aT[0]*roaT[1][0]);
00602    if (t > ra + rb)
00603       return kOutside;
00604    else if (ra < t + rb)
00605       return kPartial;
00606 
00607    // A2 x B1
00608    ra = aHL[0]*fabs(roaT[1][1]) + aHL[1]*fabs(roaT[0][1]);
00609    rb = bHL[0]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][0]);
00610    t = fabs(aT[1]*roaT[0][1] - aT[0]*roaT[1][1]);
00611    if (t > ra + rb)
00612       return kOutside;
00613    else if (ra < t + rb)
00614       return kPartial;
00615 
00616    // A2 x B2
00617    ra = aHL[0]*fabs(roaT[1][2]) + aHL[1]*fabs(roaT[0][2]);
00618    rb = bHL[0]*fabs(roaT[2][1]) + bHL[1]*fabs(roaT[2][0]);
00619    t = fabs(aT[1]*roaT[0][2] - aT[0]*roaT[1][2]);
00620    if (t > ra + rb)
00621       return kOutside;
00622    else if (ra < t + rb)
00623       return kPartial;
00624 
00625    // No separating axis - b is inside a
00626    return kInside;
00627 }
00628 
00629 //______________________________________________________________________________
00630 void TGLBoundingBox::Draw(Bool_t solid) const
00631 {
00632    // Draw the bounding box as either wireframe (default) of solid
00633    // using current GL color.
00634 
00635    if (!solid) {
00636       glBegin(GL_LINE_LOOP);
00637       glVertex3dv(fVertex[0].CArr());
00638       glVertex3dv(fVertex[1].CArr());
00639       glVertex3dv(fVertex[2].CArr());
00640       glVertex3dv(fVertex[3].CArr());
00641       glVertex3dv(fVertex[7].CArr());
00642       glVertex3dv(fVertex[6].CArr());
00643       glVertex3dv(fVertex[5].CArr());
00644       glVertex3dv(fVertex[4].CArr());
00645       glEnd();
00646       glBegin(GL_LINES);
00647       glVertex3dv(fVertex[1].CArr());
00648       glVertex3dv(fVertex[5].CArr());
00649       glVertex3dv(fVertex[2].CArr());
00650       glVertex3dv(fVertex[6].CArr());
00651       glVertex3dv(fVertex[0].CArr());
00652       glVertex3dv(fVertex[3].CArr());
00653       glVertex3dv(fVertex[4].CArr());
00654       glVertex3dv(fVertex[7].CArr());
00655       glEnd();
00656    } else {
00657    //    y
00658    //    |
00659    //    |
00660    //    |________x
00661    //   /  3-------2
00662    //  /  /|      /|
00663    // z  7-------6 |
00664    //    | 0-----|-1
00665    //    |/      |/
00666    //    4-------5
00667       // Clockwise winding
00668       glBegin(GL_QUADS);
00669       // Near
00670       glNormal3d ( fAxesNorm[2].X(),  fAxesNorm[2].Y(),  fAxesNorm[2].Z());
00671       glVertex3dv(fVertex[4].CArr());
00672       glVertex3dv(fVertex[7].CArr());
00673       glVertex3dv(fVertex[6].CArr());
00674       glVertex3dv(fVertex[5].CArr());
00675       // Far
00676       glNormal3d (-fAxesNorm[2].X(), -fAxesNorm[2].Y(), -fAxesNorm[2].Z());
00677       glVertex3dv(fVertex[0].CArr());
00678       glVertex3dv(fVertex[1].CArr());
00679       glVertex3dv(fVertex[2].CArr());
00680       glVertex3dv(fVertex[3].CArr());
00681       // Left
00682       glNormal3d (-fAxesNorm[0].X(), -fAxesNorm[0].Y(), -fAxesNorm[0].Z());
00683       glVertex3dv(fVertex[0].CArr());
00684       glVertex3dv(fVertex[3].CArr());
00685       glVertex3dv(fVertex[7].CArr());
00686       glVertex3dv(fVertex[4].CArr());
00687       // Right
00688       glNormal3d ( fAxesNorm[0].X(),  fAxesNorm[0].Y(),  fAxesNorm[0].Z());
00689       glVertex3dv(fVertex[6].CArr());
00690       glVertex3dv(fVertex[2].CArr());
00691       glVertex3dv(fVertex[1].CArr());
00692       glVertex3dv(fVertex[5].CArr());
00693       // Top
00694       glNormal3d ( fAxesNorm[1].X(),  fAxesNorm[1].Y(),  fAxesNorm[1].Z());
00695       glVertex3dv(fVertex[3].CArr());
00696       glVertex3dv(fVertex[2].CArr());
00697       glVertex3dv(fVertex[6].CArr());
00698       glVertex3dv(fVertex[7].CArr());
00699       // Bottom
00700       glNormal3d (-fAxesNorm[1].X(), -fAxesNorm[1].Y(), -fAxesNorm[1].Z());
00701       glVertex3dv(fVertex[4].CArr());
00702       glVertex3dv(fVertex[5].CArr());
00703       glVertex3dv(fVertex[1].CArr());
00704       glVertex3dv(fVertex[0].CArr());
00705 
00706       glEnd();
00707    }
00708 
00709 }
00710 
00711 //______________________________________________________________________________
00712 Double_t TGLBoundingBox::Min(UInt_t index) const
00713 {
00714    // Find minimum vertex value for axis of index X(0), Y(1), Z(2)
00715    Double_t min = fVertex[0][index];
00716    for (UInt_t v = 1; v < 8; v++) {
00717       if (fVertex[v][index] < min) {
00718          min = fVertex[v][index];
00719       }
00720    }
00721    return min;
00722 }
00723 
00724 //______________________________________________________________________________
00725 Double_t TGLBoundingBox::Max(UInt_t index) const
00726 {
00727    // Find maximum vertex value for axis of index X(0), Y(1), Z(2)
00728    Double_t max = fVertex[0][index];
00729    for (UInt_t v = 1; v < 8; v++) {
00730       if (fVertex[v][index] > max) {
00731          max = fVertex[v][index];
00732       }
00733    }
00734    return max;
00735 }
00736 
00737 //______________________________________________________________________________
00738 TGLVertex3 TGLBoundingBox::MinAAVertex() const
00739 {
00740    // Find minimum vertex values.
00741 
00742    return TGLVertex3(Min(0), Min(1), Min(2));
00743 }
00744 
00745 //______________________________________________________________________________
00746 TGLVertex3 TGLBoundingBox::MaxAAVertex() const
00747 {
00748    // Find maximum vertex values.
00749 
00750    return TGLVertex3(Max(0), Max(1), Max(2));
00751 }
00752 
00753 //______________________________________________________________________________
00754 void TGLBoundingBox::Dump() const
00755 {
00756    // Output to std::cout the vertices, center and volume of box
00757    for (UInt_t i = 0; i<8; i++) {
00758       std::cout << "[" << i << "] (" << fVertex[i].X() << "," << fVertex[i].Y() << "," << fVertex[i].Z() << ")" << std::endl;
00759    }
00760    std::cout << "Center:  ";   Center().Dump();
00761    std::cout << "Extents: ";   Extents().Dump();
00762    std::cout << "Volume:  " << Volume() << std::endl;
00763 }
00764 

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1