Remove SIGTYPE_LAST_NOPBS
[openttd/fttd.git] / src / tilematrix_type.hpp
blob9f897fc5f411a5f1acd7b758ed6e3fc0c6cbeadc
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file tilematrix_type.hpp Template for storing a value per area of the map. */
12 #ifndef TILEMATRIX_TYPE_HPP
13 #define TILEMATRIX_TYPE_HPP
15 #include "core/alloc_func.hpp"
16 #include "map/tilearea.h"
18 /**
19 * A simple matrix that stores one value per N*N square of the map.
20 * Storage is only allocated for the part of the map that has values
21 * assigned.
23 * @note No constructor is called for newly allocated values, you
24 * have to do this yourself if needed.
25 * @tparam T The type of the stored items.
26 * @tparam N Grid size.
28 template <typename T, uint N>
29 class TileMatrix {
31 /** Allocates space for a new tile in the matrix.
32 * @param tile Tile to add.
34 void AllocateStorage(TileIndex tile)
36 uint old_left = TileX(this->area.tile) / N;
37 uint old_top = TileY(this->area.tile) / N;
38 uint old_w = this->area.w / N;
39 uint old_h = this->area.h / N;
41 /* Add the square the tile is in to the tile area. We do this
42 * by adding top-left and bottom-right of the square. */
43 uint grid_x = (TileX(tile) / N) * N;
44 uint grid_y = (TileY(tile) / N) * N;
45 this->area.Add(TileXY(grid_x, grid_y));
46 this->area.Add(TileXY(grid_x + N - 1, grid_y + N - 1));
48 /* Allocate new storage. */
49 T *new_data = CallocT<T>(this->area.w / N * this->area.h / N);
51 if (old_w > 0) {
52 /* Copy old data if present. */
53 uint offs_x = old_left - TileX(this->area.tile) / N;
54 uint offs_y = old_top - TileY(this->area.tile) / N;
56 for (uint row = 0; row < old_h; row++) {
57 MemCpyT(&new_data[(row + offs_y) * this->area.w / N + offs_x], &this->data[row * old_w], old_w);
61 free(this->data);
62 this->data = new_data;
65 public:
66 static const uint GRID = N;
68 TileArea area; ///< Area covered by the matrix.
70 T *data; ///< Pointer to data array.
72 TileMatrix() : area(INVALID_TILE, 0, 0), data(NULL) {}
74 ~TileMatrix()
76 free(this->data);
79 /**
80 * Get the total covered area.
81 * @return The area covered by the matrix.
83 const TileArea& GetArea() const
85 return this->area;
88 /**
89 * Get the area of the matrix square that contains a specific tile.
90 * @param The tile to get the map area for.
91 * @param extend Extend the area by this many squares on all sides.
92 * @return Tile area containing the tile.
94 static TileArea GetAreaForTile(TileIndex tile, uint extend = 0)
96 uint tile_x = (TileX(tile) / N) * N;
97 uint tile_y = (TileY(tile) / N) * N;
98 uint w = N, h = N;
100 w += min(extend * N, tile_x);
101 h += min(extend * N, tile_y);
103 tile_x -= min(extend * N, tile_x);
104 tile_y -= min(extend * N, tile_y);
106 w += min(extend * N, MapSizeX() - tile_x - w);
107 h += min(extend * N, MapSizeY() - tile_y - h);
109 return TileArea(TileXY(tile_x, tile_y), w, h);
113 * Extend the coverage area to include a tile.
114 * @param tile The tile to include.
116 void Add(TileIndex tile)
118 if (!this->area.Contains(tile)) {
119 this->AllocateStorage(tile);
124 * Get the value associated to a tile index.
125 * @param tile The tile to get the value for.
126 * @return Pointer to the value.
128 T *Get(TileIndex tile)
130 this->Add(tile);
132 tile -= this->area.tile;
133 uint x = TileX(tile) / N;
134 uint y = TileY(tile) / N;
136 return &this->data[y * this->area.w / N + x];
139 /** Array access operator, see #Get. */
140 inline T &operator[](TileIndex tile)
142 return *this->Get(tile);
146 #endif /* TILEMATRIX_TYPE_HPP */