Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
17/** \class TGLBoundingBox
18\ingroup opengl
19Concrete class describing an orientated (free) or axis aligned box
20of 8 vertices. Supports methods for setting aligned or orientated
21boxes, find volume, axes, extents, centers, face planes etc.
22Also tests for overlap testing of planes and other bounding boxes,
23with fast sphere approximation.
24*/
25
26
27////////////////////////////////////////////////////////////////////////////////
28/// Construct an empty bounding box
29
34
35////////////////////////////////////////////////////////////////////////////////
36/// Construct a bounding box from provided 8 vertices
37
42
43////////////////////////////////////////////////////////////////////////////////
44/// Construct a bounding box from provided 8 vertices
45
50
51////////////////////////////////////////////////////////////////////////////////
52/// Construct an global axis ALIGNED bounding box from provided low/high vertex pair
53
58
59////////////////////////////////////////////////////////////////////////////////
60/// Construct a bounding box as copy of existing one
61
66
67////////////////////////////////////////////////////////////////////////////////
68/// Destroy bounding box
69
73
74////////////////////////////////////////////////////////////////////////////////
75/// Update the internally cached volume and axes vectors - these are retained
76/// for efficiency - many more reads than modifications
77
79{
80 // y
81 // |
82 // |
83 // |________x
84 // / 3-------2
85 // / /| /|
86 // z 7-------6 |
87 // | 0-----|-1
88 // |/ |/
89 // 4-------5
90 //
91
92 // Do axes first so Extents() is correct
93 fAxes[0].Set(fVertex[1] - fVertex[0]);
94 fAxes[1].Set(fVertex[3] - fVertex[0]);
95 fAxes[2].Set(fVertex[4] - fVertex[0]);
96
97 // Sometimes have zero volume BB due to single zero magnitude
98 // axis record and try to fix below
101 for (UInt_t i = 0; i<3; i++) {
102 fAxesNorm[i] = fAxes[i];
103 Double_t mag = fAxesNorm[i].Mag();
104 if (mag > 0.0) {
105 fAxesNorm[i] /= mag;
106 } else {
107 if (!fixZeroMagAxis && zeroMagAxisInd == -1) {
108 zeroMagAxisInd = i;
110 } else if (fixZeroMagAxis) {
112 }
113 }
114 }
115
116 // Try to cope with a zero volume bounding box where one
117 // axis is zero by using cross product of other two
118 if (fixZeroMagAxis) {
121 }
122
124 fVolume = TMath::Abs(extents.X() * extents.Y() * extents.Z());
125 fDiagonal = extents.Mag();
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Set a bounding box from provided 8 vertices
130
132{
133 for (UInt_t v = 0; v < 8; v++) {
134 fVertex[v] = vertex[v];
135 }
136 // Could change cached volume/axes
137 UpdateCache();
138}
139
140////////////////////////////////////////////////////////////////////////////////
141/// Set a bounding box from provided 8 vertices
142
144{
145 for (UInt_t v = 0; v < 8; v++) {
146 for (UInt_t a = 0; a < 3; a++) {
147 fVertex[v][a] = vertex[v][a];
148 }
149 }
150 // Could change cached volume/axes
151 UpdateCache();
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Set a bounding box from vertices of other
156
158{
159 for (UInt_t v = 0; v < 8; v++) {
160 fVertex[v].Set(other.fVertex[v]);
161 }
162 // Could change cached volume/axes
163 UpdateCache();
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// Set bounding box empty - all vertices at (0,0,0)
168
170{
171 for (UInt_t v = 0; v < 8; v++) {
172 fVertex[v].Fill(0.0);
173 }
174 // Could change cached volume/axes
175 UpdateCache();
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// Set ALIGNED box from two low/high vertices. Box axes are aligned with
180/// global frame axes that vertices are specified in.
181
183{
184 // lowVertex = vertex[0]
185 // highVertex = vertex[6]
186 //
187 // y
188 // |
189 // |
190 // |________x
191 // / 3-------2
192 // / /| /|
193 // z 7-------6 |
194 // | 0-----|-1
195 // |/ |/
196 // 4-------5
197 //
198
200 if (diff.X() < 0.0 || diff.Y() < 0.0 || diff.Z() < 0.0) {
201 Error("TGLBoundingBox::SetAligned", "low/high vertex range error");
202 }
203 fVertex[0] = lowVertex;
204 fVertex[1] = lowVertex; fVertex[1].X() += diff.X();
205 fVertex[2] = lowVertex; fVertex[2].X() += diff.X(); fVertex[2].Y() += diff.Y();
206 fVertex[3] = lowVertex; fVertex[3].Y() += diff.Y();
207 fVertex[4] = highVertex; fVertex[4].X() -= diff.X(); fVertex[4].Y() -= diff.Y();
208 fVertex[5] = highVertex; fVertex[5].Y() -= diff.Y();
209 fVertex[6] = highVertex;
210 fVertex[7] = highVertex; fVertex[7].X() -= diff.X();
211 // Could change cached volume/axes
212 UpdateCache();
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Set ALIGNED box from one or more points. Box axes are aligned with
217/// global frame axes that points are specified in.
218
220{
221 if (nbPnts < 1 || !pnts) {
222 assert(false);
223 return;
224 }
225
226 // Single point gives a zero volume BB
227 TGLVertex3 low(pnts[0], pnts[1], pnts[2]);
228 TGLVertex3 high(pnts[0], pnts[1], pnts[2]);
229
230 for (UInt_t p = 1; p < nbPnts; p++) {
231 for (UInt_t i = 0; i < 3; i++) {
232 if (pnts[3*p + i] < low[i]) {
233 low[i] = pnts[3*p + i] ;
234 }
235 if (pnts[3*p + i] > high[i]) {
236 high[i] = pnts[3*p + i] ;
237 }
238 }
239 }
240
241 SetAligned(low, high);
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Expand current bbox so that it includes other's bbox.
246/// This make the bbox axis-aligned.
247
249{
250 if (other.IsEmpty()) return;
251 if (IsEmpty())
252 {
253 Set(other);
254 }
255 else
256 {
257 TGLVertex3 low (other.MinAAVertex());
258 TGLVertex3 high(other.MaxAAVertex());
259
260 low .Minimum(MinAAVertex());
261 high.Maximum(MaxAAVertex());
262 SetAligned(low, high);
263 }
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// Expand current bbox so that it includes the point.
268/// This make the bbox axis-aligned.
269
271{
272 TGLVertex3 low (MinAAVertex());
273 TGLVertex3 high(MaxAAVertex());
274
275 low .Minimum(point);
276 high.Maximum(point);
277
278 SetAligned(low, high);
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// Isotropically scale bounding box along it's LOCAL axes, preserving center
283
285{
286 Scale(factor, factor, factor);
287 // Could change cached volume/axes
288 UpdateCache();
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Asymmetrically scale box along it's LOCAL x,y,z axes, preserving center
293
295{
296 // Get x,y,z edges (non-normalised axis) and scale
297 // them by factors
298 const TGLVector3 xOffset = Axis(0, kFALSE)*(xFactor - 1.0) / 2.0;
299 const TGLVector3 yOffset = Axis(1, kFALSE)*(yFactor - 1.0) / 2.0;
300 const TGLVector3 zOffset = Axis(2, kFALSE)*(zFactor - 1.0) / 2.0;
301
302 // y
303 // |
304 // |
305 // |________x
306 // / 3-------2
307 // / /| /|
308 // z 7-------6 |
309 // | 0-----|-1
310 // |/ |/
311 // 4-------5
312 //
313 fVertex[0] += -xOffset - yOffset - zOffset;
314 fVertex[1] += xOffset - yOffset - zOffset;
315 fVertex[2] += xOffset + yOffset - zOffset;
316 fVertex[3] += -xOffset + yOffset - zOffset;
317
318 fVertex[4] += -xOffset - yOffset + zOffset;
319 fVertex[5] += xOffset - yOffset + zOffset;
320 fVertex[6] += xOffset + yOffset + zOffset;
321 fVertex[7] += -xOffset + yOffset + zOffset;
322
323 // Could change cached volume/axes
324 UpdateCache();
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// Translate all vertices by offset
329
331{
332 for (UInt_t v = 0; v < 8; v++) {
333 fVertex[v] = fVertex[v] + offset;
334 }
335
336 // No cache change - volume and axes vectors remain same
337}
338
339////////////////////////////////////////////////////////////////////////////////
340/// Transform all vertices with matrix.
341
343{
344 for (UInt_t v = 0; v < 8; v++) {
345 matrix.TransformVertex(fVertex[v]);
346 }
347
348 // Could change cached volume/axes
349 UpdateCache();
350}
351
352////////////////////////////////////////////////////////////////////////////////
353///return a vector of face vertices
354/// y
355/// |
356/// |
357/// |________x
358/// / 3-------2
359/// / /| /|
360/// z 7-------6 |
361/// | 0-----|-1
362/// |/ |/
363/// 4-------5
364///
365
366const std::vector<UInt_t> & TGLBoundingBox::FaceVertices(EFace face) const
367{
368 static Bool_t init = kFALSE;
369 static std::vector<UInt_t> faceIndexes[kFaceCount];
370 if (!init) {
371 // Low X - 7403
372 faceIndexes[kFaceLowX].push_back(7);
373 faceIndexes[kFaceLowX].push_back(4);
374 faceIndexes[kFaceLowX].push_back(0);
375 faceIndexes[kFaceLowX].push_back(3);
376 // High X - 2156
377 faceIndexes[kFaceHighX].push_back(2);
378 faceIndexes[kFaceHighX].push_back(1);
379 faceIndexes[kFaceHighX].push_back(5);
380 faceIndexes[kFaceHighX].push_back(6);
381 // Low Y - 5104
382 faceIndexes[kFaceLowY].push_back(5);
383 faceIndexes[kFaceLowY].push_back(1);
384 faceIndexes[kFaceLowY].push_back(0);
385 faceIndexes[kFaceLowY].push_back(4);
386 // High Y - 2673
387 faceIndexes[kFaceHighY].push_back(2);
388 faceIndexes[kFaceHighY].push_back(6);
389 faceIndexes[kFaceHighY].push_back(7);
390 faceIndexes[kFaceHighY].push_back(3);
391 // Low Z - 3012
392 faceIndexes[kFaceLowZ].push_back(3);
393 faceIndexes[kFaceLowZ].push_back(0);
394 faceIndexes[kFaceLowZ].push_back(1);
395 faceIndexes[kFaceLowZ].push_back(2);
396 // High Z - 6547
397 faceIndexes[kFaceHighZ].push_back(6);
398 faceIndexes[kFaceHighZ].push_back(5);
399 faceIndexes[kFaceHighZ].push_back(4);
400 faceIndexes[kFaceHighZ].push_back(7);
401 init= kTRUE;
402 }
403 return faceIndexes[face];
404}
405
406////////////////////////////////////////////////////////////////////////////////
407/// Fill out supplied plane set vector with TGLPlane objects
408/// representing six faces of box
409
411{
412 assert(planeSet.empty());
413
414 // y
415 // |
416 // |
417 // |________x
418 // / 3-------2
419 // / /| /|
420 // z 7-------6 |
421 // | 0-----|-1
422 // |/ |/
423 // 4-------5
424 //
425 // Construct plane set using axis + vertices
426 planeSet.push_back(TGLPlane( fAxesNorm[2], fVertex[4])); // Near
427 planeSet.push_back(TGLPlane(-fAxesNorm[2], fVertex[0])); // Far
428 planeSet.push_back(TGLPlane(-fAxesNorm[0], fVertex[0])); // Left
429 planeSet.push_back(TGLPlane( fAxesNorm[0], fVertex[1])); // Right
430 planeSet.push_back(TGLPlane(-fAxesNorm[1], fVertex[0])); // Bottom
431 planeSet.push_back(TGLPlane( fAxesNorm[1], fVertex[3])); // Top
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// Return the near-plane.
436
438{
439 return TGLPlane(fAxesNorm[2], fVertex[4]);
440}
441
442////////////////////////////////////////////////////////////////////////////////
443/// Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
444
446{
447 using namespace Rgl;
448
449 // First : cheap square approximation test. If distance of our
450 // center to plane > our half extent length we are outside plane
451 if (plane.DistanceTo(Center()) + (Extents().Mag()/2.0) < 0.0) {
452 return kOutside;
453 }
454
455 // Second : test all 8 box vertices against plane
457 for (UInt_t v = 0; v < 8; v++) {
458 if (plane.DistanceTo(fVertex[v]) < 0.0) {
460 }
461 }
462
463 if ( verticesInsidePlane == 0 ) {
464 return kOutside;
465 } else if ( verticesInsidePlane == 8 ) {
466 return kInside;
467 } else {
468 return kPartial;
469 }
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Find overlap (Inside, Outside, Partial) of other bounding box c.f. us.
474
476{
477 using namespace Rgl;
478
479 // Simplify code with refs
480 const TGLBoundingBox & a = *this;
481 const TGLBoundingBox & b = other;
482
483 TGLVector3 aHL = a.Extents() / 2.0; // Half length extents
484 TGLVector3 bHL = b.Extents() / 2.0; // Half length extents
485
486 // Following tests are greatly simplified
487 // if we convert into our local frame
488
489 // Find translation in parent frame
490 TGLVector3 parentT = b.Center() - a.Center();
491
492 // First: Do a simple & cheap sphere approximation containment test.
493 // In many uses b will be completely contained by a and very much smaller
494 // these cases short circuited here
495
496 // We need the inner sphere for the container (box a) - radius = shortest box half length
497 Double_t aSphereRadius = aHL[0] < aHL[1] ? aHL[0] : aHL[1];
498 if (aHL[2] < aSphereRadius) {
499 aSphereRadius = aHL[2];
500 }
501 // and the outer sphere for container (box b) - radius = box diagonal
502 Double_t bSphereRadius = bHL.Mag();
503
504 // If b sphere radius + translation mag is smaller than b sphere radius
505 // b is complete contained by a
506 if (bSphereRadius + parentT.Mag() < aSphereRadius) {
507 return kInside;
508 }
509
510 // Second: Perform more expensive 15 separating axes test
511
512 // Find translation in A's frame
513 TGLVector3 aT(Dot(parentT, a.Axis(0)), Dot(parentT, a.Axis(1)), Dot(parentT, a.Axis(2)));
514
515 // Find B's basis with respect to A's local frame
516 // Get rotation matrix
517 Double_t roaT[3][3];
518 UInt_t i, k;
519 for (i=0 ; i<3 ; i++) {
520 for (k=0; k<3; k++) {
521 roaT[i][k] = Dot(a.Axis(i), b.Axis(k));
522 // Force very small components to zero to avoid rounding errors
523 if (fabs(roaT[i][k]) < 1e-14) {
524 roaT[i][k] = 0.0;
525 }
526 }
527 // Normalise columns to avoid rounding errors
528 Double_t norm = sqrt(roaT[i][0]*roaT[i][0] + roaT[i][1]*roaT[i][1] + roaT[i][2]*roaT[i][2]);
529 roaT[i][0] /= norm; roaT[i][1] /= norm; roaT[i][2] /= norm;
530 }
531
532 // Perform separating axis test for all 15 potential
533 // axes. If no separating axes found, the two boxes overlap.
534 Double_t ra, rb, t;
535
536 // A's 3 basis vectors
537 for (i=0; i<3; i++) {
538 ra = aHL[i];
539 rb = bHL[0]*fabs(roaT[i][0]) + bHL[1]*fabs(roaT[i][1]) + bHL[2]*fabs(roaT[i][2]);
540 t = fabs(aT[i]);
541 if (t > ra + rb)
542 return kOutside;
543 else if (ra < t + rb)
544 return kPartial;
545 }
546
547 // B's 3 basis vectors
548 for (k=0; k<3; k++) {
549 ra = aHL[0]*fabs(roaT[0][k]) + aHL[1]*fabs(roaT[1][k]) + aHL[2]*fabs(roaT[2][k]);
550 rb = bHL[k];
551 t = fabs(aT[0]*roaT[0][k] + aT[1]*roaT[1][k] + aT[2]*roaT[2][k]);
552 if (t > ra + rb)
553 return kOutside;
554 else if (ra < t + rb)
555 return kPartial;
556 }
557
558 // Now the 9 cross products
559
560 // A0 x B0
561 ra = aHL[1]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[1][0]);
562 rb = bHL[1]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][1]);
563 t = fabs(aT[2]*roaT[1][0] - aT[1]*roaT[2][0]);
564 if (t > ra + rb)
565 return kOutside;
566 else if (ra < t + rb)
567 return kPartial;
568
569 // A0 x B1
570 ra = aHL[1]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[1][1]);
571 rb = bHL[0]*fabs(roaT[0][2]) + bHL[2]*fabs(roaT[0][0]);
572 t = fabs(aT[2]*roaT[1][1] - aT[1]*roaT[2][1]);
573 if (t > ra + rb)
574 return kOutside;
575 else if (ra < t + rb)
576 return kPartial;
577
578 // A0 x B2
579 ra = aHL[1]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[1][2]);
580 rb = bHL[0]*fabs(roaT[0][1]) + bHL[1]*fabs(roaT[0][0]);
581 t = fabs(aT[2]*roaT[1][2] - aT[1]*roaT[2][2]);
582 if (t > ra + rb)
583 return kOutside;
584 else if (ra < t + rb)
585 return kPartial;
586
587 // A1 x B0
588 ra = aHL[0]*fabs(roaT[2][0]) + aHL[2]*fabs(roaT[0][0]);
589 rb = bHL[1]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][1]);
590 t = fabs(aT[0]*roaT[2][0] - aT[2]*roaT[0][0]);
591 if (t > ra + rb)
592 return kOutside;
593 else if (ra < t + rb)
594 return kPartial;
595
596 // A1 x B1
597 ra = aHL[0]*fabs(roaT[2][1]) + aHL[2]*fabs(roaT[0][1]);
598 rb = bHL[0]*fabs(roaT[1][2]) + bHL[2]*fabs(roaT[1][0]);
599 t = fabs(aT[0]*roaT[2][1] - aT[2]*roaT[0][1]);
600 if (t > ra + rb)
601 return kOutside;
602 else if (ra < t + rb)
603 return kPartial;
604
605 // A1 x B2
606 ra = aHL[0]*fabs(roaT[2][2]) + aHL[2]*fabs(roaT[0][2]);
607 rb = bHL[0]*fabs(roaT[1][1]) + bHL[1]*fabs(roaT[1][0]);
608 t = fabs(aT[0]*roaT[2][2] - aT[2]*roaT[0][2]);
609 if (t > ra + rb)
610 return kOutside;
611 else if (ra < t + rb)
612 return kPartial;
613
614 // A2 x B0
615 ra = aHL[0]*fabs(roaT[1][0]) + aHL[1]*fabs(roaT[0][0]);
616 rb = bHL[1]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][1]);
617 t = fabs(aT[1]*roaT[0][0] - aT[0]*roaT[1][0]);
618 if (t > ra + rb)
619 return kOutside;
620 else if (ra < t + rb)
621 return kPartial;
622
623 // A2 x B1
624 ra = aHL[0]*fabs(roaT[1][1]) + aHL[1]*fabs(roaT[0][1]);
625 rb = bHL[0]*fabs(roaT[2][2]) + bHL[2]*fabs(roaT[2][0]);
626 t = fabs(aT[1]*roaT[0][1] - aT[0]*roaT[1][1]);
627 if (t > ra + rb)
628 return kOutside;
629 else if (ra < t + rb)
630 return kPartial;
631
632 // A2 x B2
633 ra = aHL[0]*fabs(roaT[1][2]) + aHL[1]*fabs(roaT[0][2]);
634 rb = bHL[0]*fabs(roaT[2][1]) + bHL[1]*fabs(roaT[2][0]);
635 t = fabs(aT[1]*roaT[0][2] - aT[0]*roaT[1][2]);
636 if (t > ra + rb)
637 return kOutside;
638 else if (ra < t + rb)
639 return kPartial;
640
641 // No separating axis - b is inside a
642 return kInside;
643}
644
645////////////////////////////////////////////////////////////////////////////////
646/// Draw the bounding box as either wireframe (default) of solid
647/// using current GL color.
648
650{
651 if (!solid) {
652 glBegin(GL_LINE_LOOP);
653 glVertex3dv(fVertex[0].CArr());
654 glVertex3dv(fVertex[1].CArr());
655 glVertex3dv(fVertex[2].CArr());
656 glVertex3dv(fVertex[3].CArr());
657 glVertex3dv(fVertex[7].CArr());
658 glVertex3dv(fVertex[6].CArr());
659 glVertex3dv(fVertex[5].CArr());
660 glVertex3dv(fVertex[4].CArr());
661 glEnd();
662 glBegin(GL_LINES);
663 glVertex3dv(fVertex[1].CArr());
664 glVertex3dv(fVertex[5].CArr());
665 glVertex3dv(fVertex[2].CArr());
666 glVertex3dv(fVertex[6].CArr());
667 glVertex3dv(fVertex[0].CArr());
668 glVertex3dv(fVertex[3].CArr());
669 glVertex3dv(fVertex[4].CArr());
670 glVertex3dv(fVertex[7].CArr());
671 glEnd();
672 } else {
673 // y
674 // |
675 // |
676 // |________x
677 // / 3-------2
678 // / /| /|
679 // z 7-------6 |
680 // | 0-----|-1
681 // |/ |/
682 // 4-------5
683 // Clockwise winding
685 // Near
686 glNormal3d ( fAxesNorm[2].X(), fAxesNorm[2].Y(), fAxesNorm[2].Z());
687 glVertex3dv(fVertex[4].CArr());
688 glVertex3dv(fVertex[7].CArr());
689 glVertex3dv(fVertex[6].CArr());
690 glVertex3dv(fVertex[5].CArr());
691 // Far
692 glNormal3d (-fAxesNorm[2].X(), -fAxesNorm[2].Y(), -fAxesNorm[2].Z());
693 glVertex3dv(fVertex[0].CArr());
694 glVertex3dv(fVertex[1].CArr());
695 glVertex3dv(fVertex[2].CArr());
696 glVertex3dv(fVertex[3].CArr());
697 // Left
698 glNormal3d (-fAxesNorm[0].X(), -fAxesNorm[0].Y(), -fAxesNorm[0].Z());
699 glVertex3dv(fVertex[0].CArr());
700 glVertex3dv(fVertex[3].CArr());
701 glVertex3dv(fVertex[7].CArr());
702 glVertex3dv(fVertex[4].CArr());
703 // Right
704 glNormal3d ( fAxesNorm[0].X(), fAxesNorm[0].Y(), fAxesNorm[0].Z());
705 glVertex3dv(fVertex[6].CArr());
706 glVertex3dv(fVertex[2].CArr());
707 glVertex3dv(fVertex[1].CArr());
708 glVertex3dv(fVertex[5].CArr());
709 // Top
710 glNormal3d ( fAxesNorm[1].X(), fAxesNorm[1].Y(), fAxesNorm[1].Z());
711 glVertex3dv(fVertex[3].CArr());
712 glVertex3dv(fVertex[2].CArr());
713 glVertex3dv(fVertex[6].CArr());
714 glVertex3dv(fVertex[7].CArr());
715 // Bottom
716 glNormal3d (-fAxesNorm[1].X(), -fAxesNorm[1].Y(), -fAxesNorm[1].Z());
717 glVertex3dv(fVertex[4].CArr());
718 glVertex3dv(fVertex[5].CArr());
719 glVertex3dv(fVertex[1].CArr());
720 glVertex3dv(fVertex[0].CArr());
721
722 glEnd();
723 }
724
725}
726
727////////////////////////////////////////////////////////////////////////////////
728/// Find minimum vertex value for axis of index X(0), Y(1), Z(2)
729
731{
732 Double_t min = fVertex[0][index];
733 for (UInt_t v = 1; v < 8; v++) {
734 if (fVertex[v][index] < min) {
735 min = fVertex[v][index];
736 }
737 }
738 return min;
739}
740
741////////////////////////////////////////////////////////////////////////////////
742/// Find maximum vertex value for axis of index X(0), Y(1), Z(2)
743
745{
746 Double_t max = fVertex[0][index];
747 for (UInt_t v = 1; v < 8; v++) {
748 if (fVertex[v][index] > max) {
749 max = fVertex[v][index];
750 }
751 }
752 return max;
753}
754
755////////////////////////////////////////////////////////////////////////////////
756/// Find minimum vertex values.
757
759{
760 return TGLVertex3(Min(0), Min(1), Min(2));
761}
762
763////////////////////////////////////////////////////////////////////////////////
764/// Find maximum vertex values.
765
767{
768 return TGLVertex3(Max(0), Max(1), Max(2));
769}
770
771////////////////////////////////////////////////////////////////////////////////
772/// Output to std::cout the vertices, center and volume of box
773
775{
776 for (UInt_t i = 0; i<8; i++) {
777 std::cout << "[" << i << "] (" << fVertex[i].X() << "," << fVertex[i].Y() << "," << fVertex[i].Z() << ")" << std::endl;
778 }
779 std::cout << "Center: "; Center().Dump();
780 std::cout << "Extents: "; Extents().Dump();
781 std::cout << "Volume: " << Volume() << std::endl;
782}
783
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
#define X(type, name)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
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
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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
3D plane class - of format Ax + By + Cz + D = 0
Definition TGLUtil.h:525
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:129
void Minimum(const TGLVertex3 &other)
Definition TGLUtil.cxx:110
Double_t X() const
Definition TGLUtil.h:119
Double_t Z() const
Definition TGLUtil.h:123
void Maximum(const TGLVertex3 &other)
Definition TGLUtil.cxx:119
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
EOverlap
Definition TGLUtil.h:35
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124