Logo ROOT   6.14/05
Reference Guide
TGLBoundingBox.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Richard Maunder 25/05/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "Riostream.h"
13 #include "TGLBoundingBox.h"
14 #include "TGLIncludes.h"
15 #include "TMathBase.h"
16 
17 using namespace std;
18 
19 /** \class TGLBoundingBox
20 \ingroup opengl
21 Concrete class describing an orientated (free) or axis aligned box
22 of 8 vertices. Supports methods for setting aligned or orientated
23 boxes, find volume, axes, extents, centers, face planes etc.
24 Also tests for overlap testing of planes and other bounding boxes,
25 with fast sphere approximation.
26 */
27 
29 
30 ////////////////////////////////////////////////////////////////////////////////
31 /// Construct an empty bounding box
32 
34 {
35  SetEmpty();
36 }
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Construct a bounding box from provided 8 vertices
40 
42 {
43  Set(vertex);
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Construct a bounding box from provided 8 vertices
48 
50 {
51  Set(vertex);
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// Construct an global axis ALIGNED bounding box from provided low/high vertex pair
56 
57 TGLBoundingBox::TGLBoundingBox(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
58 {
59  SetAligned(lowVertex, highVertex);
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// Construct a bounding box as copy of existing one
64 
66 {
67  Set(other);
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// Destroy bounding box
72 
74 {
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 /// Update the internally cached volume and axes vectors - these are retained
79 /// for efficiency - many more reads than modifications
80 
82 {
83  // y
84  // |
85  // |
86  // |________x
87  // / 3-------2
88  // / /| /|
89  // z 7-------6 |
90  // | 0-----|-1
91  // |/ |/
92  // 4-------5
93  //
94 
95  // Do axes first so Extents() is correct
96  fAxes[0].Set(fVertex[1] - fVertex[0]);
97  fAxes[1].Set(fVertex[3] - fVertex[0]);
98  fAxes[2].Set(fVertex[4] - fVertex[0]);
99 
100  // Sometimes have zero volume BB due to single zero magnitude
101  // axis record and try to fix below
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();
107  if (mag > 0.0) {
108  fAxesNorm[i] /= mag;
109  } else {
110  if (!fixZeroMagAxis && zeroMagAxisInd == -1) {
111  zeroMagAxisInd = i;
112  fixZeroMagAxis = kTRUE;
113  } else if (fixZeroMagAxis) {
114  fixZeroMagAxis = kFALSE;
115  }
116  }
117  }
118 
119  // Try to cope with a zero volume bounding box where one
120  // axis is zero by using cross product of other two
121  if (fixZeroMagAxis) {
122  fAxesNorm[zeroMagAxisInd] = Cross(fAxesNorm[(zeroMagAxisInd+1)%3],
123  fAxesNorm[(zeroMagAxisInd+2)%3]);
124  }
125 
126  TGLVector3 extents = Extents();
127  fVolume = TMath::Abs(extents.X() * extents.Y() * extents.Z());
128  fDiagonal = extents.Mag();
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Set a bounding box from provided 8 vertices
133 
135 {
136  for (UInt_t v = 0; v < 8; v++) {
137  fVertex[v] = vertex[v];
138  }
139  // Could change cached volume/axes
140  UpdateCache();
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 /// Set a bounding box from provided 8 vertices
145 
147 {
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];
151  }
152  }
153  // Could change cached volume/axes
154  UpdateCache();
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Set a bounding box from vertices of other
159 
161 {
162  for (UInt_t v = 0; v < 8; v++) {
163  fVertex[v].Set(other.fVertex[v]);
164  }
165  // Could change cached volume/axes
166  UpdateCache();
167 }
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Set bounding box empty - all vertices at (0,0,0)
171 
173 {
174  for (UInt_t v = 0; v < 8; v++) {
175  fVertex[v].Fill(0.0);
176  }
177  // Could change cached volume/axes
178  UpdateCache();
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Set ALIGNED box from two low/high vertices. Box axes are aligned with
183 /// global frame axes that vertices are specified in.
184 
185 void TGLBoundingBox::SetAligned(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex)
186 {
187  // lowVertex = vertex[0]
188  // highVertex = vertex[6]
189  //
190  // y
191  // |
192  // |
193  // |________x
194  // / 3-------2
195  // / /| /|
196  // z 7-------6 |
197  // | 0-----|-1
198  // |/ |/
199  // 4-------5
200  //
201 
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");
205  }
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();
214  // Could change cached volume/axes
215  UpdateCache();
216 }
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 /// Set ALIGNED box from one or more points. Box axes are aligned with
220 /// global frame axes that points are specified in.
221 
222 void TGLBoundingBox::SetAligned(UInt_t nbPnts, const Double_t * pnts)
223 {
224  if (nbPnts < 1 || !pnts) {
225  assert(false);
226  return;
227  }
228 
229  // Single point gives a zero volume BB
230  TGLVertex3 low(pnts[0], pnts[1], pnts[2]);
231  TGLVertex3 high(pnts[0], pnts[1], pnts[2]);
232 
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] ;
237  }
238  if (pnts[3*p + i] > high[i]) {
239  high[i] = pnts[3*p + i] ;
240  }
241  }
242  }
243 
244  SetAligned(low, high);
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Expand current bbox so that it includes other's bbox.
249 /// This make the bbox axis-aligned.
250 
252 {
253  if (other.IsEmpty()) return;
254  if (IsEmpty())
255  {
256  Set(other);
257  }
258  else
259  {
260  TGLVertex3 low (other.MinAAVertex());
261  TGLVertex3 high(other.MaxAAVertex());
262 
263  low .Minimum(MinAAVertex());
264  high.Maximum(MaxAAVertex());
265  SetAligned(low, high);
266  }
267 }
268 
269 ////////////////////////////////////////////////////////////////////////////////
270 /// Expand current bbox so that it includes the point.
271 /// This make the bbox axis-aligned.
272 
274 {
275  TGLVertex3 low (MinAAVertex());
276  TGLVertex3 high(MaxAAVertex());
277 
278  low .Minimum(point);
279  high.Maximum(point);
280 
281  SetAligned(low, high);
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Isotropically scale bounding box along it's LOCAL axes, preserving center
286 
288 {
289  Scale(factor, factor, factor);
290  // Could change cached volume/axes
291  UpdateCache();
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Asymmetrically scale box along it's LOCAL x,y,z axes, preserving center
296 
297 void TGLBoundingBox::Scale(Double_t xFactor, Double_t yFactor, Double_t zFactor)
298 {
299  // Get x,y,z edges (non-normalised axis) and scale
300  // them by factors
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;
304 
305  // y
306  // |
307  // |
308  // |________x
309  // / 3-------2
310  // / /| /|
311  // z 7-------6 |
312  // | 0-----|-1
313  // |/ |/
314  // 4-------5
315  //
316  fVertex[0] += -xOffset - yOffset - zOffset;
317  fVertex[1] += xOffset - yOffset - zOffset;
318  fVertex[2] += xOffset + yOffset - zOffset;
319  fVertex[3] += -xOffset + yOffset - zOffset;
320 
321  fVertex[4] += -xOffset - yOffset + zOffset;
322  fVertex[5] += xOffset - yOffset + zOffset;
323  fVertex[6] += xOffset + yOffset + zOffset;
324  fVertex[7] += -xOffset + yOffset + zOffset;
325 
326  // Could change cached volume/axes
327  UpdateCache();
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Translate all vertices by offset
332 
334 {
335  for (UInt_t v = 0; v < 8; v++) {
336  fVertex[v] = fVertex[v] + offset;
337  }
338 
339  // No cache change - volume and axes vectors remain same
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Transform all vertices with matrix.
344 
346 {
347  for (UInt_t v = 0; v < 8; v++) {
348  matrix.TransformVertex(fVertex[v]);
349  }
350 
351  // Could change cached volume/axes
352  UpdateCache();
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 ///return a vector of face vertices
357 /// y
358 /// |
359 /// |
360 /// |________x
361 /// / 3-------2
362 /// / /| /|
363 /// z 7-------6 |
364 /// | 0-----|-1
365 /// |/ |/
366 /// 4-------5
367 ///
368 
369 const std::vector<UInt_t> & TGLBoundingBox::FaceVertices(EFace face) const
370 {
371  static Bool_t init = kFALSE;
372  static std::vector<UInt_t> faceIndexes[kFaceCount];
373  if (!init) {
374  // Low X - 7403
375  faceIndexes[kFaceLowX].push_back(7);
376  faceIndexes[kFaceLowX].push_back(4);
377  faceIndexes[kFaceLowX].push_back(0);
378  faceIndexes[kFaceLowX].push_back(3);
379  // High X - 2156
380  faceIndexes[kFaceHighX].push_back(2);
381  faceIndexes[kFaceHighX].push_back(1);
382  faceIndexes[kFaceHighX].push_back(5);
383  faceIndexes[kFaceHighX].push_back(6);
384  // Low Y - 5104
385  faceIndexes[kFaceLowY].push_back(5);
386  faceIndexes[kFaceLowY].push_back(1);
387  faceIndexes[kFaceLowY].push_back(0);
388  faceIndexes[kFaceLowY].push_back(4);
389  // High Y - 2673
390  faceIndexes[kFaceHighY].push_back(2);
391  faceIndexes[kFaceHighY].push_back(6);
392  faceIndexes[kFaceHighY].push_back(7);
393  faceIndexes[kFaceHighY].push_back(3);
394  // Low Z - 3012
395  faceIndexes[kFaceLowZ].push_back(3);
396  faceIndexes[kFaceLowZ].push_back(0);
397  faceIndexes[kFaceLowZ].push_back(1);
398  faceIndexes[kFaceLowZ].push_back(2);
399  // High Z - 6547
400  faceIndexes[kFaceHighZ].push_back(6);
401  faceIndexes[kFaceHighZ].push_back(5);
402  faceIndexes[kFaceHighZ].push_back(4);
403  faceIndexes[kFaceHighZ].push_back(7);
404  init= kTRUE;
405  }
406  return faceIndexes[face];
407 }
408 
409 ////////////////////////////////////////////////////////////////////////////////
410 /// Fill out supplied plane set vector with TGLPlane objects
411 /// representing six faces of box
412 
414 {
415  assert(planeSet.empty());
416 
417  // y
418  // |
419  // |
420  // |________x
421  // / 3-------2
422  // / /| /|
423  // z 7-------6 |
424  // | 0-----|-1
425  // |/ |/
426  // 4-------5
427  //
428  // Construct plane set using axis + vertices
429  planeSet.push_back(TGLPlane( fAxesNorm[2], fVertex[4])); // Near
430  planeSet.push_back(TGLPlane(-fAxesNorm[2], fVertex[0])); // Far
431  planeSet.push_back(TGLPlane(-fAxesNorm[0], fVertex[0])); // Left
432  planeSet.push_back(TGLPlane( fAxesNorm[0], fVertex[1])); // Right
433  planeSet.push_back(TGLPlane(-fAxesNorm[1], fVertex[0])); // Bottom
434  planeSet.push_back(TGLPlane( fAxesNorm[1], fVertex[3])); // Top
435 }
436 
437 ////////////////////////////////////////////////////////////////////////////////
438 /// Return the near-plane.
439 
441 {
442  return TGLPlane(fAxesNorm[2], fVertex[4]);
443 }
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 /// Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
447 
449 {
450  using namespace Rgl;
451 
452  // First : cheap square approximation test. If distance of our
453  // center to plane > our half extent length we are outside plane
454  if (plane.DistanceTo(Center()) + (Extents().Mag()/2.0) < 0.0) {
455  return kOutside;
456  }
457 
458  // Second : test all 8 box vertices against plane
459  Int_t verticesInsidePlane = 8;
460  for (UInt_t v = 0; v < 8; v++) {
461  if (plane.DistanceTo(fVertex[v]) < 0.0) {
462  verticesInsidePlane--;
463  }
464  }
465 
466  if ( verticesInsidePlane == 0 ) {
467  return kOutside;
468  } else if ( verticesInsidePlane == 8 ) {
469  return kInside;
470  } else {
471  return kPartial;
472  }
473 }
474 
475 ////////////////////////////////////////////////////////////////////////////////
476 /// Find overlap (Inside, Outside, Partial) of other bounding box c.f. us.
477 
479 {
480  using namespace Rgl;
481 
482  // Simplify code with refs
483  const TGLBoundingBox & a = *this;
484  const TGLBoundingBox & b = other;
485 
486  TGLVector3 aHL = a.Extents() / 2.0; // Half length extents
487  TGLVector3 bHL = b.Extents() / 2.0; // Half length extents
488 
489  // Following tests are greatly simplified
490  // if we convert into our local frame
491 
492  // Find translation in parent frame
493  TGLVector3 parentT = b.Center() - a.Center();
494 
495  // First: Do a simple & cheap sphere approximation containment test.
496  // In many uses b will be completely contained by a and very much smaller
497  // these cases short circuited here
498 
499  // We need the inner sphere for the container (box a) - radius = shortest box half length
500  Double_t aSphereRadius = aHL[0] < aHL[1] ? aHL[0] : aHL[1];
501  if (aHL[2] < aSphereRadius) {
502  aSphereRadius = aHL[2];
503  }
504  // and the outer sphere for container (box b) - radius = box diagonal
505  Double_t bSphereRadius = bHL.Mag();
506 
507  // If b sphere radius + translation mag is smaller than b sphere radius
508  // b is complete contained by a
509  if (bSphereRadius + parentT.Mag() < aSphereRadius) {
510  return kInside;
511  }
512 
513  // Second: Perform more expensive 15 separating axes test
514 
515  // Find translation in A's frame
516  TGLVector3 aT(Dot(parentT, a.Axis(0)), Dot(parentT, a.Axis(1)), Dot(parentT, a.Axis(2)));
517 
518  // Find B's basis with respect to A's local frame
519  // Get rotation matrix
520  Double_t roaT[3][3];
521  UInt_t i, k;
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));
525  // Force very small components to zero to avoid rounding errors
526  if (fabs(roaT[i][k]) < 1e-14) {
527  roaT[i][k] = 0.0;
528  }
529  }
530  // Normalise columns to avoid rounding errors
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;
533  }
534 
535  // Perform separating axis test for all 15 potential
536  // axes. If no separating axes found, the two boxes overlap.
537  Double_t ra, rb, t;
538 
539  // A's 3 basis vectors
540  for (i=0; i<3; i++) {
541  ra = aHL[i];
542  rb = bHL[0]*fabs(roaT[i][0]) + bHL[1]*fabs(roaT[i][1]) + bHL[2]*fabs(roaT[i][2]);
543  t = fabs(aT[i]);
544  if (t > ra + rb)
545  return kOutside;
546  else if (ra < t + rb)
547  return kPartial;
548  }
549 
550  // B's 3 basis vectors
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]);
553  rb = bHL[k];
554  t = fabs(aT[0]*roaT[0][k] + aT[1]*roaT[1][k] + aT[2]*roaT[2][k]);
555  if (t > ra + rb)
556  return kOutside;
557  else if (ra < t + rb)
558  return kPartial;
559  }
560 
561  // Now the 9 cross products
562 
563  // A0 x B0
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]);
567  if (t > ra + rb)
568  return kOutside;
569  else if (ra < t + rb)
570  return kPartial;
571 
572  // A0 x B1
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]);
576  if (t > ra + rb)
577  return kOutside;
578  else if (ra < t + rb)
579  return kPartial;
580 
581  // A0 x B2
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]);
585  if (t > ra + rb)
586  return kOutside;
587  else if (ra < t + rb)
588  return kPartial;
589 
590  // A1 x B0
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]);
594  if (t > ra + rb)
595  return kOutside;
596  else if (ra < t + rb)
597  return kPartial;
598 
599  // A1 x B1
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]);
603  if (t > ra + rb)
604  return kOutside;
605  else if (ra < t + rb)
606  return kPartial;
607 
608  // A1 x B2
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]);
612  if (t > ra + rb)
613  return kOutside;
614  else if (ra < t + rb)
615  return kPartial;
616 
617  // A2 x B0
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]);
621  if (t > ra + rb)
622  return kOutside;
623  else if (ra < t + rb)
624  return kPartial;
625 
626  // A2 x B1
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]);
630  if (t > ra + rb)
631  return kOutside;
632  else if (ra < t + rb)
633  return kPartial;
634 
635  // A2 x B2
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]);
639  if (t > ra + rb)
640  return kOutside;
641  else if (ra < t + rb)
642  return kPartial;
643 
644  // No separating axis - b is inside a
645  return kInside;
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// Draw the bounding box as either wireframe (default) of solid
650 /// using current GL color.
651 
652 void TGLBoundingBox::Draw(Bool_t solid) const
653 {
654  if (!solid) {
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());
664  glEnd();
665  glBegin(GL_LINES);
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());
674  glEnd();
675  } else {
676  // y
677  // |
678  // |
679  // |________x
680  // / 3-------2
681  // / /| /|
682  // z 7-------6 |
683  // | 0-----|-1
684  // |/ |/
685  // 4-------5
686  // Clockwise winding
687  glBegin(GL_QUADS);
688  // Near
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());
694  // Far
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());
700  // Left
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());
706  // Right
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());
712  // Top
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());
718  // Bottom
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());
724 
725  glEnd();
726  }
727 
728 }
729 
730 ////////////////////////////////////////////////////////////////////////////////
731 /// Find minimum vertex value for axis of index X(0), Y(1), Z(2)
732 
734 {
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];
739  }
740  }
741  return min;
742 }
743 
744 ////////////////////////////////////////////////////////////////////////////////
745 /// Find maximum vertex value for axis of index X(0), Y(1), Z(2)
746 
748 {
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];
753  }
754  }
755  return max;
756 }
757 
758 ////////////////////////////////////////////////////////////////////////////////
759 /// Find minimum vertex values.
760 
762 {
763  return TGLVertex3(Min(0), Min(1), Min(2));
764 }
765 
766 ////////////////////////////////////////////////////////////////////////////////
767 /// Find maximum vertex values.
768 
770 {
771  return TGLVertex3(Max(0), Max(1), Max(2));
772 }
773 
774 ////////////////////////////////////////////////////////////////////////////////
775 /// Output to std::cout the vertices, center and volume of box
776 
778 {
779  for (UInt_t i = 0; i<8; i++) {
780  std::cout << "[" << i << "] (" << fVertex[i].X() << "," << fVertex[i].Y() << "," << fVertex[i].Z() << ")" << std::endl;
781  }
782  std::cout << "Center: "; Center().Dump();
783  std::cout << "Extents: "; Extents().Dump();
784  std::cout << "Volume: " << Volume() << std::endl;
785 }
786 
void SetAligned(const TGLVertex3 &lowVertex, const TGLVertex3 &highVertex)
Set ALIGNED box from two low/high vertices.
Double_t DistanceTo(const TGLVertex3 &vertex) const
Distance from plane to vertex.
Definition: TGLUtil.cxx:520
TGLVertex3 Center() const
TGLVector3 Extents() const
TGLVertex3 fVertex[8]
void Dump() const
Output to std::cout the vertices, center and volume of box.
void Set(const TGLVertex3 vertex[8])
Set a bounding box from provided 8 vertices.
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition: TGLUtil.h:596
void TransformVertex(TGLVertex3 &vertex) const
Transform passed &#39;vertex&#39; by this matrix - converts local frame to parent.
Definition: TGLUtil.cxx:961
Double_t Max(UInt_t index) const
Find maximum vertex value for axis of index X(0), Y(1), Z(2)
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
STL namespace.
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
TGLVertex3 MinAAVertex() const
Find minimum vertex values.
Bool_t IsEmpty() const
double sqrt(double)
void Transform(const TGLMatrix &matrix)
Transform all vertices with matrix.
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:82
TGLPlane GetNearPlane() const
Return the near-plane.
3 component (x/y/z) vector class.
Definition: TGLUtil.h:246
void UpdateCache()
normalised box axes in global frame - cached for speed
void PlaneSet(TGLPlaneSet_t &planeSet) const
Fill out supplied plane set vector with TGLPlane objects representing six faces of box...
void Error(const char *location, const char *msgfmt,...)
Double_t Min(UInt_t index) const
Find minimum vertex value for axis of index X(0), Y(1), Z(2)
TGLBoundingBox()
Construct an empty bounding box.
REAL * vertex
Definition: triangle.c:512
TGLVertex3 MaxAAVertex() const
Find maximum vertex values.
void ExpandAligned(const TGLVertex3 &point)
Expand current bbox so that it includes the point.
Double_t Mag() const
Definition: TGLUtil.h:299
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
virtual ~TGLBoundingBox()
Destroy bounding box.
SVector< double, 2 > v
Definition: Dict.h:5
auto * a
Definition: textangle.C:12
void Minimum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:112
unsigned int UInt_t
Definition: RtypesCore.h:42
void MergeAligned(const TGLBoundingBox &other)
Expand current bbox so that it includes other&#39;s bbox.
const Bool_t kFALSE
Definition: RtypesCore.h:88
void Scale(Double_t factor)
Isotropically scale bounding box along it&#39;s LOCAL axes, preserving center.
Double_t Z() const
Definition: TGLUtil.h:122
Double_t Dot(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:318
#define ClassImp(name)
Definition: Rtypes.h:359
static Int_t init()
std::vector< TGLPlane > TGLPlaneSet_t
Definition: TGLUtil.h:570
double Double_t
Definition: RtypesCore.h:55
void Draw(Bool_t solid=kFALSE) const
Draw the bounding box as either wireframe (default) of solid using current GL color.
void SetEmpty()
Set bounding box empty - all vertices at (0,0,0)
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
const std::vector< UInt_t > & FaceVertices(EFace face) const
return a vector of face vertices y | | |________x / 3----—2 / /| /| z 7----—6 | | 0--—|-1 |/ |/ 4-...
EOverlap
Definition: TGLUtil.h:33
void Maximum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:121
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
void Translate(const TGLVector3 &offset)
Translate all vertices by offset.
const TGLVector3 & Axis(UInt_t i, Bool_t normalised=kTRUE) const
TGLVector3 Cross(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:324
Rgl::EOverlap Overlap(const TGLPlane &plane) const
Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
Double_t Y() const
Definition: TGLUtil.h:120
const Bool_t kTRUE
Definition: RtypesCore.h:87
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:525
Double_t X() const
Definition: TGLUtil.h:118