Main MRPT website > C++ reference
MRPT logo
CDynamicGrid.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef CDynamicGrid_H
00029 #define CDynamicGrid_H
00030 
00031 #include <mrpt/utils/utils_defs.h>
00032 
00033 namespace mrpt
00034 {
00035     namespace utils
00036     {
00037         using namespace mrpt::system;
00038 
00039         /** A 2D grid of dynamic size which stores any kind of data at each cell.
00040           * \tparam T The type of each cell in the 2D grid.
00041           * \ingroup mrpt_base_grp
00042           */
00043         template <class T>
00044         class CDynamicGrid
00045         {
00046         protected:
00047             /** The cells.
00048               */
00049             std::vector<T>              m_map;
00050 
00051             /** Used only from logically const method that really need to modify the object */
00052             inline std::vector<T> &     m_map_castaway_const() const  { return const_cast< std::vector<T>& >( m_map ); }
00053 
00054             float                       m_x_min,m_x_max,m_y_min,m_y_max;
00055             float                       m_resolution;
00056             size_t                      m_size_x, m_size_y;
00057 
00058         public:
00059             /** Constructor
00060               */
00061             CDynamicGrid(       float   x_min = -10.0f,
00062                             float       x_max = 10.0f,
00063                             float       y_min = -10.0f,
00064                             float       y_max = 10.0f,
00065                             float       resolution  = 0.10f) :
00066                                 m_map(),
00067                                 m_x_min(),m_x_max(),m_y_min(),m_y_max(),
00068                                 m_resolution(),
00069                                 m_size_x(), m_size_y()
00070             {
00071                 setSize(x_min,x_max,y_min,y_max,resolution);
00072             }
00073 
00074             /** Destructor
00075               */
00076             virtual ~CDynamicGrid()
00077             {
00078             }
00079 
00080             /** Changes the size of the grid, ERASING all previous contents.
00081               * \sa resize
00082               */
00083             void  setSize(      float   x_min,
00084                                         float   x_max,
00085                                         float   y_min,
00086                                         float   y_max,
00087                                         float   resolution )
00088             {
00089                 // Adjust sizes to adapt them to full sized cells acording to the resolution:
00090                 m_x_min = resolution*round(x_min/resolution);
00091                 m_y_min = resolution*round(y_min/resolution);
00092                 m_x_max = resolution*round(x_max/resolution);
00093                 m_y_max = resolution*round(y_max/resolution);
00094 
00095                 // Res:
00096                 m_resolution = resolution;
00097 
00098                 // Now the number of cells should be integers:
00099                 m_size_x = round((m_x_max-m_x_min)/m_resolution);
00100                 m_size_y = round((m_y_max-m_y_min)/m_resolution);
00101 
00102                 // Cells memory:
00103                 m_map.resize(m_size_x*m_size_y);
00104             }
00105 
00106             /** Erase the contents of all the cells.
00107               */
00108             void  clear()
00109             {
00110                 m_map.clear();
00111                 m_map.resize(m_size_x*m_size_y);
00112             }
00113 
00114             /** Fills all the cells with the same value
00115               */
00116             inline void fill( const T& value ) { std::fill(m_map.begin(),m_map.end(),value); }
00117 
00118             /** Changes the size of the grid, maintaining previous contents.
00119               * \sa setSize
00120               */
00121             virtual void  resize(
00122                 float   new_x_min,
00123                 float   new_x_max,
00124                 float   new_y_min,
00125                 float   new_y_max,
00126                 const T& defaultValueNewCells,
00127                 float   additionalMarginMeters = 2.0f )
00128             {
00129                 MRPT_START
00130 
00131                                 MRPT_CHECK_NORMAL_NUMBER(new_x_min)
00132                                 MRPT_CHECK_NORMAL_NUMBER(new_x_max)
00133                                 MRPT_CHECK_NORMAL_NUMBER(new_y_min)
00134                                 MRPT_CHECK_NORMAL_NUMBER(new_y_max)
00135 
00136                 unsigned int                            x,y;
00137                 unsigned int                            extra_x_izq,extra_y_arr,new_size_x=0,new_size_y=0;
00138                 typename std::vector<T>                         new_map;
00139                 typename std::vector<T>::iterator       itSrc,itDst;
00140 
00141                 // Is resize really necesary?
00142                 if (new_x_min>=m_x_min &&
00143                     new_y_min>=m_y_min &&
00144                     new_x_max<=m_x_max &&
00145                     new_y_max<=m_y_max) return;
00146 
00147                 if (new_x_min>m_x_min) new_x_min=m_x_min;
00148                 if (new_x_max<m_x_max) new_x_max=m_x_max;
00149                 if (new_y_min>m_y_min) new_y_min=m_y_min;
00150                 if (new_y_max<m_y_max) new_y_max=m_y_max;
00151 
00152                 // Additional margin:
00153                 if (additionalMarginMeters>0)
00154                 {
00155                     if (new_x_min<m_x_min) new_x_min= floor(new_x_min-additionalMarginMeters);
00156                     if (new_x_max>m_x_max) new_x_max= ceil(new_x_max+additionalMarginMeters);
00157                     if (new_y_min<m_y_min) new_y_min= floor(new_y_min-additionalMarginMeters);
00158                     if (new_y_max>m_y_max) new_y_max= ceil(new_y_max+additionalMarginMeters);
00159                 }
00160 
00161                 // Adjust sizes to adapt them to full sized cells acording to the resolution:
00162                 if (fabs(new_x_min/m_resolution - round(new_x_min/m_resolution))>0.05f )
00163                     new_x_min = m_resolution*round(new_x_min/m_resolution);
00164                 if (fabs(new_y_min/m_resolution - round(new_y_min/m_resolution))>0.05f )
00165                     new_y_min = m_resolution*round(new_y_min/m_resolution);
00166                 if (fabs(new_x_max/m_resolution - round(new_x_max/m_resolution))>0.05f )
00167                     new_x_max = m_resolution*round(new_x_max/m_resolution);
00168                 if (fabs(new_y_max/m_resolution - round(new_y_max/m_resolution))>0.05f )
00169                     new_y_max = m_resolution*round(new_y_max/m_resolution);
00170 
00171                 // Change the map size: Extensions at each side:
00172                 extra_x_izq = round((m_x_min-new_x_min) / m_resolution);
00173                 extra_y_arr = round((m_y_min-new_y_min) / m_resolution);
00174 
00175                 new_size_x = round((new_x_max-new_x_min) / m_resolution);
00176                 new_size_y = round((new_y_max-new_y_min) / m_resolution);
00177 
00178                 // Reserve new memory:
00179                 new_map.resize(new_size_x*new_size_y,defaultValueNewCells);
00180 
00181                 // Copy previous rows:
00182                 for (y=0;y<m_size_y;y++)
00183                 {
00184                     for (x=0,itSrc=(m_map.begin()+y*m_size_x),itDst=(new_map.begin()+extra_x_izq + (y+extra_y_arr)*new_size_x);
00185                             x<m_size_x;
00186                         x++,itSrc++,itDst++)
00187                     {
00188                         *itDst = *itSrc;
00189                     }
00190                 }
00191 
00192                 // Update the new map limits:
00193                 m_x_min = new_x_min;
00194                 m_x_max = new_x_max;
00195                 m_y_min = new_y_min;
00196                 m_y_max = new_y_max;
00197 
00198                 m_size_x = new_size_x;
00199                 m_size_y = new_size_y;
00200 
00201                 // Keep the new map only:
00202                 m_map.swap(new_map);
00203 
00204                 MRPT_END
00205 
00206             }
00207 
00208             /** Returns a pointer to the contents of a cell given by its coordinates, or NULL if it is out of the map extensions.
00209               */
00210             inline T*   cellByPos( float x, float y )
00211             {
00212                 int cx = x2idx(x);
00213                 int cy = y2idx(y);
00214 
00215                 if( cx<0 || cx>=static_cast<int>(m_size_x) ) return NULL;
00216                 if( cy<0 || cy>=static_cast<int>(m_size_y) ) return NULL;
00217 
00218                 return &m_map[ cx + cy*m_size_x ];
00219             }
00220 
00221             /** Returns a pointer to the contents of a cell given by its coordinates, or NULL if it is out of the map extensions.
00222               */
00223             inline const T*     cellByPos( float x, float y ) const
00224             {
00225                 int cx = x2idx(x);
00226                 int cy = y2idx(y);
00227 
00228                 if( cx<0 || cx>=static_cast<int>(m_size_x) ) return NULL;
00229                 if( cy<0 || cy>=static_cast<int>(m_size_y) ) return NULL;
00230 
00231                 return &m_map[ cx + cy*m_size_x ];
00232             }
00233 
00234             /** Returns a pointer to the contents of a cell given by its cell indexes, or NULL if it is out of the map extensions.
00235               */
00236             inline  T*  cellByIndex( unsigned int cx, unsigned int cy )
00237             {
00238                 if( cx>=m_size_x || cy>=m_size_y)
00239                         return NULL;
00240                 else    return &m_map[ cx + cy*m_size_x ];
00241             }
00242 
00243             /** Returns a pointer to the contents of a cell given by its cell indexes, or NULL if it is out of the map extensions.
00244               */
00245             inline const T* cellByIndex( unsigned int cx, unsigned int cy ) const
00246             {
00247                 if( cx>=m_size_x || cy>=m_size_y)
00248                         return NULL;
00249                 else    return &m_map[ cx + cy*m_size_x ];
00250             }
00251 
00252             /** Returns the horizontal size of grid map in cells count.
00253                 */
00254             inline size_t getSizeX() const { return m_size_x; }
00255 
00256             /** Returns the vertical size of grid map in cells count.
00257                 */
00258             inline size_t getSizeY() const { return m_size_y; }
00259 
00260             /** Returns the "x" coordinate of left side of grid map.
00261                 */
00262             inline float  getXMin()const  { return m_x_min; }
00263 
00264             /** Returns the "x" coordinate of right side of grid map.
00265                 */
00266             inline float  getXMax()const  { return m_x_max; }
00267 
00268             /** Returns the "y" coordinate of top side of grid map.
00269                 */
00270             inline float  getYMin()const  { return m_y_min; }
00271 
00272             /** Returns the "y" coordinate of bottom side of grid map.
00273                 */
00274             inline float  getYMax()const  { return m_y_max; }
00275 
00276             /** Returns the resolution of the grid map.
00277                 */
00278             inline float  getResolution()const  { return m_resolution; }
00279 
00280             /** The user must implement this in order to provide "saveToTextFile" a way to convert each cell into a numeric value */
00281             virtual float cell2float(const T& c) const
00282             {
00283                 return 0;
00284             }
00285 
00286             void  saveToTextFile(const std::string &fileName) const
00287             {
00288                 FILE    *f=os::fopen(fileName.c_str(),"wt");
00289                 if(!f) return;
00290                 for (unsigned int cy=0;cy<m_size_y;cy++)
00291                 {
00292                     for (unsigned int cx=0;cx<m_size_x;cx++)
00293                         os::fprintf(f,"%f ",cell2float(m_map[ cx + cy*m_size_x ]));
00294                     os::fprintf(f,"\n");
00295                 }
00296                 os::fclose(f);
00297             }
00298 
00299             /** Transform a coordinate values into cell indexes.
00300               */
00301             inline int   x2idx(float x) const { return static_cast<int>( (x-m_x_min)/m_resolution ); }
00302             inline int   y2idx(float y) const { return static_cast<int>( (y-m_y_min)/m_resolution ); }
00303             inline int   xy2idx(float x,float y) const { return x2idx(x) + y2idx(y)*m_size_x; }
00304 
00305             /** Transform a global (linear) cell index value into its corresponding (x,y) cell indexes. */
00306             inline void  idx2cxcy(const int &idx,  int &cx, int &cy ) const
00307             {
00308                 cx = idx % m_size_x;
00309                 cy = idx / m_size_x;
00310             }
00311 
00312             /** Transform a cell index into a coordinate value.
00313               */
00314             inline float   idx2x(int cx) const { return m_x_min+(cx+0.5f)*m_resolution; }
00315             inline float   idx2y(int cy) const { return m_y_min+(cy+0.5f)*m_resolution; }
00316 
00317             /** Transform a coordinate value into a cell index, using a diferent "x_min" value
00318                 */
00319             inline int   x2idx(float x,float x_min) const { return static_cast<int>((x-m_x_min)/m_resolution ); }
00320             inline int   y2idx(float y, float y_min) const { return static_cast<int>((y-m_y_min)/m_resolution ); }
00321 
00322                         /** Get the entire grid as a matrix. 
00323                           *  \tparam MAT The type of the matrix, typically a CMatrixDouble.
00324                           *  \param[out] m The output matrix; will be set automatically to the correct size.
00325                           *  Entry (cy,cx) in the matrix contains the grid cell with indices (cx,cy).
00326                           * \note This method will compile only for cell types that can be converted to the type of the matrix elements (e.g. double).
00327                           */
00328                         template <class MAT>
00329                         void getAsMatrix(MAT &m) const
00330                         {
00331                                 m.setSize(m_size_y, m_size_x);
00332                                 if (m_map.empty()) return;
00333                                 const T* c = &m_map[0];
00334                                 for (size_t cy=0;cy<m_size_y;cy++)
00335                                         for (size_t cx=0;cx<m_size_x;cx++)
00336                                                 m.set_unsafe(cy,cx, *c++);
00337                         }
00338 
00339         };
00340 
00341         } // End of namespace
00342 } // end of namespace
00343 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011