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