OpenTTD Source 20260911-master-gee2b2ac12a
tilearea_type.h
Go to the documentation of this file.
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef TILEAREA_TYPE_H
11#define TILEAREA_TYPE_H
12
13#include "map_func.h"
14
16
20 uint16_t w;
21 uint16_t h;
22
29 OrthogonalTileArea(TileIndex tile = INVALID_TILE, uint16_t w = 0, uint16_t h = 0) : tile(tile), w(w), h(h)
30 {
31 }
32
34
39 inline bool IsEmpty() const { return this->tile == INVALID_TILE; }
40
41 void Add(TileIndex to_add);
42
47 inline void Add(const OrthogonalTileArea &area)
48 {
49 /* Only the top and bottom corners need to be added. */
50 this->Add(area.tile);
51 this->Add(TileAddXY(area.tile, area.w - 1, area.h - 1));
52 }
53
57 void Clear()
58 {
59 this->tile = INVALID_TILE;
60 this->w = 0;
61 this->h = 0;
62 }
63
64 bool Intersects(const OrthogonalTileArea &ta) const;
65
66 bool Contains(TileIndex tile) const;
67
68 OrthogonalTileArea &Expand(int rad);
69
70 void ClampToMap();
71
77 {
78 return TileAddXY(this->tile, this->w / 2, this->h / 2);
79 }
80
82
84};
85
88
90 int16_t a;
91 int16_t b;
92
99 DiagonalTileArea(TileIndex tile = INVALID_TILE, int16_t a = 0, int16_t b = 0) : tile(tile), a(a), b(b)
100 {
101 }
102
104
108 void Clear()
109 {
110 this->tile = INVALID_TILE;
111 this->a = 0;
112 this->b = 0;
113 }
114
115 bool Contains(TileIndex tile) const;
116};
117
120
123protected:
125
133
134public:
136 virtual ~TileIterator() = default;
137
142 inline operator TileIndex () const
143 {
144 return this->tile;
145 }
146
151 inline TileIndex operator *() const
152 {
153 return this->tile;
154 }
155
160 virtual TileIterator& operator ++() = 0;
161
167 bool operator ==(const TileIterator &rhs) const
168 {
169 return this->tile == rhs.tile;
170 }
171
177 bool operator ==(const TileIndex &rhs) const
178 {
179 return this->tile == rhs;
180 }
181
182 static std::unique_ptr<TileIterator> Create(TileIndex corner1, TileIndex corner2, bool diagonal);
183};
184
187private:
188 int w;
189 int x;
190 int y;
191
192public:
197 OrthogonalTileIterator(const OrthogonalTileArea &ta) : TileIterator(ta.w == 0 || ta.h == 0 ? INVALID_TILE : ta.tile), w(ta.w), x(ta.w), y(ta.h)
198 {
199 }
200
207 {
208 *this = OrthogonalTileIterator(OrthogonalTileArea(corner1, corner2));
209 }
210
215 inline TileIterator& operator ++() override
216 {
217 assert(this->tile != INVALID_TILE);
218
219 if (--this->x > 0) {
220 this->tile++;
221 } else if (--this->y > 0) {
222 this->x = this->w;
223 this->tile += TileDiffXY(1 - this->w, 1);
224 } else {
225 this->tile = INVALID_TILE;
226 }
227 return *this;
228 }
229};
230
233private:
234 uint base_x;
235 uint base_y;
236 int a_cur;
237 int b_cur;
238 int a_max;
239 int b_max;
240
241public:
242
248 TileIterator(ta.tile), base_x(TileX(ta.tile)), base_y(TileY(ta.tile)), a_cur(0), b_cur(0), a_max(ta.a), b_max(ta.b)
249 {
250 }
251
258 {
259 *this = DiagonalTileIterator(DiagonalTileArea(corner1, corner2));
260 }
261
262 TileIterator& operator ++() override;
263};
264
269public:
270 using value_type = TileIndex;
271 using difference_type = std::ptrdiff_t;
272 using iterator_category = std::forward_iterator_tag;
273 using pointer = void;
274 using reference = void;
275
276 SpiralTileIterator(TileIndex center, uint diameter);
277 SpiralTileIterator(TileIndex start_north, uint radius, uint w, uint h);
278
279 bool operator==(const SpiralTileIterator &rhs) const { return this->x == rhs.x && this->y == rhs.y; }
280 bool operator==(const std::default_sentinel_t &) const { return this->IsEnd(); }
281
282 TileIndex operator*() const { return TileXY(this->x, this->y); }
283
284 SpiralTileIterator &operator++()
285 {
286 this->Increment();
287 this->SkipOutsideMap();
288 return *this;
289 }
290
291 SpiralTileIterator operator++(int)
292 {
293 SpiralTileIterator result = *this;
294 ++*this;
295 return result;
296 }
297
298private:
299 /* set by constructor, const afterwards */
300 uint max_radius;
302
303 /* mutable iterator state */
304 uint cur_radius;
305 DiagDirection dir;
306 uint position;
307 uint x, y;
308
309 void SkipOutsideMap();
310 void InitPosition();
311 void Increment();
312
317 bool IsEnd() const
318 {
319 return this->cur_radius == this->max_radius && this->dir != DiagDirection::Invalid;
320 }
321};
322
327public:
349 SpiralTileSequence(TileIndex center, uint diameter) : start(center, diameter) {}
350
375 SpiralTileSequence(TileIndex start_north, uint radius, uint w, uint h) : start(start_north, radius, w, h) {}
376
377 SpiralTileIterator begin() const { return start; }
378 std::default_sentinel_t end() const { return std::default_sentinel_t(); }
379
380private:
381 SpiralTileIterator start;
382};
383
384#endif /* TILEAREA_TYPE_H */
TileIterator & operator++() override
Move ourselves to the next tile in the rectangle on the map.
Definition tilearea.cpp:235
DiagonalTileIterator(const DiagonalTileArea &ta)
Construct the iterator.
uint base_x
The base tile x coordinate from where the iterating happens.
int a_max
The (rotated) x coordinate of the end of the iteration.
DiagonalTileIterator(TileIndex corner1, TileIndex corner2)
Construct the iterator.
int b_max
The (rotated) y coordinate of the end of the iteration.
int b_cur
The current (rotated) y coordinate of the iteration.
int a_cur
The current (rotated) x coordinate of the iteration.
uint base_y
The base tile y coordinate from where the iterating happens.
Iterator to iterate over a tile area (rectangle) of the map.
OrthogonalTileIterator(TileIndex corner1, TileIndex corner2)
Construct the iterator.
OrthogonalTileIterator(const OrthogonalTileArea &ta)
Construct the iterator.
int y
The current 'y' position in the rectangle.
int w
The width of the iterated area.
int x
The current 'x' position in the rectangle.
TileIterator & operator++() override
Move ourselves to the next tile in the rectangle on the map.
Helper class for SpiralTileSequence.
SpiralTileIterator(TileIndex center, uint diameter)
Create the iterator.
Definition tilearea.cpp:301
void InitPosition()
Initialise "position" after "dir" was changed.
Definition tilearea.cpp:353
bool IsEnd() const
Test whether the iterator reached the end.
void Increment()
Advance the internal state to the next potential tile.
Definition tilearea.cpp:362
void SkipOutsideMap()
Advance the internal state until it reaches a valid tile or the end.
Definition tilearea.cpp:345
SpiralTileSequence(TileIndex center, uint diameter)
Generate TileIndices for a square area around a center tile.
SpiralTileSequence(TileIndex start_north, uint radius, uint w, uint h)
Generate TileIndices for a rectangular area with an optional rectangular hole in the center.
Base class for tile iterators.
TileIndex operator*() const
Get the tile we are currently at.
TileIterator(TileIndex tile=INVALID_TILE)
Initialise the iterator starting at this tile.
TileIndex tile
The current tile we are at.
bool operator==(const TileIterator &rhs) const
Equality comparison.
virtual ~TileIterator()=default
Ensure the destructor of the sub classes are called as well.
virtual TileIterator & operator++()=0
Move ourselves to the next tile in the rectangle on the map.
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition tilearea.cpp:292
EnumIndexArray< T, DiagDirection, DiagDirection::End > DiagDirectionIndexArray
Array with DiagDirection as index.
DiagDirection
Enumeration for diagonal directions.
@ Invalid
Flag for an invalid DiagDirection.
Functions related to maps.
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:474
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:392
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:376
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
Represents a diagonal tile area.
void Clear()
Clears the TileArea by making the tile invalid and setting a and b to 0.
int16_t b
Extent in diagonal "y" direction (may be negative to signify the area stretches upwards).
bool Contains(TileIndex tile) const
Does this tile area contain a tile?
Definition tilearea.cpp:205
int16_t a
Extent in diagonal "x" direction (may be negative to signify the area stretches to the left).
TileIndex tile
Base tile of the area.
DiagonalTileArea(TileIndex tile=INVALID_TILE, int16_t a=0, int16_t b=0)
Construct this tile area with some set values.
Represents the covered area of e.g.
OrthogonalTileIterator end() const
Returns an iterator to the end of the tile area.
Definition tilearea.cpp:162
void ClampToMap()
Clamp the tile area to map borders.
Definition tilearea.cpp:142
void Add(const OrthogonalTileArea &area)
Add another tile area to this tile area.
bool Contains(TileIndex tile) const
Does this tile area contain a tile?
Definition tilearea.cpp:104
uint16_t w
The width of the area.
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
bool Intersects(const OrthogonalTileArea &ta) const
Does this tile area intersect with another?
Definition tilearea.cpp:75
TileIndex GetCenterTile() const
Get the center tile.
void Clear()
Clears the 'tile area', i.e.
TileIndex tile
The base tile of the area.
bool IsEmpty() const
Test if this tile area is empty.
uint16_t h
The height of the area.
OrthogonalTileIterator begin() const
Returns an iterator to the beginning of the tile area.
Definition tilearea.cpp:153
OrthogonalTileArea(TileIndex tile=INVALID_TILE, uint16_t w=0, uint16_t h=0)
Construct this tile area with some set values.
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Definition tilearea.cpp:123
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.