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/>.
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"
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
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
>
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
);
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
);
60 this->data
= new_data
;
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) {}
78 * Get the total covered area.
79 * @return The area covered by the matrix.
81 const TileArea
&GetArea() const
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
;
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
)
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 */