Grid.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2011, SRI International (R)
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU Lesser General Public License as published by
00006  * the Free Software Foundation, either version 3 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #pragma once
00019 
00020 #ifndef __OpenKarto_Grid_h__
00021 #define __OpenKarto_Grid_h__
00022 
00023 #include <OpenKarto/Object.h>
00024 #include <OpenKarto/CoordinateConverter.h>
00025 
00026 namespace karto
00027 {
00028 
00030 
00031 
00035 
00039   class KARTO_EXPORT Functor
00040   {
00041   public:
00045     virtual void operator() (kt_int32u) {};
00046   }; // Functor
00047 
00051 
00055   template<typename T>
00056   class Grid : public Object
00057   {
00058     KARTO_RTTI();
00059 
00060   public:
00068     static Grid* CreateGrid(kt_int32s width, kt_int32s height, kt_double resolution)
00069     {
00070       Grid* pGrid = new Grid(width, height);
00071       
00072       pGrid->GetCoordinateConverter()->SetScale(1.0 / resolution);
00073       
00074       return pGrid;
00075     }
00076     
00077   protected:
00078     //@cond EXCLUDE
00082     virtual ~Grid()
00083     {
00084       delete [] m_pData;
00085       delete m_pCoordinateConverter;
00086     }
00087     //@endcond
00088 
00089   public:
00093     void Clear()
00094     {
00095       memset(m_pData, 0, GetDataSize() * sizeof(T));
00096     }
00097     
00102     Grid* Clone()
00103     {
00104       Grid* pGrid = CreateGrid(GetWidth(), GetHeight(), GetResolution());
00105       pGrid->GetCoordinateConverter()->SetOffset(GetCoordinateConverter()->GetOffset());
00106       
00107       memcpy(pGrid->GetDataPointer(), GetDataPointer(), GetDataSize());
00108       
00109       return pGrid;
00110     }
00111     
00117     virtual void Resize(kt_int32s width, kt_int32s height)
00118     {
00119       m_Width = width;
00120       m_Height = height;
00121       m_WidthStep = math::AlignValue<kt_int32s>(width, 8);
00122       
00123       if (m_pData != NULL)
00124       {
00125         delete[] m_pData;
00126         m_pData = NULL;
00127       }
00128 
00129       try
00130       {
00131         m_pData = new T[GetDataSize()];
00132 
00133         if (m_pCoordinateConverter == NULL)
00134         {
00135           m_pCoordinateConverter = new CoordinateConverter();
00136         }
00137 
00138         m_pCoordinateConverter->SetSize(Size2<kt_int32s>(width, height));
00139       }
00140       catch (...)
00141       {
00142         m_pData = NULL;
00143 
00144         m_Width = 0;
00145         m_Height = 0;
00146         m_WidthStep = 0;
00147       }
00148       
00149       Clear();
00150     }
00151     
00157     inline kt_bool IsValidGridIndex(const Vector2i& rGrid) const
00158     {
00159       return (math::IsUpTo(rGrid.GetX(), GetWidth()) && math::IsUpTo(rGrid.GetY(), GetHeight()));
00160     }
00161     
00169     virtual kt_int32s GridIndex(const Vector2i& rGrid, kt_bool boundaryCheck = true) const
00170     {
00171       if (boundaryCheck == true)
00172       { 
00173         if (IsValidGridIndex(rGrid) == false)
00174         {
00175           StringBuilder errorMessage;
00176           errorMessage << "Index (" << rGrid.GetX() << ", " << rGrid.GetY() << ")" << " out of range.  Index must be between [0; " << GetWidth() << ") and [0; " << GetHeight() << ")";
00177           throw Exception(errorMessage.ToString());          
00178         }
00179       }
00180 
00181       kt_int32s index = rGrid.GetX() + (rGrid.GetY() * m_WidthStep);
00182       
00183       if (boundaryCheck == true)
00184       {
00185         assert(math::IsUpTo(index, GetDataSize()));
00186       }
00187       
00188       return index;
00189     }
00190 
00196     Vector2i IndexToGrid(kt_int32s index) const
00197     {
00198       Vector2i grid;
00199 
00200       grid.SetY(index / m_WidthStep);
00201       grid.SetX(index - grid.GetY() * m_WidthStep);
00202 
00203       return grid;
00204     }
00205     
00212     inline Vector2i WorldToGrid(const Vector2d& rWorld, kt_bool flipY = false) const
00213     {
00214       return GetCoordinateConverter()->WorldToGrid(rWorld, flipY);
00215     }
00216     
00223     inline Vector2d GridToWorld(const Vector2i& rGrid, kt_bool flipY = false) const
00224     {      
00225       return GetCoordinateConverter()->GridToWorld(rGrid, flipY);
00226     }    
00227 
00233     T* GetDataPointer(const Vector2i& rGrid)
00234     {
00235       kt_int32s index = GridIndex(rGrid, true);      
00236       return m_pData + index;
00237     }
00238 
00244     T* GetDataPointer(const Vector2i& rGrid) const
00245     {
00246       kt_int32s index = GridIndex(rGrid, true);      
00247       return m_pData + index;
00248     }
00249 
00254     inline kt_int32s GetWidth() const
00255     {
00256       return m_Width;
00257     };
00258 
00263     inline kt_int32s GetHeight() const
00264     {
00265       return m_Height;
00266     };
00267 
00272     inline const Size2<kt_int32s> GetSize() const
00273     {
00274       return Size2<kt_int32s>(GetWidth(), GetHeight());
00275     }
00276 
00281     inline kt_int32s GetWidthStep() const
00282     {
00283       return m_WidthStep;
00284     }
00285 
00290     inline T* GetDataPointer()
00291     {
00292       return m_pData;
00293     }
00294 
00299     inline T* GetDataPointer() const
00300     {
00301       return m_pData;
00302     }
00303 
00308     inline kt_int32s GetDataSize() const
00309     {
00310       return m_WidthStep * GetHeight();
00311     }
00312 
00318     inline T GetValue(const Vector2i& rGrid) const
00319     {
00320       kt_int32s index = GridIndex(rGrid);
00321       return m_pData[index];
00322     }
00323     
00329     inline void SetValue(const Vector2i& rGrid, T rValue) const
00330     {
00331       kt_int32s index = GridIndex(rGrid);
00332       m_pData[index] = rValue;
00333     }
00334 
00339     inline CoordinateConverter* GetCoordinateConverter() const
00340     {
00341       return m_pCoordinateConverter;
00342     }
00343 
00348     inline kt_double GetResolution() const
00349     {
00350       return GetCoordinateConverter()->GetResolution();
00351     }
00352     
00357     inline BoundingBox2 GetBoundingBox() const
00358     {
00359       return GetCoordinateConverter()->GetBoundingBox();
00360     }
00361     
00371     void TraceLine(kt_int32s x0, kt_int32s y0, kt_int32s x1, kt_int32s y1, Functor* f = NULL)
00372     {
00373       kt_bool steep = abs(y1 - y0) > abs(x1 - x0);
00374       if (steep)
00375       {
00376         math::Swap(x0, y0);
00377         math::Swap(x1, y1);
00378       }
00379       if (x0 > x1)
00380       {
00381         math::Swap(x0, x1);
00382         math::Swap(y0, y1);
00383       }
00384 
00385       kt_int32s deltaX = x1 - x0;
00386       kt_int32s deltaY = abs(y1 - y0);
00387       kt_int32s error = 0;
00388       kt_int32s ystep;
00389       kt_int32s y = y0;
00390 
00391       if (y0 < y1)
00392       {
00393         ystep = 1;
00394       }
00395       else
00396       {
00397         ystep = -1;
00398       }
00399 
00400       kt_int32s pointX;
00401       kt_int32s pointY;
00402       for (kt_int32s x = x0; x <= x1; x++)
00403       {
00404         if (steep)
00405         {
00406           pointX = y;
00407           pointY = x;
00408         }
00409         else
00410         {
00411           pointX = x;
00412           pointY = y;
00413         }
00414 
00415         error += deltaY;
00416 
00417         if (2 * error >= deltaX)
00418         {
00419           y += ystep;
00420           error -= deltaX;
00421         }
00422 
00423         Vector2i gridIndex(pointX, pointY);
00424         if (IsValidGridIndex(gridIndex))
00425         {
00426           kt_int32s index = GridIndex(gridIndex, false);
00427           T* pGridPointer = GetDataPointer();
00428           pGridPointer[index]++;
00429           
00430           if (f != NULL)
00431           {
00432             (*f)(index); 
00433           }
00434         }
00435       }
00436     }
00437 
00438   protected:
00444     Grid(kt_int32s width, kt_int32s height)
00445       : m_Width(0)
00446       , m_Height(0)
00447       , m_WidthStep(0)
00448       , m_pData(NULL)
00449 
00450       , m_pCoordinateConverter(NULL)
00451     {
00452       Resize(width, height);
00453     }
00454     
00455   private:
00456     Grid(const Grid&);
00457     const Grid& operator=(const Grid&);
00458 
00459   private:
00460     kt_int32s m_Width;       // width of grid
00461     kt_int32s m_Height;      // height of grid
00462     kt_int32s m_WidthStep;   // 8-byte aligned width of grid
00463     T* m_pData;              // grid data
00464 
00465     CoordinateConverter* m_pCoordinateConverter; // coordinate converter to convert between world coordinates and grid coordinates
00466   }; // Grid
00467 
00471   KARTO_TYPE(Grid<kt_int8u>);
00472 
00476   KARTO_TYPE(Grid<kt_int32u>);
00477 
00481   KARTO_TYPE(Grid<kt_float>);
00482 
00486   KARTO_TYPE(Grid<kt_double>);
00487 
00489 
00490 }
00491 
00492 #endif // __OpenKarto_Grid_h__


nav2d_karto
Author(s): Sebastian Kasperski
autogenerated on Sun Apr 2 2017 03:53:08