VR-Forces Development_Version Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
spatialSubdivision.h
Go to the documentation of this file.
1 /*******************************************************************************
2 ** Copyright (c) 2004 MAK Technologies, Inc.
3 ** All rights reserved.
4 *******************************************************************************/
5 /*******************************************************************************
6 ** $RCSfile: spatialSubdivision.h,v $ $Revision: 1.29 $ $State: Exp $
7 *******************************************************************************/
8 #ifndef spatialSubdivision_H_
9 #define spatialSubdivision_H_
10 
11 #include "geometry/point.h"
12 #include "geometry/extent.h"
13 
14 #include <vlutil/vlConfig.h>
15 #include <list>
16 #include <vector>
17 #include <assert.h>
18 
19 #include <vlutil/vlPrint.h>
20 
21 class DtGdbNode;
22 
23 // class DtSpatialSubdivision:
24 //
25 // Instances of DtSpatialSubdivision represent a spatially sorted collection
26 // of cells, which contain the types specified at creation. Each cell in the
27 // rectangular area (or rectangular solid if 3D) will contain a container of
28 // the items referenced in it.
29 //
30 // -------------------
31 // |\ \ \
32 // | \________\________\
33 // | |\ \ \
34 // | | \ \ \
35 // | | \--------\--------\
36 // |\| | | |
37 // | \ | | |
38 // | |\ | | |
39 // | | \ | | |
40 // | | \--------\--------\
41 // \| | | |
42 // \ | | |
43 // \ | | |
44 // \ | | |
45 // \--------\--------\
46 // A 2 x 2 x 2 Spatial Subdivision
47 //
48 // This class provides a minimal interface to make it easy for users to extend
49 // the types of elements contained within it by writing examination and modification
50 // classes outside of this one. Thus no mechanism for examination or
51 // modification, outside of points, is provided.
52 //
53 // This class is *not* threadsafe.
54 //
55 // \b Class Invariant:
56 // A fully constructed spatial subdivision must always respect the following:
57 // - A positive cell size in any dimension where the number of cells is greater
58 // than one.
59 // - The number of cells in each dimension must be greater than or equal to 1 at
60 // all times. The smallest number of cells in any dimension is 1. If a
61 // subdivision is created or resized with an extent that is either
62 // uninitialized or has an empty dimension, the number of cells in that
63 // dimension is still one, and the cell size will be zero.
64 // - The same number of cells in the container as equals the dimensions multiplied
65 // together.
66 //
67 template <typename T>
69 {
70 public:
71  // typedefs for the containers used to hold the contained elements
72  typedef std::list<T> DtSpatialSubCellType;
73  typedef typename DtSpatialSubCellType::iterator DtSpatialSubCellIter;
74  typedef typename DtSpatialSubCellType::const_iterator DtSpatialSubCellConstIter;
75 
76  // As this is a 3D grid, cells can be addressed by indices as well.
77  typedef int DtSpatialSubCellIndex;
78 
79  // Iterators into the spatial subdivision's cells
80  typedef typename std::vector< DtSpatialSubCellType >::iterator DtSpatialSubIter;
81  typedef typename std::vector< DtSpatialSubCellType >::const_iterator DtSpatialSubConstIter;
82 
83 
84  // Intended default constructor
85  // \throws std::bad_alloc if there is not enough memory to allocate the object
87  unsigned int cellCountX,
88  unsigned int cellCountY,
89  unsigned int cellCountZ,
90  double cellDx,
91  double cellDy,
92  double cellDz);
93 
94  // Cover this extent with the given number of cells.
95  // \throws std::bad_alloc if there is not enough memory to allocate the object
96  explicit DtSpatialSubdivision(DtExtent extent,
97  unsigned int cellCountX,
98  unsigned int cellCountY,
99  unsigned int cellCountZ = 1);
100 
101  // Cover this extent with the given cell sizes (in DB units)
102  // \throws std::bad_alloc if there is not enough memory to allocate the object
103  explicit DtSpatialSubdivision(DtExtent extent,
104  double cellDx,
105  double cellDy,
106  double cellDz = -1.0);
107 
108  // Destructor
109  virtual ~DtSpatialSubdivision();
110 
111 private:
112  // Copy constructor & Assignment operator - not implemented
115 
116 public:
117 
118  // Resizes the spatial subdivision to fit the specified extent. This function
119  // clears the contents of the subdivision, and updates the cell sizes and origin
120  // with the specified extent.
121  virtual void setExtent(DtExtent extent);
122 
123  // Warning: clears all contents!
124  // Resets the cell counts of the spatial subdivision to the specified values,
125  // reallocating the memory associated if necessary.
126  //
127  // \implementation As an optimization, it will not reallocate if the total
128  // cell count is the same as before, even if the resolutions are actually
129  // different. Thus if the previous resolutions were 10,15,1 and the new
130  // resolutions are 15,10,1, no reallocation will occur.
131  //
132  // \note The minimum resolution is 1, which will be used if 0 is specified.
133  virtual void setResolutions(unsigned int cellCountX, unsigned int cellCountY,
134  unsigned int cellCountZ = 1);
135 
136  // Resizes the spatial subdivision to fit the specified extent. This function
137  // clears the contents of the subdivision, and updates the cell sizes and origin
138  // with the specified extent.
139  // This function will \b only reallocate the container of cells when the
140  // requested cell count total differs from the existing cell count total.
141  //
142  // \note Thus if a subdivision is resized from 10,10,1 to 10,1,10, the cells
143  // will only be cleared, not reallocated. This is meant as a possible
144  // optimization when it is possible to reuse an existing container.
145  virtual void resize(DtExtent extent, unsigned int cellCountX,
146  unsigned int cellCountY, unsigned int cellCountZ);
147 
148  // Empties the entire spatial subdivision, removing all contents
149  // \note Does not deallocate the container, just clears the contents
150  // of the cells.
151  virtual void clear();
152 
153  // Clears the cells referenced by the specified iterators.
154  // \note The template type must support the clear() function, as
155  // this function will call clear() on all cells at or between the
156  // specified iterators.
157  virtual void clearCell(DtSpatialSubIter& cellIter);
158  virtual void clearCell(DtSpatialSubIter& startIter, DtSpatialSubIter& endIter);
159 
160  // \return A boolean indicating whether or not anything is contained
161  // in the subdivision
162  virtual bool empty() const;
163 
164  // \return the total number of cells in the subdivision
165  virtual unsigned int size() const;
166 
167  //
168  // Accessors
169  //
170  // \return iterators to the first and last cells respectively.
172  virtual DtSpatialSubIter begin();
173  virtual DtSpatialSubConstIter begin() const;
174 
175  virtual DtSpatialSubIter end();
176  virtual DtSpatialSubConstIter end() const;
178 
179  // \return an iterator to the spatial subdivision cell at the specified index,
180  // if the index is valid.
181  // \note the results are undefined if the index is outside of the range of the
182  // spatial subdivision's cells. (technically, this just passes the index
183  // down to the std::vector at() call, so it will throw a range error exception.)
184  //
187  virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex index) const;
188 
191  virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex xIndex,
192  DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
194 
195  // \return an iterator to the spatial subdivision cell at the specified index,
196  // \note Does \b not check if the index is valid or not.
199  virtual const DtSpatialSubCellType& operator[](DtSpatialSubCellIndex index) const;
201 
202 
203  // \return a reference (const or not) to the first or last spatial subdivision cell
204  // in the spatial subdivision.
205  // \note User \b must ensure the spatial subdivision is \b not empty before
206  // calling these functions.
208  virtual DtSpatialSubCellType& front();
209  virtual const DtSpatialSubCellType& front() const;
210 
211  virtual DtSpatialSubCellType& back();
212  virtual const DtSpatialSubCellType& back() const;
214 
215  // Get/Set the origin of the spatial index (the point of lowest X, Y, Z)
217  virtual const DtPoint& origin() const;
218  virtual void setOrigin(const DtPoint& newOrigin);
220 
221  // \return the cell count in the specified dimension.
223  virtual unsigned int cellCountX() const;
224  virtual unsigned int cellCountY() const;
225  virtual unsigned int cellCountZ() const;
227 
228  // \return the size of each cell in the specified dimension.
230  virtual double cellDx() const;
231  virtual double cellDy() const;
232  virtual double cellDz() const;
234 
235  // Get the cell that contains the given coordinate if the coordinate lies
236  // within the spatial subdivision.
237  //
238  // If the specified point lies within the spatial subdivision, the
239  // function sets the specified point to point to the cell and returns true.
240  //
241  // \return A boolean indicating whether or not the point lies within the
242  // spatial subdivision. If it does not, the cell pointer is not set.
244  virtual bool cell(double x, double y, double z, DtSpatialSubCellType*& cell);
245  virtual bool cell(double x, double y, double z, const DtSpatialSubCellType*& cell) const;
246 
247  virtual bool cell(const DtPoint& containing, DtSpatialSubCellType*& cell);
248  virtual bool cell(const DtPoint& containing, const DtSpatialSubCellType*& cell) const;
250 
251  // Given an offset vector (local coordinate - origin), return the cell
252  // index values.
253  //
254  // \param xIndex The index in X, of the specified point. Set by the function.
255  // \param yIndex The index in Y, of the specified point. Set by the function.
256  // \param zIndex The index in Z, of the specified point. Set by the function.
257  //
258  // \note There is no guarantee that the resulting indices are inside the spatial
259  // subdivision.
260  virtual void offsetToIndices(const DtPoint& offset, DtSpatialSubCellIndex& xIndex,
261  DtSpatialSubCellIndex& yIndex, DtSpatialSubCellIndex& zIndex) const;
262 
263  // Check if the given index values are within the spatial subdivision
264  // \return a boolean signifying whether or not the specified index/indices
265  // are valid (refer to cells inside the spatial subdivision)
266  virtual bool indexIsValid(DtSpatialSubCellIndex index) const;
267  virtual bool indicesAreValid(DtSpatialSubCellIndex xIndex,
268  DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
269 
270  virtual int sizeInBytes() const;
271 
272 protected:
273  // Tests the class invariant. Called at the beginning of every public
274  // member function and at the end of all non-const public member functions.
275  bool testInvariant() const;
276 
277 protected:
278  // \return the inverse of the size of each cell in the specified dimension.
279  // \note If the dimension is 0, then the function returns 0.0 as a default.
280  // \note These should not be called when the dimension is 0, even though they
281  // return 0.0 to be safe.
283  double inverseCellDx() const;
284  double inverseCellDy() const;
285  double inverseCellDz() const;
287 
289  // Calculates the minimum and maximum sizes, in each dimension, of any offset
290  // that is to be translated into an index. An offset that contains any
291  // dimension larger or smaller (negative) than these will result in rollover
292  // problems and the wrong index being calculated. Since this is a function
293  // of std::limits<>max() and the cell delta in the appropriate dimension
294  void calculateMinMaxOffsets();
295 
296  // Calculates the inverse of the cell deltas in each dimension. Used every time
297  // an index is calculated from an offset.
298  void calculateInverseDeltas();
299 
301 
302  unsigned int myCellCountX;
303  unsigned int myCellCountY;
304  unsigned int myCellCountZ;
305 
306  double myCellDx;
307  double myCellDy;
308  double myCellDz;
309 
310  // These are used instead of dividing when calculating indexes from an offset
314 
315  // These are the maximum sizes, in each dimension, of any offset that is to
316  // be translated into and index. An offset that contains any dimension larger
317  // than these will result in rollover problems and the wrong index being
318  // calculated.
319  double myMaxOffsetX;
320  double myMaxOffsetY;
321  double myMaxOffsetZ;
322 
323  double myMinOffsetX;
324  double myMinOffsetY;
325  double myMinOffsetZ;
326 
327  std::vector< DtSpatialSubCellType > myCells;
328 };
329 
330 
331 //------------------------------------------------------
332 // INLINE METHODS
333 //------------------------------------------------------
334 // include the inline code
335 #define SPATIALSUBDIVISION_HEADER
336 #include "geometry/spatialSubdivision.inl"
337 #undef SPATIALSUBDIVISION_HEADER
338 
339 #endif

Document ID: Generated on Mon Jul 4 01:00:18 EDT 2016 from SVN revision 166489
Copyright © 2005-2015 VT MÄK. All Rights Reserved (www.mak.com)