Add general function for checking size of contiguous tile area
This commit is contained in:
53
src/map.cpp
53
src/map.cpp
@@ -16,6 +16,7 @@
|
|||||||
#include "tunnelbridge_map.h"
|
#include "tunnelbridge_map.h"
|
||||||
#include "3rdparty/cpp-btree/btree_map.h"
|
#include "3rdparty/cpp-btree/btree_map.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
@@ -370,6 +371,58 @@ bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOn
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generalized contiguous matching tile area size threshold function.
|
||||||
|
* Contiguous means directly adjacent by DiagDirection directions.
|
||||||
|
*
|
||||||
|
* @param tile to start the search from.
|
||||||
|
* @param threshold minimum number of matching tiles for success, searching is halted when this is reached.
|
||||||
|
* @param proc callback testing function pointer.
|
||||||
|
* @param user_data to be passed to the callback function. Depends on the implementation
|
||||||
|
* @return whether the contiguous tile area size is >= threshold
|
||||||
|
* @pre proc != nullptr
|
||||||
|
*/
|
||||||
|
bool EnoughContiguousTilesMatchingCondition(TileIndex tile, uint threshold, TestTileOnSearchProc proc, void *user_data)
|
||||||
|
{
|
||||||
|
assert(proc != nullptr);
|
||||||
|
if (threshold == 0) return true;
|
||||||
|
|
||||||
|
static_assert(MAX_MAP_TILES_BITS <= 30);
|
||||||
|
|
||||||
|
btree::btree_set<uint32> processed_tiles;
|
||||||
|
std::deque<uint32> candidates;
|
||||||
|
uint matching_count = 0;
|
||||||
|
|
||||||
|
auto process_tile = [&](TileIndex t, DiagDirection exclude_onward_dir) {
|
||||||
|
auto iter = processed_tiles.lower_bound(t);
|
||||||
|
if (iter != processed_tiles.end() && *iter == t) {
|
||||||
|
/* done this tile already */
|
||||||
|
} else {
|
||||||
|
if (proc(t, user_data)) {
|
||||||
|
matching_count++;
|
||||||
|
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
||||||
|
if (dir == exclude_onward_dir) continue;
|
||||||
|
TileIndex neighbour_tile = AddTileIndexDiffCWrap(t, TileIndexDiffCByDiagDir(dir));
|
||||||
|
if (IsValidTile(neighbour_tile)) {
|
||||||
|
candidates.push_back(neighbour_tile | (ReverseDiagDir(dir) << 30));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processed_tiles.insert(iter, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process_tile(tile, INVALID_DIAGDIR);
|
||||||
|
|
||||||
|
while (matching_count < threshold && !candidates.empty()) {
|
||||||
|
uint32 next = candidates.front();
|
||||||
|
candidates.pop_front();
|
||||||
|
TileIndex t = GB(next, 0, 30);
|
||||||
|
DiagDirection exclude_onward_dir = (DiagDirection)GB(next, 30, 2);
|
||||||
|
process_tile(t, exclude_onward_dir);
|
||||||
|
}
|
||||||
|
return matching_count >= threshold;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the distance for the closest tile with water/land given a tile
|
* Finds the distance for the closest tile with water/land given a tile
|
||||||
* @param tile the tile to find the distance too
|
* @param tile the tile to find the distance too
|
||||||
|
@@ -438,6 +438,8 @@ typedef bool TestTileOnSearchProc(TileIndex tile, void *user_data);
|
|||||||
bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
|
bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data);
|
||||||
bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
|
bool CircularTileSearch(TileIndex *tile, uint radius, uint w, uint h, TestTileOnSearchProc proc, void *user_data);
|
||||||
|
|
||||||
|
bool EnoughContiguousTilesMatchingCondition(TileIndex tile, uint threshold, TestTileOnSearchProc proc, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a random tile out of a given seed.
|
* Get a random tile out of a given seed.
|
||||||
* @param r the random 'seed'
|
* @param r the random 'seed'
|
||||||
|
Reference in New Issue
Block a user