28 ClassImp(TGLBoundingBox);
33 TGLBoundingBox::TGLBoundingBox()
41 TGLBoundingBox::TGLBoundingBox(
const TGLVertex3 vertex[8])
49 TGLBoundingBox::TGLBoundingBox(
const Double_t vertex[8][3])
57 TGLBoundingBox::TGLBoundingBox(
const TGLVertex3 & lowVertex,
const TGLVertex3 & highVertex)
59 SetAligned(lowVertex, highVertex);
65 TGLBoundingBox::TGLBoundingBox(
const TGLBoundingBox & other)
73 TGLBoundingBox::~TGLBoundingBox()
81 void TGLBoundingBox::UpdateCache()
96 fAxes[0].Set(fVertex[1] - fVertex[0]);
97 fAxes[1].Set(fVertex[3] - fVertex[0]);
98 fAxes[2].Set(fVertex[4] - fVertex[0]);
102 Bool_t fixZeroMagAxis = kFALSE;
103 Int_t zeroMagAxisInd = -1;
104 for (UInt_t i = 0; i<3; i++) {
105 fAxesNorm[i] = fAxes[i];
106 Double_t mag = fAxesNorm[i].Mag();
110 if (!fixZeroMagAxis && zeroMagAxisInd == -1) {
112 fixZeroMagAxis = kTRUE;
113 }
else if (fixZeroMagAxis) {
114 fixZeroMagAxis = kFALSE;
121 if (fixZeroMagAxis) {
122 fAxesNorm[zeroMagAxisInd] = Cross(fAxesNorm[(zeroMagAxisInd+1)%3],
123 fAxesNorm[(zeroMagAxisInd+2)%3]);
126 TGLVector3 extents = Extents();
127 fVolume = TMath::Abs(extents.X() * extents.Y() * extents.Z());
128 fDiagonal = extents.Mag();
134 void TGLBoundingBox::Set(
const TGLVertex3 vertex[8])
136 for (UInt_t v = 0; v < 8; v++) {
137 fVertex[v] = vertex[v];
146 void TGLBoundingBox::Set(
const Double_t vertex[8][3])
148 for (UInt_t v = 0; v < 8; v++) {
149 for (UInt_t a = 0; a < 3; a++) {
150 fVertex[v][a] = vertex[v][a];
160 void TGLBoundingBox::Set(
const TGLBoundingBox & other)
162 for (UInt_t v = 0; v < 8; v++) {
163 fVertex[v].Set(other.fVertex[v]);
172 void TGLBoundingBox::SetEmpty()
174 for (UInt_t v = 0; v < 8; v++) {
175 fVertex[v].Fill(0.0);
185 void TGLBoundingBox::SetAligned(
const TGLVertex3 & lowVertex,
const TGLVertex3 & highVertex)
202 TGLVector3 diff = highVertex - lowVertex;
203 if (diff.X() < 0.0 || diff.Y() < 0.0 || diff.Z() < 0.0) {
204 Error(
"TGLBoundingBox::SetAligned",
"low/high vertex range error");
206 fVertex[0] = lowVertex;
207 fVertex[1] = lowVertex; fVertex[1].X() += diff.X();
208 fVertex[2] = lowVertex; fVertex[2].X() += diff.X(); fVertex[2].Y() += diff.Y();
209 fVertex[3] = lowVertex; fVertex[3].Y() += diff.Y();
210 fVertex[4] = highVertex; fVertex[4].X() -= diff.X(); fVertex[4].Y() -= diff.Y();
211 fVertex[5] = highVertex; fVertex[5].Y() -= diff.Y();
212 fVertex[6] = highVertex;
213 fVertex[7] = highVertex; fVertex[7].X() -= diff.X();
222 void TGLBoundingBox::SetAligned(UInt_t nbPnts,
const Double_t * pnts)
224 if (nbPnts < 1 || !pnts) {
230 TGLVertex3 low(pnts[0], pnts[1], pnts[2]);
231 TGLVertex3 high(pnts[0], pnts[1], pnts[2]);
233 for (UInt_t p = 1; p < nbPnts; p++) {
234 for (UInt_t i = 0; i < 3; i++) {
235 if (pnts[3*p + i] < low[i]) {
236 low[i] = pnts[3*p + i] ;
238 if (pnts[3*p + i] > high[i]) {
239 high[i] = pnts[3*p + i] ;
244 SetAligned(low, high);
251 void TGLBoundingBox::MergeAligned(
const TGLBoundingBox & other)
253 if (other.IsEmpty())
return;
260 TGLVertex3 low (other.MinAAVertex());
261 TGLVertex3 high(other.MaxAAVertex());
263 low .Minimum(MinAAVertex());
264 high.Maximum(MaxAAVertex());
265 SetAligned(low, high);
273 void TGLBoundingBox::ExpandAligned(
const TGLVertex3 & point)
275 TGLVertex3 low (MinAAVertex());
276 TGLVertex3 high(MaxAAVertex());
281 SetAligned(low, high);
287 void TGLBoundingBox::Scale(Double_t factor)
289 Scale(factor, factor, factor);
297 void TGLBoundingBox::Scale(Double_t xFactor, Double_t yFactor, Double_t zFactor)
301 const TGLVector3 xOffset = Axis(0, kFALSE)*(xFactor - 1.0) / 2.0;
302 const TGLVector3 yOffset = Axis(1, kFALSE)*(yFactor - 1.0) / 2.0;
303 const TGLVector3 zOffset = Axis(2, kFALSE)*(zFactor - 1.0) / 2.0;
316 fVertex[0] += -xOffset - yOffset - zOffset;
317 fVertex[1] += xOffset - yOffset - zOffset;
318 fVertex[2] += xOffset + yOffset - zOffset;
319 fVertex[3] += -xOffset + yOffset - zOffset;
321 fVertex[4] += -xOffset - yOffset + zOffset;
322 fVertex[5] += xOffset - yOffset + zOffset;
323 fVertex[6] += xOffset + yOffset + zOffset;
324 fVertex[7] += -xOffset + yOffset + zOffset;
333 void TGLBoundingBox::Translate(
const TGLVector3 & offset)
335 for (UInt_t v = 0; v < 8; v++) {
336 fVertex[v] = fVertex[v] + offset;
345 void TGLBoundingBox::Transform(
const TGLMatrix & matrix)
347 for (UInt_t v = 0; v < 8; v++) {
348 matrix.TransformVertex(fVertex[v]);
369 const std::vector<UInt_t> & TGLBoundingBox::FaceVertices(EFace face)
const
371 static Bool_t init = kFALSE;
372 static std::vector<UInt_t> faceIndexes[kFaceCount];
375 faceIndexes[kFaceLowX].push_back(7);
376 faceIndexes[kFaceLowX].push_back(4);
377 faceIndexes[kFaceLowX].push_back(0);
378 faceIndexes[kFaceLowX].push_back(3);
380 faceIndexes[kFaceHighX].push_back(2);
381 faceIndexes[kFaceHighX].push_back(1);
382 faceIndexes[kFaceHighX].push_back(5);
383 faceIndexes[kFaceHighX].push_back(6);
385 faceIndexes[kFaceLowY].push_back(5);
386 faceIndexes[kFaceLowY].push_back(1);
387 faceIndexes[kFaceLowY].push_back(0);
388 faceIndexes[kFaceLowY].push_back(4);
390 faceIndexes[kFaceHighY].push_back(2);
391 faceIndexes[kFaceHighY].push_back(6);
392 faceIndexes[kFaceHighY].push_back(7);
393 faceIndexes[kFaceHighY].push_back(3);
395 faceIndexes[kFaceLowZ].push_back(3);
396 faceIndexes[kFaceLowZ].push_back(0);
397 faceIndexes[kFaceLowZ].push_back(1);
398 faceIndexes[kFaceLowZ].push_back(2);
400 faceIndexes[kFaceHighZ].push_back(6);
401 faceIndexes[kFaceHighZ].push_back(5);
402 faceIndexes[kFaceHighZ].push_back(4);
403 faceIndexes[kFaceHighZ].push_back(7);
406 return faceIndexes[face];
413 void TGLBoundingBox::PlaneSet(TGLPlaneSet_t & planeSet)
const
415 assert(planeSet.empty());
429 planeSet.push_back(TGLPlane( fAxesNorm[2], fVertex[4]));
430 planeSet.push_back(TGLPlane(-fAxesNorm[2], fVertex[0]));
431 planeSet.push_back(TGLPlane(-fAxesNorm[0], fVertex[0]));
432 planeSet.push_back(TGLPlane( fAxesNorm[0], fVertex[1]));
433 planeSet.push_back(TGLPlane(-fAxesNorm[1], fVertex[0]));
434 planeSet.push_back(TGLPlane( fAxesNorm[1], fVertex[3]));
440 TGLPlane TGLBoundingBox::GetNearPlane()
const
442 return TGLPlane(fAxesNorm[2], fVertex[4]);
448 Rgl::EOverlap TGLBoundingBox::Overlap(
const TGLPlane & plane)
const
454 if (plane.DistanceTo(Center()) + (Extents().Mag()/2.0) < 0.0) {
459 Int_t verticesInsidePlane = 8;
460 for (UInt_t v = 0; v < 8; v++) {
461 if (plane.DistanceTo(fVertex[v]) < 0.0) {
462 verticesInsidePlane--;
466 if ( verticesInsidePlane == 0 ) {
468 }
else if ( verticesInsidePlane == 8 ) {
478 Rgl::EOverlap TGLBoundingBox::Overlap(
const TGLBoundingBox & other)
const
483 const TGLBoundingBox & a = *
this;
484 const TGLBoundingBox & b = other;
486 TGLVector3 aHL = a.Extents() / 2.0;
487 TGLVector3 bHL = b.Extents() / 2.0;
493 TGLVector3 parentT = b.Center() - a.Center();
500 Double_t aSphereRadius = aHL[0] < aHL[1] ? aHL[0] : aHL[1];
501 if (aHL[2] < aSphereRadius) {
502 aSphereRadius = aHL[2];
505 Double_t bSphereRadius = bHL.Mag();
509 if (bSphereRadius + parentT.Mag() < aSphereRadius) {
516 TGLVector3 aT(Dot(parentT, a.Axis(0)), Dot(parentT, a.Axis(1)), Dot(parentT, a.Axis(2)));
522 for (i=0 ; i<3 ; i++) {
523 for (k=0; k<3; k++) {
524 roaT[i][k] = Dot(a.Axis(i), b.Axis(k));
526 if (fabs(roaT[i][k]) < 1e-14) {
531 Double_t norm = sqrt(roaT[i][0]*roaT[i][0] + roaT[i][1]*roaT[i][1] + roaT[i][2]*roaT[i][2]);
532 roaT[i][0] /= norm; roaT[i][1] /= norm; roaT[i][2] /= norm;
540 for (i=0; i<3; i++) {
542 rb = bHL[0]*fabs(roaT[i][0]) + bHL[1]*fabs(roaT[i][1]) + bHL[2]*fabs(roaT[i][2]);
546 else if (ra < t + rb)
551 for (k=0; k<3; k++) {
552 ra = aHL[0]*fabs(roaT[0][k]) + aHL[1]*fabs(roaT[1][k]) + aHL[2]*fabs(roaT[2][k]);
554 t = fabs(aT[0]*roaT[0][k] + aT[1]*roaT[1][k] + aT[2]*roaT[2][k]);
557 else if (ra < t + rb)
564 ra = aHL[1]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[1][0]);
565 rb = bHL[1]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][1]);
566 t = fabs(aT[2]*roaT[1][0] - aT[1]*roaT[2][0]);
569 else if (ra < t + rb)
573 ra = aHL[1]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[1][1]);
574 rb = bHL[0]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][0]);
575 t = fabs(aT[2]*roaT[1][1] - aT[1]*roaT[2][1]);
578 else if (ra < t + rb)
582 ra = aHL[1]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[1][2]);
583 rb = bHL[0]*fabs(roaT[0][1]) + bHL[1]*fabs(roaT[0][0]);
584 t = fabs(aT[2]*roaT[1][2] - aT[1]*roaT[2][2]);
587 else if (ra < t + rb)
591 ra = aHL[0]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[0][0]);
592 rb = bHL[1]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][1]);
593 t = fabs(aT[0]*roaT[2][0] - aT[2]*roaT[0][0]);
596 else if (ra < t + rb)
600 ra = aHL[0]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[0][1]);
601 rb = bHL[0]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][0]);
602 t = fabs(aT[0]*roaT[2][1] - aT[2]*roaT[0][1]);
605 else if (ra < t + rb)
609 ra = aHL[0]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[0][2]);
610 rb = bHL[0]*fabs(roaT[1][1]) + bHL[1]*fabs(roaT[1][0]);
611 t = fabs(aT[0]*roaT[2][2] - aT[2]*roaT[0][2]);
614 else if (ra < t + rb)
618 ra = aHL[0]*fabs(roaT[1][0]) + aHL[1]*fabs(roaT[0][0]);
619 rb = bHL[1]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][1]);
620 t = fabs(aT[1]*roaT[0][0] - aT[0]*roaT[1][0]);
623 else if (ra < t + rb)
627 ra = aHL[0]*fabs(roaT[1][1]) + aHL[1]*fabs(roaT[0][1]);
628 rb = bHL[0]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][0]);
629 t = fabs(aT[1]*roaT[0][1] - aT[0]*roaT[1][1]);
632 else if (ra < t + rb)
636 ra = aHL[0]*fabs(roaT[1][2]) + aHL[1]*fabs(roaT[0][2]);
637 rb = bHL[0]*fabs(roaT[2][1]) + bHL[1]*fabs(roaT[2][0]);
638 t = fabs(aT[1]*roaT[0][2] - aT[0]*roaT[1][2]);
641 else if (ra < t + rb)
652 void TGLBoundingBox::Draw(Bool_t solid)
const
655 glBegin(GL_LINE_LOOP);
656 glVertex3dv(fVertex[0].CArr());
657 glVertex3dv(fVertex[1].CArr());
658 glVertex3dv(fVertex[2].CArr());
659 glVertex3dv(fVertex[3].CArr());
660 glVertex3dv(fVertex[7].CArr());
661 glVertex3dv(fVertex[6].CArr());
662 glVertex3dv(fVertex[5].CArr());
663 glVertex3dv(fVertex[4].CArr());
666 glVertex3dv(fVertex[1].CArr());
667 glVertex3dv(fVertex[5].CArr());
668 glVertex3dv(fVertex[2].CArr());
669 glVertex3dv(fVertex[6].CArr());
670 glVertex3dv(fVertex[0].CArr());
671 glVertex3dv(fVertex[3].CArr());
672 glVertex3dv(fVertex[4].CArr());
673 glVertex3dv(fVertex[7].CArr());
689 glNormal3d ( fAxesNorm[2].X(), fAxesNorm[2].Y(), fAxesNorm[2].Z());
690 glVertex3dv(fVertex[4].CArr());
691 glVertex3dv(fVertex[7].CArr());
692 glVertex3dv(fVertex[6].CArr());
693 glVertex3dv(fVertex[5].CArr());
695 glNormal3d (-fAxesNorm[2].X(), -fAxesNorm[2].Y(), -fAxesNorm[2].Z());
696 glVertex3dv(fVertex[0].CArr());
697 glVertex3dv(fVertex[1].CArr());
698 glVertex3dv(fVertex[2].CArr());
699 glVertex3dv(fVertex[3].CArr());
701 glNormal3d (-fAxesNorm[0].X(), -fAxesNorm[0].Y(), -fAxesNorm[0].Z());
702 glVertex3dv(fVertex[0].CArr());
703 glVertex3dv(fVertex[3].CArr());
704 glVertex3dv(fVertex[7].CArr());
705 glVertex3dv(fVertex[4].CArr());
707 glNormal3d ( fAxesNorm[0].X(), fAxesNorm[0].Y(), fAxesNorm[0].Z());
708 glVertex3dv(fVertex[6].CArr());
709 glVertex3dv(fVertex[2].CArr());
710 glVertex3dv(fVertex[1].CArr());
711 glVertex3dv(fVertex[5].CArr());
713 glNormal3d ( fAxesNorm[1].X(), fAxesNorm[1].Y(), fAxesNorm[1].Z());
714 glVertex3dv(fVertex[3].CArr());
715 glVertex3dv(fVertex[2].CArr());
716 glVertex3dv(fVertex[6].CArr());
717 glVertex3dv(fVertex[7].CArr());
719 glNormal3d (-fAxesNorm[1].X(), -fAxesNorm[1].Y(), -fAxesNorm[1].Z());
720 glVertex3dv(fVertex[4].CArr());
721 glVertex3dv(fVertex[5].CArr());
722 glVertex3dv(fVertex[1].CArr());
723 glVertex3dv(fVertex[0].CArr());
733 Double_t TGLBoundingBox::Min(UInt_t index)
const
735 Double_t min = fVertex[0][index];
736 for (UInt_t v = 1; v < 8; v++) {
737 if (fVertex[v][index] < min) {
738 min = fVertex[v][index];
747 Double_t TGLBoundingBox::Max(UInt_t index)
const
749 Double_t max = fVertex[0][index];
750 for (UInt_t v = 1; v < 8; v++) {
751 if (fVertex[v][index] > max) {
752 max = fVertex[v][index];
761 TGLVertex3 TGLBoundingBox::MinAAVertex()
const
763 return TGLVertex3(Min(0), Min(1), Min(2));
769 TGLVertex3 TGLBoundingBox::MaxAAVertex()
const
771 return TGLVertex3(Max(0), Max(1), Max(2));
777 void TGLBoundingBox::Dump()
const
779 for (UInt_t i = 0; i<8; i++) {
780 std::cout <<
"[" << i <<
"] (" << fVertex[i].X() <<
"," << fVertex[i].Y() <<
"," << fVertex[i].Z() <<
")" << std::endl;
782 std::cout <<
"Center: "; Center().Dump();
783 std::cout <<
"Extents: "; Extents().Dump();
784 std::cout <<
"Volume: " << Volume() << std::endl;