Skip to content

Instantly share code, notes, and snippets.

@kherel
Last active December 23, 2021 13:04
Show Gist options
  • Save kherel/5366438770964fbff166464a63ad7401 to your computer and use it in GitHub Desktop.
Save kherel/5366438770964fbff166464a63ad7401 to your computer and use it in GitHub Desktop.
Find all tiles inside bounding box
import 'package:app/config/map_config.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
class TilesHelper {
final TileLayerOptions options;
final double minZoom;
final double maxZoom;
/// Tile size (default 256)
final int tileSize;
final LatLng southEast;
final LatLng northWest;
TilesHelper({
this.minZoom = MapConfig.minZoom,
this.maxZoom = MapConfig.maxZoom,
this.tileSize = 256,
required this.southEast,
required this.northWest,
TileLayerOptions? options,
}) : options =
options ?? TileLayerOptions(urlTemplate: MapConfig.urlTemplate);
List<Coords<num>> _rectangleTiles() {
final LatLngBounds bounds = LatLngBounds.fromPoints([southEast, northWest]);
const Crs crs = Epsg3857();
final CustomPoint<num> tileSize = CustomPoint(this.tileSize, this.tileSize);
final coords = <Coords<num>>[];
for (int zoomLvl = minZoom.floor(); zoomLvl <= maxZoom; zoomLvl++) {
final nwCustomPoint = crs
.latLngToPoint(bounds.northWest, zoomLvl.toDouble())
.unscaleBy(tileSize)
.floor();
final seCustomPoint = crs
.latLngToPoint(bounds.southEast, zoomLvl.toDouble())
.unscaleBy(tileSize)
.ceil() -
const CustomPoint(1, 1);
for (num x = nwCustomPoint.x; x <= seCustomPoint.x; x++) {
for (num y = nwCustomPoint.y; y <= seCustomPoint.y; y++) {
coords.add(Coords(x, y)..z = zoomLvl);
}
}
}
return coords;
}
int invertY(int y, int z) {
return ((1 << z) - 1) - y;
}
String getSubdomain(Coords coords, TileLayerOptions options) {
if (options.subdomains.isEmpty) {
return '';
}
var index = (coords.x + coords.y).round() % options.subdomains.length;
return options.subdomains[index];
}
List<OneTileData> get tileDataList => _rectangleTiles().map(oneTile).toList();
OneTileData oneTile(Coords<num> coords) {
var z = coords.z;
if (options.zoomReverse) {
z = options.maxZoom - z;
}
z += options.zoomOffset;
return OneTileData(
initCoors: coords,
x: coords.x.round(),
y: options.tms ? invertY(coords.y.round(), z.round()) : coords.y.round(),
z: z.round(),
options: options,
);
}
}
class OneTileData {
final int x;
final int y;
final int z;
final Coords<num> initCoors;
final TileLayerOptions options;
OneTileData({
required this.x,
required this.y,
required this.z,
required this.initCoors,
required this.options,
});
Map<String, String> toMap() {
return {
'x': x.toString(),
'y': y.toString(),
'z': z.toString(),
'r': '@2x',
};
}
@override
String toString() {
return toMap().toString();
}
String get url => options.templateFunction(options.urlTemplate!, toMap());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment