From 706b457de483936f938b1bef062ea226af9e0ea3 Mon Sep 17 00:00:00 2001 From: Ian Date: Sat, 9 Apr 2022 15:23:35 +0100 Subject: [PATCH 1/3] Added tileBounds param and code, to allow a restricted set of tiles within a latLngBounds only --- lib/src/layer/tile_layer.dart | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/src/layer/tile_layer.dart b/lib/src/layer/tile_layer.dart index a5acd776e..a1855769e 100644 --- a/lib/src/layer/tile_layer.dart +++ b/lib/src/layer/tile_layer.dart @@ -4,6 +4,7 @@ import 'dart:math' as math; import 'package:collection/collection.dart' show MapEquality; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/core/bounds.dart'; import 'package:flutter_map/src/core/point.dart'; import 'package:flutter_map/src/core/util.dart' as util; @@ -249,6 +250,9 @@ class TileLayerOptions extends LayerOptions { /// Stream to notify the [TileLayer] that it needs resetting Stream? reset; + /// Only load tiles that are within these bounds + LatLngBounds? tileBounds; + TileLayerOptions( {this.attributionAlignment = Alignment.bottomRight, this.attributionBuilder, @@ -295,7 +299,8 @@ class TileLayerOptions extends LayerOptions { this.tilesContainerBuilder, this.evictErrorTileStrategy = EvictErrorTileStrategy.none, this.fastReplace = false, - this.reset}) + this.reset, + this.tileBounds}) : updateInterval = updateInterval <= 0 ? null : Duration(milliseconds: updateInterval), tileFadeInDuration = tileFadeInDuration <= 0 @@ -953,6 +958,22 @@ class _TileLayerState extends State with TickerProviderStateMixin { return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); } + // Take the existing pixelBounds, for the whole display. If there is a + // restricted tileBounds, calculate which is smaller. + Bounds _getRestrictedPixelBounds( + Bounds existingPxBounds, LatLngBounds bounds, double thisZoom) { + var swPixel = map.project(bounds.southWest!, thisZoom); + var nePixel = map.project(bounds.northEast!, thisZoom); + + var newBounds = Bounds( + CustomPoint(math.max(swPixel.x, existingPxBounds.bottomLeft.x), + math.max(nePixel.y, existingPxBounds.topRight.y)), + CustomPoint(math.min(nePixel.x, existingPxBounds.topRight.x), + math.min(swPixel.y, existingPxBounds.bottomLeft.y))); + + return newBounds; + } + // Private method to load tiles in the grid's active zoom level according to // map bounds void _update(LatLng? center) { @@ -964,6 +985,12 @@ class _TileLayerState extends State with TickerProviderStateMixin { center ??= map.center; var pixelBounds = _getTiledPixelBounds(center); + + if (options.tileBounds != null) { + pixelBounds = _getRestrictedPixelBounds( + pixelBounds, options.tileBounds!, _tileZoom ?? map.zoom); + } + var tileRange = _pxBoundsToTileRange(pixelBounds); var tileCenter = tileRange.center; final queue = >[]; From dc212c18f5dcdfbb8e5ad136fb901fc6227aea3f Mon Sep 17 00:00:00 2001 From: Ian Date: Sat, 9 Apr 2022 15:30:10 +0100 Subject: [PATCH 2/3] Remove unneeded packages... --- lib/src/layer/tile_layer.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/src/layer/tile_layer.dart b/lib/src/layer/tile_layer.dart index a1855769e..180f42dd3 100644 --- a/lib/src/layer/tile_layer.dart +++ b/lib/src/layer/tile_layer.dart @@ -6,17 +6,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/core/bounds.dart'; -import 'package:flutter_map/src/core/point.dart'; import 'package:flutter_map/src/core/util.dart' as util; -import 'package:flutter_map/src/geo/crs/crs.dart'; -import 'package:flutter_map/src/layer/tile_builder/tile_builder.dart'; -import 'package:flutter_map/src/layer/tile_provider/tile_provider.dart'; import 'package:flutter_map/src/map/map.dart'; import 'package:latlong2/latlong.dart'; import 'package:tuple/tuple.dart'; -import 'layer.dart'; - typedef TemplateFunction = String Function( String str, Map data); From 5b6c61b0890fd710cb443a5593daf35a079f9925 Mon Sep 17 00:00:00 2001 From: Ian Date: Sun, 10 Apr 2022 21:24:20 +0100 Subject: [PATCH 3/3] add option tileBounds which will do a basic latLng test to check its inside, and not use tile if outside --- lib/src/layer/tile_layer.dart | 46 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/lib/src/layer/tile_layer.dart b/lib/src/layer/tile_layer.dart index 180f42dd3..6fad594cf 100644 --- a/lib/src/layer/tile_layer.dart +++ b/lib/src/layer/tile_layer.dart @@ -952,22 +952,6 @@ class _TileLayerState extends State with TickerProviderStateMixin { return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); } - // Take the existing pixelBounds, for the whole display. If there is a - // restricted tileBounds, calculate which is smaller. - Bounds _getRestrictedPixelBounds( - Bounds existingPxBounds, LatLngBounds bounds, double thisZoom) { - var swPixel = map.project(bounds.southWest!, thisZoom); - var nePixel = map.project(bounds.northEast!, thisZoom); - - var newBounds = Bounds( - CustomPoint(math.max(swPixel.x, existingPxBounds.bottomLeft.x), - math.max(nePixel.y, existingPxBounds.topRight.y)), - CustomPoint(math.min(nePixel.x, existingPxBounds.topRight.x), - math.min(swPixel.y, existingPxBounds.bottomLeft.y))); - - return newBounds; - } - // Private method to load tiles in the grid's active zoom level according to // map bounds void _update(LatLng? center) { @@ -979,12 +963,6 @@ class _TileLayerState extends State with TickerProviderStateMixin { center ??= map.center; var pixelBounds = _getTiledPixelBounds(center); - - if (options.tileBounds != null) { - pixelBounds = _getRestrictedPixelBounds( - pixelBounds, options.tileBounds!, _tileZoom ?? map.zoom); - } - var tileRange = _pxBoundsToTileRange(pixelBounds); var tileCenter = tileRange.center; final queue = >[]; @@ -1017,6 +995,14 @@ class _TileLayerState extends State with TickerProviderStateMixin { final coords = Coords(i.toDouble(), j.toDouble()); coords.z = _tileZoom!; + if (options.tileBounds != null) { + var tilePxBounds = _pxBoundsToTileRange( + _latLngBoundsToPixelBounds(options.tileBounds!, _tileZoom!)); + if (!_areCoordsInsideTileBounds(coords, tilePxBounds)) { + continue; + } + } + if (!_isValidTile(coords)) { continue; } @@ -1058,6 +1044,22 @@ class _TileLayerState extends State with TickerProviderStateMixin { return true; } + bool _areCoordsInsideTileBounds(Coords coords, Bounds? tileBounds) { + var bounds = tileBounds ?? _globalTileRange; + if ((coords.x < bounds.min.x || coords.x > bounds.max.x) || + (coords.y < bounds.min.y || coords.y > bounds.max.y)) { + return false; + } + return true; + } + + Bounds _latLngBoundsToPixelBounds(LatLngBounds bounds, double thisZoom) { + var swPixel = map.project(bounds.southWest!, thisZoom).floor(); + var nePixel = map.project(bounds.northEast!, thisZoom).ceil(); + var pxBounds = Bounds(swPixel, nePixel); + return pxBounds; + } + String _tileCoordsToKey(Coords coords) { return '${coords.x}:${coords.y}:${coords.z}'; }