From c41d4521072d460e1bfcbe958372eb52d7db0c95 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 9 Jan 2024 03:17:15 +0000 Subject: [PATCH] Add function to iterate (curved) circular tile area --- src/map.cpp | 33 +++++++++++++++++++++++++++++++++ src/tilesearch_func.h | 10 ++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/map.cpp b/src/map.cpp index 78867f4c5e..80e97dc6a0 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -476,6 +476,39 @@ bool EnoughContiguousTilesMatchingCondition(TileIndex tile, uint threshold, Test return matching_count >= threshold; } +void IterateCurvedCircularTileArea(TileIndex centre_tile, uint diameter, TileIteratorProc proc, void *user_data) +{ + const uint radius_sq = ((diameter * diameter) + 2) / 4; + const uint centre_radius = (diameter + 1) / 2; + + const int centre_x = TileX(centre_tile); + const int centre_y = TileY(centre_tile); + + /* Centre row */ + for (int x = std::max(0, centre_x - centre_radius); x <= std::min(MapMaxX(), centre_x + centre_radius); x++) { + proc(TileXY(x, centre_y), user_data); + } + + /* Other (shorter) rows */ + for (uint offset = 1; offset <= centre_radius; offset++) { + const uint offset_sq = offset * offset; + uint half_width = 0; + while (offset_sq + (half_width * half_width) < radius_sq) { + half_width++; + } + const int x_left = std::max(0, centre_x - half_width); + const int x_right = std::min(MapMaxX(), centre_x + half_width); + auto iterate_row = [&](int y) { + if (y < 0 || y > (int)MapMaxY()) return; + for (int x = x_left; x <= x_right; x++) { + proc(TileXY(x, y), user_data); + } + }; + iterate_row(centre_y - offset); + iterate_row(centre_y + offset); + } +} + /** * Finds the distance for the closest tile with water/land given a tile * @param tile the tile to find the distance too diff --git a/src/tilesearch_func.h b/src/tilesearch_func.h index b74df845fc..734be04e4a 100644 --- a/src/tilesearch_func.h +++ b/src/tilesearch_func.h @@ -26,4 +26,14 @@ bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOn bool EnoughContiguousTilesMatchingCondition(TileIndex tile, uint threshold, TestTileOnSearchProc proc, void *user_data); +/** + * A callback function type for iterating tiles. + * + * @param tile The tile to test + * @param user_data additional data for the callback function to use + */ +typedef void TileIteratorProc(TileIndex tile, void *user_data); + +void IterateCurvedCircularTileArea(TileIndex centre_tile, uint diameter, TileIteratorProc proc, void *user_data); + #endif /* TILESEARCH_FUNC_H */