Logo ROOT  
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 <iostream>
13#include "TGLBoundingBox.h"
14#include "TGLIncludes.h"
15#include "TMathBase.h"
16
17using namespace std;
18
19/** \class TGLBoundingBox
20\ingroup opengl
21Concrete class describing an orientated (free) or axis aligned box
22of 8 vertices. Supports methods for setting aligned or orientated
23boxes, find volume, axes, extents, centers, face planes etc.
24Also tests for overlap testing of planes and other bounding boxes,
25with 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
57TGLBoundingBox::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
185void 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
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
297void 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
369const 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
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
#define GL_QUADS
Definition: GL_glu.h:290
#define GL_LINES
Definition: GL_glu.h:284
#define GL_LINE_LOOP
Definition: GL_glu.h:285
#define b(i)
Definition: RSha256.hxx:100
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:45
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
double Double_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
Double_t Dot(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:317
std::vector< TGLPlane > TGLPlaneSet_t
Definition: TGLUtil.h:571
TGLVector3 Cross(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:323
Concrete class describing an orientated (free) or axis aligned box of 8 vertices.
Double_t Volume() const
Double_t Min(UInt_t index) const
Find minimum vertex value for axis of index X(0), Y(1), Z(2)
Double_t fDiagonal
box volume - cached for speed
TGLPlane GetNearPlane() const
Return the near-plane.
TGLVector3 Extents() const
TGLVertex3 Center() const
void Set(const TGLVertex3 vertex[8])
Set a bounding box from provided 8 vertices.
void SetEmpty()
Set bounding box empty - all vertices at (0,0,0)
void PlaneSet(TGLPlaneSet_t &planeSet) const
Fill out supplied plane set vector with TGLPlane objects representing six faces of box.
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----...
TGLVertex3 fVertex[8]
Bool_t IsEmpty() const
void Transform(const TGLMatrix &matrix)
Transform all vertices with matrix.
TGLVector3 fAxesNorm[3]
box axes in global frame - cached for speed
void MergeAligned(const TGLBoundingBox &other)
Expand current bbox so that it includes other's bbox.
void Translate(const TGLVector3 &offset)
Translate all vertices by offset.
TGLVertex3 MinAAVertex() const
Find minimum vertex values.
TGLBoundingBox()
Construct an empty bounding box.
void Scale(Double_t factor)
Isotropically scale bounding box along it's LOCAL axes, preserving center.
TGLVector3 fAxes[3]
max box diagonal - cached for speed
void SetAligned(const TGLVertex3 &lowVertex, const TGLVertex3 &highVertex)
Set ALIGNED box from two low/high vertices.
TGLVertex3 MaxAAVertex() const
Find maximum vertex values.
void UpdateCache()
normalised box axes in global frame - cached for speed
Double_t Max(UInt_t index) const
Find maximum vertex value for axis of index X(0), Y(1), Z(2)
const TGLVector3 & Axis(UInt_t i, Bool_t normalised=kTRUE) const
void ExpandAligned(const TGLVertex3 &point)
Expand current bbox so that it includes the point.
Double_t fVolume
the 8 bounding box vertices
virtual ~TGLBoundingBox()
Destroy bounding box.
void Dump() const
Output to std::cout the vertices, center and volume of box.
Rgl::EOverlap Overlap(const TGLPlane &plane) const
Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
void Draw(Bool_t solid=kFALSE) const
Draw the bounding box as either wireframe (default) of solid using current GL color.
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition: TGLUtil.h:598
void TransformVertex(TGLVertex3 &vertex) const
Transform passed 'vertex' by this matrix - converts local frame to parent.
Definition: TGLUtil.cxx:933
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:525
Double_t DistanceTo(const TGLVertex3 &vertex) const
Distance from plane to vertex.
Definition: TGLUtil.cxx:492
3 component (x/y/z) vector class.
Definition: TGLUtil.h:248
Double_t Mag() const
Definition: TGLUtil.h:298
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:84
void Dump() const
Output vertex component values to std::cout.
Definition: TGLUtil.cxx:130
void Minimum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:111
Double_t X() const
Definition: TGLUtil.h:119
Double_t Z() const
Definition: TGLUtil.h:123
void Maximum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:120
void Fill(Double_t val)
Definition: TGLUtil.h:204
void Set(Double_t x, Double_t y, Double_t z)
Definition: TGLUtil.h:210
Double_t Y() const
Definition: TGLUtil.h:121
T Mag(const SVector< T, D > &rhs)
Vector magnitude (Euclidian norm) Compute : .
Definition: Functions.h:253
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
EOverlap
Definition: TGLUtil.h:35
@ kInside
Definition: TGLUtil.h:36
@ kOutside
Definition: TGLUtil.h:38
@ kPartial
Definition: TGLUtil.h:37
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
auto * a
Definition: textangle.C:12
REAL * vertex
Definition: triangle.c:513