// @(#)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
 TGLBoundingBox.h:1
 TGLBoundingBox.h:2
 TGLBoundingBox.h:3
 TGLBoundingBox.h:4
 TGLBoundingBox.h:5
 TGLBoundingBox.h:6
 TGLBoundingBox.h:7
 TGLBoundingBox.h:8
 TGLBoundingBox.h:9
 TGLBoundingBox.h:10
 TGLBoundingBox.h:11
 TGLBoundingBox.h:12
 TGLBoundingBox.h:13
 TGLBoundingBox.h:14
 TGLBoundingBox.h:15
 TGLBoundingBox.h:16
 TGLBoundingBox.h:17
 TGLBoundingBox.h:18
 TGLBoundingBox.h:19
 TGLBoundingBox.h:20
 TGLBoundingBox.h:21
 TGLBoundingBox.h:22
 TGLBoundingBox.h:23
 TGLBoundingBox.h:24
 TGLBoundingBox.h:25
 TGLBoundingBox.h:26
 TGLBoundingBox.h:27
 TGLBoundingBox.h:28
 TGLBoundingBox.h:29
 TGLBoundingBox.h:30
 TGLBoundingBox.h:31
 TGLBoundingBox.h:32
 TGLBoundingBox.h:33
 TGLBoundingBox.h:34
 TGLBoundingBox.h:35
 TGLBoundingBox.h:36
 TGLBoundingBox.h:37
 TGLBoundingBox.h:38
 TGLBoundingBox.h:39
 TGLBoundingBox.h:40
 TGLBoundingBox.h:41
 TGLBoundingBox.h:42
 TGLBoundingBox.h:43
 TGLBoundingBox.h:44
 TGLBoundingBox.h:45
 TGLBoundingBox.h:46
 TGLBoundingBox.h:47
 TGLBoundingBox.h:48
 TGLBoundingBox.h:49
 TGLBoundingBox.h:50
 TGLBoundingBox.h:51
 TGLBoundingBox.h:52
 TGLBoundingBox.h:53
 TGLBoundingBox.h:54
 TGLBoundingBox.h:55
 TGLBoundingBox.h:56
 TGLBoundingBox.h:57
 TGLBoundingBox.h:58
 TGLBoundingBox.h:59
 TGLBoundingBox.h:60
 TGLBoundingBox.h:61
 TGLBoundingBox.h:62
 TGLBoundingBox.h:63
 TGLBoundingBox.h:64
 TGLBoundingBox.h:65
 TGLBoundingBox.h:66
 TGLBoundingBox.h:67
 TGLBoundingBox.h:68
 TGLBoundingBox.h:69
 TGLBoundingBox.h:70
 TGLBoundingBox.h:71
 TGLBoundingBox.h:72
 TGLBoundingBox.h:73
 TGLBoundingBox.h:74
 TGLBoundingBox.h:75
 TGLBoundingBox.h:76
 TGLBoundingBox.h:77
 TGLBoundingBox.h:78
 TGLBoundingBox.h:79
 TGLBoundingBox.h:80
 TGLBoundingBox.h:81
 TGLBoundingBox.h:82
 TGLBoundingBox.h:83
 TGLBoundingBox.h:84
 TGLBoundingBox.h:85
 TGLBoundingBox.h:86
 TGLBoundingBox.h:87
 TGLBoundingBox.h:88
 TGLBoundingBox.h:89
 TGLBoundingBox.h:90
 TGLBoundingBox.h:91
 TGLBoundingBox.h:92
 TGLBoundingBox.h:93
 TGLBoundingBox.h:94
 TGLBoundingBox.h:95
 TGLBoundingBox.h:96
 TGLBoundingBox.h:97
 TGLBoundingBox.h:98
 TGLBoundingBox.h:99
 TGLBoundingBox.h:100
 TGLBoundingBox.h:101
 TGLBoundingBox.h:102
 TGLBoundingBox.h:103
 TGLBoundingBox.h:104
 TGLBoundingBox.h:105
 TGLBoundingBox.h:106
 TGLBoundingBox.h:107
 TGLBoundingBox.h:108
 TGLBoundingBox.h:109
 TGLBoundingBox.h:110
 TGLBoundingBox.h:111
 TGLBoundingBox.h:112
 TGLBoundingBox.h:113
 TGLBoundingBox.h:114
 TGLBoundingBox.h:115
 TGLBoundingBox.h:116
 TGLBoundingBox.h:117
 TGLBoundingBox.h:118
 TGLBoundingBox.h:119
 TGLBoundingBox.h:120
 TGLBoundingBox.h:121
 TGLBoundingBox.h:122
 TGLBoundingBox.h:123
 TGLBoundingBox.h:124
 TGLBoundingBox.h:125
 TGLBoundingBox.h:126
 TGLBoundingBox.h:127
 TGLBoundingBox.h:128
 TGLBoundingBox.h:129
 TGLBoundingBox.h:130
 TGLBoundingBox.h:131
 TGLBoundingBox.h:132
 TGLBoundingBox.h:133
 TGLBoundingBox.h:134
 TGLBoundingBox.h:135
 TGLBoundingBox.h:136
 TGLBoundingBox.h:137
 TGLBoundingBox.h:138
 TGLBoundingBox.h:139
 TGLBoundingBox.h:140
 TGLBoundingBox.h:141
 TGLBoundingBox.h:142
 TGLBoundingBox.h:143
 TGLBoundingBox.h:144
 TGLBoundingBox.h:145
 TGLBoundingBox.h:146
 TGLBoundingBox.h:147
 TGLBoundingBox.h:148
 TGLBoundingBox.h:149
 TGLBoundingBox.h:150
 TGLBoundingBox.h:151
 TGLBoundingBox.h:152
 TGLBoundingBox.h:153
 TGLBoundingBox.h:154
 TGLBoundingBox.h:155
 TGLBoundingBox.h:156
 TGLBoundingBox.h:157
 TGLBoundingBox.h:158
 TGLBoundingBox.h:159
 TGLBoundingBox.h:160
 TGLBoundingBox.h:161
 TGLBoundingBox.h:162
 TGLBoundingBox.h:163
 TGLBoundingBox.h:164
 TGLBoundingBox.h:165
 TGLBoundingBox.h:166
 TGLBoundingBox.h:167
 TGLBoundingBox.h:168
 TGLBoundingBox.h:169
 TGLBoundingBox.h:170
 TGLBoundingBox.h:171
 TGLBoundingBox.h:172
 TGLBoundingBox.h:173
 TGLBoundingBox.h:174
 TGLBoundingBox.h:175
 TGLBoundingBox.h:176
 TGLBoundingBox.h:177
 TGLBoundingBox.h:178
 TGLBoundingBox.h:179
 TGLBoundingBox.h:180
 TGLBoundingBox.h:181
 TGLBoundingBox.h:182
 TGLBoundingBox.h:183
 TGLBoundingBox.h:184
 TGLBoundingBox.h:185
 TGLBoundingBox.h:186
 TGLBoundingBox.h:187
 TGLBoundingBox.h:188
 TGLBoundingBox.h:189
 TGLBoundingBox.h:190
 TGLBoundingBox.h:191
 TGLBoundingBox.h:192
 TGLBoundingBox.h:193
 TGLBoundingBox.h:194
 TGLBoundingBox.h:195
 TGLBoundingBox.h:196
 TGLBoundingBox.h:197
 TGLBoundingBox.h:198
 TGLBoundingBox.h:199
 TGLBoundingBox.h:200
 TGLBoundingBox.h:201
 TGLBoundingBox.h:202
 TGLBoundingBox.h:203
 TGLBoundingBox.h:204
 TGLBoundingBox.h:205
 TGLBoundingBox.h:206
 TGLBoundingBox.h:207
 TGLBoundingBox.h:208
 TGLBoundingBox.h:209
 TGLBoundingBox.h:210
 TGLBoundingBox.h:211
 TGLBoundingBox.h:212
 TGLBoundingBox.h:213
 TGLBoundingBox.h:214
 TGLBoundingBox.h:215