VR-Forces 4.7 Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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 public:
112 
113  // Resizes the spatial subdivision to fit the specified extent. This function
114  // clears the contents of the subdivision, and updates the cell sizes and origin
115  // with the specified extent.
116  virtual void setExtent(DtExtent extent);
117 
118  // Warning: clears all contents!
119  // Resets the cell counts of the spatial subdivision to the specified values,
120  // reallocating the memory associated if necessary.
121  //
122  // \implementation As an optimization, it will not reallocate if the total
123  // cell count is the same as before, even if the resolutions are actually
124  // different. Thus if the previous resolutions were 10,15,1 and the new
125  // resolutions are 15,10,1, no reallocation will occur.
126  //
127  // \note The minimum resolution is 1, which will be used if 0 is specified.
128  virtual void setResolutions(unsigned int cellCountX, unsigned int cellCountY,
129  unsigned int cellCountZ = 1);
130 
131  // Resizes the spatial subdivision to fit the specified extent. This function
132  // clears the contents of the subdivision, and updates the cell sizes and origin
133  // with the specified extent.
134  // This function will \b only reallocate the container of cells when the
135  // requested cell count total differs from the existing cell count total.
136  //
137  // \note Thus if a subdivision is resized from 10,10,1 to 10,1,10, the cells
138  // will only be cleared, not reallocated. This is meant as a possible
139  // optimization when it is possible to reuse an existing container.
140  virtual void resize(DtExtent extent, unsigned int cellCountX,
141  unsigned int cellCountY, unsigned int cellCountZ);
142 
143  // Empties the entire spatial subdivision, removing all contents
144  // \note Does not deallocate the container, just clears the contents
145  // of the cells.
146  virtual void clear();
147 
148  // Clears the cells referenced by the specified iterators.
149  // \note The template type must support the clear() function, as
150  // this function will call clear() on all cells at or between the
151  // specified iterators.
152  virtual void clearCell(DtSpatialSubIter& cellIter);
153  virtual void clearCell(DtSpatialSubIter& startIter, DtSpatialSubIter& endIter);
154 
155  // \return A boolean indicating whether or not anything is contained
156  // in the subdivision
157  virtual bool empty() const;
158 
159  // \return the total number of cells in the subdivision
160  virtual unsigned int size() const;
161 
162  //
163  // Accessors
164  //
165  // \return iterators to the first and last cells respectively.
167  virtual DtSpatialSubIter begin();
168  virtual DtSpatialSubConstIter begin() const;
169 
170  virtual DtSpatialSubIter end();
171  virtual DtSpatialSubConstIter end() const;
173 
174  // \return an iterator to the spatial subdivision cell at the specified index,
175  // if the index is valid.
176  // \note the results are undefined if the index is outside of the range of the
177  // spatial subdivision's cells. (technically, this just passes the index
178  // down to the std::vector at() call, so it will throw a range error exception.)
179  //
182  virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex index) const;
183 
186  virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex xIndex,
187  DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
189 
190  // \return an iterator to the spatial subdivision cell at the specified index,
191  // \note Does \b not check if the index is valid or not.
194  virtual const DtSpatialSubCellType& operator[](DtSpatialSubCellIndex index) const;
196 
197 
198  // \return a reference (const or not) to the first or last spatial subdivision cell
199  // in the spatial subdivision.
200  // \note User \b must ensure the spatial subdivision is \b not empty before
201  // calling these functions.
203  virtual DtSpatialSubCellType& front();
204  virtual const DtSpatialSubCellType& front() const;
205 
206  virtual DtSpatialSubCellType& back();
207  virtual const DtSpatialSubCellType& back() const;
209 
210  // Get/Set the origin of the spatial index (the point of lowest X, Y, Z)
212  virtual const DtPoint& origin() const;
213  virtual void setOrigin(const DtPoint& newOrigin);
215 
216  // \return the cell count in the specified dimension.
218  virtual unsigned int cellCountX() const;
219  virtual unsigned int cellCountY() const;
220  virtual unsigned int cellCountZ() const;
222 
223  // \return the size of each cell in the specified dimension.
225  virtual double cellDx() const;
226  virtual double cellDy() const;
227  virtual double cellDz() const;
229 
230  // Get the cell that contains the given coordinate if the coordinate lies
231  // within the spatial subdivision.
232  //
233  // If the specified point lies within the spatial subdivision, the
234  // function sets the specified point to point to the cell and returns true.
235  //
236  // \return A boolean indicating whether or not the point lies within the
237  // spatial subdivision. If it does not, the cell pointer is not set.
239  virtual bool cell(double x, double y, double z, DtSpatialSubCellType*& cell);
240  virtual bool cell(double x, double y, double z, const DtSpatialSubCellType*& cell) const;
241 
242  virtual bool cell(const DtPoint& containing, DtSpatialSubCellType*& cell);
243  virtual bool cell(const DtPoint& containing, const DtSpatialSubCellType*& cell) const;
245 
246  // Given an offset vector (local coordinate - origin), return the cell
247  // index values.
248  //
249  // \param xIndex The index in X, of the specified point. Set by the function.
250  // \param yIndex The index in Y, of the specified point. Set by the function.
251  // \param zIndex The index in Z, of the specified point. Set by the function.
252  //
253  // \note There is no guarantee that the resulting indices are inside the spatial
254  // subdivision.
255  virtual void offsetToIndices(const DtPoint& offset, DtSpatialSubCellIndex& xIndex,
256  DtSpatialSubCellIndex& yIndex, DtSpatialSubCellIndex& zIndex) const;
257 
258  // Check if the given index values are within the spatial subdivision
259  // \return a boolean signifying whether or not the specified index/indices
260  // are valid (refer to cells inside the spatial subdivision)
261  virtual bool indexIsValid(DtSpatialSubCellIndex index) const;
262  virtual bool indicesAreValid(DtSpatialSubCellIndex xIndex,
263  DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
264 
265  virtual int sizeInBytes() const;
266 
267 protected:
268  // Tests the class invariant. Called at the beginning of every public
269  // member function and at the end of all non-const public member functions.
270  bool testInvariant() const;
271 
272 protected:
273  // \return the inverse of the size of each cell in the specified dimension.
274  // \note If the dimension is 0, then the function returns 0.0 as a default.
275  // \note These should not be called when the dimension is 0, even though they
276  // return 0.0 to be safe.
278  double inverseCellDx() const;
279  double inverseCellDy() const;
280  double inverseCellDz() const;
282 
284  // Calculates the minimum and maximum sizes, in each dimension, of any offset
285  // that is to be translated into an index. An offset that contains any
286  // dimension larger or smaller (negative) than these will result in rollover
287  // problems and the wrong index being calculated. Since this is a function
288  // of std::limits<>max() and the cell delta in the appropriate dimension
289  void calculateMinMaxOffsets();
290 
291  // Calculates the inverse of the cell deltas in each dimension. Used every time
292  // an index is calculated from an offset.
293  void calculateInverseDeltas();
294 
296 
297  unsigned int myCellCountX;
298  unsigned int myCellCountY;
299  unsigned int myCellCountZ;
300 
301  double myCellDx;
302  double myCellDy;
303  double myCellDz;
304 
305  // These are used instead of dividing when calculating indexes from an offset
309 
310  // These are the maximum sizes, in each dimension, of any offset that is to
311  // be translated into and index. An offset that contains any dimension larger
312  // than these will result in rollover problems and the wrong index being
313  // calculated.
314  double myMaxOffsetX;
315  double myMaxOffsetY;
316  double myMaxOffsetZ;
317 
318  double myMinOffsetX;
319  double myMinOffsetY;
320  double myMinOffsetZ;
321 
322  std::vector< DtSpatialSubCellType > myCells;
323 };
324 
325 
326 //------------------------------------------------------
327 // INLINE METHODS
328 //------------------------------------------------------
329 // include the inline code
330 #define SPATIALSUBDIVISION_HEADER
331 #include "geometry/spatialSubdivision.inl"
332 #undef SPATIALSUBDIVISION_HEADER
333 
334 #endif

Document ID: Generated on Fri Apr 26 21:53:14 EDT 2019 from SVN revision 197883
Copyright © 2005-2019 VT MAK. All Rights Reserved (www.mak.com)