Skip to content

Commit 77bd6da

Browse files
authored
v10.1: support flutter_map v8 (#177)
1 parent b9aaf09 commit 77bd6da

File tree

10 files changed

+226
-202
lines changed

10 files changed

+226
-202
lines changed

.github/workflows/main.yml

-22
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,6 @@ concurrency:
88
cancel-in-progress: true
99

1010
jobs:
11-
score-package:
12-
name: "Score Package"
13-
runs-on: ubuntu-latest
14-
steps:
15-
- name: Checkout Repository
16-
uses: actions/checkout@v4
17-
- name: Run Dart Package Analyser
18-
uses: axel-op/dart-package-analyzer@master
19-
id: analysis
20-
with:
21-
githubToken: ${{ secrets.GITHUB_TOKEN }}
22-
- name: Check Package Scores
23-
env:
24-
TOTAL: ${{ steps.analysis.outputs.total }}
25-
TOTAL_MAX: ${{ steps.analysis.outputs.total_max }}
26-
run: |
27-
if (( $TOTAL < $TOTAL_MAX ))
28-
then
29-
echo Package score less than available score. Improve the score!
30-
exit 1
31-
fi
32-
3311
analyse-code:
3412
name: "Analyse Code"
3513
runs-on: ubuntu-latest

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Many thanks to my sponsors, no matter how much or how little they donated. Spons
1818

1919
# Changelog
2020

21+
## [10.1.0] - 2025/02/02
22+
23+
* Added support for flutter_map v8
24+
2125
## [10.0.0] - "Better Browsing" - 2025/01/11
2226

2327
This update builds on v9 to fully embrace the new many-to-many relationship between tiles and stores, which allows for more flexibility when constructing the `FMTCTileProvider`.

example/lib/src/screens/main/map_view/components/download_progress/components/render_object.dart

+17-6
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,9 @@ class _DownloadProgressMaskerRenderer extends RenderProxyBox {
230230

231231
/// Project specified coordinates to a screen space [Rect]
232232
Rect _calculateRectOfCoords(LatLng nwCoord, LatLng seCoord) {
233-
final nwScreen = mapCamera.latLngToScreenPoint(nwCoord);
234-
final seScreen = mapCamera.latLngToScreenPoint(seCoord);
235-
return Rect.fromPoints(nwScreen.toOffset(), seScreen.toOffset());
233+
final nwScreen = mapCamera.latLngToScreenOffset(nwCoord);
234+
final seScreen = mapCamera.latLngToScreenOffset(seCoord);
235+
return Rect.fromPoints(nwScreen, seScreen);
236236
}
237237

238238
/// Handles incoming tiles from the input stream, modifying the [_tileMapping]
@@ -272,9 +272,20 @@ class _DownloadProgressMaskerRenderer extends RenderProxyBox {
272272
} else {
273273
final zoom = tile.z.toDouble();
274274
_tileMapping[intermediateZoomTile] = tmv = _TileMappingValue.newTile(
275-
nwCoord: mapCamera.crs.pointToLatLng(tile * tileSize, zoom),
276-
seCoord: mapCamera.crs
277-
.pointToLatLng((tile + const Point(1, 1)) * tileSize, zoom),
275+
nwCoord: mapCamera.crs.offsetToLatLng(
276+
Offset(
277+
(tile.x * tileSize).toDouble(),
278+
(tile.y * tileSize).toDouble(),
279+
),
280+
zoom,
281+
),
282+
seCoord: mapCamera.crs.offsetToLatLng(
283+
Offset(
284+
((tile.x + 1) * tileSize).toDouble(),
285+
((tile.y + 1) * tileSize).toDouble(),
286+
),
287+
zoom,
288+
),
278289
);
279290
_mostRecentTile =
280291
() => _calculateRectOfCoords(tmv.nwCoord, tmv.seCoord);

example/lib/src/screens/main/map_view/map_view.dart

+3-6
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ class _MapViewState extends State<MapView> with TickerProviderStateMixin {
171171
final coords = provider.currentConstructingCoordinates;
172172
if (coords.length > 1) {
173173
final newPointPos = _mapController.mapController.camera
174-
.latLngToScreenPoint(coords.first)
175-
.toOffset();
174+
.latLngToScreenOffset(coords.first);
176175
provider.customPolygonSnap = coords.first != coords.last &&
177176
sqrt(
178177
pow(newPointPos.dx - evt.localPosition.dx, 2) +
@@ -196,11 +195,9 @@ class _MapViewState extends State<MapView> with TickerProviderStateMixin {
196195
final coords = provider.currentConstructingCoordinates;
197196
if (coords.length > 1) {
198197
final newPointPos = _mapController.mapController.camera
199-
.latLngToScreenPoint(coords.first)
200-
.toOffset();
198+
.latLngToScreenOffset(coords.first);
201199
final centerPos = _mapController.mapController.camera
202-
.latLngToScreenPoint(provider.currentNewPointPos!)
203-
.toOffset();
200+
.latLngToScreenOffset(provider.currentNewPointPos!);
204201
provider.customPolygonSnap = coords.first != coords.last &&
205202
sqrt(
206203
pow(newPointPos.dx - centerPos.dx, 2) +

example/pubspec.yaml

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: fmtc_demo
22
description: The demo app for 'flutter_map_tile_caching', showcasing its functionality and use-cases.
33
publish_to: "none"
4-
version: 10.0.0
4+
version: 10.1.0
55

66
environment:
77
sdk: ">=3.6.0 <4.0.0"
@@ -33,9 +33,7 @@ dependencies:
3333

3434
dependency_overrides:
3535
flutter_map:
36-
git:
37-
url: https://github.com/fleaflet/flutter_map.git
38-
ref: d816b4d54f9245e260b125ea1adbf300b5c39843
36+
git: https://github.com/fleaflet/flutter_map.git
3937
flutter_map_tile_caching:
4038
path: ../
4139

lib/src/bulk_download/internal/tile_loops/count.dart

+74-65
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,17 @@ class TileCounters {
3838
for (double zoomLvl = region.minZoom.toDouble();
3939
zoomLvl <= region.maxZoom;
4040
zoomLvl++) {
41-
final nwPoint = (region.crs.latLngToPoint(northWest, zoomLvl) /
42-
region.options.tileSize)
43-
.floor();
44-
final sePoint = (region.crs.latLngToPoint(southEast, zoomLvl) /
45-
region.options.tileSize)
46-
.ceil() -
47-
const Point(1, 1);
48-
49-
tileCount += (sePoint.x - nwPoint.x + 1) * (sePoint.y - nwPoint.y + 1);
41+
final scaleLvl = region.crs.scale(zoomLvl);
42+
43+
final nw = region.crs.latLngToXY(northWest, scaleLvl);
44+
final nwX = (nw.$1 / region.options.tileDimension).floor();
45+
final nwY = (nw.$2 / region.options.tileDimension).floor();
46+
47+
final se = region.crs.latLngToXY(southEast, scaleLvl);
48+
final seX = (se.$1 / region.options.tileDimension).ceil() - 1;
49+
final seY = (se.$2 / region.options.tileDimension).ceil() - 1;
50+
51+
tileCount += (seX - nwX + 1) * (seY - nwY + 1);
5052
}
5153

5254
return _trimToRange(region, tileCount);
@@ -64,20 +66,19 @@ class TileCounters {
6466
0,
6567
);
6668

67-
for (int zoomLvl = region.minZoom; zoomLvl <= region.maxZoom; zoomLvl++) {
68-
final centerTile = (region.crs.latLngToPoint(
69-
region.originalRegion.center,
70-
zoomLvl.toDouble(),
71-
) /
72-
region.options.tileSize)
73-
.floor();
69+
for (double zoomLvl = region.minZoom.toDouble();
70+
zoomLvl <= region.maxZoom;
71+
zoomLvl++) {
72+
final scaleLvl = region.crs.scale(zoomLvl);
73+
74+
final (_, rawCenterY) =
75+
region.crs.latLngToXY(region.originalRegion.center, scaleLvl);
76+
final centerY = (rawCenterY / region.options.tileDimension).floor();
7477

75-
final radius = centerTile.y -
76-
(region.crs.latLngToPoint(edgeTile, zoomLvl.toDouble()) /
77-
region.options.tileSize)
78-
.floor()
79-
.y;
78+
final (_, rawEdgeY) = region.crs.latLngToXY(edgeTile, scaleLvl);
79+
final edgeY = (rawEdgeY / region.options.tileDimension).floor();
8080

81+
final radius = centerY - edgeY;
8182
final radiusSquared = radius * radius;
8283

8384
if (radius == 0) {
@@ -113,20 +114,20 @@ class TileCounters {
113114
final p1 = polygon.points[i1];
114115
final p2 = polygon.points[i2];
115116

116-
final normal = Point(p2.y - p1.y, p1.x - p2.x);
117+
final normal = Point(p2.$2 - p1.$2, p1.$1 - p2.$1);
117118

118119
var minA = largestInt;
119120
var maxA = smallestInt;
120121
for (final p in a.points) {
121-
final projected = normal.x * p.x + normal.y * p.y;
122+
final projected = normal.x * p.$1 + normal.y * p.$2;
122123
if (projected < minA) minA = projected;
123124
if (projected > maxA) maxA = projected;
124125
}
125126

126127
var minB = largestInt;
127128
var maxB = smallestInt;
128129
for (final p in b.points) {
129-
final projected = normal.x * p.x + normal.y * p.y;
130+
final projected = normal.x * p.$1 + normal.y * p.$2;
130131
if (projected < minB) minB = projected;
131132
if (projected > maxB) maxB = projected;
132133
}
@@ -145,6 +146,8 @@ class TileCounters {
145146
for (double zoomLvl = region.minZoom.toDouble();
146147
zoomLvl <= region.maxZoom;
147148
zoomLvl++) {
149+
final scaleLvl = region.crs.scale(zoomLvl);
150+
148151
final generatedTiles = <int>[];
149152

150153
for (final rect in lineOutline) {
@@ -169,51 +172,49 @@ class TileCounters {
169172
];
170173

171174
final rotatedRectangleNW =
172-
(region.crs.latLngToPoint(rotatedRectangle.topLeft, zoomLvl) /
173-
region.options.tileSize)
175+
(region.crs.latLngToXY(rotatedRectangle.topLeft, scaleLvl) /
176+
region.options.tileDimension)
174177
.floor();
175178
final rotatedRectangleNE =
176-
(region.crs.latLngToPoint(rotatedRectangle.topRight, zoomLvl) /
177-
region.options.tileSize)
179+
(region.crs.latLngToXY(rotatedRectangle.topRight, scaleLvl) /
180+
region.options.tileDimension)
178181
.ceil() -
179-
const Point(1, 0);
182+
(1, 0);
180183
final rotatedRectangleSW =
181-
(region.crs.latLngToPoint(rotatedRectangle.bottomLeft, zoomLvl) /
182-
region.options.tileSize)
184+
(region.crs.latLngToXY(rotatedRectangle.bottomLeft, scaleLvl) /
185+
region.options.tileDimension)
183186
.ceil() -
184-
const Point(0, 1);
187+
(0, 1);
185188
final rotatedRectangleSE =
186-
(region.crs.latLngToPoint(rotatedRectangle.bottomRight, zoomLvl) /
187-
region.options.tileSize)
189+
(region.crs.latLngToXY(rotatedRectangle.bottomRight, scaleLvl) /
190+
region.options.tileDimension)
188191
.ceil() -
189-
const Point(1, 1);
192+
(1, 1);
190193

191-
final straightRectangleNW = (region.crs.latLngToPoint(
194+
final straightRectangleNW = (region.crs.latLngToXY(
192195
LatLng(rotatedRectangleLats.max, rotatedRectangleLngs.min),
193-
zoomLvl,
196+
scaleLvl,
194197
) /
195-
region.options.tileSize)
198+
region.options.tileDimension)
196199
.floor();
197-
final straightRectangleSE = (region.crs.latLngToPoint(
200+
final straightRectangleSE = (region.crs.latLngToXY(
198201
LatLng(
199202
rotatedRectangleLats.min,
200203
rotatedRectangleLngs.max,
201204
),
202-
zoomLvl,
205+
scaleLvl,
203206
) /
204-
region.options.tileSize)
207+
region.options.tileDimension)
205208
.ceil() -
206-
const Point(1, 1);
209+
(1, 1);
207210

208-
for (int x = straightRectangleNW.x; x <= straightRectangleSE.x; x++) {
211+
for (int x = straightRectangleNW.$1; x <= straightRectangleSE.$1; x++) {
209212
bool foundOverlappingTile = false;
210-
for (int y = straightRectangleNW.y; y <= straightRectangleSE.y; y++) {
211-
final tile = _Polygon(
212-
Point(x, y),
213-
Point(x + 1, y),
214-
Point(x + 1, y + 1),
215-
Point(x, y + 1),
216-
);
213+
for (int y = straightRectangleNW.$2;
214+
y <= straightRectangleSE.$2;
215+
y++) {
216+
final tile =
217+
_Polygon((x, y), (x + 1, y), (x + 1, y + 1), (x, y + 1));
217218
if (generatedTiles.contains(tile.hashCode)) continue;
218219
if (overlap(
219220
_Polygon(
@@ -251,35 +252,43 @@ class TileCounters {
251252
for (double zoomLvl = region.minZoom.toDouble();
252253
zoomLvl <= region.maxZoom;
253254
zoomLvl++) {
254-
final allOutlineTiles = <Point<int>>{};
255+
final scaleLvl = region.crs.scale(zoomLvl);
255256

256-
final pointsOutline = customPolygonOutline
257-
.map((e) => region.crs.latLngToPoint(e, zoomLvl).floor());
257+
final allOutlineTiles = <(int, int)>{};
258258

259-
for (final triangle in Earcut.triangulateFromPoints(
260-
pointsOutline.map((e) => e.toDoublePoint()),
259+
final pointsOutline = customPolygonOutline
260+
.map((e) => region.crs.latLngToXY(e, scaleLvl).floorToDouble());
261+
262+
for (final triangle in Earcut.triangulateRaw(
263+
List.generate(
264+
pointsOutline.length * 2,
265+
(i) => i.isEven
266+
? pointsOutline.elementAt(i ~/ 2).$1
267+
: pointsOutline.elementAt(i ~/ 2).$2,
268+
growable: false,
269+
),
261270
).map(pointsOutline.elementAt).slices(3)) {
262271
final outlineTiles = {
263272
..._bresenhamsLGA(
264-
Point(triangle[0].x, triangle[0].y),
265-
Point(triangle[1].x, triangle[1].y),
266-
unscaleBy: region.options.tileSize,
273+
triangle[0],
274+
triangle[1],
275+
unscaleBy: region.options.tileDimension,
267276
),
268277
..._bresenhamsLGA(
269-
Point(triangle[1].x, triangle[1].y),
270-
Point(triangle[2].x, triangle[2].y),
271-
unscaleBy: region.options.tileSize,
278+
triangle[1],
279+
triangle[2],
280+
unscaleBy: region.options.tileDimension,
272281
),
273282
..._bresenhamsLGA(
274-
Point(triangle[2].x, triangle[2].y),
275-
Point(triangle[0].x, triangle[0].y),
276-
unscaleBy: region.options.tileSize,
283+
triangle[2],
284+
triangle[0],
285+
unscaleBy: region.options.tileDimension,
277286
),
278287
};
279288
allOutlineTiles.addAll(outlineTiles);
280289

281290
final byY = <int, Set<int>>{};
282-
for (final Point(:x, :y) in outlineTiles) {
291+
for (final (x, y) in outlineTiles) {
283292
(byY[y] ??= {}).add(x);
284293
}
285294

0 commit comments

Comments
 (0)