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 map/tilearea.h Handling of tile areas. */
10 #ifndef MAP_TILEAREA_H
11 #define MAP_TILEAREA_H
15 /** Represents the covered area of e.g. a rail station */
16 struct OrthogonalTileArea
{
17 TileIndex tile
; ///< The base tile of the area
18 uint16 w
; ///< The width of the area
19 uint16 h
; ///< The height of the area
21 /** Just construct this tile area */
22 OrthogonalTileArea() : tile(INVALID_TILE
), w(0), h(0) {}
25 * Construct this tile area with some set values
26 * @param tile the base tile
30 OrthogonalTileArea(TileIndex tile
, uint8 w
, uint8 h
) : tile(tile
), w(w
), h(h
) {}
32 OrthogonalTileArea(TileIndex start
, TileIndex end
);
34 void Set(uint x0
, uint y0
, uint x1
, uint y1
);
36 void Add(TileIndex to_add
);
38 void Add(const OrthogonalTileArea
&to_add
);
41 * Clears the 'tile area', i.e. make the tile invalid.
45 this->tile
= INVALID_TILE
;
50 bool Intersects(const OrthogonalTileArea
&ta
) const;
52 bool Contains(TileIndex tile
) const;
57 * Get the center tile.
58 * @return The tile at the center, or just north of it.
60 TileIndex
GetCenterTile() const
62 return TILE_ADDXY(this->tile
, this->w
/ 2, this->h
/ 2);
66 * Get the tile in the area closest to a given tile.
67 * @param t The reference tile.
68 * @return The closest tile, or INVALID_TILE if the area is empty.
70 TileIndex
get_closest_tile(TileIndex t
) const
72 if (this->tile
== INVALID_TILE
) return INVALID_TILE
;
74 /* clamp x coordinate */
75 uint x
= TileX(this->tile
);
76 x
= ClampU(TileX(t
), x
, x
+ this->w
- 1);
78 /* clamp y coordinate */
79 uint y
= TileY(this->tile
);
80 y
= ClampU(TileY(t
), y
, y
+ this->h
- 1);
82 /* return the tile of our target coordinates */
87 /** Shorthand for the much more common orthogonal tile area. */
88 typedef OrthogonalTileArea TileArea
;
91 /** Base class for tile iterators. */
94 TileIndex tile
; ///< The current tile we are at.
97 * Initialise the iterator starting at this tile.
98 * @param tile The tile we start iterating from.
100 TileIterator(TileIndex tile
) : tile(tile
)
105 * Compute the next tile.
107 virtual void Next() = 0;
110 /** Some compilers really like this. */
111 virtual ~TileIterator()
116 * Get the tile we are currently at.
117 * @return The tile we are at, or INVALID_TILE when we're done.
119 inline operator TileIndex () const
125 * Move ourselves to the next tile in the rectangle on the map.
127 TileIterator
& operator ++()
129 assert(this->tile
!= INVALID_TILE
);
135 * Allocate a new iterator that is a copy of this one.
137 virtual TileIterator
*Clone() const = 0;
140 /** Iterator to iterate over a tile area (rectangle) of the map. */
141 class OrthogonalTileIterator
: public TileIterator
{
143 const uint w
; ///< The width of the iterated area.
144 const uint rowdiff
; ///< The amount to add when switching rows
145 uint x
; ///< The current 'x' position in the rectangle.
146 uint y
; ///< The current 'y' position in the rectangle.
150 * Move ourselves to the next tile in the rectangle on the map.
152 inline void Next() OVERRIDE
154 assert(this->tile
!= INVALID_TILE
);
158 } else if (--this->y
> 0) {
160 this->tile
+= this->rowdiff
;
162 this->tile
= INVALID_TILE
;
168 * Construct the iterator.
169 * @param ta Area, i.e. begin point and width/height of to-be-iterated area.
171 OrthogonalTileIterator(const OrthogonalTileArea
&ta
)
172 : TileIterator(ta
.w
== 0 || ta
.h
== 0 ? INVALID_TILE
: ta
.tile
),
173 w(ta
.w
), rowdiff(TileDiffXY(1, 1) - ta
.w
), x(ta
.w
), y(ta
.h
)
177 OrthogonalTileIterator
*Clone() const OVERRIDE
179 return new OrthogonalTileIterator(*this);
183 /** Iterator to iterate over a diagonal area of the map. */
184 class DiagonalTileIterator
: public TileIterator
{
186 uint x
; ///< x coordinate of the current tile
187 uint y
; ///< y coordinate of the current tile
188 bool odd
; ///< Whether this is an "odd" area
189 int8 s1
; ///< Advancing a tile adds (s1,s1)
190 int s2x
; ///< Advancing a row adds (s2x,s2y)
191 int s2y
; ///< Advancing a row adds (s2x,s2y)
192 uint w
; ///< The width of the main rectangle side
193 uint n
; ///< The number of tiles left on the current row
194 uint m
; ///< The number of rows left
197 void Next() OVERRIDE
;
200 DiagonalTileIterator(TileIndex begin
, TileIndex end
);
202 DiagonalTileIterator
*Clone() const OVERRIDE
204 return new DiagonalTileIterator(*this);
209 * A loop which iterates over the tiles of a TileArea.
210 * @param var The name of the variable which contains the current tile.
211 * This variable will be allocated in this \c for of this loop.
212 * @param ta The tile area to search over.
214 #define TILE_AREA_LOOP(var, ta) for (OrthogonalTileIterator var(ta); var != INVALID_TILE; ++var)
216 #endif /* MAP_TILEAREA_H */