00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "Riostream.h"
00013 #include "TGLBoundingBox.h"
00014 #include "TGLIncludes.h"
00015 #include "TMathBase.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 ClassImp(TGLBoundingBox)
00029
00030
00031 TGLBoundingBox::TGLBoundingBox()
00032 {
00033
00034 SetEmpty();
00035 }
00036
00037
00038 TGLBoundingBox::TGLBoundingBox(const TGLVertex3 vertex[8])
00039 {
00040
00041 Set(vertex);
00042 }
00043
00044
00045 TGLBoundingBox::TGLBoundingBox(const Double_t vertex[8][3])
00046 {
00047
00048 Set(vertex);
00049 }
00050
00051
00052 TGLBoundingBox::TGLBoundingBox(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
00053 {
00054
00055 SetAligned(lowVertex, highVertex);
00056 }
00057
00058
00059 TGLBoundingBox::TGLBoundingBox(const TGLBoundingBox & other)
00060 {
00061
00062 Set(other);
00063 }
00064
00065
00066 TGLBoundingBox::~TGLBoundingBox()
00067 {
00068
00069 }
00070
00071
00072 void TGLBoundingBox::UpdateCache()
00073 {
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
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
00095
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
00114
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
00129 for (UInt_t v = 0; v < 8; v++) {
00130 fVertex[v] = vertex[v];
00131 }
00132
00133 UpdateCache();
00134 }
00135
00136
00137 void TGLBoundingBox::Set(const Double_t vertex[8][3])
00138 {
00139
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
00146 UpdateCache();
00147 }
00148
00149
00150 void TGLBoundingBox::Set(const TGLBoundingBox & other)
00151 {
00152
00153 for (UInt_t v = 0; v < 8; v++) {
00154 fVertex[v].Set(other.fVertex[v]);
00155 }
00156
00157 UpdateCache();
00158 }
00159
00160
00161 void TGLBoundingBox::SetEmpty()
00162 {
00163
00164 for (UInt_t v = 0; v < 8; v++) {
00165 fVertex[v].Fill(0.0);
00166 }
00167
00168 UpdateCache();
00169 }
00170
00171
00172 void TGLBoundingBox::SetAligned(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
00173 {
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
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
00205 UpdateCache();
00206 }
00207
00208
00209 void TGLBoundingBox::SetAligned(UInt_t nbPnts, const Double_t * pnts)
00210 {
00211
00212
00213 if (nbPnts < 1 || !pnts) {
00214 assert(false);
00215 return;
00216 }
00217
00218
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
00240
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
00262
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
00277 Scale(factor, factor, factor);
00278
00279 UpdateCache();
00280 }
00281
00282
00283 void TGLBoundingBox::Scale(Double_t xFactor, Double_t yFactor, Double_t zFactor)
00284 {
00285
00286
00287
00288
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
00294
00295
00296
00297
00298
00299
00300
00301
00302
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
00315 UpdateCache();
00316 }
00317
00318
00319 void TGLBoundingBox::Translate(const TGLVector3 & offset)
00320 {
00321
00322 for (UInt_t v = 0; v < 8; v++) {
00323 fVertex[v] = fVertex[v] + offset;
00324 }
00325
00326
00327 }
00328
00329
00330 void TGLBoundingBox::Transform(const TGLMatrix & matrix)
00331 {
00332
00333
00334 for (UInt_t v = 0; v < 8; v++) {
00335 matrix.TransformVertex(fVertex[v]);
00336 }
00337
00338
00339 UpdateCache();
00340 }
00341
00342
00343 const std::vector<UInt_t> & TGLBoundingBox::FaceVertices(EFace face) const
00344 {
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 static Bool_t init = kFALSE;
00358 static std::vector<UInt_t> faceIndexes[kFaceCount];
00359 if (!init) {
00360
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
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
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
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
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
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
00399
00400 assert(planeSet.empty());
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 planeSet.push_back(TGLPlane( fAxesNorm[2], fVertex[4]));
00415 planeSet.push_back(TGLPlane(-fAxesNorm[2], fVertex[0]));
00416 planeSet.push_back(TGLPlane(-fAxesNorm[0], fVertex[0]));
00417 planeSet.push_back(TGLPlane( fAxesNorm[0], fVertex[1]));
00418 planeSet.push_back(TGLPlane(-fAxesNorm[1], fVertex[0]));
00419 planeSet.push_back(TGLPlane( fAxesNorm[1], fVertex[3]));
00420 }
00421
00422
00423 TGLPlane TGLBoundingBox::GetNearPlane() const
00424 {
00425
00426
00427 return TGLPlane(fAxesNorm[2], fVertex[4]);
00428 }
00429
00430
00431 EOverlap TGLBoundingBox::Overlap(const TGLPlane & plane) const
00432 {
00433
00434
00435
00436
00437 if (plane.DistanceTo(Center()) + (Extents().Mag()/2.0) < 0.0) {
00438 return kOutside;
00439 }
00440
00441
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
00462
00463
00464 const TGLBoundingBox & a = *this;
00465 const TGLBoundingBox & b = other;
00466
00467 TGLVector3 aHL = a.Extents() / 2.0;
00468 TGLVector3 bHL = b.Extents() / 2.0;
00469
00470
00471
00472
00473
00474 TGLVector3 parentT = b.Center() - a.Center();
00475
00476
00477
00478
00479
00480
00481 Double_t aSphereRadius = aHL[0] < aHL[1] ? aHL[0] : aHL[1];
00482 if (aHL[2] < aSphereRadius) {
00483 aSphereRadius = aHL[2];
00484 }
00485
00486 Double_t bSphereRadius = bHL.Mag();
00487
00488
00489
00490 if (bSphereRadius + parentT.Mag() < aSphereRadius) {
00491 return kInside;
00492 }
00493
00494
00495
00496
00497 TGLVector3 aT(Dot(parentT, a.Axis(0)), Dot(parentT, a.Axis(1)), Dot(parentT, a.Axis(2)));
00498
00499
00500
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
00507 if (fabs(roaT[i][k]) < 1e-14) {
00508 roaT[i][k] = 0.0;
00509 }
00510 }
00511
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
00517
00518 Double_t ra, rb, t;
00519
00520
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
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
00543
00544
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
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
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
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
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
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
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
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
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
00626 return kInside;
00627 }
00628
00629
00630 void TGLBoundingBox::Draw(Bool_t solid) const
00631 {
00632
00633
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
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 glBegin(GL_QUADS);
00669
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
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
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
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
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
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
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
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
00741
00742 return TGLVertex3(Min(0), Min(1), Min(2));
00743 }
00744
00745
00746 TGLVertex3 TGLBoundingBox::MaxAAVertex() const
00747 {
00748
00749
00750 return TGLVertex3(Max(0), Max(1), Max(2));
00751 }
00752
00753
00754 void TGLBoundingBox::Dump() const
00755 {
00756
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