circleTiles function
Implementation
List<Coords<num>> circleTiles(Map<String, dynamic> input) {
// This took some time and is fairly complicated, so this is the overall explanation:
// 1. Given a `LatLng` for every x degrees on a circle's circumference, convert it into a tile number
// 2. Using a `Map` per zoom level, record all the X values in it without duplicates
// 3. Under the previous record, add all the Y values within the circle (ie. to opposite the X value)
// 4. Loop over these XY values and add them to the list
// Theoretically, this could have been done using the same method as `lineTiles`, but `lineTiles` was built after this algorithm and this makes more sense for a circle
final List<LatLng> circleOutline = input['circleOutline'];
final int minZoom = input['minZoom'];
final int maxZoom = input['maxZoom'];
final Crs crs = input['crs'];
final CustomPoint<num> tileSize = input['tileSize'];
// Format: Map<z, Map<x, List<y>>>
final Map<int, Map<int, List<int>>> outlineTileNums = {};
final List<Coords<num>> coords = [];
for (int zoomLvl = minZoom; zoomLvl <= maxZoom; zoomLvl++) {
outlineTileNums[zoomLvl] = <int, List<int>>{};
for (final LatLng node in circleOutline) {
final CustomPoint<num> tile = crs
.latLngToPoint(node, zoomLvl.toDouble())
.unscaleBy(tileSize)
.floor();
outlineTileNums[zoomLvl]![tile.x.toInt()] ??= [
1000000000000,
-1000000000000
];
outlineTileNums[zoomLvl]![tile.x.toInt()] = [
tile.y < outlineTileNums[zoomLvl]![tile.x.toInt()]![0]
? tile.y.toInt()
: outlineTileNums[zoomLvl]![tile.x.toInt()]![0],
tile.y > outlineTileNums[zoomLvl]![tile.x.toInt()]![1]
? tile.y.toInt()
: outlineTileNums[zoomLvl]![tile.x.toInt()]![1],
];
}
for (final int x in outlineTileNums[zoomLvl]!.keys) {
for (int y = outlineTileNums[zoomLvl]![x]![0];
y <= outlineTileNums[zoomLvl]![x]![1];
y++) {
coords.add(
Coords(x.toDouble(), y.toDouble())..z = zoomLvl.toDouble(),
);
}
}
}
return coords;
}