Fix #10490: Allow ships to exit depots if another is not moving at the exit point...
[openttd-github.git] / src / tilematrix_type.hpp
blob006267b5bd1da15e95172b8801e8be9d4650ee4a
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
8 /** @file tilematrix_type.hpp Template for storing a value per area of the map. */
10 #ifndef TILEMATRIX_TYPE_HPP
11 #define TILEMATRIX_TYPE_HPP
13 #include "core/alloc_func.hpp"
14 #include "tilearea_type.h"
16 /**
17 * A simple matrix that stores one value per N*N square of the map.
18 * Storage is only allocated for the part of the map that has values
19 * assigned.
21 * @note No constructor is called for newly allocated values, you
22 * have to do this yourself if needed.
23 * @tparam T The type of the stored items.
24 * @tparam N Grid size.
26 template <typename T, uint N>
27 class TileMatrix {
29 /** Allocates space for a new tile in the matrix.
30 * @param tile Tile to add.
32 void AllocateStorage(TileIndex tile)
34 uint old_left = TileX(this->area.tile) / N;
35 uint old_top = TileY(this->area.tile) / N;
36 uint old_w = this->area.w / N;
37 uint old_h = this->area.h / N;
39 /* Add the square the tile is in to the tile area. We do this
40 * by adding top-left and bottom-right of the square. */
41 uint grid_x = (TileX(tile) / N) * N;
42 uint grid_y = (TileY(tile) / N) * N;
43 this->area.Add(TileXY(grid_x, grid_y));
44 this->area.Add(TileXY(grid_x + N - 1, grid_y + N - 1));
46 /* Allocate new storage. */
47 T *new_data = CallocT<T>(this->area.w / N * this->area.h / N);
49 if (old_w > 0) {
50 /* Copy old data if present. */
51 uint offs_x = old_left - TileX(this->area.tile) / N;
52 uint offs_y = old_top - TileY(this->area.tile) / N;
54 for (uint row = 0; row < old_h; row++) {
55 MemCpyT(&new_data[(row + offs_y) * this->area.w / N + offs_x], &this->data[row * old_w], old_w);
59 free(this->data);
60 this->data = new_data;
63 public:
64 static const uint GRID = N;
66 TileArea area; ///< Area covered by the matrix.
68 T *data; ///< Pointer to data array.
70 TileMatrix() : area(INVALID_TILE, 0, 0), data(nullptr) {}
72 ~TileMatrix()
74 free(this->data);
77 /**
78 * Get the total covered area.
79 * @return The area covered by the matrix.
81 const TileArea &GetArea() const
83 return this->area;
86 /**
87 * Get the area of the matrix square that contains a specific tile.
88 * @param tile The tile to get the map area for.
89 * @param extend Extend the area by this many squares on all sides.
90 * @return Tile area containing the tile.
92 static TileArea GetAreaForTile(TileIndex tile, uint extend = 0)
94 uint tile_x = (TileX(tile) / N) * N;
95 uint tile_y = (TileY(tile) / N) * N;
96 uint w = N, h = N;
98 w += std::min(extend * N, tile_x);
99 h += std::min(extend * N, tile_y);
101 tile_x -= std::min(extend * N, tile_x);
102 tile_y -= std::min(extend * N, tile_y);
104 w += std::min(extend * N, Map::SizeX() - tile_x - w);
105 h += std::min(extend * N, Map::SizeY() - tile_y - h);
107 return TileArea(TileXY(tile_x, tile_y), w, h);
111 * Extend the coverage area to include a tile.
112 * @param tile The tile to include.
114 void Add(TileIndex tile)
116 if (!this->area.Contains(tile)) {
117 this->AllocateStorage(tile);
122 * Get the value associated to a tile index.
123 * @param tile The tile to get the value for.
124 * @return Pointer to the value.
126 T *Get(TileIndex tile)
128 this->Add(tile);
130 tile -= this->area.tile;
131 uint x = TileX(tile) / N;
132 uint y = TileY(tile) / N;
134 return &this->data[y * this->area.w / N + x];
137 /** Array access operator, see #Get. */
138 inline T &operator[](TileIndex tile)
140 return *this->Get(tile);
144 #endif /* TILEMATRIX_TYPE_HPP */