tilematrix_type.hpp

Go to the documentation of this file.
00001 /* $Id: tilematrix_type.hpp 23735 2012-01-03 20:26:05Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef TILEMATRIX_TYPE_HPP
00013 #define TILEMATRIX_TYPE_HPP
00014 
00015 #include "core/alloc_func.hpp"
00016 #include "tilearea_type.h"
00017 
00028 template <typename T, uint N>
00029 class TileMatrix {
00030 
00034   void AllocateStorage(TileIndex tile)
00035   {
00036     uint old_left = TileX(this->area.tile) / N;
00037     uint old_top  = TileY(this->area.tile) / N;
00038     uint old_w    = this->area.w / N;
00039     uint old_h    = this->area.h / N;
00040 
00041     /* Add the square the tile is in to the tile area. We do this
00042      * by adding top-left and bottom-right of the square. */
00043     uint grid_x = (TileX(tile) / N) * N;
00044     uint grid_y = (TileY(tile) / N) * N;
00045     this->area.Add(TileXY(grid_x, grid_y));
00046     this->area.Add(TileXY(grid_x + N - 1, grid_y + N - 1));
00047 
00048     /* Allocate new storage. */
00049     T *new_data = CallocT<T>(this->area.w / N * this->area.h / N);
00050 
00051     if (old_w > 0) {
00052       /* Copy old data if present. */
00053       uint offs_x = old_left - TileX(this->area.tile) / N;
00054       uint offs_y = old_top  - TileY(this->area.tile) / N;
00055 
00056       for (uint row = 0; row < old_h; row++) {
00057         MemCpyT(&new_data[(row + offs_y) * this->area.w / N + offs_x], &this->data[row * old_w], old_w);
00058       }
00059     }
00060 
00061     free(this->data);
00062     this->data = new_data;
00063   }
00064 
00065 public:
00066   static const uint GRID = N;
00067 
00068   TileArea area; 
00069 
00070   T *data; 
00071 
00072   TileMatrix() : area(INVALID_TILE, 0, 0), data(NULL) {}
00073 
00074   ~TileMatrix()
00075   {
00076     free(this->data);
00077   }
00078 
00083   const TileArea& GetArea() const
00084   {
00085     return this->area;
00086   }
00087 
00094   static TileArea GetAreaForTile(TileIndex tile, uint extend = 0)
00095   {
00096     uint tile_x = (TileX(tile) / N) * N;
00097     uint tile_y = (TileY(tile) / N) * N;
00098     uint w = N, h = N;
00099 
00100     w += min(extend * N, tile_x);
00101     h += min(extend * N, tile_y);
00102 
00103     tile_x -= min(extend * N, tile_x);
00104     tile_y -= min(extend * N, tile_y);
00105 
00106     w += min(extend * N, MapSizeX() - tile_x - w);
00107     h += min(extend * N, MapSizeY() - tile_y - h);
00108 
00109     return TileArea(TileXY(tile_x, tile_y), w, h);
00110   }
00111 
00116   void Add(TileIndex tile)
00117   {
00118     if (!this->area.Contains(tile)) {
00119       this->AllocateStorage(tile);
00120     }
00121   }
00122 
00128   T *Get(TileIndex tile)
00129   {
00130     this->Add(tile);
00131 
00132     tile -= this->area.tile;
00133     uint x = TileX(tile) / N;
00134     uint y = TileY(tile) / N;
00135 
00136     return &this->data[y * this->area.w / N + x];
00137   }
00138 
00140   inline T &operator[](TileIndex tile)
00141   {
00142     return *this->Get(tile);
00143   }
00144 };
00145 
00146 #endif /* TILEMATRIX_TYPE_HPP */