forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TGLBoundingBox.h
215 lines (186 loc) · 7.54 KB
/
TGLBoundingBox.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// @(#)root/gl:$Id$
// Author: Richard Maunder 25/05/2005
/*************************************************************************
* Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifndef ROOT_TGLBoundingBox
#define ROOT_TGLBoundingBox
#ifndef ROOT_TGLUtil
#include "TGLUtil.h"
#endif
//////////////////////////////////////////////////////////////////////////
// //
// TGLBoundingBox //
// //
// Concrete class describing an orientated (free) or axis aligned box //
// of 8 verticies. Supports methods for setting aligned or orientated //
// boxes, find volume, axes, extents, centers, face planes etc. //
// Also tests for overlap testing of planes and other bounding boxes, //
// with fast sphere approximation. //
//////////////////////////////////////////////////////////////////////////
// TODO: Create more compact version + axis aligned version, both with lazy
// sphere testing.
class TGLBoundingBox
{
private:
// Fields
// Box vertices are indexed thus (OpenGL is left handed by default)
// y
// |
// |
// |________x
// / 3-------2
// / /| /|
// z 7-------6 |
// | 0-----|-1
// |/ |/
// 4-------5
//
// 0123 'far' face
// 4567 'near' face
//
// This could be more compact:
// For orientated box 3 vertices which form plane cutting box
// diagonally (e.g. 0,5,6 or 1,3,6 etc) would fix in space.
// For axis aligned 2 verticies would suffice.
// Rest could be calculated on demand - however speed more important
// than memory considerations
TGLVertex3 fVertex[8]; //! the 8 bounding box vertices
Double_t fVolume; //! box volume - cached for speed
Double_t fDiagonal; //! max box diagonal - cached for speed
TGLVector3 fAxes[3]; //! box axes in global frame - cached for speed
TGLVector3 fAxesNorm[3];//! normalised box axes in global frame - cached for speed
// Methods
void UpdateCache();
Bool_t ValidIndex(UInt_t index) const { return (index < 8); }
Double_t Min(UInt_t index) const;
Double_t Max(UInt_t index) const;
public:
TGLBoundingBox();
TGLBoundingBox(const TGLVertex3 vertex[8]);
TGLBoundingBox(const Double_t vertex[8][3]);
TGLBoundingBox(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex);
TGLBoundingBox(const TGLBoundingBox & other);
virtual ~TGLBoundingBox(); // ClassDef introduces virtual fns
// Set orientated box
TGLBoundingBox & operator =(const TGLBoundingBox & other);
void Set(const TGLVertex3 vertex[8]);
void Set(const Double_t vertex[8][3]);
void Set(const TGLBoundingBox & other);
void SetEmpty();
// Set axis aligned box
void SetAligned(const TGLVertex3 & lowVertex, const TGLVertex3 & highVertex); // axis aligned
void SetAligned(UInt_t nbPnts, const Double_t * pnts); // axis aligned
void MergeAligned(const TGLBoundingBox & other);
void ExpandAligned(const TGLVertex3 & point);
// Manipulation
void Transform(const TGLMatrix & matrix);
void Scale(Double_t factor);
void Scale(Double_t xFactor, Double_t yFactor, Double_t zFactor);
void Translate(const TGLVector3 & offset);
// Single vertex accessors
const TGLVertex3 & operator [] (UInt_t index) const;
const TGLVertex3 & Vertex(UInt_t index) const;
Double_t XMin() const { return Min(0); }
Double_t XMax() const { return Max(0); }
Double_t YMin() const { return Min(1); }
Double_t YMax() const { return Max(1); }
Double_t ZMin() const { return Min(2); }
Double_t ZMax() const { return Max(2); }
TGLVertex3 MinAAVertex() const;
TGLVertex3 MaxAAVertex() const;
// Multiple vertices accessors
const TGLVertex3* Vertices() const; // All 8 box vertices
Int_t NumVertices() const { return 8; }
enum EFace { kFaceLowX, kFaceHighX, kFaceLowY, kFaceHighY, kFaceLowZ, kFaceHighZ, kFaceCount };
const std::vector<UInt_t> & FaceVertices(EFace face) const; // 4 box face vertices
// Other properties
TGLVertex3 Center() const;
TGLVector3 Extents() const;
const TGLVector3 & Axis(UInt_t i, Bool_t normalised = kTRUE) const;
Bool_t IsEmpty() const;
Double_t Volume() const { return fVolume; }
Double_t Diagonal() const { return fDiagonal; }
void PlaneSet(TGLPlaneSet_t & planeSet) const;
TGLPlane GetNearPlane() const;
// Overlap testing
Rgl::EOverlap Overlap(const TGLPlane & plane) const;
Rgl::EOverlap Overlap(const TGLBoundingBox & box) const;
void Draw(Bool_t solid = kFALSE) const;
void Dump() const;
ClassDef(TGLBoundingBox,0); // a 3D orientated bounding box
};
//______________________________________________________________________________
inline TGLBoundingBox & TGLBoundingBox::operator =(const TGLBoundingBox & other)
{
// Check for self-assignment
if (this != &other) {
Set(other);
}
return *this;
}
//______________________________________________________________________________
inline const TGLVertex3 & TGLBoundingBox::operator [] (UInt_t index) const
{
return fVertex[index];
}
//______________________________________________________________________________
inline const TGLVertex3 & TGLBoundingBox::Vertex(UInt_t index) const
{
return fVertex[index];
}
//______________________________________________________________________________
inline const TGLVertex3* TGLBoundingBox::Vertices() const
{
return fVertex;
}
//______________________________________________________________________________
inline TGLVector3 TGLBoundingBox::Extents() const
{
// Return the local axis entents of the box
return TGLVector3(Axis(0,kFALSE).Mag(),
Axis(1,kFALSE).Mag(),
Axis(2,kFALSE).Mag());
}
//______________________________________________________________________________
inline TGLVertex3 TGLBoundingBox::Center() const
{
// Return the center vertex of the box
return TGLVertex3((fVertex[0].X() + fVertex[6].X())/2.0,
(fVertex[0].Y() + fVertex[6].Y())/2.0,
(fVertex[0].Z() + fVertex[6].Z())/2.0);
}
//______________________________________________________________________________
inline const TGLVector3 & TGLBoundingBox::Axis(UInt_t i, Bool_t normalised) const
{
// Return a vector representing axis of index i (0:X, 1:Y, 2:Z).
// Vector can be as-is (edge, magnitude == extent) or normalised (default)
// y
// |
// |
// |________x
// / 3-------2
// / /| /|
// z 7-------6 |
// | 0-----|-1
// |/ |/
// 4-------5
//
if (normalised) {
return fAxesNorm[i];
} else {
return fAxes[i];
}
}
//______________________________________________________________________________
inline Bool_t TGLBoundingBox::IsEmpty() const
{
// Return kTRUE if box has zero diagonal - kFALSE otherwise
// TODO: Round errors - should have epsilon test
return (Diagonal() == 0.0);
}
#endif // ROOT_TGLBoundingBox