Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 };
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
00082 virtual ~Grid()
00083 {
00084 delete [] m_pData;
00085 delete m_pCoordinateConverter;
00086 }
00087
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;
00461 kt_int32s m_Height;
00462 kt_int32s m_WidthStep;
00463 T* m_pData;
00464
00465 CoordinateConverter* m_pCoordinateConverter;
00466 };
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__