mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-06-23 13:40:35 +01:00
(svn r21499) -Add: diagonal tile iterator. Based on patch by fonsinchen
This commit is contained in:
parent
652e262601
commit
b20e77be92
@ -104,3 +104,64 @@ void TileArea::ClampToMap()
|
|||||||
this->h = min(this->h, MapSizeY() - TileY(this->tile));
|
this->h = min(this->h, MapSizeY() - TileY(this->tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiagonalTileIterator::DiagonalTileIterator(TileIndex corner1, TileIndex corner2) : TileIterator(corner2), base_x(TileX(corner2)), base_y(TileY(corner2)), a_cur(0), b_cur(0)
|
||||||
|
{
|
||||||
|
assert(corner1 < MapSize());
|
||||||
|
assert(corner2 < MapSize());
|
||||||
|
|
||||||
|
int dist_x = TileX(corner1) - TileX(corner2);
|
||||||
|
int dist_y = TileY(corner1) - TileY(corner2);
|
||||||
|
this->a_max = dist_x + dist_y;
|
||||||
|
this->b_max = dist_y - dist_x;
|
||||||
|
|
||||||
|
/* Unfortunately we can't find a new base and make all a and b positive because
|
||||||
|
* the new base might be a "flattened" corner where there actually is no single
|
||||||
|
* tile. If we try anyway the result is either inaccurate ("one off" half of the
|
||||||
|
* time) or the code gets much more complex;
|
||||||
|
*
|
||||||
|
* We also need to increment here to have equality as marker for the end of a row or
|
||||||
|
* column. Like that it's shorter than having another if/else in operator++
|
||||||
|
*/
|
||||||
|
if (this->a_max > 0) {
|
||||||
|
this->a_max++;
|
||||||
|
} else {
|
||||||
|
this->a_max--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->b_max > 0) {
|
||||||
|
this->b_max++;
|
||||||
|
} else {
|
||||||
|
this->b_max--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TileIterator &DiagonalTileIterator::operator++()
|
||||||
|
{
|
||||||
|
assert(this->tile != INVALID_TILE);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Iterate using the rotated coordinates. */
|
||||||
|
if (this->a_max > 0) {
|
||||||
|
++this->a_cur;
|
||||||
|
} else {
|
||||||
|
--this->a_cur;
|
||||||
|
}
|
||||||
|
if (this->a_cur == this->a_max) {
|
||||||
|
this->a_cur = 0;
|
||||||
|
if (this->b_max > 0) {
|
||||||
|
++this->b_cur;
|
||||||
|
} else {
|
||||||
|
--this->b_cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And convert the coordinates back once we've gone to the next tile. */
|
||||||
|
uint x = this->base_x + (this->a_cur - this->b_cur) / 2;
|
||||||
|
uint y = this->base_y + (this->b_cur + this->a_cur) / 2;
|
||||||
|
/* Prevent wrapping around the map's borders. */
|
||||||
|
this->tile = x >= MapSizeX() || y >= MapSizeY() ? INVALID_TILE : TileXY(x, y);
|
||||||
|
} while (this->tile > MapSize() && this->b_max != this->b_cur);
|
||||||
|
|
||||||
|
if (this->b_max == this->b_cur) this->tile = INVALID_TILE;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
@ -73,11 +73,12 @@ protected:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
/** Some compilers really like this. */
|
/** Some compilers really like this. */
|
||||||
virtual ~TileIterator()
|
virtual ~TileIterator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
/**
|
/**
|
||||||
* Get the tile we are currently at.
|
* Get the tile we are currently at.
|
||||||
* @return The tile we are at, or INVALID_TILE when we're done.
|
* @return The tile we are at, or INVALID_TILE when we're done.
|
||||||
@ -128,6 +129,27 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Iterator to iterate over a diagonal area of the map. */
|
||||||
|
class DiagonalTileIterator : public TileIterator {
|
||||||
|
private:
|
||||||
|
uint base_x, base_y; ///< The base tile x and y coordinates from where the iterating happens.
|
||||||
|
int a_cur, b_cur; ///< The current (rotated) x and y coordinates of the iteration.
|
||||||
|
int a_max, b_max; ///< The (rotated) x and y coordinates of the end of the iteration.
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct the iterator.
|
||||||
|
* @param begin Tile from where to begin iterating.
|
||||||
|
* @param end Tile where to end the iterating.
|
||||||
|
*/
|
||||||
|
DiagonalTileIterator(TileIndex begin, TileIndex end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move ourselves to the next tile in the rectange on the map.
|
||||||
|
*/
|
||||||
|
TileIterator& operator ++();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A loop which iterates over the tiles of a TileArea.
|
* A loop which iterates over the tiles of a TileArea.
|
||||||
* @param var The name of the variable which contains the current tile.
|
* @param var The name of the variable which contains the current tile.
|
||||||
|
Loading…
Reference in New Issue
Block a user