VR-Forces 4.0.4 Class Documentation
include/geometry/spatialSubdivision.h
Go to the documentation of this file.
00001 /*******************************************************************************
00002 ** Copyright (c) 2004 MAK Technologies, Inc.
00003 ** All rights reserved.
00004 *******************************************************************************/
00005 /*******************************************************************************
00006 ** $RCSfile: spatialSubdivision.h,v $ $Revision: 1.29 $ $State: Exp $
00007 *******************************************************************************/
00008 #ifndef spatialSubdivision_H_
00009 #define spatialSubdivision_H_
00010 
00011 #include "geometry/point.h"
00012 #include "geometry/tdbextent.h"
00013 
00014 #include <vlutil/vlConfig.h> 
00015 #include <list>
00016 #include <vector>
00017 #include <assert.h>
00018 
00019 #include <vlutil/vlPrint.h>
00020 
00021 class DtGdbNode;
00022 
00023 // class DtSpatialSubdivision:
00024 //
00025 // Instances of DtSpatialSubdivision represent a spatially sorted collection
00026 // of cells, which contain the types specified at creation.  Each cell in the 
00027 // rectangular area (or rectangular solid if 3D) will contain a container of 
00028 // the items referenced in it.
00029 //
00030 // -------------------
00031 // |\        \        \
00032 // | \________\________\
00033 // | |\        \        \
00034 // | | \        \        \
00035 // | |  \--------\--------\
00036 // |\|   |       |        |
00037 // | \   |       |        |
00038 // | |\  |       |        |
00039 // | | \ |       |        |
00040 // | |  \--------\--------\
00041 //  \|   |       |        |
00042 //   \   |       |        |
00043 //    \  |       |        |
00044 //     \ |       |        |
00045 //      \--------\--------\
00046 //       A 2 x 2 x 2 Spatial Subdivision
00047 //
00048 // This class provides a minimal interface to make it easy for users to extend
00049 // the types of elements contained within it by writing examination and modification
00050 // classes outside of this one.  Thus no mechanism for examination or 
00051 // modification, outside of points, is provided.  
00052 // 
00053 // This class is *not* threadsafe.
00054 // 
00055 // \b Class Invariant:
00056 // A fully constructed spatial subdivision must always respect the following:
00057 // - A positive cell size in any dimension where the number of cells is greater 
00058 //   than one. 
00059 // - The number of cells in each dimension must be greater than or equal to 1 at 
00060 //   all times.  The smallest number of cells in any dimension is 1.  If a 
00061 //   subdivision is created or resized with an extent that is either 
00062 //   uninitialized or has an empty dimension, the number of cells in that 
00063 //   dimension is still one, and the cell size will be zero.
00064 // - The same number of cells in the container as equals the dimensions multiplied
00065 //   together.
00066 // 
00067 template <typename T>
00068 class DtSpatialSubdivision
00069 {
00070 public:
00071    // typedefs for the containers used to hold the contained elements
00072    typedef std::list<T> DtSpatialSubCellType;
00073    typedef typename DtSpatialSubCellType::iterator DtSpatialSubCellIter;
00074    typedef typename DtSpatialSubCellType::const_iterator DtSpatialSubCellConstIter;
00075 
00076    // As this is a 3D grid, cells can be addressed by indices as well.  
00077    typedef int DtSpatialSubCellIndex;
00078    
00079    // Iterators into the spatial subdivision's cells
00080    typedef typename std::vector< DtSpatialSubCellType >::iterator DtSpatialSubIter;
00081    typedef typename std::vector< DtSpatialSubCellType >::const_iterator DtSpatialSubConstIter;
00082 
00083 
00084    // Intended default constructor
00085    // \throws std::bad_alloc if there is not enough memory to allocate the object
00086    DtSpatialSubdivision(const DtPoint& origin, 
00087                         unsigned int cellCountX, 
00088                         unsigned int cellCountY, 
00089                         unsigned int cellCountZ,
00090                         double cellDx, 
00091                         double cellDy, 
00092                         double cellDz);
00093 
00094    // Cover this extent with the given number of cells.
00095    // \throws std::bad_alloc if there is not enough memory to allocate the object
00096    explicit DtSpatialSubdivision(DtExtent extent, 
00097                                  unsigned int cellCountX, 
00098                                  unsigned int cellCountY, 
00099                                  unsigned int cellCountZ = 1);
00100 
00101    // Cover this extent with the given cell sizes (in DB units)
00102    // \throws std::bad_alloc if there is not enough memory to allocate the object
00103    explicit DtSpatialSubdivision(DtExtent extent, 
00104                                  double cellDx, 
00105                                  double cellDy,
00106                                  double cellDz = -1.0);
00107 
00108    // Destructor
00109    virtual ~DtSpatialSubdivision();
00110 
00111 private:
00112    // Copy constructor & Assignment operator  - not implemented
00113    DtSpatialSubdivision(const DtSpatialSubdivision& orig);
00114    DtSpatialSubdivision& operator=(const DtSpatialSubdivision& orig);
00115 
00116 public:
00117 
00118    // Resizes the spatial subdivision to fit the specified extent.  This function
00119    // clears the contents of the subdivision, and updates the cell sizes and origin
00120    // with the specified extent. 
00121    virtual void setExtent(DtExtent extent);
00122 
00123    // Warning:  clears all contents!
00124    // Resets the cell counts of the spatial subdivision to the specified values,
00125    // reallocating the memory associated if necessary.
00126    //
00127    // \implementation As an optimization, it will not reallocate if the total 
00128    // cell count is the same as before, even if the resolutions are actually
00129    // different.  Thus if the previous resolutions were 10,15,1 and the new 
00130    // resolutions are 15,10,1, no reallocation will occur.  
00131    //
00132    // \note The minimum resolution is 1, which will be used if 0 is specified.
00133    virtual void setResolutions(unsigned int cellCountX, unsigned int cellCountY, 
00134       unsigned int cellCountZ = 1);
00135 
00136    // Resizes the spatial subdivision to fit the specified extent.  This function
00137    // clears the contents of the subdivision, and updates the cell sizes and origin
00138    // with the specified extent.  
00139    // This function will \b only reallocate the container of cells when the 
00140    // requested cell count total differs from the existing cell count total.  
00141    // 
00142    // \note Thus if a subdivision is resized from 10,10,1 to 10,1,10, the cells 
00143    // will only be cleared, not reallocated.  This is meant as a possible 
00144    // optimization when it is possible to reuse an existing container.
00145    virtual void resize(DtExtent extent, unsigned int cellCountX, 
00146                        unsigned int cellCountY, unsigned int cellCountZ);
00147 
00148    // Empties the entire spatial subdivision, removing all contents
00149    // \note Does not deallocate the container, just clears the contents
00150    // of the cells.
00151    virtual void clear();
00152 
00153    // Clears the cells referenced by the specified iterators.
00154    // \note The template type must support the clear() function, as
00155    // this function will call clear() on all cells at or between the 
00156    // specified iterators.
00157    virtual void clearCell(DtSpatialSubIter& cellIter);
00158    virtual void clearCell(DtSpatialSubIter& startIter, DtSpatialSubIter& endIter);
00159 
00160    // \return A boolean indicating whether or not anything is contained
00161    // in the subdivision
00162    virtual bool empty() const;
00163 
00164    // \return the total number of cells in the subdivision
00165    virtual unsigned int size() const;
00166 
00167    //
00168    // Accessors
00169    //
00170    // \return iterators to the first and last cells respectively.
00172    virtual DtSpatialSubIter begin();
00173    virtual DtSpatialSubConstIter begin() const;
00174 
00175    virtual DtSpatialSubIter end();
00176    virtual DtSpatialSubConstIter end() const;
00178 
00179    // \return an iterator to the spatial subdivision cell at the specified index, 
00180    // if the index is valid.
00181    // \note the results are undefined if the index is outside of the range of the
00182    // spatial subdivision's cells.  (technically, this just passes the index 
00183    // down to the std::vector at() call, so it will throw a range error exception.)
00184    // 
00186    virtual DtSpatialSubCellType& at(DtSpatialSubCellIndex index);
00187    virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex index) const;
00188 
00189    virtual DtSpatialSubCellType& at(DtSpatialSubCellIndex xIndex, 
00190       DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex);
00191    virtual const DtSpatialSubCellType& at(DtSpatialSubCellIndex xIndex, 
00192       DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
00194 
00195    // \return an iterator to the spatial subdivision cell at the specified index, 
00196    // \note Does \b not check if the index is valid or not.
00198    virtual DtSpatialSubCellType& operator[](DtSpatialSubCellIndex index);
00199    virtual const DtSpatialSubCellType& operator[](DtSpatialSubCellIndex index) const;
00201 
00202 
00203    // \return a reference (const or not) to the first or last spatial subdivision cell 
00204    // in the spatial subdivision.  
00205    // \note User \b must ensure the spatial subdivision is \b not empty before 
00206    // calling these functions.
00208    virtual DtSpatialSubCellType& front();
00209    virtual const DtSpatialSubCellType& front() const;
00210 
00211    virtual DtSpatialSubCellType& back();
00212    virtual const DtSpatialSubCellType& back() const;
00214 
00215    // Get/Set the origin of the spatial index (the point of lowest X, Y, Z)
00217    virtual const DtPoint& origin() const;
00218    virtual void setOrigin(const DtPoint& newOrigin);
00220 
00221    // \return the cell count in the specified dimension.
00223    virtual unsigned int cellCountX() const;
00224    virtual unsigned int cellCountY() const;
00225    virtual unsigned int cellCountZ() const;
00227 
00228    // \return the size of each cell in the specified dimension.
00230    virtual double cellDx() const;
00231    virtual double cellDy() const;
00232    virtual double cellDz() const;
00234 
00235    // Get the cell that contains the given coordinate if the coordinate lies
00236    // within the spatial subdivision.
00237    // 
00238    // If the specified point lies within the spatial subdivision, the 
00239    // function sets the specified point to point to the cell and returns true.
00240    //
00241    // \return A boolean indicating whether or not the point lies within the 
00242    // spatial subdivision.  If it does not, the cell pointer is not set.
00244    virtual bool cell(double x, double y, double z, DtSpatialSubCellType*& cell);
00245    virtual bool cell(double x, double y, double z, const DtSpatialSubCellType*& cell) const;
00246 
00247    virtual bool cell(const DtPoint& containing, DtSpatialSubCellType*& cell);
00248    virtual bool cell(const DtPoint& containing, const DtSpatialSubCellType*& cell) const;
00250 
00251    // Given an offset vector (local coordinate - origin), return the cell
00252    // index values.  
00253    //
00254    // \param xIndex The index in X, of the specified point.  Set by the function.
00255    // \param yIndex The index in Y, of the specified point.  Set by the function.
00256    // \param zIndex The index in Z, of the specified point.  Set by the function.
00257    //
00258    // \note There is no guarantee that the resulting indices are inside the spatial 
00259    // subdivision.
00260    virtual void offsetToIndices(const DtPoint& offset, DtSpatialSubCellIndex& xIndex, 
00261                                 DtSpatialSubCellIndex& yIndex, DtSpatialSubCellIndex& zIndex) const;
00262 
00263    // Check if the given index values are within the spatial subdivision
00264    // \return a boolean signifying whether or not the specified index/indices
00265    // are valid (refer to cells inside the spatial subdivision)
00266    virtual bool indexIsValid(DtSpatialSubCellIndex index) const;
00267    virtual bool indicesAreValid(DtSpatialSubCellIndex xIndex, 
00268       DtSpatialSubCellIndex yIndex, DtSpatialSubCellIndex zIndex) const;
00269 
00270    virtual int sizeInBytes() const;
00271 
00272 protected:
00273    // Tests the class invariant.  Called at the beginning of every public 
00274    // member function and at the end of all non-const public member functions.
00275    bool testInvariant() const;
00276 
00277 protected:
00278    // \return the inverse of the size of each cell in the specified dimension.
00279    // \note If the dimension is 0, then the function returns 0.0 as a default.
00280    // \note These should not be called when the dimension is 0, even though they
00281    // return 0.0 to be safe.
00283    double inverseCellDx() const;
00284    double inverseCellDy() const;
00285    double inverseCellDz() const;
00287 
00289    // Calculates the minimum and maximum sizes, in each dimension, of any offset 
00290    // that is to be translated into an index.  An offset that contains any 
00291    // dimension larger or smaller (negative) than these will result in rollover 
00292    // problems and the wrong index being calculated.  Since this is a function 
00293    // of std::limits<>max() and the cell delta in the appropriate dimension
00294    void calculateMinMaxOffsets();
00295 
00296    // Calculates the inverse of the cell deltas in each dimension.  Used every time
00297    // an index is calculated from an offset.
00298    void calculateInverseDeltas();
00299 
00300    DtPoint myOrigin;
00301 
00302    unsigned int myCellCountX;
00303    unsigned int myCellCountY;
00304    unsigned int myCellCountZ;
00305 
00306    double myCellDx;
00307    double myCellDy;
00308    double myCellDz;
00309 
00310    // These are used instead of dividing when calculating indexes from an offset
00311    double myInverseCellDx;
00312    double myInverseCellDy;
00313    double myInverseCellDz;
00314 
00315    // These are the maximum sizes, in each dimension, of any offset that is to 
00316    // be translated into and index.  An offset that contains any dimension larger
00317    // than these will result in rollover problems and the wrong index being 
00318    // calculated.
00319    double myMaxOffsetX;
00320    double myMaxOffsetY;
00321    double myMaxOffsetZ;
00322 
00323    double myMinOffsetX;
00324    double myMinOffsetY;
00325    double myMinOffsetZ;
00326 
00327    std::vector< DtSpatialSubCellType > myCells;
00328 };
00329 
00330 
00331 //------------------------------------------------------
00332 //  INLINE METHODS
00333 //------------------------------------------------------
00334 // include the inline code
00335 #define SPATIALSUBDIVISION_HEADER
00336 #include "geometry/spatialSubdivision.inl"
00337 #undef  SPATIALSUBDIVISION_HEADER
00338 
00339 #endif

Document ID: Generated on Fri Jun 29 16:33:32 EDT 2012 from SVN revision 116588
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)