@@ -38,15 +38,17 @@ class TileCounters {
38
38
for (double zoomLvl = region.minZoom.toDouble ();
39
39
zoomLvl <= region.maxZoom;
40
40
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 );
50
52
}
51
53
52
54
return _trimToRange (region, tileCount);
@@ -64,20 +66,19 @@ class TileCounters {
64
66
0 ,
65
67
);
66
68
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 ();
74
77
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 ();
80
80
81
+ final radius = centerY - edgeY;
81
82
final radiusSquared = radius * radius;
82
83
83
84
if (radius == 0 ) {
@@ -113,20 +114,20 @@ class TileCounters {
113
114
final p1 = polygon.points[i1];
114
115
final p2 = polygon.points[i2];
115
116
116
- final normal = Point (p2.y - p1.y , p1.x - p2.x );
117
+ final normal = Point (p2.$2 - p1.$2 , p1.$1 - p2.$1 );
117
118
118
119
var minA = largestInt;
119
120
var maxA = smallestInt;
120
121
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 ;
122
123
if (projected < minA) minA = projected;
123
124
if (projected > maxA) maxA = projected;
124
125
}
125
126
126
127
var minB = largestInt;
127
128
var maxB = smallestInt;
128
129
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 ;
130
131
if (projected < minB) minB = projected;
131
132
if (projected > maxB) maxB = projected;
132
133
}
@@ -145,6 +146,8 @@ class TileCounters {
145
146
for (double zoomLvl = region.minZoom.toDouble ();
146
147
zoomLvl <= region.maxZoom;
147
148
zoomLvl++ ) {
149
+ final scaleLvl = region.crs.scale (zoomLvl);
150
+
148
151
final generatedTiles = < int > [];
149
152
150
153
for (final rect in lineOutline) {
@@ -169,51 +172,49 @@ class TileCounters {
169
172
];
170
173
171
174
final rotatedRectangleNW =
172
- (region.crs.latLngToPoint (rotatedRectangle.topLeft, zoomLvl ) /
173
- region.options.tileSize )
175
+ (region.crs.latLngToXY (rotatedRectangle.topLeft, scaleLvl ) /
176
+ region.options.tileDimension )
174
177
.floor ();
175
178
final rotatedRectangleNE =
176
- (region.crs.latLngToPoint (rotatedRectangle.topRight, zoomLvl ) /
177
- region.options.tileSize )
179
+ (region.crs.latLngToXY (rotatedRectangle.topRight, scaleLvl ) /
180
+ region.options.tileDimension )
178
181
.ceil () -
179
- const Point (1 , 0 );
182
+ (1 , 0 );
180
183
final rotatedRectangleSW =
181
- (region.crs.latLngToPoint (rotatedRectangle.bottomLeft, zoomLvl ) /
182
- region.options.tileSize )
184
+ (region.crs.latLngToXY (rotatedRectangle.bottomLeft, scaleLvl ) /
185
+ region.options.tileDimension )
183
186
.ceil () -
184
- const Point (0 , 1 );
187
+ (0 , 1 );
185
188
final rotatedRectangleSE =
186
- (region.crs.latLngToPoint (rotatedRectangle.bottomRight, zoomLvl ) /
187
- region.options.tileSize )
189
+ (region.crs.latLngToXY (rotatedRectangle.bottomRight, scaleLvl ) /
190
+ region.options.tileDimension )
188
191
.ceil () -
189
- const Point (1 , 1 );
192
+ (1 , 1 );
190
193
191
- final straightRectangleNW = (region.crs.latLngToPoint (
194
+ final straightRectangleNW = (region.crs.latLngToXY (
192
195
LatLng (rotatedRectangleLats.max, rotatedRectangleLngs.min),
193
- zoomLvl ,
196
+ scaleLvl ,
194
197
) /
195
- region.options.tileSize )
198
+ region.options.tileDimension )
196
199
.floor ();
197
- final straightRectangleSE = (region.crs.latLngToPoint (
200
+ final straightRectangleSE = (region.crs.latLngToXY (
198
201
LatLng (
199
202
rotatedRectangleLats.min,
200
203
rotatedRectangleLngs.max,
201
204
),
202
- zoomLvl ,
205
+ scaleLvl ,
203
206
) /
204
- region.options.tileSize )
207
+ region.options.tileDimension )
205
208
.ceil () -
206
- const Point (1 , 1 );
209
+ (1 , 1 );
207
210
208
- for (int x = straightRectangleNW.x ; x <= straightRectangleSE.x ; x++ ) {
211
+ for (int x = straightRectangleNW.$1 ; x <= straightRectangleSE.$1 ; x++ ) {
209
212
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 ));
217
218
if (generatedTiles.contains (tile.hashCode)) continue ;
218
219
if (overlap (
219
220
_Polygon (
@@ -251,35 +252,43 @@ class TileCounters {
251
252
for (double zoomLvl = region.minZoom.toDouble ();
252
253
zoomLvl <= region.maxZoom;
253
254
zoomLvl++ ) {
254
- final allOutlineTiles = < Point < int > > {} ;
255
+ final scaleLvl = region.crs. scale (zoomLvl) ;
255
256
256
- final pointsOutline = customPolygonOutline
257
- .map ((e) => region.crs.latLngToPoint (e, zoomLvl).floor ());
257
+ final allOutlineTiles = < (int , int )> {};
258
258
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
+ ),
261
270
).map (pointsOutline.elementAt).slices (3 )) {
262
271
final outlineTiles = {
263
272
..._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 ,
267
276
),
268
277
..._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 ,
272
281
),
273
282
..._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 ,
277
286
),
278
287
};
279
288
allOutlineTiles.addAll (outlineTiles);
280
289
281
290
final byY = < int , Set <int >> {};
282
- for (final Point ( : x, : y) in outlineTiles) {
291
+ for (final ( x, y) in outlineTiles) {
283
292
(byY[y] ?? = {}).add (x);
284
293
}
285
294
0 commit comments