1 /* $Id: tilematrix_type.hpp 23735 2012-01-03 20:26:05Z rubidium $ */
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/>.
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 "tilearea_type.h"
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
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
>
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
);
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
);
62 this->data
= new_data
;
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(nullptr) {}
80 * Get the total covered area.
81 * @return The area covered by the matrix.
83 const TileArea
& GetArea() const
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
;
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
)
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 */