From e1a894bf97116074238a4cc17c1fc0a4879ea14f Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 17:15:24 -0600 Subject: [PATCH 01/51] initial commit, started work, going well --- benchmark/crs.dart | 11 +-- example/lib/pages/latlng_to_screen_point.dart | 4 +- lib/src/geo/crs.dart | 23 +++--- lib/src/gestures/map_interactive_viewer.dart | 25 +++--- lib/src/layer/circle_layer/circle_layer.dart | 2 +- lib/src/layer/marker_layer/marker_layer.dart | 12 +-- .../overlay_image_layer/overlay_image.dart | 1 + lib/src/layer/polygon_layer/label.dart | 10 +-- lib/src/layer/polygon_layer/painter.dart | 2 +- .../layer/polygon_layer/polygon_layer.dart | 4 +- .../polygon_layer/projected_polygon.dart | 16 ++-- lib/src/layer/polyline_layer/painter.dart | 4 +- .../layer/polyline_layer/polyline_layer.dart | 2 +- .../polyline_layer/projected_polyline.dart | 6 +- .../tile_layer/tile_range_calculator.dart | 2 +- lib/src/map/camera/camera.dart | 79 +++++++++---------- .../map/controller/map_controller_impl.dart | 2 +- lib/src/misc/extensions.dart | 4 +- lib/src/misc/offsets.dart | 4 +- lib/src/misc/simplify.dart | 55 +++++-------- 20 files changed, 127 insertions(+), 141 deletions(-) diff --git a/benchmark/crs.dart b/benchmark/crs.dart index af749f26b..6b7d41ab1 100644 --- a/benchmark/crs.dart +++ b/benchmark/crs.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:math' as math; +import 'dart:ui'; import 'package:flutter_map/src/geo/crs.dart'; import 'package:latlong2/latlong.dart'; @@ -55,8 +56,8 @@ Future main() async { for (int i = 0; i < N; ++i) { final latlng = LatLng((i % 90).toDouble(), (i % 180).toDouble()); final p = crs.latLngToPoint(latlng, 1); - x += p.x; - y += p.y; + x += p.dx; + y += p.dy; } return x + y; })); @@ -85,8 +86,8 @@ Future main() async { for (int i = 0; i < N; ++i) { final latlng = LatLng((i % 90).toDouble(), (i % 180).toDouble()); final point = crs.latLngToPoint(latlng, 1); - x += point.x; - y += point.y; + x += point.dx; + y += point.dy; } return x + y; })); @@ -95,7 +96,7 @@ Future main() async { double x = 0; double y = 0; for (int i = 0; i < N; ++i) { - final latlng = crs.pointToLatLng(math.Point(x, y), 1); + final latlng = crs.pointToLatLng(Offset(x, y), 1); x += latlng.longitude; y += latlng.latitude; } diff --git a/example/lib/pages/latlng_to_screen_point.dart b/example/lib/pages/latlng_to_screen_point.dart index 4b35f2920..08c03ac7d 100644 --- a/example/lib/pages/latlng_to_screen_point.dart +++ b/example/lib/pages/latlng_to_screen_point.dart @@ -52,8 +52,8 @@ class _LatLngToScreenPointPageState extends State { ), onTap: (_, latLng) { final point = mapController.camera - .latLngToScreenPoint(tappedCoords = latLng); - setState(() => tappedPoint = Point(point.x, point.y)); + .latLngToScreenOffset(tappedCoords = latLng); + setState(() => tappedPoint = Point(point.dx, point.dy)); }, ), children: [ diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 446ab371e..ef66ce50d 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -1,5 +1,6 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; +import 'dart:ui'; import 'package:flutter_map/src/misc/bounds.dart'; import 'package:latlong2/latlong.dart'; @@ -51,13 +52,13 @@ abstract class Crs { (double, double) latLngToXY(LatLng latlng, double scale); /// Similar to [latLngToXY] but converts the XY coordinates to a [Point]. - Point latLngToPoint(LatLng latlng, double zoom) { + Offset latLngToPoint(LatLng latlng, double zoom) { final (x, y) = latLngToXY(latlng, scale(zoom)); - return Point(x, y); + return Offset(x, y); } /// Converts a map point to the sphere coordinate (at a certain zoom). - LatLng pointToLatLng(Point point, double zoom); + LatLng pointToLatLng(Offset point, double zoom); /// Zoom to Scale function. double scale(double zoom) => 256.0 * math.pow(2, zoom); @@ -107,10 +108,10 @@ abstract class CrsWithStaticTransformation extends Crs { } @override - LatLng pointToLatLng(Point point, double zoom) { + LatLng pointToLatLng(Offset point, double zoom) { final (x, y) = _transformation.untransform( - point.x.toDouble(), - point.y.toDouble(), + point.dx, + point.dy, scale(zoom), ); return projection.unprojectXY(x, y); @@ -170,13 +171,13 @@ class Epsg3857 extends CrsWithStaticTransformation { ); @override - Point latLngToPoint(LatLng latlng, double zoom) { + Offset latLngToPoint(LatLng latlng, double zoom) { final (x, y) = _transformation.transform( SphericalMercator.projectLng(latlng.longitude), SphericalMercator.projectLat(latlng.latitude), scale(zoom), ); - return Point(x, y); + return Offset(x, y); } @override @@ -281,10 +282,10 @@ class Proj4Crs extends Crs { /// Converts a map point to the sphere coordinate (at a certain zoom). @override - LatLng pointToLatLng(Point point, double zoom) { + LatLng pointToLatLng(Offset point, double zoom) { final (x, y) = _getTransformationByZoom(zoom).untransform( - point.x.toDouble(), - point.y.toDouble(), + point.dx, + point.dy, scale(zoom), ); return projection.unprojectXY(x, y); diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index ebe756de5..06999a0fa 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -403,7 +403,7 @@ class MapInteractiveViewerState extends State .clamp(minZoom, maxZoom); // Calculate offset of mouse cursor from viewport center final newCenter = _camera.focusedZoomCenter( - pointerSignal.localPosition.toPoint(), + pointerSignal.localPosition, newZoom, ); widget.controller.moveRaw( @@ -636,7 +636,7 @@ class MapInteractiveViewerState extends State final zoomDifference = oldFocalPt - newFocalPt; final moveDifference = _rotateOffset(_focalStartLocal - _lastFocalLocal); - final newCenterPt = oldCenterPt + zoomDifference + moveDifference.toPoint(); + final newCenterPt = oldCenterPt + zoomDifference + moveDifference; return _camera.unproject(newCenterPt, zoomAfterPinchZoom); } @@ -728,9 +728,9 @@ class MapInteractiveViewerState extends State } final direction = details.velocity.pixelsPerSecond / magnitude; - final distance = - (Offset.zero & Size(_camera.nonRotatedSize.x, _camera.nonRotatedSize.y)) - .shortestSide; + final distance = (Offset.zero & + Size(_camera.nonRotatedSize.dx, _camera.nonRotatedSize.dy)) + .shortestSide; final flingOffset = _focalStartLocal - _lastFocalLocal; _flingAnimation = Tween( @@ -803,7 +803,7 @@ class MapInteractiveViewerState extends State if (InteractiveFlag.hasDoubleTapZoom(_interactionOptions.flags)) { final newZoom = _getZoomForScale(_camera.zoom, 2); final newCenter = _camera.focusedZoomCenter( - tapPosition.relative!.toPoint(), + tapPosition.relative!, newZoom, ); _startDoubleTapAnimation(newZoom, newCenter); @@ -882,19 +882,20 @@ class MapInteractiveViewerState extends State } final newCenterPoint = _camera.project(_mapCenterStart) + - _flingAnimation.value.toPoint().rotate(_camera.rotationRad); + _flingAnimation.value.rotate(_camera.rotationRad); final LatLng newCenter; if (!_camera.crs.replicatesWorldLongitude) { newCenter = _camera.unproject(newCenterPoint); } else { - final math.Point bestCenterPoint; + final Offset bestCenterPoint; final double worldSize = _camera.crs.scale(_camera.zoom); - if (newCenterPoint.x > worldSize) { + // TODO there has to be an easier way to write this code... + if (newCenterPoint.dx > worldSize) { bestCenterPoint = - math.Point(newCenterPoint.x - worldSize, newCenterPoint.y); - } else if (newCenterPoint.x < 0) { + Offset(newCenterPoint.dx - worldSize, newCenterPoint.dy); + } else if (newCenterPoint.dx < 0) { bestCenterPoint = - math.Point(newCenterPoint.x + worldSize, newCenterPoint.y); + Offset(newCenterPoint.dx + worldSize, newCenterPoint.dy); } else { bestCenterPoint = newCenterPoint; } diff --git a/lib/src/layer/circle_layer/circle_layer.dart b/lib/src/layer/circle_layer/circle_layer.dart index 98e2235ec..5f18146e1 100644 --- a/lib/src/layer/circle_layer/circle_layer.dart +++ b/lib/src/layer/circle_layer/circle_layer.dart @@ -36,7 +36,7 @@ class CircleLayer extends StatelessWidget { camera: camera, hitNotifier: hitNotifier, ), - size: Size(camera.size.x, camera.size.y), + size: Size(camera.size.dx, camera.size.dy), isComplex: true, ), ); diff --git a/lib/src/layer/marker_layer/marker_layer.dart b/lib/src/layer/marker_layer/marker_layer.dart index f976d8dca..0e0ef0cc4 100644 --- a/lib/src/layer/marker_layer/marker_layer.dart +++ b/lib/src/layer/marker_layer/marker_layer.dart @@ -60,10 +60,12 @@ class MarkerLayer extends StatelessWidget { // Cull if out of bounds if (!map.pixelBounds.containsPartialBounds( Bounds( - Point(pxPoint.x + left, pxPoint.y - bottom), - Point(pxPoint.x - right, pxPoint.y + top), + Point(pxPoint.dx + left, pxPoint.dy - bottom), + Point(pxPoint.dx - right, pxPoint.dy + top), ), - )) continue; + )) { + continue; + } // Apply map camera to marker position final pos = pxPoint - map.pixelOrigin; @@ -72,8 +74,8 @@ class MarkerLayer extends StatelessWidget { key: m.key, width: m.width, height: m.height, - left: pos.x - right, - top: pos.y - bottom, + left: pos.dx - right, + top: pos.dy - bottom, child: (m.rotate ?? rotate) ? Transform.rotate( angle: -map.rotationRad, diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index 22ab1565b..31cb7c4a4 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -80,6 +80,7 @@ class OverlayImage extends BaseOverlayImage { required Image child, }) { final camera = MapCamera.of(context); + // northWest is not necessarily upperLeft depending on projection final bounds = Bounds( diff --git a/lib/src/layer/polygon_layer/label.dart b/lib/src/layer/polygon_layer/label.dart index 372cdead0..ee9ff0f80 100644 --- a/lib/src/layer/polygon_layer/label.dart +++ b/lib/src/layer/polygon_layer/label.dart @@ -1,7 +1,7 @@ part of 'polygon_layer.dart'; void Function(Canvas canvas)? _buildLabelTextPainter({ - required math.Point mapSize, + required Offset mapSize, required Offset placementPoint, required ({Offset min, Offset max}) bounds, required TextPainter textPainter, @@ -18,10 +18,10 @@ void Function(Canvas canvas)? _buildLabelTextPainter({ // Currently this is only enabled when the map isn't rotated, since the placementOffset // is relative to the MobileLayerTransformer rather than in actual screen coordinates. if (rotationRad == 0) { - if (dx + width / 2 < 0 || dx - width / 2 > mapSize.x) { + if (dx + width / 2 < 0 || dx - width / 2 > mapSize.dx) { return null; } - if (dy + height / 2 < 0 || dy - height / 2 > mapSize.y) { + if (dy + height / 2 < 0 || dy - height / 2 > mapSize.dy) { return null; } } @@ -77,8 +77,8 @@ LatLng _computeCentroid(List points) { LatLng _computePolylabel(List points) { final labelPosition = polylabel( [ - List.generate(points.length, - (i) => math.Point(points[i].longitude, points[i].latitude)), + List.generate(points.length, + (i) => Offset(points[i].longitude, points[i].latitude)), ], // "precision" is a bit of a misnomer. It's a threshold for when to stop // dividing-and-conquering the polygon in the hopes of finding a better diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart index 44aff4b8b..eff23a099 100644 --- a/lib/src/layer/polygon_layer/painter.dart +++ b/lib/src/layer/polygon_layer/painter.dart @@ -193,7 +193,7 @@ base class _PolygonPainter lastHash = null; } - final origin = (camera.project(camera.center) - camera.size / 2).toOffset(); + final origin = camera.project(camera.center) - camera.size / 2; // Main loop constructing batched fill and border paths from given polygons. for (int i = 0; i <= polygons.length - 1; i++) { diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index 0f310ea3d..2089e00e4 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -152,8 +152,8 @@ class _PolygonLayerState extends State> List.generate( points.length * 2, (ii) => ii.isEven - ? points.elementAt(ii ~/ 2).x - : points.elementAt(ii ~/ 2).y, + ? points.elementAt(ii ~/ 2).dx + : points.elementAt(ii ~/ 2).dy, growable: false, ), holeIndices: culledPolygon.holePoints.isEmpty diff --git a/lib/src/layer/polygon_layer/projected_polygon.dart b/lib/src/layer/polygon_layer/projected_polygon.dart index 1c25ef0f5..b1d0f206e 100644 --- a/lib/src/layer/polygon_layer/projected_polygon.dart +++ b/lib/src/layer/polygon_layer/projected_polygon.dart @@ -3,8 +3,8 @@ part of 'polygon_layer.dart'; @immutable class _ProjectedPolygon with HitDetectableElement { final Polygon polygon; - final List points; - final List> holePoints; + final List points; + final List> holePoints; @override R? get hitValue => polygon.hitValue; @@ -18,11 +18,11 @@ class _ProjectedPolygon with HitDetectableElement { _ProjectedPolygon._fromPolygon(Projection projection, Polygon polygon) : this._( polygon: polygon, - points: List.generate( + points: List.generate( polygon.points.length, (j) { final (x, y) = projection.projectXY(polygon.points[j]); - return DoublePoint(x, y); + return Offset(x, y); }, growable: false, ), @@ -31,18 +31,18 @@ class _ProjectedPolygon with HitDetectableElement { if (holes == null || holes.isEmpty || holes.every((e) => e.isEmpty)) { - return >[]; + return >[]; } - return List>.generate( + return List>.generate( holes.length, (j) { final points = holes[j]; - return List.generate( + return List.generate( points.length, (k) { final (x, y) = projection.projectXY(points[k]); - return DoublePoint(x, y); + return Offset(x, y); }, growable: false, ); diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index 1f60aee39..e7297dbcb 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -108,7 +108,7 @@ base class _PolylinePainter } final origin = - camera.project(camera.center).toOffset() - camera.size.toOffset() / 2; + camera.project(camera.center) - camera.size.toOffset() / 2; for (final projectedPolyline in polylines) { final polyline = projectedPolyline.polyline; @@ -278,7 +278,7 @@ base class _PolylinePainter return delta.distance; } - LatLng _unproject(DoublePoint p0) => + LatLng _unproject(Offset p0) => camera.crs.projection.unprojectXY(p0.x, p0.y); @override diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 47da085ff..0be991f58 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -157,7 +157,7 @@ class _PolylineLayerState extends State> final p1 = projectedPolyline.points[i]; final p2 = projectedPolyline.points[i + 1]; - containsSegment = projBounds.aabbContainsLine(p1.x, p1.y, p2.x, p2.y); + containsSegment = projBounds.aabbContainsLine(p1.dx, p1.dy, p2.dx, p2.dy); if (containsSegment) { if (start == -1) { start = i; diff --git a/lib/src/layer/polyline_layer/projected_polyline.dart b/lib/src/layer/polyline_layer/projected_polyline.dart index eca98465a..a16575dfd 100644 --- a/lib/src/layer/polyline_layer/projected_polyline.dart +++ b/lib/src/layer/polyline_layer/projected_polyline.dart @@ -3,7 +3,7 @@ part of 'polyline_layer.dart'; @immutable class _ProjectedPolyline with HitDetectableElement { final Polyline polyline; - final List points; + final List points; @override R? get hitValue => polyline.hitValue; @@ -16,11 +16,11 @@ class _ProjectedPolyline with HitDetectableElement { _ProjectedPolyline._fromPolyline(Projection projection, Polyline polyline) : this._( polyline: polyline, - points: List.generate( + points: List.generate( polyline.points.length, (j) { final (x, y) = projection.projectXY(polyline.points[j]); - return DoublePoint(x, y); + return Offset(x, y); }, growable: false, ), diff --git a/lib/src/layer/tile_layer/tile_range_calculator.dart b/lib/src/layer/tile_layer/tile_range_calculator.dart index 169f11c17..0271673fc 100644 --- a/lib/src/layer/tile_layer/tile_range_calculator.dart +++ b/lib/src/layer/tile_layer/tile_range_calculator.dart @@ -46,7 +46,7 @@ class TileRangeCalculator { final tileZoomDouble = tileZoom.toDouble(); final scale = camera.getZoomScale(viewingZoom, tileZoomDouble); final pixelCenter = - camera.project(center, tileZoomDouble).floor().toDoublePoint(); + camera.project(center, tileZoomDouble).floor().toOffset(); final halfSize = camera.size / (scale * 2); return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 81853ea09..a9f5d3bd1 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -18,7 +18,7 @@ class MapCamera { /// in a subsequent build to the actual constraints. We set the size to this /// impossible (negative) value initially and only change it once Flutter /// provides real constraints. - static const kImpossibleSize = Point(-1, -1); + static const kImpossibleSize = Offset(-1, -1); /// The used coordinate reference system final Crs crs; @@ -41,10 +41,10 @@ class MapCamera { /// The size of the map view ignoring rotation. This will be the size of the /// FlutterMap widget. - final Point nonRotatedSize; + final Offset nonRotatedSize; /// Lazily calculated field - Point? _cameraSize; + Offset? _cameraSize; /// Lazily calculated field Bounds? _pixelBounds; @@ -53,7 +53,7 @@ class MapCamera { LatLngBounds? _bounds; /// Lazily calculated field - Point? _pixelOrigin; + Offset? _pixelOrigin; /// This is the [LatLngBounds] corresponding to four corners of this camera. /// This takes rotation in to account. @@ -66,7 +66,7 @@ class MapCamera { /// rotation. When the rotation is zero this will equal [nonRotatedSize], /// otherwise it will be the size of the rectangle which contains this /// camera. - Point get size => _cameraSize ??= calculateRotatedSize( + Offset get size => _cameraSize ??= calculateRotatedSize( rotation, nonRotatedSize, ); @@ -74,8 +74,8 @@ class MapCamera { /// The offset of the top-left corner of the bounding rectangle of this /// camera. This will not equal the offset of the top-left visible pixel when /// the map is rotated. - Point get pixelOrigin => - _pixelOrigin ??= project(center, zoom) - size / 2.0; + Offset get pixelOrigin => + _pixelOrigin ??= project(center, zoom) - (size / 2.0); /// The camera of the closest [FlutterMap] ancestor. If this is called from a /// context with no [FlutterMap] ancestor null, is returned. @@ -100,10 +100,10 @@ class MapCamera { required this.nonRotatedSize, this.minZoom, this.maxZoom, - Point? size, + Offset? size, Bounds? pixelBounds, LatLngBounds? bounds, - Point? pixelOrigin, + Offset? pixelOrigin, }) : _cameraSize = size, _pixelBounds = pixelBounds, _bounds = bounds, @@ -121,7 +121,7 @@ class MapCamera { nonRotatedSize = kImpossibleSize; /// Returns a new instance of [MapCamera] with the given [nonRotatedSize]. - MapCamera withNonRotatedSize(Point nonRotatedSize) { + MapCamera withNonRotatedSize(Offset nonRotatedSize) { if (nonRotatedSize == this.nonRotatedSize) return this; return MapCamera( @@ -208,20 +208,20 @@ class MapCamera { /// Calculates the size of a bounding box which surrounds a box of size /// [nonRotatedSize] which is rotated by [rotation]. - static Point calculateRotatedSize( + static Offset calculateRotatedSize( double rotation, - Point nonRotatedSize, + Offset nonRotatedSize, ) { if (rotation == 0.0) return nonRotatedSize; final rotationRad = degrees2Radians * rotation; final cosAngle = math.cos(rotationRad).abs(); final sinAngle = math.sin(rotationRad).abs(); - final width = (nonRotatedSize.x * cosAngle) + (nonRotatedSize.y * sinAngle); + final width = (nonRotatedSize.dx * cosAngle) + (nonRotatedSize.dy * sinAngle); final height = - (nonRotatedSize.y * cosAngle) + (nonRotatedSize.x * sinAngle); + (nonRotatedSize.dy * cosAngle) + (nonRotatedSize.dx * sinAngle); - return Point(width, height); + return Offset(width, height); } /// The current rotation value in radians @@ -229,16 +229,16 @@ class MapCamera { /// Calculates point value for the given [latlng] using this camera's /// [crs] and [zoom] (or the provided [zoom]). - Point project(LatLng latlng, [double? zoom]) => + Offset project(LatLng latlng, [double? zoom]) => crs.latLngToPoint(latlng, zoom ?? this.zoom); /// Calculates the [LatLng] for the given [point] using this camera's /// [crs] and [zoom] (or the provided [zoom]). - LatLng unproject(Point point, [double? zoom]) => - crs.pointToLatLng(point, zoom ?? this.zoom); + LatLng unproject(Offset point, [double? zoom]) => + crs.pointToLatLng(point.toPoint(), zoom ?? this.zoom); /// Same as the [unproject] function. - LatLng layerPointToLatLng(Point point) => unproject(point); + LatLng layerPointToLatLng(Offset point) => unproject(point); /// Calculates the scale for a zoom from [fromZoom] to [toZoom] using this /// camera\s [crs]. @@ -254,13 +254,13 @@ class MapCamera { /// Calculates the [Offset] from the [pos] to this camera's [pixelOrigin]. Offset getOffsetFromOrigin(LatLng pos) => - (project(pos) - pixelOrigin).toOffset(); + project(pos) - pixelOrigin; /// Calculates the pixel origin of this [MapCamera] at the given /// [center]/[zoom]. - Point getNewPixelOrigin(LatLng center, [double? zoom]) { - final halfSize = size / 2.0; - return (project(center, zoom) - halfSize).round(); + Offset getNewPixelOrigin(LatLng center, [double? zoom]) { + // TODO was explcitly rounded + return project(center, zoom) - (size / 2.0); } /// Calculates the pixel bounds of this [MapCamera]. This value is cached. @@ -274,13 +274,14 @@ class MapCamera { final scale = getZoomScale(this.zoom, zoom); halfSize = size / (scale * 2); } - final pixelCenter = project(center, zoom).floor().toDoublePoint(); + // TODO was explicitly floored + final pixelCenter = project(center, zoom); return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); } /// This will convert a latLng to a position that we could use with a widget /// outside of FlutterMap layer space. Eg using a Positioned Widget. - Point latLngToScreenPoint(LatLng latLng) { + Offset latLngToScreenOffset(LatLng latLng) { final nonRotatedPixelOrigin = project(center, zoom) - nonRotatedSize / 2.0; var point = crs.latLngToPoint(latLng, zoom); @@ -288,7 +289,7 @@ class MapCamera { final mapCenter = crs.latLngToPoint(center, zoom); if (rotation != 0.0) { - point = rotatePoint(mapCenter, point, counterRotation: false); + point = rotateOffset(mapCenter, point, counterRotation: false); } return point - nonRotatedPixelOrigin; @@ -296,16 +297,16 @@ class MapCamera { /// Calculate the [LatLng] coordinates for a [localPoint]. LatLng pointToLatLng(Point localPoint) { - final localPointCenterDistance = Point( - (nonRotatedSize.x / 2) - localPoint.x, - (nonRotatedSize.y / 2) - localPoint.y, + final localPointCenterDistance = Offset( + (nonRotatedSize.dx / 2) - localPoint.x, + (nonRotatedSize.dy / 2) - localPoint.y, ); final mapCenter = crs.latLngToPoint(center, zoom); var point = mapCenter - localPointCenterDistance; if (rotation != 0.0) { - point = rotatePoint(mapCenter, point); + point = rotateOffset(mapCenter, point); } return crs.pointToLatLng(point, zoom); @@ -315,21 +316,19 @@ class MapCamera { /// it needs to be reversed (pointToLatLng), and sometimes we want to use /// the same rotation to create a new position (latLngToScreenpoint). /// counterRotation just makes allowances this for this. - Point rotatePoint( - Point mapCenter, - Point point, { + Offset rotateOffset( + Offset mapCenter, + Offset point, { bool counterRotation = true, }) { final counterRotationFactor = counterRotation ? -1 : 1; final m = Matrix4.identity() - ..translate(mapCenter.x, mapCenter.y) + ..translate(mapCenter.dx, mapCenter.dy) ..rotateZ(rotationRad * counterRotationFactor) - ..translate(-mapCenter.x, -mapCenter.y); + ..translate(-mapCenter.dx, -mapCenter.dy); - final tp = MatrixUtils.transformPoint(m, point.toOffset()); - - return Point(tp.dx, tp.dy); + return MatrixUtils.transformPoint(m, point); } /// Clamps the provided [zoom] to the range specified by [minZoom] and @@ -345,7 +344,7 @@ class MapCamera { LatLng offsetToCrs(Offset offset, [double? zoom]) { final focalStartPt = project(center, zoom ?? this.zoom); final point = - (offset.toPoint() - (nonRotatedSize / 2.0)).rotate(rotationRad); + (offset - (nonRotatedSize / 2.0)).rotate(rotationRad); final newCenterPt = focalStartPt + point; return unproject(newCenterPt, zoom ?? this.zoom); @@ -353,7 +352,7 @@ class MapCamera { /// Calculate the center point which would keep the same point of the map /// visible at the given [cursorPos] with the zoom set to [zoom]. - LatLng focusedZoomCenter(Point cursorPos, double zoom) { + LatLng focusedZoomCenter(Offset cursorPos, double zoom) { // Calculate offset of mouse cursor from viewport center final viewCenter = nonRotatedSize / 2; final offset = (cursorPos - viewCenter).rotate(rotationRad); diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index e1480c1e4..307e3852c 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -154,7 +154,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> if (offset != Offset.zero) { final newPoint = camera.project(newCenter, newZoom); center = camera.unproject( - camera.rotatePoint( + camera.rotateOffset( newPoint, newPoint - Point(offset.dx, offset.dy), ), diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index dfd7a23fc..8ac289a74 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -44,14 +44,14 @@ extension PointExtension on Point { return Point(nx, ny); } - return toDoublePoint(); + return toOffset(); } /// Cast the object to a [Point] object with integer values Point toIntPoint() => Point(x.toInt(), y.toInt()); /// Case the object to a [Point] object with double values - Point toDoublePoint() => Point(x.toDouble(), y.toDouble()); + Point toOffset() => Point(x.toDouble(), y.toDouble()); /// Maps the [Point] to an [Offset]. Offset toOffset() => Offset(x.toDouble(), y.toDouble()); diff --git a/lib/src/misc/offsets.dart b/lib/src/misc/offsets.dart index c22c216de..2278dd347 100644 --- a/lib/src/misc/offsets.dart +++ b/lib/src/misc/offsets.dart @@ -45,8 +45,8 @@ List getOffsets(MapCamera camera, Offset origin, List points) { List getOffsetsXY({ required MapCamera camera, required Offset origin, - required List points, - List>? holePoints, + required List points, + List>? holePoints, }) { // Critically create as little garbage as possible. This is called on every frame. final crs = camera.crs; diff --git a/lib/src/misc/simplify.dart b/lib/src/misc/simplify.dart index acde80bc5..47f73a615 100644 --- a/lib/src/misc/simplify.dart +++ b/lib/src/misc/simplify.dart @@ -2,36 +2,17 @@ // https://github.com/mourner/simplify-js/blob/master/simplify.js import 'dart:math' as math; +import 'dart:ui'; import 'package:flutter_map/src/geo/crs.dart'; import 'package:meta/meta.dart'; -/// Internal double-precision point/vector implementation not to be used in publicly. -/// -/// This is an optimization. Vector operations on math.Point tend to incur a 20+x -/// penalty due to virtual function overhead caused by reified generics. -/// -/// Further note that unlike math.Point, members are mutable to allow object reuse/pooling -/// and therefore reduce GC pressure. -@internal -final class DoublePoint { - double x; - double y; - - DoublePoint(this.x, this.y); - - DoublePoint operator -(DoublePoint rhs) => DoublePoint(x - rhs.x, y - rhs.y); - - double distanceSq(DoublePoint rhs) { - final double dx = x - rhs.x; - final double dy = y - rhs.y; +double distanceSq(Offset a, Offset b) { + final double dx = a.dx - b.dx; + final double dy = a.dy - b.dy; return dx * dx + dy * dy; } - @override - String toString() => 'DoublePoint($x, $y)'; -} - /// square distance from a point to a segment double getSqSegDist( final double px, @@ -65,16 +46,16 @@ double getSqSegDist( /// Alternative algorithm to the Douglas Peucker simplification algorithm. /// /// Might actually be more expensive than DP, which is also better -List simplifyRadialDist( - List points, +List simplifyRadialDist( + List points, double sqTolerance, ) { - DoublePoint prevPoint = points[0]; - final List newPoints = [prevPoint]; - late DoublePoint point; + Offset prevPoint = points[0]; + final List newPoints = [prevPoint]; + late Offset point; for (int i = 1, len = points.length; i < len; i++) { point = points[i]; - if (point.distanceSq(prevPoint) > sqTolerance) { + if (distanceSq(point, prevPoint) > sqTolerance) { newPoints.add(point); prevPoint = point; } @@ -86,11 +67,11 @@ List simplifyRadialDist( } void _simplifyDPStep( - List points, + List points, final int first, final int last, double sqTolerance, - List simplified, + List simplified, ) { double maxSqDist = sqTolerance; final p0 = points[first]; @@ -99,7 +80,7 @@ void _simplifyDPStep( late int index; for (int i = first + 1; i < last; i++) { final p = points[i]; - final double sqDist = getSqSegDist(p.x, p.y, p0.x, p0.y, p1.x, p1.y); + final double sqDist = getSqSegDist(p.dx, p.dy, p0.dx, p0.dy, p1.dx, p1.dy); if (sqDist > maxSqDist) { index = i; @@ -118,20 +99,20 @@ void _simplifyDPStep( } /// simplification using the Ramer-Douglas-Peucker algorithm -List simplifyDouglasPeucker( - List points, +List simplifyDouglasPeucker( + List points, double sqTolerance, ) { final int last = points.length - 1; - final List simplified = [points[0]]; + final List simplified = [points[0]]; _simplifyDPStep(points, 0, last, sqTolerance, simplified); simplified.add(points[last]); return simplified; } /// Simplify the list of points for better performance. -List simplifyPoints({ - required final List points, +List simplifyPoints({ + required final List points, required double tolerance, required bool highQuality, }) { From 2ab131bf7d0ca0c260ca049c933f920169621f4c Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 17:33:01 -0600 Subject: [PATCH 02/51] more insane progress, still going well --- .../overlay_image_layer/overlay_image.dart | 12 +++---- .../layer/polygon_layer/polygon_layer.dart | 2 +- lib/src/layer/polyline_layer/painter.dart | 4 +-- .../layer/polyline_layer/polyline_layer.dart | 2 +- .../internal_hit_detectable.dart | 5 ++- .../shared/mobile_layer_transformer.dart | 8 ++--- lib/src/layer/tile_layer/tile.dart | 8 ++--- .../tile_layer/wms_tile_layer_options.dart | 4 +-- lib/src/map/camera/camera.dart | 4 ++- lib/src/map/camera/camera_fit.dart | 34 +++++++++--------- .../map/controller/map_controller_impl.dart | 19 +++++----- lib/src/misc/extensions.dart | 35 +++++++------------ lib/src/misc/offsets.dart | 5 ++- test/map/camera/camera_constraint_test.dart | 2 +- 14 files changed, 65 insertions(+), 79 deletions(-) diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index 31cb7c4a4..fbbed59e9 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -154,12 +154,12 @@ class RotatedOverlayImage extends BaseOverlayImage { final vectorY = (pxBottomLeft - pxTopLeft) / bounds.size.y; final offset = pxTopLeft - bounds.topLeft; - final a = vectorX.x; - final b = vectorX.y; - final c = vectorY.x; - final d = vectorY.y; - final tx = offset.x; - final ty = offset.y; + final a = vectorX.dx; + final b = vectorX.dy; + final c = vectorY.dx; + final d = vectorY.dy; + final tx = offset.dx; + final ty = offset.dy; return Positioned( left: bounds.topLeft.x, diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index 2089e00e4..4ccb4669a 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -176,7 +176,7 @@ class _PolygonLayerState extends State> debugAltRenderer: widget.debugAltRenderer, hitNotifier: widget.hitNotifier, ), - size: Size(camera.size.x, camera.size.y), + size: Size(camera.size.dx, camera.size.dy), ), ); } diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index e7297dbcb..db4aca4b0 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -108,7 +108,7 @@ base class _PolylinePainter } final origin = - camera.project(camera.center) - camera.size.toOffset() / 2; + camera.project(camera.center) - camera.size / 2; for (final projectedPolyline in polylines) { final polyline = projectedPolyline.polyline; @@ -279,7 +279,7 @@ base class _PolylinePainter } LatLng _unproject(Offset p0) => - camera.crs.projection.unprojectXY(p0.x, p0.y); + camera.crs.projection.unprojectXY(p0.dx, p0.dy); @override bool shouldRepaint(_PolylinePainter oldDelegate) => diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 0be991f58..615362ffb 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -111,7 +111,7 @@ class _PolylineLayerState extends State> hitNotifier: widget.hitNotifier, minimumHitbox: widget.minimumHitbox, ), - size: Size(camera.size.x, camera.size.y), + size: Size(camera.size.dx, camera.size.dy), ), ); } diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 3a9c3c8ee..5e17c7e4c 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -98,7 +98,7 @@ base mixin HitTestRequiresCameraOrigin currentPixelOrigin; + final Offset currentPixelOrigin; /// Position Coordinates. /// @@ -71,9 +69,9 @@ class _TileState extends State { Widget build(BuildContext context) { return Positioned( left: widget.positionCoordinates.x * widget.scaledTileDimension - - widget.currentPixelOrigin.x, + widget.currentPixelOrigin.dx, top: widget.positionCoordinates.y * widget.scaledTileDimension - - widget.currentPixelOrigin.y, + widget.currentPixelOrigin.dy, width: widget.scaledTileDimension, height: widget.scaledTileDimension, child: widget.tileBuilder?.call(context, _tileImage, widget.tileImage) ?? diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index 650012e82..12fe22b1f 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -71,8 +71,8 @@ class WMSTileLayerOptions { String getUrl(TileCoordinates coords, int tileDimension, bool retinaMode) { final nwPoint = coords * tileDimension; final sePoint = nwPoint + Point(tileDimension, tileDimension); - final nwCoords = crs.pointToLatLng(nwPoint, coords.z.toDouble()); - final seCoords = crs.pointToLatLng(sePoint, coords.z.toDouble()); + final nwCoords = crs.pointToLatLng(nwPoint.toDoublePoint(), coords.z.toDouble()); + final seCoords = crs.pointToLatLng(sePoint.toDoublePoint(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); final bounds = Bounds(nw, se); diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index a9f5d3bd1..7914b83c0 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -235,7 +235,7 @@ class MapCamera { /// Calculates the [LatLng] for the given [point] using this camera's /// [crs] and [zoom] (or the provided [zoom]). LatLng unproject(Offset point, [double? zoom]) => - crs.pointToLatLng(point.toPoint(), zoom ?? this.zoom); + crs.pointToLatLng(point, zoom ?? this.zoom); /// Same as the [unproject] function. LatLng layerPointToLatLng(Offset point) => unproject(point); @@ -321,6 +321,8 @@ class MapCamera { Offset point, { bool counterRotation = true, }) { + + //TODO what is the difference between this and the extension method on Offset.rotate?????!?!?! final counterRotationFactor = counterRotation ? -1 : 1; final m = Matrix4.identity() diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index ca4b31e2c..9290bde9a 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -102,8 +102,8 @@ class FitBounds extends CameraFit { /// Returns a new [MapCamera] which fits this classes configuration. @override MapCamera fit(MapCamera camera) { - final paddingTL = Point(padding.left, padding.top); - final paddingBR = Point(padding.right, padding.bottom); + final paddingTL = Offset(padding.left, padding.top); + final paddingBR = Offset(padding.right, padding.bottom); final paddingTotalXY = paddingTL + paddingBR; @@ -114,7 +114,7 @@ class FitBounds extends CameraFit { final swPoint = camera.project(bounds.southWest, newZoom); final nePoint = camera.project(bounds.northEast, newZoom); - final Point projectedCenter; + final Offset projectedCenter; if (camera.rotation != 0.0) { final swPointRotated = swPoint.rotate(-camera.rotationRad); final nePointRotated = nePoint.rotate(-camera.rotationRad); @@ -135,13 +135,13 @@ class FitBounds extends CameraFit { double _getBoundsZoom( MapCamera camera, - Point pixelPadding, + Offset pixelPadding, ) { final nw = bounds.northWest; final se = bounds.southEast; var size = camera.nonRotatedSize - pixelPadding; // Prevent negative size which results in NaN zoom value later on in the calculation - size = Point(math.max(0, size.x), math.max(0, size.y)); + size = Offset(math.max(0, size.dx), math.max(0, size.dy)); var boundsSize = Bounds( camera.project(se, camera.zoom), camera.project(nw, camera.zoom), @@ -155,9 +155,7 @@ class FitBounds extends CameraFit { ); } - final scaleX = size.x / boundsSize.x; - final scaleY = size.y / boundsSize.y; - final scale = math.min(scaleX, scaleY); + final scale = math.min(size.dx / boundsSize.x, size.dy / boundsSize.y); var boundsZoom = camera.getScaleZoom(scale); @@ -218,8 +216,8 @@ class FitInsideBounds extends CameraFit { @override MapCamera fit(MapCamera camera) { - final paddingTL = Point(padding.left, padding.top); - final paddingBR = Point(padding.right, padding.bottom); + final paddingTL = Offset(padding.left, padding.top); + final paddingBR = Offset(padding.right, padding.bottom); final paddingTotalXY = paddingTL + paddingBR; final paddingOffset = (paddingBR - paddingTL) / 2; @@ -232,8 +230,8 @@ class FitInsideBounds extends CameraFit { final scale = _rectInRotRectScale( angleRad: camera.rotationRad, - smallRectHalfWidth: cameraSize.x / 2.0, - smallRectHalfHeight: cameraSize.y / 2.0, + smallRectHalfWidth: cameraSize.dx / 2.0, + smallRectHalfHeight: cameraSize.dy / 2.0, bigRectHalfWidth: projectedBoundsSize.x / 2.0, bigRectHalfHeight: projectedBoundsSize.y / 2.0, ); @@ -269,7 +267,7 @@ class FitInsideBounds extends CameraFit { LatLng _getCenter( MapCamera camera, { required double newZoom, - required Point paddingOffset, + required Offset paddingOffset, }) { if (camera.rotation == 0.0) { final swPoint = camera.project(bounds.southWest, newZoom); @@ -447,7 +445,7 @@ class FitCoordinates extends CameraFit { final rotatedNewCenter = rotatedBounds.center + paddingOffset; // Undo the rotation - final unrotatedNewCenter = rotatedNewCenter.rotate(camera.rotationRad); + final unrotatedNewCenter = rotatedNewCenter.toOffset().rotate(camera.rotationRad); final newCenter = camera.unproject(unrotatedNewCenter, newZoom); @@ -459,11 +457,11 @@ class FitCoordinates extends CameraFit { double _getCoordinatesZoom( MapCamera camera, - Point pixelPadding, + Offset pixelPadding, ) { var size = camera.nonRotatedSize - pixelPadding; // Prevent negative size which results in NaN zoom value later on in the calculation - size = Point(math.max(0, size.x), math.max(0, size.y)); + size = Offset(math.max(0, size.dx), math.max(0, size.dy)); final projectedPoints = [ for (final coord in coordinates) camera.project(coord) @@ -475,8 +473,8 @@ class FitCoordinates extends CameraFit { final boundsSize = rotatedBounds.size; - final scaleX = size.x / boundsSize.x; - final scaleY = size.y / boundsSize.y; + final scaleX = size.dx / boundsSize.x; + final scaleY = size.dy / boundsSize.y; final scale = math.min(scaleX, scaleY); var newZoom = camera.getScaleZoom(scale); diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 307e3852c..20bcec1a8 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -24,7 +24,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> Animation? _flingAnimation; late bool _animationHasGesture; late Offset _animationOffset; - late Point _flingMapCenterStartPoint; + late Offset _flingMapCenterStartPoint; /// Constructor of the [MapController] implementation for internal usage. MapControllerImpl({MapOptions? options, TickerProvider? vsync}) @@ -113,7 +113,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> }) => rotateAroundPointRaw( degree, - point: point, + point: point?.toOffset(), offset: offset, hasGesture: false, source: MapEventSource.mapController, @@ -156,7 +156,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> center = camera.unproject( camera.rotateOffset( newPoint, - newPoint - Point(offset.dx, offset.dy), + newPoint - offset, ), newZoom, ); @@ -224,7 +224,8 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> /// the map. MoveAndRotateResult rotateAroundPointRaw( double degree, { - required Point? point, + //TODO this looks insanely jank + required Offset? point, required Offset? offset, required bool hasGesture, required MapEventSource source, @@ -255,9 +256,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> final rotationDiff = degree - camera.rotation; final rotationCenter = camera.project(camera.center) + - (point != null - ? (point - (camera.nonRotatedSize / 2.0)) - : Point(offset!.dx, offset.dy)) + (point != null ? (point - (camera.nonRotatedSize / 2.0)) : offset) .rotate(camera.rotationRad); return ( @@ -388,7 +387,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> void dragUpdated(MapEventSource source, Offset offset) { final oldCenterPt = camera.project(camera.center); - final newCenterPt = oldCenterPt + offset.toPoint(); + final newCenterPt = oldCenterPt + offset; final newCenter = camera.unproject(newCenterPt); moveRaw( @@ -662,7 +661,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> _flingMapCenterStartPoint = camera.project(camera.center); final distance = - (Offset.zero & Size(camera.nonRotatedSize.x, camera.nonRotatedSize.y)) + (Offset.zero & Size(camera.nonRotatedSize.dx, camera.nonRotatedSize.dy)) .shortestSide; _flingAnimation = Tween( @@ -728,7 +727,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> // fling animation if (_flingAnimation != null) { final newCenterPoint = _flingMapCenterStartPoint + - _flingAnimation!.value.toPoint().rotate(camera.rotationRad); + _flingAnimation!.value.rotate(camera.rotationRad); moveRaw( camera.unproject(newCenterPoint), camera.zoom, diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 8ac289a74..b1d63128c 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -32,33 +32,24 @@ extension PointExtension on Point { return Point(x.floor(), y.floor()); } - /// Create a new [Point] whose [x] and [y] values are rotated clockwise by - /// [radians]. - Point rotate(num radians) { - if (radians != 0.0) { - final cosTheta = cos(radians); - final sinTheta = sin(radians); - final nx = (cosTheta * x) + (sinTheta * y); - final ny = (cosTheta * y) - (sinTheta * x); - - return Point(nx, ny); - } - - return toOffset(); - } - - /// Cast the object to a [Point] object with integer values - Point toIntPoint() => Point(x.toInt(), y.toInt()); + /// Converts to offset + Offset toOffset () => Offset(x.toDouble(), y.toDouble()); - /// Case the object to a [Point] object with double values - Point toOffset() => Point(x.toDouble(), y.toDouble()); - - /// Maps the [Point] to an [Offset]. - Offset toOffset() => Offset(x.toDouble(), y.toDouble()); } /// Extension methods for [Offset] extension OffsetToPointExtension on Offset { + /// Creates a [Point] representation of this offset. Point toPoint() => Point(dx, dy); + + /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by + /// [radians]. + Offset rotate(num radians) { + final cosTheta = cos(radians); + final sinTheta = sin(radians); + final nx = (cosTheta * dx) + (sinTheta * dy); + final ny = (cosTheta * dy) - (sinTheta * dx); + return Offset(nx, ny); + } } diff --git a/lib/src/misc/offsets.dart b/lib/src/misc/offsets.dart index 2278dd347..238a0fc86 100644 --- a/lib/src/misc/offsets.dart +++ b/lib/src/misc/offsets.dart @@ -2,7 +2,6 @@ import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/geo/crs.dart'; -import 'package:flutter_map/src/misc/simplify.dart'; import 'package:latlong2/latlong.dart'; /// Calculate the [Offset] for the [LatLng] point. @@ -66,7 +65,7 @@ List getOffsetsXY({ final v = List.filled(len, Offset.zero, growable: true); for (int i = 0; i < len; ++i) { final p = realPoints.elementAt(i); - final (x, y) = crs.transform(p.x, p.y, zoomScale); + final (x, y) = crs.transform(p.dx, p.dy, zoomScale); v[i] = Offset(x + ox, y + oy); } return v; @@ -75,7 +74,7 @@ List getOffsetsXY({ final v = List.filled(len, Offset.zero, growable: true); for (int i = 0; i < len; ++i) { final p = realPoints.elementAt(i); - final (x, y) = crs.transform(p.x, p.y, zoomScale); + final (x, y) = crs.transform(p.dx, p.dy, zoomScale); v[i] = Offset(x + ox, y + oy); } return v; diff --git a/test/map/camera/camera_constraint_test.dart b/test/map/camera/camera_constraint_test.dart index ff4a804db..d3994439d 100644 --- a/test/map/camera/camera_constraint_test.dart +++ b/test/map/camera/camera_constraint_test.dart @@ -20,7 +20,7 @@ void main() { center: const LatLng(-90, -180), zoom: 1, rotation: 45, - nonRotatedSize: const Point(200, 300), + nonRotatedSize: const Offset(200, 300), ); final clamped = mapConstraint.constrain(camera)!; From c918f083092d9348df991d23311d880724554dc4 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 17:50:45 -0600 Subject: [PATCH 03/51] compiler happy --- benchmark/crs.dart | 1 - .../overlay_image_layer/overlay_image.dart | 13 +++++----- lib/src/layer/scalebar/scalebar.dart | 2 +- .../tile_layer/tile_bounds/tile_bounds.dart | 16 ++++++------- .../tile_layer/tile_range_calculator.dart | 6 ++--- .../tile_layer/wms_tile_layer_options.dart | 4 ++-- lib/src/map/camera/camera.dart | 23 ++++++++---------- lib/src/map/camera/camera_constraint.dart | 18 +++++++------- lib/src/map/camera/camera_fit.dart | 24 +++++++++---------- .../map/controller/map_controller_impl.dart | 4 ++-- lib/src/map/widget.dart | 4 +--- lib/src/misc/extensions.dart | 10 +++++++- lib/src/misc/simplify.dart | 9 +------ .../tile_layer/tile_bounds/crs_fakes.dart | 4 ++-- .../tile_bounds/tile_bounds_test.dart | 2 +- test/map/camera/camera_constraint_test.dart | 2 -- 16 files changed, 67 insertions(+), 75 deletions(-) diff --git a/benchmark/crs.dart b/benchmark/crs.dart index 6b7d41ab1..8a50370c5 100644 --- a/benchmark/crs.dart +++ b/benchmark/crs.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:math' as math; import 'dart:ui'; import 'package:flutter_map/src/geo/crs.dart'; diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index fbbed59e9..3c01ecb97 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -80,12 +80,11 @@ class OverlayImage extends BaseOverlayImage { required Image child, }) { final camera = MapCamera.of(context); - // northWest is not necessarily upperLeft depending on projection final bounds = Bounds( - camera.project(this.bounds.northWest) - camera.pixelOrigin, - camera.project(this.bounds.southEast) - camera.pixelOrigin, + (camera.project(this.bounds.northWest) - camera.pixelOrigin).toPoint(), + (camera.project(this.bounds.southEast) - camera.pixelOrigin).toPoint(), ); return Positioned( @@ -146,13 +145,13 @@ class RotatedOverlayImage extends BaseOverlayImage { final pxTopRight = pxTopLeft - pxBottomLeft + pxBottomRight; /// update/enlarge bounds so the new corner points fit within - final bounds = Bounds(pxTopLeft, pxBottomRight) - .extend(pxTopRight) - .extend(pxBottomLeft); + final bounds = Bounds(pxTopLeft.toPoint(), pxBottomRight.toPoint()) + .extend(pxTopRight.toPoint()) + .extend(pxBottomLeft.toPoint()); final vectorX = (pxTopRight - pxTopLeft) / bounds.size.x; final vectorY = (pxBottomLeft - pxTopLeft) / bounds.size.y; - final offset = pxTopLeft - bounds.topLeft; + final offset = pxTopLeft - bounds.topLeft.toOffset(); final a = vectorX.dx; final b = vectorX.dy; diff --git a/lib/src/layer/scalebar/scalebar.dart b/lib/src/layer/scalebar/scalebar.dart index b65fba9cc..8ec22a5bc 100644 --- a/lib/src/layer/scalebar/scalebar.dart +++ b/lib/src/layer/scalebar/scalebar.dart @@ -95,7 +95,7 @@ class Scalebar extends StatelessWidget { : '${(metricDst / 1000.0).toStringAsFixed(0)} km'; final ScalebarPainter scalebarPainter = _SimpleScalebarPainter( // use .abs() to avoid wrong placements on the right map border - scalebarLength: (offsetDistance.x - offsetCenter.x).abs(), + scalebarLength: (offsetDistance.dx - offsetCenter.dx).abs(), text: TextSpan( style: textStyle, text: label, diff --git a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart index f2ef8b1d1..27b370a3a 100644 --- a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart +++ b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart @@ -91,8 +91,8 @@ class DiscreteTileBounds extends TileBounds { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { pixelBounds = Bounds( - crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble), - crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble), + crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble).toPoint(), + crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble).toPoint(), ); } @@ -131,17 +131,17 @@ class WrappedTileBounds extends TileBounds { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { pixelBounds = Bounds( - crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble), - crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble), + crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble).toPoint(), + crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble).toPoint(), ); } (int, int)? wrapX; if (crs.wrapLng case final wrapLng?) { - final wrapXMin = (crs.latLngToPoint(LatLng(0, wrapLng.$1), zoomDouble).x / + final wrapXMin = (crs.latLngToPoint(LatLng(0, wrapLng.$1), zoomDouble).dx / _tileDimension) .floor(); - final wrapXMax = (crs.latLngToPoint(LatLng(0, wrapLng.$2), zoomDouble).x / + final wrapXMax = (crs.latLngToPoint(LatLng(0, wrapLng.$2), zoomDouble).dx / _tileDimension) .ceil(); wrapX = (wrapXMin, wrapXMax - 1); @@ -149,10 +149,10 @@ class WrappedTileBounds extends TileBounds { (int, int)? wrapY; if (crs.wrapLat case final wrapLat?) { - final wrapYMin = (crs.latLngToPoint(LatLng(wrapLat.$1, 0), zoomDouble).y / + final wrapYMin = (crs.latLngToPoint(LatLng(wrapLat.$1, 0), zoomDouble).dy / _tileDimension) .floor(); - final wrapYMax = (crs.latLngToPoint(LatLng(wrapLat.$2, 0), zoomDouble).y / + final wrapYMax = (crs.latLngToPoint(LatLng(wrapLat.$2, 0), zoomDouble).dy / _tileDimension) .ceil(); wrapY = (wrapYMin, wrapYMax - 1); diff --git a/lib/src/layer/tile_layer/tile_range_calculator.dart b/lib/src/layer/tile_layer/tile_range_calculator.dart index 0271673fc..7df6e060d 100644 --- a/lib/src/layer/tile_layer/tile_range_calculator.dart +++ b/lib/src/layer/tile_layer/tile_range_calculator.dart @@ -45,10 +45,10 @@ class TileRangeCalculator { ) { final tileZoomDouble = tileZoom.toDouble(); final scale = camera.getZoomScale(viewingZoom, tileZoomDouble); - final pixelCenter = - camera.project(center, tileZoomDouble).floor().toOffset(); + final pixelCenter = camera.project(center, tileZoomDouble).floor(); final halfSize = camera.size / (scale * 2); - return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); + return Bounds( + (pixelCenter - halfSize).toPoint(), (pixelCenter + halfSize).toPoint()); } } diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index 12fe22b1f..ef2dfb90f 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -71,8 +71,8 @@ class WMSTileLayerOptions { String getUrl(TileCoordinates coords, int tileDimension, bool retinaMode) { final nwPoint = coords * tileDimension; final sePoint = nwPoint + Point(tileDimension, tileDimension); - final nwCoords = crs.pointToLatLng(nwPoint.toDoublePoint(), coords.z.toDouble()); - final seCoords = crs.pointToLatLng(sePoint.toDoublePoint(), coords.z.toDouble()); + final nwCoords = crs.pointToLatLng(nwPoint.toOffset(), coords.z.toDouble()); + final seCoords = crs.pointToLatLng(sePoint.toOffset(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); final bounds = Bounds(nw, se); diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 7914b83c0..76087f0f7 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -58,8 +58,8 @@ class MapCamera { /// This is the [LatLngBounds] corresponding to four corners of this camera. /// This takes rotation in to account. LatLngBounds get visibleBounds => _bounds ??= LatLngBounds( - unproject(pixelBounds.bottomLeft, zoom), - unproject(pixelBounds.topRight, zoom), + unproject(pixelBounds.bottomLeft.toOffset(), zoom), + unproject(pixelBounds.topRight.toOffset(), zoom), ); /// The size of bounding box of this camera taking in to account its @@ -217,7 +217,8 @@ class MapCamera { final rotationRad = degrees2Radians * rotation; final cosAngle = math.cos(rotationRad).abs(); final sinAngle = math.sin(rotationRad).abs(); - final width = (nonRotatedSize.dx * cosAngle) + (nonRotatedSize.dy * sinAngle); + final width = + (nonRotatedSize.dx * cosAngle) + (nonRotatedSize.dy * sinAngle); final height = (nonRotatedSize.dy * cosAngle) + (nonRotatedSize.dx * sinAngle); @@ -253,14 +254,12 @@ class MapCamera { crs.getProjectedBounds(zoom ?? this.zoom); /// Calculates the [Offset] from the [pos] to this camera's [pixelOrigin]. - Offset getOffsetFromOrigin(LatLng pos) => - project(pos) - pixelOrigin; + Offset getOffsetFromOrigin(LatLng pos) => project(pos) - pixelOrigin; /// Calculates the pixel origin of this [MapCamera] at the given /// [center]/[zoom]. Offset getNewPixelOrigin(LatLng center, [double? zoom]) { - // TODO was explcitly rounded - return project(center, zoom) - (size / 2.0); + return (project(center, zoom) - (size / 2.0)).round(); } /// Calculates the pixel bounds of this [MapCamera]. This value is cached. @@ -274,9 +273,9 @@ class MapCamera { final scale = getZoomScale(this.zoom, zoom); halfSize = size / (scale * 2); } - // TODO was explicitly floored - final pixelCenter = project(center, zoom); - return Bounds(pixelCenter - halfSize, pixelCenter + halfSize); + final pixelCenter = project(center, zoom).floor(); + return Bounds( + (pixelCenter - halfSize).toPoint(), (pixelCenter + halfSize).toPoint()); } /// This will convert a latLng to a position that we could use with a widget @@ -321,7 +320,6 @@ class MapCamera { Offset point, { bool counterRotation = true, }) { - //TODO what is the difference between this and the extension method on Offset.rotate?????!?!?! final counterRotationFactor = counterRotation ? -1 : 1; @@ -345,8 +343,7 @@ class MapCamera { /// [MapCamera] gets used. LatLng offsetToCrs(Offset offset, [double? zoom]) { final focalStartPt = project(center, zoom ?? this.zoom); - final point = - (offset - (nonRotatedSize / 2.0)).rotate(rotationRad); + final point = (offset - (nonRotatedSize / 2.0)).rotate(rotationRad); final newCenterPt = focalStartPt + point; return unproject(newCenterPt, zoom ?? this.zoom); diff --git a/lib/src/map/camera/camera_constraint.dart b/lib/src/map/camera/camera_constraint.dart index c5f632a91..23a12866c 100644 --- a/lib/src/map/camera/camera_constraint.dart +++ b/lib/src/map/camera/camera_constraint.dart @@ -1,5 +1,5 @@ -import 'dart:math' as math hide Point; -import 'dart:math' show Point; +import 'dart:math' as math; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -117,19 +117,19 @@ class ContainCamera extends CameraConstraint { // Find the limits for the map center which would keep the camera within the // [latLngBounds]. - final leftOkCenter = math.min(swPixel.x, nePixel.x) + halfSize.x; - final rightOkCenter = math.max(swPixel.x, nePixel.x) - halfSize.x; - final topOkCenter = math.min(swPixel.y, nePixel.y) + halfSize.y; - final botOkCenter = math.max(swPixel.y, nePixel.y) - halfSize.y; + final leftOkCenter = math.min(swPixel.dx, nePixel.dx) + halfSize.dx; + final rightOkCenter = math.max(swPixel.dx, nePixel.dx) - halfSize.dx; + final topOkCenter = math.min(swPixel.dy, nePixel.dy) + halfSize.dy; + final botOkCenter = math.max(swPixel.dy, nePixel.dy) - halfSize.dy; // Stop if we are zoomed out so far that the camera cannot be translated to // stay within [latLngBounds]. if (leftOkCenter > rightOkCenter || topOkCenter > botOkCenter) return null; final centerPix = camera.project(testCenter, testZoom); - final newCenterPix = Point( - centerPix.x.clamp(leftOkCenter, rightOkCenter), - centerPix.y.clamp(topOkCenter, botOkCenter), + final newCenterPix = Offset( + centerPix.dx.clamp(leftOkCenter, rightOkCenter), + centerPix.dy.clamp(topOkCenter, botOkCenter), ); if (newCenterPix == centerPix) return camera; diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 9290bde9a..6fac69533 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -143,8 +143,8 @@ class FitBounds extends CameraFit { // Prevent negative size which results in NaN zoom value later on in the calculation size = Offset(math.max(0, size.dx), math.max(0, size.dy)); var boundsSize = Bounds( - camera.project(se, camera.zoom), - camera.project(nw, camera.zoom), + camera.project(se, camera.zoom).toPoint(), + camera.project(nw, camera.zoom).toPoint(), ).size; if (camera.rotation != 0.0) { final cosAngle = math.cos(camera.rotationRad).abs(); @@ -224,8 +224,8 @@ class FitInsideBounds extends CameraFit { final cameraSize = camera.nonRotatedSize - paddingTotalXY; final projectedBoundsSize = Bounds( - camera.project(bounds.southEast, camera.zoom), - camera.project(bounds.northWest, camera.zoom), + camera.project(bounds.southEast, camera.zoom).toPoint(), + camera.project(bounds.northWest, camera.zoom).toPoint(), ).size; final scale = _rectInRotRectScale( @@ -424,8 +424,8 @@ class FitCoordinates extends CameraFit { /// Returns a new [MapCamera] which fits this classes configuration. @override MapCamera fit(MapCamera camera) { - final paddingTL = Point(padding.left, padding.top); - final paddingBR = Point(padding.right, padding.bottom); + final paddingTL = Offset(padding.left, padding.top); + final paddingBR = Offset(padding.right, padding.bottom); final paddingTotalXY = paddingTL + paddingBR; @@ -435,17 +435,17 @@ class FitCoordinates extends CameraFit { final projectedPoints = coordinates.map((coord) => camera.project(coord, newZoom)); - final rotatedPoints = - projectedPoints.map((point) => point.rotate(-camera.rotationRad)); + final rotatedPoints = projectedPoints + .map((point) => point.rotate(-camera.rotationRad).toPoint()); final rotatedBounds = Bounds.containing(rotatedPoints); // Apply padding final paddingOffset = (paddingBR - paddingTL) / 2; - final rotatedNewCenter = rotatedBounds.center + paddingOffset; + final rotatedNewCenter = rotatedBounds.center.toOffset() + paddingOffset; // Undo the rotation - final unrotatedNewCenter = rotatedNewCenter.toOffset().rotate(camera.rotationRad); + final unrotatedNewCenter = rotatedNewCenter.rotate(camera.rotationRad); final newCenter = camera.unproject(unrotatedNewCenter, newZoom); @@ -467,8 +467,8 @@ class FitCoordinates extends CameraFit { for (final coord in coordinates) camera.project(coord) ]; - final rotatedPoints = - projectedPoints.map((point) => point.rotate(-camera.rotationRad)); + final rotatedPoints = projectedPoints + .map((point) => point.rotate(-camera.rotationRad).toPoint()); final rotatedBounds = Bounds.containing(rotatedPoints); final boundsSize = rotatedBounds.size; diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 20bcec1a8..5df04639a 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -256,7 +256,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> final rotationDiff = degree - camera.rotation; final rotationCenter = camera.project(camera.center) + - (point != null ? (point - (camera.nonRotatedSize / 2.0)) : offset) + (point != null ? (point - (camera.nonRotatedSize / 2.0)) : offset!) .rotate(camera.rotationRad); return ( @@ -325,7 +325,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> /// Set the widget size but don't emit a event to the event system. bool setNonRotatedSizeWithoutEmittingEvent( - Point nonRotatedSize, + Offset nonRotatedSize, ) { if (nonRotatedSize != MapCamera.kImpossibleSize && nonRotatedSize != camera.nonRotatedSize) { diff --git a/lib/src/map/widget.dart b/lib/src/map/widget.dart index a17e58e4a..622333034 100644 --- a/lib/src/map/widget.dart +++ b/lib/src/map/widget.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -143,7 +141,7 @@ class _FlutterMapStateContainer extends State } void _updateAndEmitSizeIfConstraintsChanged(BoxConstraints constraints) { - final nonRotatedSize = Point( + final nonRotatedSize = Offset( constraints.maxWidth, constraints.maxHeight, ); diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index b1d63128c..17e614146 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -40,7 +40,8 @@ extension PointExtension on Point { /// Extension methods for [Offset] extension OffsetToPointExtension on Offset { - /// Creates a [Point] representation of this offset. + /// Creates a [Point] representation of this offset. This is ONLY used for backwards compatibility + @Deprecated('Only used for backwards compatibility') Point toPoint() => Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by @@ -52,4 +53,11 @@ extension OffsetToPointExtension on Offset { final ny = (cosTheta * dy) - (sinTheta * dx); return Offset(nx, ny); } + + /// returns new [Offset] where floorToDouble() is called on [dx] and [dy] independently + Offset floor() => Offset(dx.floorToDouble(), dy.floorToDouble()); + + /// returns new [Offset] where roundToDouble() is called on [dx] and [dy] independently + Offset round() => Offset(dx.roundToDouble(), dy.roundToDouble()); + } diff --git a/lib/src/misc/simplify.dart b/lib/src/misc/simplify.dart index 47f73a615..e14974cd0 100644 --- a/lib/src/misc/simplify.dart +++ b/lib/src/misc/simplify.dart @@ -5,13 +5,6 @@ import 'dart:math' as math; import 'dart:ui'; import 'package:flutter_map/src/geo/crs.dart'; -import 'package:meta/meta.dart'; - -double distanceSq(Offset a, Offset b) { - final double dx = a.dx - b.dx; - final double dy = a.dy - b.dy; - return dx * dx + dy * dy; - } /// square distance from a point to a segment double getSqSegDist( @@ -55,7 +48,7 @@ List simplifyRadialDist( late Offset point; for (int i = 1, len = points.length; i < len; i++) { point = points[i]; - if (distanceSq(point, prevPoint) > sqTolerance) { + if ((point - prevPoint).distanceSquared > sqTolerance) { newPoints.add(point); prevPoint = point; } diff --git a/test/layer/tile_layer/tile_bounds/crs_fakes.dart b/test/layer/tile_layer/tile_bounds/crs_fakes.dart index ea7f13f46..f74e86800 100644 --- a/test/layer/tile_layer/tile_bounds/crs_fakes.dart +++ b/test/layer/tile_layer/tile_bounds/crs_fakes.dart @@ -1,4 +1,4 @@ -import 'dart:math'; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -25,7 +25,7 @@ class FakeInfiniteCrs extends Crs { const Epsg3857().untransform(x, y, scale); @override - LatLng pointToLatLng(Point point, double zoom) => throw UnimplementedError(); + LatLng pointToLatLng(Offset point, double zoom) => throw UnimplementedError(); @override Bounds? getProjectedBounds(double zoom) => throw UnimplementedError(); diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart index 1df422e43..aede15062 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart @@ -93,7 +93,7 @@ void main() { tileDimension: 256, latLngBounds: LatLngBounds( const LatLng(0, 0), - crs.pointToLatLng(crs.getProjectedBounds(0)!.max, 0), + crs.pointToLatLng(crs.getProjectedBounds(0)!.max.toOffset(), 0), ), ); diff --git a/test/map/camera/camera_constraint_test.dart b/test/map/camera/camera_constraint_test.dart index d3994439d..fc5fd08b3 100644 --- a/test/map/camera/camera_constraint_test.dart +++ b/test/map/camera/camera_constraint_test.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:latlong2/latlong.dart'; From bd99ca1bf34ad056307b178c876d2222a868ff63 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 18:01:51 -0600 Subject: [PATCH 04/51] deprecate notices, only really needed because of bounds and tilecoordinates --- lib/src/misc/extensions.dart | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 17e614146..4f7fc5e44 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -3,31 +3,22 @@ import 'dart:ui'; /// Extension methods for the math.[Point] class extension PointExtension on Point { - /// Create new [Point] whose [x] and [y] values are divided by the respective - /// values in [point]. - Point unscaleBy(Point point) { - return Point(x / point.x, y / point.y); - } - /// Create a new [Point] where the [x] and [y] values are divided by [factor]. + @Deprecated('Replace with Offset') Point operator /(num factor) { return Point(x / factor, y / factor); } - /// Create a new [Point] where the [x] and [y] values are rounded to the - /// nearest integer. - Point round() { - return Point(x.round(), y.round()); - } - /// Create a new [Point] where the [x] and [y] values are rounded up to the /// nearest integer. + @Deprecated('Replace with Offset') Point ceil() { return Point(x.ceil(), y.ceil()); } /// Create a new [Point] where the [x] and [y] values are rounded down to the /// nearest integer. + @Deprecated('Replace with Offset') Point floor() { return Point(x.floor(), y.floor()); } From f3c2132073499b5b975e5556202a090c47d109a9 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 18:40:23 -0600 Subject: [PATCH 05/51] this definitely touches an externally accessible API: mapController.camera.pointToLatLng --- benchmark/point_in_polygon.dart | 4 ++-- example/lib/pages/screen_point_to_latlng.dart | 4 +--- lib/src/layer/circle_layer/painter.dart | 4 ++-- lib/src/layer/polygon_layer/painter.dart | 2 +- lib/src/layer/polygon_layer/polygon_layer.dart | 1 - lib/src/layer/polyline_layer/painter.dart | 4 ++-- .../layer_interactivity/internal_hit_detectable.dart | 6 ++---- .../shared/layer_interactivity/layer_hit_result.dart | 4 ++-- lib/src/map/camera/camera.dart | 9 ++++----- lib/src/map/camera/camera_fit.dart | 4 ++-- lib/src/misc/bounds.dart | 11 ++++++----- lib/src/misc/point_in_polygon.dart | 7 +++---- test/misc/point_in_polygon_test.dart | 8 ++++---- 13 files changed, 31 insertions(+), 37 deletions(-) diff --git a/benchmark/point_in_polygon.dart b/benchmark/point_in_polygon.dart index d75a643af..cb32bbea5 100644 --- a/benchmark/point_in_polygon.dart +++ b/benchmark/point_in_polygon.dart @@ -49,7 +49,7 @@ Future main() async { final circle = makeCircle(1000, 1, 0); results.add(await timedRun('In circle', () { - const point = math.Point(0, 0); + const point = Offset.zero; bool yesPlease = true; for (int i = 0; i < N; ++i) { @@ -61,7 +61,7 @@ Future main() async { })); results.add(await timedRun('Not in circle', () { - const point = math.Point(4, 4); + const point = Offset(4, 4); bool noSir = false; for (int i = 0; i < N; ++i) { diff --git a/example/lib/pages/screen_point_to_latlng.dart b/example/lib/pages/screen_point_to_latlng.dart index 02d08ccb7..cbde93e29 100644 --- a/example/lib/pages/screen_point_to_latlng.dart +++ b/example/lib/pages/screen_point_to_latlng.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_example/misc/tile_providers.dart'; @@ -96,7 +94,7 @@ class PointToLatlngPage extends State { } void updatePoint(BuildContext context) => setState(() => latLng = - mapController.camera.pointToLatLng(Point(_getPointX(context), pointY))); + mapController.camera.pointToLatLng(Offset(_getPointX(context), pointY))); double _getPointX(BuildContext context) => MediaQuery.sizeOf(context).width / 2; diff --git a/lib/src/layer/circle_layer/painter.dart b/lib/src/layer/circle_layer/painter.dart index e0e0ab684..a87bc8fd5 100644 --- a/lib/src/layer/circle_layer/painter.dart +++ b/lib/src/layer/circle_layer/painter.dart @@ -20,7 +20,7 @@ base class CirclePainter @override bool elementHitTest( CircleMarker element, { - required Point point, + required Offset point, required LatLng coordinate, }) { final circle = element; // Should be optimized out by compiler, avoids lint @@ -33,7 +33,7 @@ base class CirclePainter .distance : circle.radius; - return pow(point.x - center.dx, 2) + pow(point.y - center.dy, 2) <= + return pow(point.dx - center.dx, 2) + pow(point.dy - center.dy, 2) <= radius * radius; } diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart index eff23a099..25e541b96 100644 --- a/lib/src/layer/polygon_layer/painter.dart +++ b/lib/src/layer/polygon_layer/painter.dart @@ -49,7 +49,7 @@ base class _PolygonPainter @override bool elementHitTest( _ProjectedPolygon projectedPolygon, { - required math.Point point, + required Offset point, required LatLng coordinate, }) { // TODO: We should check the bounding box here, for efficiency diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index 4ccb4669a..a32678fe8 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -1,4 +1,3 @@ -import 'dart:math' as math; import 'dart:ui'; import 'package:collection/collection.dart'; diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index db4aca4b0..ca5fdc87b 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -20,7 +20,7 @@ base class _PolylinePainter @override bool elementHitTest( _ProjectedPolyline projectedPolyline, { - required math.Point point, + required Offset point, required LatLng coordinate, }) { final polyline = projectedPolyline.polyline; @@ -57,7 +57,7 @@ base class _PolylinePainter final o2 = offsets[i + 1]; final distanceSq = - getSqSegDist(point.x, point.y, o1.dx, o1.dy, o2.dx, o2.dy); + getSqSegDist(point.dx, point.dy, o1.dx, o1.dy, o2.dx, o2.dy); if (distanceSq <= hittableDistance * hittableDistance) return true; } diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 5e17c7e4c..357ac0260 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -54,7 +52,7 @@ abstract base class HitDetectablePainter point, + required Offset point, required LatLng coordinate, }); @@ -66,7 +64,7 @@ abstract base class HitDetectablePainter= 0; i--) { diff --git a/lib/src/layer/shared/layer_interactivity/layer_hit_result.dart b/lib/src/layer/shared/layer_interactivity/layer_hit_result.dart index 535cac558..d0089cb61 100644 --- a/lib/src/layer/shared/layer_interactivity/layer_hit_result.dart +++ b/lib/src/layer/shared/layer_interactivity/layer_hit_result.dart @@ -1,4 +1,4 @@ -import 'dart:math'; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -29,7 +29,7 @@ class LayerHitResult { /// Screen point of the detected hit /// /// See [coordinate] for the geographical coordinate which was hit. - final Point point; + final Offset point; /// Construct a new [LayerHitResult] @internal diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 76087f0f7..ef69a64d2 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -1,5 +1,4 @@ -import 'dart:math' as math hide Point; -import 'dart:math' show Point; +import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -295,10 +294,10 @@ class MapCamera { } /// Calculate the [LatLng] coordinates for a [localPoint]. - LatLng pointToLatLng(Point localPoint) { + LatLng pointToLatLng(Offset localPoint) { final localPointCenterDistance = Offset( - (nonRotatedSize.dx / 2) - localPoint.x, - (nonRotatedSize.dy / 2) - localPoint.y, + (nonRotatedSize.dx / 2) - localPoint.dx, + (nonRotatedSize.dy / 2) - localPoint.dy, ); final mapCenter = crs.latLngToPoint(center, zoom); diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 6fac69533..cb72df35c 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -436,7 +436,7 @@ class FitCoordinates extends CameraFit { coordinates.map((coord) => camera.project(coord, newZoom)); final rotatedPoints = projectedPoints - .map((point) => point.rotate(-camera.rotationRad).toPoint()); + .map((point) => point.rotate(-camera.rotationRad)); final rotatedBounds = Bounds.containing(rotatedPoints); @@ -468,7 +468,7 @@ class FitCoordinates extends CameraFit { ]; final rotatedPoints = projectedPoints - .map((point) => point.rotate(-camera.rotationRad).toPoint()); + .map((point) => point.rotate(-camera.rotationRad)); final rotatedBounds = Bounds.containing(rotatedPoints); final boundsSize = rotatedBounds.size; diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index 501f3de9f..fa60aac79 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -1,5 +1,6 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; +import 'dart:ui'; import 'package:meta/meta.dart'; @@ -41,17 +42,17 @@ class Bounds { const Bounds.unsafe(this.min, this.max); /// Create a [Bounds] as bounding box of a list of points. - static Bounds containing(Iterable> points) { + static Bounds containing(Iterable points) { var maxX = double.negativeInfinity; var maxY = double.negativeInfinity; var minX = double.infinity; var minY = double.infinity; for (final point in points) { - maxX = math.max(point.x, maxX); - minX = math.min(point.x, minX); - maxY = math.max(point.y, maxY); - minY = math.min(point.y, minY); + maxX = math.max(point.dx, maxX); + minX = math.min(point.dx, minX); + maxY = math.max(point.dy, maxY); + minY = math.min(point.dy, minY); } return Bounds.unsafe(Point(minX, minY), Point(maxX, maxY)); diff --git a/lib/src/misc/point_in_polygon.dart b/lib/src/misc/point_in_polygon.dart index 9f0192da0..9a58b0bc3 100644 --- a/lib/src/misc/point_in_polygon.dart +++ b/lib/src/misc/point_in_polygon.dart @@ -1,16 +1,15 @@ -import 'dart:math' as math; import 'dart:ui'; /// Checks whether point [p] is within the specified closed [polygon] /// /// Uses the even-odd algorithm and requires closed loop polygons, i.e. /// `polygon.first == polygon.last`. -bool isPointInPolygon(math.Point p, List polygon) { +bool isPointInPolygon(Offset p, List polygon) { final len = polygon.length; assert(len >= 3, 'not a polygon'); assert(polygon.first == polygon.last, 'polygon not closed'); - final double px = p.x.toDouble(); - final double py = p.y.toDouble(); + final double px = p.dx; + final double py = p.dy; bool isInPolygon = false; for (int i = 0, j = len - 1; i < len; j = i++) { diff --git a/test/misc/point_in_polygon_test.dart b/test/misc/point_in_polygon_test.dart index b9f697125..2e2827570 100644 --- a/test/misc/point_in_polygon_test.dart +++ b/test/misc/point_in_polygon_test.dart @@ -19,22 +19,22 @@ void main() { // Inside points for (final point in makeCircle(32, 0.8, 0.0001)) { - final p = math.Point(point.dx, point.dy); + final p = Offset(point.dx, point.dy); expect(isPointInPolygon(p, circle), isTrue); } // Edge-case: check origin - expect(isPointInPolygon(const math.Point(0, 0), circle), isTrue); + expect(isPointInPolygon(Offset.zero, circle), isTrue); // Outside points: small radius for (final point in makeCircle(32, 1.1, 0.0001)) { - final p = math.Point(point.dx, point.dy); + final p = Offset(point.dx, point.dy); expect(isPointInPolygon(p, circle), isFalse); } // Outside points: large radius for (final point in makeCircle(32, 100000, 0.0001)) { - final p = math.Point(point.dx, point.dy); + final p = Offset(point.dx, point.dy); expect(isPointInPolygon(p, circle), isFalse); } }); From d726a5eaecf3aad39aac57856bbe15750bb58ba4 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 18:41:58 -0600 Subject: [PATCH 06/51] dart format --- lib/src/layer/polyline_layer/painter.dart | 3 +- .../layer/polyline_layer/polyline_layer.dart | 3 +- .../tile_layer/tile_bounds/tile_bounds.dart | 28 +++++++++++-------- lib/src/map/camera/camera_fit.dart | 8 +++--- lib/src/misc/extensions.dart | 5 +--- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index ca5fdc87b..d47c45671 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -107,8 +107,7 @@ base class _PolylinePainter paint = Paint(); } - final origin = - camera.project(camera.center) - camera.size / 2; + final origin = camera.project(camera.center) - camera.size / 2; for (final projectedPolyline in polylines) { final polyline = projectedPolyline.polyline; diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 615362ffb..18a5161a3 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -157,7 +157,8 @@ class _PolylineLayerState extends State> final p1 = projectedPolyline.points[i]; final p2 = projectedPolyline.points[i + 1]; - containsSegment = projBounds.aabbContainsLine(p1.dx, p1.dy, p2.dx, p2.dy); + containsSegment = + projBounds.aabbContainsLine(p1.dx, p1.dy, p2.dx, p2.dy); if (containsSegment) { if (start == -1) { start = i; diff --git a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart index 27b370a3a..5f66bb9be 100644 --- a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart +++ b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart @@ -138,23 +138,27 @@ class WrappedTileBounds extends TileBounds { (int, int)? wrapX; if (crs.wrapLng case final wrapLng?) { - final wrapXMin = (crs.latLngToPoint(LatLng(0, wrapLng.$1), zoomDouble).dx / - _tileDimension) - .floor(); - final wrapXMax = (crs.latLngToPoint(LatLng(0, wrapLng.$2), zoomDouble).dx / - _tileDimension) - .ceil(); + final wrapXMin = + (crs.latLngToPoint(LatLng(0, wrapLng.$1), zoomDouble).dx / + _tileDimension) + .floor(); + final wrapXMax = + (crs.latLngToPoint(LatLng(0, wrapLng.$2), zoomDouble).dx / + _tileDimension) + .ceil(); wrapX = (wrapXMin, wrapXMax - 1); } (int, int)? wrapY; if (crs.wrapLat case final wrapLat?) { - final wrapYMin = (crs.latLngToPoint(LatLng(wrapLat.$1, 0), zoomDouble).dy / - _tileDimension) - .floor(); - final wrapYMax = (crs.latLngToPoint(LatLng(wrapLat.$2, 0), zoomDouble).dy / - _tileDimension) - .ceil(); + final wrapYMin = + (crs.latLngToPoint(LatLng(wrapLat.$1, 0), zoomDouble).dy / + _tileDimension) + .floor(); + final wrapYMax = + (crs.latLngToPoint(LatLng(wrapLat.$2, 0), zoomDouble).dy / + _tileDimension) + .ceil(); wrapY = (wrapYMin, wrapYMax - 1); } diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index cb72df35c..fe3d1ec2f 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -435,8 +435,8 @@ class FitCoordinates extends CameraFit { final projectedPoints = coordinates.map((coord) => camera.project(coord, newZoom)); - final rotatedPoints = projectedPoints - .map((point) => point.rotate(-camera.rotationRad)); + final rotatedPoints = + projectedPoints.map((point) => point.rotate(-camera.rotationRad)); final rotatedBounds = Bounds.containing(rotatedPoints); @@ -467,8 +467,8 @@ class FitCoordinates extends CameraFit { for (final coord in coordinates) camera.project(coord) ]; - final rotatedPoints = projectedPoints - .map((point) => point.rotate(-camera.rotationRad)); + final rotatedPoints = + projectedPoints.map((point) => point.rotate(-camera.rotationRad)); final rotatedBounds = Bounds.containing(rotatedPoints); final boundsSize = rotatedBounds.size; diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 4f7fc5e44..d9f145a54 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -24,13 +24,11 @@ extension PointExtension on Point { } /// Converts to offset - Offset toOffset () => Offset(x.toDouble(), y.toDouble()); - + Offset toOffset() => Offset(x.toDouble(), y.toDouble()); } /// Extension methods for [Offset] extension OffsetToPointExtension on Offset { - /// Creates a [Point] representation of this offset. This is ONLY used for backwards compatibility @Deprecated('Only used for backwards compatibility') Point toPoint() => Point(dx, dy); @@ -50,5 +48,4 @@ extension OffsetToPointExtension on Offset { /// returns new [Offset] where roundToDouble() is called on [dx] and [dy] independently Offset round() => Offset(dx.roundToDouble(), dy.roundToDouble()); - } From 54127a9ed432e57e1fd93514584e01848ea511ac Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 20:21:18 -0600 Subject: [PATCH 07/51] remove stuff --- lib/src/layer/tile_layer/tile_layer.dart | 1 + lib/src/layer/tile_layer/tile_range.dart | 12 +++++++++--- lib/src/misc/extensions.dart | 17 +---------------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index 3ff6cdbda..c516673c6 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -758,6 +758,7 @@ class _TileLayerState extends State with TickerProviderStateMixin { } } +// TODO replace with simple implementation of (Offset - Offset).distanceSq double _distanceSq(TileCoordinates coord, Point center) { final dx = center.x - coord.x; final dy = center.y - coord.y; diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 41eff6ee0..088f3450b 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -29,6 +29,12 @@ class EmptyTileRange extends TileRange { const Iterable.empty(); } +Point _floor(Point point) => + Point(point.x.floor(), point.y.floor()); + +Point _ceil(Point point) => + Point(point.x.ceil(), point.y.ceil()); + /// Every [TileRange] is a [DiscreteTileRange] if it's not an [EmptyTileRange]. @immutable class DiscreteTileRange extends TileRange { @@ -46,12 +52,12 @@ class DiscreteTileRange extends TileRange { }) { final Bounds bounds; if (pixelBounds.min == pixelBounds.max) { - final minAndMax = (pixelBounds.min / tileDimension).floor(); + final minAndMax = _floor(pixelBounds.min / tileDimension); bounds = Bounds(minAndMax, minAndMax); } else { bounds = Bounds( - (pixelBounds.min / tileDimension).floor(), - (pixelBounds.max / tileDimension).ceil() - const Point(1, 1), + _floor(pixelBounds.min / tileDimension), + _ceil(pixelBounds.max / tileDimension) - const Point(1, 1), ); } diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index d9f145a54..beb132bf1 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -4,25 +4,11 @@ import 'dart:ui'; /// Extension methods for the math.[Point] class extension PointExtension on Point { /// Create a new [Point] where the [x] and [y] values are divided by [factor]. - @Deprecated('Replace with Offset') + /// REPLACE IN FAVOR OF OFFSET Point operator /(num factor) { return Point(x / factor, y / factor); } - /// Create a new [Point] where the [x] and [y] values are rounded up to the - /// nearest integer. - @Deprecated('Replace with Offset') - Point ceil() { - return Point(x.ceil(), y.ceil()); - } - - /// Create a new [Point] where the [x] and [y] values are rounded down to the - /// nearest integer. - @Deprecated('Replace with Offset') - Point floor() { - return Point(x.floor(), y.floor()); - } - /// Converts to offset Offset toOffset() => Offset(x.toDouble(), y.toDouble()); } @@ -30,7 +16,6 @@ extension PointExtension on Point { /// Extension methods for [Offset] extension OffsetToPointExtension on Offset { /// Creates a [Point] representation of this offset. This is ONLY used for backwards compatibility - @Deprecated('Only used for backwards compatibility') Point toPoint() => Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by From 36d83a4d13c895bde8637e7d1ee30beed3af9cf5 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 20:31:28 -0600 Subject: [PATCH 08/51] more stuffffffffff --- example/lib/pages/latlng_to_screen_point.dart | 10 ++++------ lib/src/layer/tile_layer/tile_layer.dart | 6 +++--- lib/src/layer/tile_layer/tile_range.dart | 3 ++- lib/src/map/camera/camera_fit.dart | 2 +- lib/src/misc/bounds.dart | 6 ++---- test/core/bounds_test.dart | 4 ++-- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/example/lib/pages/latlng_to_screen_point.dart b/example/lib/pages/latlng_to_screen_point.dart index 08c03ac7d..8f69d9a1c 100644 --- a/example/lib/pages/latlng_to_screen_point.dart +++ b/example/lib/pages/latlng_to_screen_point.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -23,7 +21,7 @@ class _LatLngToScreenPointPageState extends State { final mapController = MapController(); LatLng? tappedCoords; - Point? tappedPoint; + Offset? tappedPoint; @override void initState() { @@ -53,7 +51,7 @@ class _LatLngToScreenPointPageState extends State { onTap: (_, latLng) { final point = mapController.camera .latLngToScreenOffset(tappedCoords = latLng); - setState(() => tappedPoint = Point(point.dx, point.dy)); + setState(() => tappedPoint = Offset(point.dx, point.dy)); }, ), children: [ @@ -77,8 +75,8 @@ class _LatLngToScreenPointPageState extends State { ), if (tappedPoint != null) Positioned( - left: tappedPoint!.x - 60 / 2, - top: tappedPoint!.y - 60 / 2, + left: tappedPoint!.dx - 60 / 2, + top: tappedPoint!.dy - 60 / 2, child: const IgnorePointer( child: Icon( Icons.center_focus_strong_outlined, diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index c516673c6..43629e3a5 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -759,8 +759,8 @@ class _TileLayerState extends State with TickerProviderStateMixin { } // TODO replace with simple implementation of (Offset - Offset).distanceSq -double _distanceSq(TileCoordinates coord, Point center) { - final dx = center.x - coord.x; - final dy = center.y - coord.y; +double _distanceSq(TileCoordinates coord, Offset center) { + final dx = center.dx - coord.x; + final dy = center.dy - coord.y; return dx * dx + dy * dy; } diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 088f3450b..4b235932c 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -1,5 +1,6 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:meta/meta.dart'; @@ -151,7 +152,7 @@ class DiscreteTileRange extends TileRange { Point get max => _bounds.max; /// The center [Point] of the [DiscreteTileRange] - Point get center => _bounds.center; + Offset get center => _bounds.center; /// Get a list of [TileCoordinates] for the [DiscreteTileRange]. @override diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index fe3d1ec2f..8765c4a81 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -442,7 +442,7 @@ class FitCoordinates extends CameraFit { // Apply padding final paddingOffset = (paddingBR - paddingTL) / 2; - final rotatedNewCenter = rotatedBounds.center.toOffset() + paddingOffset; + final rotatedNewCenter = rotatedBounds.center + paddingOffset; // Undo the rotation final unrotatedNewCenter = rotatedNewCenter.rotate(camera.rotationRad); diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index fa60aac79..f4d4551e4 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -2,6 +2,7 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; import 'dart:ui'; +import 'package:flutter_map/flutter_map.dart'; import 'package:meta/meta.dart'; /// Rectangular bound delimited by orthogonal lines passing through two @@ -68,10 +69,7 @@ class Bounds { } /// This [Bounds] central point. - Point get center => Point( - (min.x + max.x) / 2, - (min.y + max.y) / 2, - ); + Offset get center => (min.toOffset() + max.toOffset()) / 2; /// Bottom-Left corner's point. Point get bottomLeft => Point(min.x, max.y); diff --git a/test/core/bounds_test.dart b/test/core/bounds_test.dart index 51bcd34ba..b6539f10e 100644 --- a/test/core/bounds_test.dart +++ b/test/core/bounds_test.dart @@ -47,7 +47,7 @@ void main() { expect( Bounds(Point(5.5, randomDouble()), Point(3.3, randomDouble())) .center - .x, + .dx, equals(4.4)); }); @@ -55,7 +55,7 @@ void main() { expect( Bounds(Point(randomDouble(), 3.2), Point(randomDouble(), 6.6)) .center - .y, + .dy, equals(4.9)); }); From ac4f22ccfe0e22c952af36874f1aea8b91a978d3 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 20:36:36 -0600 Subject: [PATCH 09/51] oops --- lib/src/layer/polygon_layer/label.dart | 4 ++-- lib/src/layer/polygon_layer/polygon_layer.dart | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/layer/polygon_layer/label.dart b/lib/src/layer/polygon_layer/label.dart index ee9ff0f80..65b9b99ba 100644 --- a/lib/src/layer/polygon_layer/label.dart +++ b/lib/src/layer/polygon_layer/label.dart @@ -77,8 +77,8 @@ LatLng _computeCentroid(List points) { LatLng _computePolylabel(List points) { final labelPosition = polylabel( [ - List.generate(points.length, - (i) => Offset(points[i].longitude, points[i].latitude)), + List>.generate(points.length, + (i) => Point(points[i].longitude, points[i].latitude)), ], // "precision" is a bit of a misnomer. It's a threshold for when to stop // dividing-and-conquering the polygon in the hopes of finding a better diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index a32678fe8..f048fe23c 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -1,3 +1,4 @@ +import 'dart:math'; import 'dart:ui'; import 'package:collection/collection.dart'; From 5e29da154cf9efdec1f691d70e42c24d0a1c88a6 Mon Sep 17 00:00:00 2001 From: mootw Date: Mon, 2 Dec 2024 21:00:55 -0600 Subject: [PATCH 10/51] fix tests --- test/layer/tile_layer/tile_range_test.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/layer/tile_layer/tile_range_test.dart b/test/layer/tile_layer/tile_range_test.dart index 19a0ec39d..e010b1667 100644 --- a/test/layer/tile_layer/tile_range_test.dart +++ b/test/layer/tile_layer/tile_range_test.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; @@ -231,7 +232,7 @@ void main() { ), ); - expect(tileRange.center, const Point(3, 3)); + expect(tileRange.center, const Offset(3, 3)); }); test('multiple tiles, even number of tiles', () { @@ -244,7 +245,7 @@ void main() { ), ); - expect(tileRange.center, const Point(3.5, 3.5)); + expect(tileRange.center, const Offset(3.5, 3.5)); }); test('multiple tiles, odd number of tiles', () { @@ -257,7 +258,7 @@ void main() { ), ); - expect(tileRange.center, const Point(4, 4)); + expect(tileRange.center, const Offset(4, 4)); }); }); From 403c4311640c1dcbfc4d20ea2868ad2265f1a6ea Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:40:01 -0600 Subject: [PATCH 11/51] use double.negativeInfinity no Offset.negitiveInfinity exists --- lib/src/map/camera/camera.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index ef69a64d2..c3b46887e 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -17,7 +17,8 @@ class MapCamera { /// in a subsequent build to the actual constraints. We set the size to this /// impossible (negative) value initially and only change it once Flutter /// provides real constraints. - static const kImpossibleSize = Offset(-1, -1); + static const kImpossibleSize = + Offset(double.negativeInfinity, double.negativeInfinity); /// The used coordinate reference system final Crs crs; From 1dcb372cfb85929986fbf9236988a6cb9c8d543c Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:43:43 -0600 Subject: [PATCH 12/51] rename pointToLatLng to offsetToLatLng --- benchmark/crs.dart | 2 +- example/lib/pages/screen_point_to_latlng.dart | 2 +- lib/src/geo/crs.dart | 6 +++--- .../shared/layer_interactivity/internal_hit_detectable.dart | 4 ++-- lib/src/layer/tile_layer/wms_tile_layer_options.dart | 4 ++-- lib/src/map/camera/camera.dart | 6 +++--- test/layer/tile_layer/tile_bounds/crs_fakes.dart | 2 +- test/layer/tile_layer/tile_bounds/tile_bounds_test.dart | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/benchmark/crs.dart b/benchmark/crs.dart index 8a50370c5..8e2a5a8e8 100644 --- a/benchmark/crs.dart +++ b/benchmark/crs.dart @@ -95,7 +95,7 @@ Future main() async { double x = 0; double y = 0; for (int i = 0; i < N; ++i) { - final latlng = crs.pointToLatLng(Offset(x, y), 1); + final latlng = crs.offsetToLatLng(Offset(x, y), 1); x += latlng.longitude; y += latlng.latitude; } diff --git a/example/lib/pages/screen_point_to_latlng.dart b/example/lib/pages/screen_point_to_latlng.dart index cbde93e29..b6e550afb 100644 --- a/example/lib/pages/screen_point_to_latlng.dart +++ b/example/lib/pages/screen_point_to_latlng.dart @@ -94,7 +94,7 @@ class PointToLatlngPage extends State { } void updatePoint(BuildContext context) => setState(() => latLng = - mapController.camera.pointToLatLng(Offset(_getPointX(context), pointY))); + mapController.camera.offsetToLatLng(Offset(_getPointX(context), pointY))); double _getPointX(BuildContext context) => MediaQuery.sizeOf(context).width / 2; diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index ef66ce50d..ebd4a3087 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -58,7 +58,7 @@ abstract class Crs { } /// Converts a map point to the sphere coordinate (at a certain zoom). - LatLng pointToLatLng(Offset point, double zoom); + LatLng offsetToLatLng(Offset point, double zoom); /// Zoom to Scale function. double scale(double zoom) => 256.0 * math.pow(2, zoom); @@ -108,7 +108,7 @@ abstract class CrsWithStaticTransformation extends Crs { } @override - LatLng pointToLatLng(Offset point, double zoom) { + LatLng offsetToLatLng(Offset point, double zoom) { final (x, y) = _transformation.untransform( point.dx, point.dy, @@ -282,7 +282,7 @@ class Proj4Crs extends Crs { /// Converts a map point to the sphere coordinate (at a certain zoom). @override - LatLng pointToLatLng(Offset point, double zoom) { + LatLng offsetToLatLng(Offset point, double zoom) { final (x, y) = _getTransformationByZoom(zoom).untransform( point.dx, point.dy, diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 357ac0260..08714fa9a 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -40,7 +40,7 @@ abstract base class HitDetectablePainter= 0; i--) { final element = elements.elementAt(i); diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index ef2dfb90f..d8beceb89 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -71,8 +71,8 @@ class WMSTileLayerOptions { String getUrl(TileCoordinates coords, int tileDimension, bool retinaMode) { final nwPoint = coords * tileDimension; final sePoint = nwPoint + Point(tileDimension, tileDimension); - final nwCoords = crs.pointToLatLng(nwPoint.toOffset(), coords.z.toDouble()); - final seCoords = crs.pointToLatLng(sePoint.toOffset(), coords.z.toDouble()); + final nwCoords = crs.offsetToLatLng(nwPoint.toOffset(), coords.z.toDouble()); + final seCoords = crs.offsetToLatLng(sePoint.toOffset(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); final bounds = Bounds(nw, se); diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index c3b46887e..70aa7e392 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -236,7 +236,7 @@ class MapCamera { /// Calculates the [LatLng] for the given [point] using this camera's /// [crs] and [zoom] (or the provided [zoom]). LatLng unproject(Offset point, [double? zoom]) => - crs.pointToLatLng(point, zoom ?? this.zoom); + crs.offsetToLatLng(point, zoom ?? this.zoom); /// Same as the [unproject] function. LatLng layerPointToLatLng(Offset point) => unproject(point); @@ -295,7 +295,7 @@ class MapCamera { } /// Calculate the [LatLng] coordinates for a [localPoint]. - LatLng pointToLatLng(Offset localPoint) { + LatLng offsetToLatLng(Offset localPoint) { final localPointCenterDistance = Offset( (nonRotatedSize.dx / 2) - localPoint.dx, (nonRotatedSize.dy / 2) - localPoint.dy, @@ -308,7 +308,7 @@ class MapCamera { point = rotateOffset(mapCenter, point); } - return crs.pointToLatLng(point, zoom); + return crs.offsetToLatLng(point, zoom); } /// Sometimes we need to make allowances that a rotation already exists, so diff --git a/test/layer/tile_layer/tile_bounds/crs_fakes.dart b/test/layer/tile_layer/tile_bounds/crs_fakes.dart index f74e86800..0c5cc73d4 100644 --- a/test/layer/tile_layer/tile_bounds/crs_fakes.dart +++ b/test/layer/tile_layer/tile_bounds/crs_fakes.dart @@ -25,7 +25,7 @@ class FakeInfiniteCrs extends Crs { const Epsg3857().untransform(x, y, scale); @override - LatLng pointToLatLng(Offset point, double zoom) => throw UnimplementedError(); + LatLng offsetToLatLng(Offset point, double zoom) => throw UnimplementedError(); @override Bounds? getProjectedBounds(double zoom) => throw UnimplementedError(); diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart index aede15062..b16f18028 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart @@ -93,7 +93,7 @@ void main() { tileDimension: 256, latLngBounds: LatLngBounds( const LatLng(0, 0), - crs.pointToLatLng(crs.getProjectedBounds(0)!.max.toOffset(), 0), + crs.offsetToLatLng(crs.getProjectedBounds(0)!.max.toOffset(), 0), ), ); From e4432729d7cde8596574654490ffd6a8d0a1670c Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:46:19 -0600 Subject: [PATCH 13/51] remove unused duplicate function --- lib/src/map/camera/camera.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 70aa7e392..692be276b 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -238,9 +238,6 @@ class MapCamera { LatLng unproject(Offset point, [double? zoom]) => crs.offsetToLatLng(point, zoom ?? this.zoom); - /// Same as the [unproject] function. - LatLng layerPointToLatLng(Offset point) => unproject(point); - /// Calculates the scale for a zoom from [fromZoom] to [toZoom] using this /// camera\s [crs]. double getZoomScale(double toZoom, double fromZoom) => From 6948c2e36105c60f5032a838fefcbad23ed5cd79 Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:51:22 -0600 Subject: [PATCH 14/51] remove todo --- lib/src/gestures/map_interactive_viewer.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index 06999a0fa..e232a03a3 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -889,7 +889,6 @@ class MapInteractiveViewerState extends State } else { final Offset bestCenterPoint; final double worldSize = _camera.crs.scale(_camera.zoom); - // TODO there has to be an easier way to write this code... if (newCenterPoint.dx > worldSize) { bestCenterPoint = Offset(newCenterPoint.dx - worldSize, newCenterPoint.dy); From 5beb77ae07620b2c28ac7773b0fc53fc522a07db Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:59:20 -0600 Subject: [PATCH 15/51] Update lib/src/map/camera/camera.dart Co-authored-by: Luka S --- lib/src/map/camera/camera.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 692be276b..5f881374b 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -75,7 +75,7 @@ class MapCamera { /// camera. This will not equal the offset of the top-left visible pixel when /// the map is rotated. Offset get pixelOrigin => - _pixelOrigin ??= project(center, zoom) - (size / 2.0); + _pixelOrigin ??= project(center, zoom) - size / 2; /// The camera of the closest [FlutterMap] ancestor. If this is called from a /// context with no [FlutterMap] ancestor null, is returned. From ca7733447484ae5f42925be9a53d81ffbbc5951b Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 10:59:54 -0600 Subject: [PATCH 16/51] format change --- lib/src/map/camera/camera.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 5f881374b..986bdbd26 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -74,8 +74,7 @@ class MapCamera { /// The offset of the top-left corner of the bounding rectangle of this /// camera. This will not equal the offset of the top-left visible pixel when /// the map is rotated. - Offset get pixelOrigin => - _pixelOrigin ??= project(center, zoom) - size / 2; + Offset get pixelOrigin => _pixelOrigin ??= project(center, zoom) - size / 2; /// The camera of the closest [FlutterMap] ancestor. If this is called from a /// context with no [FlutterMap] ancestor null, is returned. From af5b36b0c26674638f98b64c23175ca0f2f98a46 Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 11:07:54 -0600 Subject: [PATCH 17/51] replace helper function --- lib/src/layer/tile_layer/tile_layer.dart | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index 43629e3a5..c153b541a 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -695,8 +695,9 @@ class _TileLayerState extends State with TickerProviderStateMixin { // Re-order the tiles by their distance to the center of the range. final tileCenter = expandedTileLoadRange.center; tilesToLoad.sort( - (a, b) => _distanceSq(a.coordinates, tileCenter) - .compareTo(_distanceSq(b.coordinates, tileCenter)), + (a, b) => (a.coordinates.toOffset() - tileCenter) + .distanceSquared + .compareTo((b.coordinates.toOffset() - tileCenter).distanceSquared), ); // Create the new Tiles. @@ -757,10 +758,3 @@ class _TileLayerState extends State with TickerProviderStateMixin { if (mounted) _loadAndPruneInVisibleBounds(MapCamera.of(context)); } } - -// TODO replace with simple implementation of (Offset - Offset).distanceSq -double _distanceSq(TileCoordinates coord, Offset center) { - final dx = center.dx - coord.x; - final dy = center.dy - coord.y; - return dx * dx + dy * dy; -} From 19ab34b00f5439394ea6ae4a8e3803c2ebf78c3f Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 11:18:01 -0600 Subject: [PATCH 18/51] start migration guide --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a0357b6c..0f0e9453a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ Please consider [donating](https://docs.fleaflet.dev/supporters#support-us) or [ This CHANGELOG does not include every commit and/or PR - it is a hand picked selection of the most important ones. For a full list of changes, please check the GitHub repository releases/tags. +## [8.0.0] - 2024/07/02 + +Migration from `Point` class internally, but this also affects the external API. + +Migration Guide: +- any methods that previously required `Point` now require `Offset` as return values and parameters +- `pointToLatLng` -> `offsetToLatLng` +- `PointExtension` has had methods removed + + +Contains the following user-affecting bug fixes: + + ## [7.0.2] - 2024/07/02 > Note that this version causes a technically breaking change by removing `PolygonLayer.useDynamicUpdate` & `PolylineLayer.useDynamicUpdate`, introduced in v7.0.1. However, the implementations for these was broken on introduction, and their intended purpose no longer exists. Therefore, these should not have been used in any capacity, and should not affect any projects. From 87f123b503a9990c5ed0b2f8ecde5029498324ef Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 11:25:15 -0600 Subject: [PATCH 19/51] mark as internal --- CHANGELOG.md | 2 +- lib/src/misc/extensions.dart | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0e9453a..bb5602c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Migration from `Point` class internally, but this also affects the external API. Migration Guide: - any methods that previously required `Point` now require `Offset` as return values and parameters - `pointToLatLng` -> `offsetToLatLng` -- `PointExtension` has had methods removed +- `PointExtension` and `OffsetToPointExtension` marked as internal Contains the following user-affecting bug fixes: diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index beb132bf1..90ec150e2 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -1,7 +1,10 @@ import 'dart:math'; import 'dart:ui'; +import 'package:meta/meta.dart'; + /// Extension methods for the math.[Point] class +@internal extension PointExtension on Point { /// Create a new [Point] where the [x] and [y] values are divided by [factor]. /// REPLACE IN FAVOR OF OFFSET @@ -14,6 +17,7 @@ extension PointExtension on Point { } /// Extension methods for [Offset] +@internal extension OffsetToPointExtension on Offset { /// Creates a [Point] representation of this offset. This is ONLY used for backwards compatibility Point toPoint() => Point(dx, dy); From 877bcca515c503122f00fed1a6f41a89350ea779 Mon Sep 17 00:00:00 2001 From: mootw Date: Tue, 3 Dec 2024 11:26:32 -0600 Subject: [PATCH 20/51] Update lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart Co-authored-by: Luka S --- .../shared/layer_interactivity/internal_hit_detectable.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 08714fa9a..34e731a13 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -96,7 +96,7 @@ base mixin HitTestRequiresCameraOrigin Date: Wed, 4 Dec 2024 19:24:06 -0600 Subject: [PATCH 21/51] rename --- benchmark/crs.dart | 6 +++--- lib/src/geo/crs.dart | 4 ++-- .../tile_layer/tile_bounds/tile_bounds.dart | 16 ++++++++-------- lib/src/map/camera/camera.dart | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/benchmark/crs.dart b/benchmark/crs.dart index 8e2a5a8e8..292409798 100644 --- a/benchmark/crs.dart +++ b/benchmark/crs.dart @@ -49,12 +49,12 @@ Future main() async { return x + y; })); - results.add(await timedRun('Concrete type: ${crs.code}.latLngToPoint()', () { + results.add(await timedRun('Concrete type: ${crs.code}.latLngToOffset()', () { double x = 0; double y = 0; for (int i = 0; i < N; ++i) { final latlng = LatLng((i % 90).toDouble(), (i % 180).toDouble()); - final p = crs.latLngToPoint(latlng, 1); + final p = crs.latLngToOffset(latlng, 1); x += p.dx; y += p.dy; } @@ -84,7 +84,7 @@ Future main() async { double y = 0; for (int i = 0; i < N; ++i) { final latlng = LatLng((i % 90).toDouble(), (i % 180).toDouble()); - final point = crs.latLngToPoint(latlng, 1); + final point = crs.latLngToOffset(latlng, 1); x += point.dx; y += point.dy; } diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index ebd4a3087..75360f3e5 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -52,7 +52,7 @@ abstract class Crs { (double, double) latLngToXY(LatLng latlng, double scale); /// Similar to [latLngToXY] but converts the XY coordinates to a [Point]. - Offset latLngToPoint(LatLng latlng, double zoom) { + Offset latLngToOffset(LatLng latlng, double zoom) { final (x, y) = latLngToXY(latlng, scale(zoom)); return Offset(x, y); } @@ -171,7 +171,7 @@ class Epsg3857 extends CrsWithStaticTransformation { ); @override - Offset latLngToPoint(LatLng latlng, double zoom) { + Offset latLngToOffset(LatLng latlng, double zoom) { final (x, y) = _transformation.transform( SphericalMercator.projectLng(latlng.longitude), SphericalMercator.projectLat(latlng.latitude), diff --git a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart index 5f66bb9be..adcc237e6 100644 --- a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart +++ b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart @@ -91,8 +91,8 @@ class DiscreteTileBounds extends TileBounds { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { pixelBounds = Bounds( - crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble).toPoint(), - crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble).toPoint(), + crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble).toPoint(), + crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble).toPoint(), ); } @@ -131,19 +131,19 @@ class WrappedTileBounds extends TileBounds { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { pixelBounds = Bounds( - crs.latLngToPoint(_latLngBounds!.southWest, zoomDouble).toPoint(), - crs.latLngToPoint(_latLngBounds!.northEast, zoomDouble).toPoint(), + crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble).toPoint(), + crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble).toPoint(), ); } (int, int)? wrapX; if (crs.wrapLng case final wrapLng?) { final wrapXMin = - (crs.latLngToPoint(LatLng(0, wrapLng.$1), zoomDouble).dx / + (crs.latLngToOffset(LatLng(0, wrapLng.$1), zoomDouble).dx / _tileDimension) .floor(); final wrapXMax = - (crs.latLngToPoint(LatLng(0, wrapLng.$2), zoomDouble).dx / + (crs.latLngToOffset(LatLng(0, wrapLng.$2), zoomDouble).dx / _tileDimension) .ceil(); wrapX = (wrapXMin, wrapXMax - 1); @@ -152,11 +152,11 @@ class WrappedTileBounds extends TileBounds { (int, int)? wrapY; if (crs.wrapLat case final wrapLat?) { final wrapYMin = - (crs.latLngToPoint(LatLng(wrapLat.$1, 0), zoomDouble).dy / + (crs.latLngToOffset(LatLng(wrapLat.$1, 0), zoomDouble).dy / _tileDimension) .floor(); final wrapYMax = - (crs.latLngToPoint(LatLng(wrapLat.$2, 0), zoomDouble).dy / + (crs.latLngToOffset(LatLng(wrapLat.$2, 0), zoomDouble).dy / _tileDimension) .ceil(); wrapY = (wrapYMin, wrapYMax - 1); diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 986bdbd26..9a406b1f2 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -230,7 +230,7 @@ class MapCamera { /// Calculates point value for the given [latlng] using this camera's /// [crs] and [zoom] (or the provided [zoom]). Offset project(LatLng latlng, [double? zoom]) => - crs.latLngToPoint(latlng, zoom ?? this.zoom); + crs.latLngToOffset(latlng, zoom ?? this.zoom); /// Calculates the [LatLng] for the given [point] using this camera's /// [crs] and [zoom] (or the provided [zoom]). @@ -279,9 +279,9 @@ class MapCamera { Offset latLngToScreenOffset(LatLng latLng) { final nonRotatedPixelOrigin = project(center, zoom) - nonRotatedSize / 2.0; - var point = crs.latLngToPoint(latLng, zoom); + var point = crs.latLngToOffset(latLng, zoom); - final mapCenter = crs.latLngToPoint(center, zoom); + final mapCenter = crs.latLngToOffset(center, zoom); if (rotation != 0.0) { point = rotateOffset(mapCenter, point, counterRotation: false); @@ -296,7 +296,7 @@ class MapCamera { (nonRotatedSize.dx / 2) - localPoint.dx, (nonRotatedSize.dy / 2) - localPoint.dy, ); - final mapCenter = crs.latLngToPoint(center, zoom); + final mapCenter = crs.latLngToOffset(center, zoom); var point = mapCenter - localPointCenterDistance; From a3b61e05613351e22e56c2d93f0b7a4caf59b2c2 Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 19:39:17 -0600 Subject: [PATCH 22/51] re-phrase things --- lib/src/misc/extensions.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 90ec150e2..4c8df9fac 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -7,7 +7,6 @@ import 'package:meta/meta.dart'; @internal extension PointExtension on Point { /// Create a new [Point] where the [x] and [y] values are divided by [factor]. - /// REPLACE IN FAVOR OF OFFSET Point operator /(num factor) { return Point(x / factor, y / factor); } @@ -18,8 +17,9 @@ extension PointExtension on Point { /// Extension methods for [Offset] @internal -extension OffsetToPointExtension on Offset { - /// Creates a [Point] representation of this offset. This is ONLY used for backwards compatibility +extension OffsetExtension on Offset { + + /// Creates a [Point] representation of this offset. Point toPoint() => Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by From 11c593d3cd5c6b09a8cef42a556a2d9a2fc434d6 Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 19:56:47 -0600 Subject: [PATCH 23/51] rotateAroundPoint fix --- CHANGELOG.md | 1 + lib/src/map/controller/map_controller.dart | 1 - lib/src/map/controller/map_controller_impl.dart | 16 ++-------------- lib/src/misc/extensions.dart | 2 +- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5602c12..5b37c702b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Migration Guide: - any methods that previously required `Point` now require `Offset` as return values and parameters - `pointToLatLng` -> `offsetToLatLng` - `PointExtension` and `OffsetToPointExtension` marked as internal +- `MapController.rotateAroundPoint` now only accepts an Offset Contains the following user-affecting bug fixes: diff --git a/lib/src/map/controller/map_controller.dart b/lib/src/map/controller/map_controller.dart index 77d6a77da..d33af23d9 100644 --- a/lib/src/map/controller/map_controller.dart +++ b/lib/src/map/controller/map_controller.dart @@ -107,7 +107,6 @@ abstract class MapController { /// `true`. MoveAndRotateResult rotateAroundPoint( double degree, { - Point? point, Offset? offset, String? id, }); diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 5df04639a..b233f4bf9 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -107,13 +107,11 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> @override MoveAndRotateResult rotateAroundPoint( double degree, { - Point? point, Offset? offset, String? id, }) => rotateAroundPointRaw( degree, - point: point?.toOffset(), offset: offset, hasGesture: false, source: MapEventSource.mapController, @@ -224,20 +222,11 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> /// the map. MoveAndRotateResult rotateAroundPointRaw( double degree, { - //TODO this looks insanely jank - required Offset? point, required Offset? offset, required bool hasGesture, required MapEventSource source, String? id, }) { - if (point != null && offset != null) { - throw ArgumentError('Only one of `point` or `offset` may be non-null'); - } - if (point == null && offset == null) { - throw ArgumentError('One of `point` or `offset` must be non-null'); - } - if (degree == camera.rotation) { return const (moveSuccess: false, rotateSuccess: false); } @@ -255,9 +244,8 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> } final rotationDiff = degree - camera.rotation; - final rotationCenter = camera.project(camera.center) + - (point != null ? (point - (camera.nonRotatedSize / 2.0)) : offset!) - .rotate(camera.rotationRad); + final rotationCenter = + (camera.project(camera.center) + offset!).rotate(camera.rotationRad); return ( moveSuccess: moveRaw( diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 4c8df9fac..81430bba6 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -20,7 +20,7 @@ extension PointExtension on Point { extension OffsetExtension on Offset { /// Creates a [Point] representation of this offset. - Point toPoint() => Point(dx, dy); +Point toPoint() => Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by /// [radians]. From 7797c41214f5df8070ff890aa1325efd6623997c Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 20:12:53 -0600 Subject: [PATCH 24/51] convert doublepoint to offset --- lib/src/geo/crs.dart | 7 +++---- lib/src/layer/polyline_layer/polyline_layer.dart | 2 +- lib/src/map/controller/map_controller.dart | 1 - lib/src/map/controller/map_controller_impl.dart | 1 - 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 37803a543..b9cca64a1 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -3,7 +3,6 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/src/misc/bounds.dart'; -import 'package:flutter_map/src/misc/simplify.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart'; import 'package:proj4dart/proj4dart.dart' as proj4; @@ -419,10 +418,10 @@ abstract class Projection { /// longitudes -179 and 179 to be projected each on one side. /// [referencePoint] is used for polygon holes: we want the holes to be /// displayed close to the polygon, not on the other side of the world. - List projectList(List points, {LatLng? referencePoint}) { + List projectList(List points, {LatLng? referencePoint}) { late double previousX; final worldWidth = getWorldWidth(); - return List.generate( + return List.generate( points.length, (j) { if (j == 0 && referencePoint != null) { @@ -437,7 +436,7 @@ abstract class Projection { } } previousX = x; - return DoublePoint(x, y); + return Offset(x, y); }, growable: false, ); diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index ed3eae42d..452086e5a 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -154,7 +154,7 @@ class _PolylineLayerState extends State> /// Returns true if the points stretch on different versions of the world. bool stretchesBeyondTheLimits() { for (final point in projectedPolyline.points) { - if (point.x > xEast || point.x < xWest) { + if (point.dx > xEast || point.dx < xWest) { return true; } } diff --git a/lib/src/map/controller/map_controller.dart b/lib/src/map/controller/map_controller.dart index d33af23d9..0fb0f60fe 100644 --- a/lib/src/map/controller/map_controller.dart +++ b/lib/src/map/controller/map_controller.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index b233f4bf9..b77072bd3 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:math'; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; From f64f1354acee5280c441493f10fe781de9476677 Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 20:17:51 -0600 Subject: [PATCH 25/51] dart format --- lib/src/layer/tile_layer/wms_tile_layer_options.dart | 6 ++++-- lib/src/misc/extensions.dart | 3 +-- test/layer/tile_layer/tile_bounds/crs_fakes.dart | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index d8beceb89..853aea254 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -71,8 +71,10 @@ class WMSTileLayerOptions { String getUrl(TileCoordinates coords, int tileDimension, bool retinaMode) { final nwPoint = coords * tileDimension; final sePoint = nwPoint + Point(tileDimension, tileDimension); - final nwCoords = crs.offsetToLatLng(nwPoint.toOffset(), coords.z.toDouble()); - final seCoords = crs.offsetToLatLng(sePoint.toOffset(), coords.z.toDouble()); + final nwCoords = + crs.offsetToLatLng(nwPoint.toOffset(), coords.z.toDouble()); + final seCoords = + crs.offsetToLatLng(sePoint.toOffset(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); final bounds = Bounds(nw, se); diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 81430bba6..6739dc05d 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -18,9 +18,8 @@ extension PointExtension on Point { /// Extension methods for [Offset] @internal extension OffsetExtension on Offset { - /// Creates a [Point] representation of this offset. -Point toPoint() => Point(dx, dy); + Point toPoint() => Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by /// [radians]. diff --git a/test/layer/tile_layer/tile_bounds/crs_fakes.dart b/test/layer/tile_layer/tile_bounds/crs_fakes.dart index 0c5cc73d4..0a4c9d2a2 100644 --- a/test/layer/tile_layer/tile_bounds/crs_fakes.dart +++ b/test/layer/tile_layer/tile_bounds/crs_fakes.dart @@ -25,7 +25,8 @@ class FakeInfiniteCrs extends Crs { const Epsg3857().untransform(x, y, scale); @override - LatLng offsetToLatLng(Offset point, double zoom) => throw UnimplementedError(); + LatLng offsetToLatLng(Offset point, double zoom) => + throw UnimplementedError(); @override Bounds? getProjectedBounds(double zoom) => throw UnimplementedError(); From 14712ad4fd45c01659e4ee2b048159377c29efd2 Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 20:23:59 -0600 Subject: [PATCH 26/51] fix visible scope lol --- lib/flutter_map.dart | 3 +-- lib/src/gestures/map_interactive_viewer.dart | 1 + lib/src/layer/overlay_image_layer/overlay_image_layer.dart | 1 + lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart | 1 + lib/src/layer/tile_layer/tile_layer.dart | 1 + lib/src/layer/tile_layer/tile_range.dart | 1 + lib/src/layer/tile_layer/tile_range_calculator.dart | 1 + lib/src/map/camera/camera.dart | 1 + lib/src/map/camera/camera_fit.dart | 1 + lib/src/map/controller/map_controller_impl.dart | 1 + lib/src/misc/bounds.dart | 2 +- test/layer/tile_layer/tile_bounds/tile_bounds_test.dart | 1 + 12 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/flutter_map.dart b/lib/flutter_map.dart index f7ad8b96d..090f4f845 100644 --- a/lib/flutter_map.dart +++ b/lib/flutter_map.dart @@ -59,5 +59,4 @@ export 'package:flutter_map/src/map/options/cursor_keyboard_rotation.dart'; export 'package:flutter_map/src/map/options/interaction.dart'; export 'package:flutter_map/src/map/options/options.dart'; export 'package:flutter_map/src/map/widget.dart'; -export 'package:flutter_map/src/misc/bounds.dart'; -export 'package:flutter_map/src/misc/extensions.dart'; +export 'package:flutter_map/src/misc/bounds.dart'; \ No newline at end of file diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index e232a03a3..1884fd031 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -5,6 +5,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/lib/src/layer/overlay_image_layer/overlay_image_layer.dart b/lib/src/layer/overlay_image_layer/overlay_image_layer.dart index 7e7922781..38d2ea75d 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image_layer.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image_layer.dart @@ -1,5 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; part 'overlay_image.dart'; diff --git a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart index adcc237e6..e0ac72a8a 100644 --- a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart +++ b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart @@ -1,6 +1,7 @@ import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index c153b541a..d9a278b8b 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -12,6 +12,7 @@ import 'package:flutter_map/src/layer/tile_layer/tile_image_manager.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range_calculator.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_scale_calculator.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:http/http.dart'; import 'package:http/retry.dart'; import 'package:logger/logger.dart'; diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 4b235932c..f98307093 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -3,6 +3,7 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:meta/meta.dart'; /// A range of tiles, this is normally a [DiscreteTileRange] and sometimes diff --git a/lib/src/layer/tile_layer/tile_range_calculator.dart b/lib/src/layer/tile_layer/tile_range_calculator.dart index 7df6e060d..07fbc28db 100644 --- a/lib/src/layer/tile_layer/tile_range_calculator.dart +++ b/lib/src/layer/tile_layer/tile_range_calculator.dart @@ -1,5 +1,6 @@ import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index 9a406b1f2..5f6bc57b3 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -3,6 +3,7 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/map/inherited_model.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 8765c4a81..cddd80c27 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -3,6 +3,7 @@ import 'dart:math' show Point; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; /// Describes a position for a [MapCamera] diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index b77072bd3..1e971e6ed 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/gestures/map_interactive_viewer.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:flutter_map/src/misc/move_and_rotate_result.dart'; import 'package:latlong2/latlong.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index f4d4551e4..307ce23ab 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -2,7 +2,7 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; import 'dart:ui'; -import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:meta/meta.dart'; /// Rectangular bound delimited by orthogonal lines passing through two diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart index b16f18028..1c2b2f531 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart @@ -4,6 +4,7 @@ import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:test/test.dart'; From 7ab7a910c77e68c2b5b8796e7bfb6844629078ce Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 20:25:50 -0600 Subject: [PATCH 27/51] Update flutter_map.dart --- lib/flutter_map.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flutter_map.dart b/lib/flutter_map.dart index 090f4f845..bea98ce16 100644 --- a/lib/flutter_map.dart +++ b/lib/flutter_map.dart @@ -59,4 +59,4 @@ export 'package:flutter_map/src/map/options/cursor_keyboard_rotation.dart'; export 'package:flutter_map/src/map/options/interaction.dart'; export 'package:flutter_map/src/map/options/options.dart'; export 'package:flutter_map/src/map/widget.dart'; -export 'package:flutter_map/src/misc/bounds.dart'; \ No newline at end of file +export 'package:flutter_map/src/misc/bounds.dart'; From 43991375bcbf41501e606d804bf8a3335d6c286f Mon Sep 17 00:00:00 2001 From: mootw Date: Wed, 4 Dec 2024 20:55:07 -0600 Subject: [PATCH 28/51] Update internal_hit_detectable.dart --- .../shared/layer_interactivity/internal_hit_detectable.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 34e731a13..e73675af7 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -39,7 +39,7 @@ abstract base class HitDetectablePainter Date: Wed, 4 Dec 2024 23:34:28 -0600 Subject: [PATCH 29/51] fix straggling Point --- lib/src/geo/crs.dart | 4 ++-- lib/src/layer/polyline_layer/polyline_layer.dart | 5 +++-- lib/src/layer/tile_layer/wms_tile_layer_options.dart | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index b9cca64a1..324fbb345 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -380,9 +380,9 @@ abstract class Projection { /// Converts a [LatLng] to a coordinates and returns them as [Point] object. @nonVirtual - Point project(LatLng latlng) { + Offset project(LatLng latlng) { final (x, y) = projectXY(latlng); - return Point(x, y); + return Offset(x, y); } /// Converts a [LatLng] to geometry coordinates. diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 452086e5a..46b86b560 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -9,6 +9,7 @@ import 'package:flutter_map/src/layer/shared/layer_interactivity/internal_hit_de import 'package:flutter_map/src/layer/shared/layer_projection_simplification/state.dart'; import 'package:flutter_map/src/layer/shared/layer_projection_simplification/widget.dart'; import 'package:flutter_map/src/layer/shared/line_patterns/pixel_hiker.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:flutter_map/src/misc/offsets.dart'; import 'package:flutter_map/src/misc/simplify.dart'; import 'package:latlong2/latlong.dart'; @@ -136,8 +137,8 @@ class _PolylineLayerState extends State> // segment is visible final projBounds = Bounds( - projection.project(boundsAdjusted.southWest), - projection.project(boundsAdjusted.northEast), + projection.project(boundsAdjusted.southWest).toPoint(), + projection.project(boundsAdjusted.northEast).toPoint(), ); final (xWest, _) = projection.projectXY(const LatLng(0, -180)); diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index 853aea254..dd636097f 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -77,7 +77,7 @@ class WMSTileLayerOptions { crs.offsetToLatLng(sePoint.toOffset(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); - final bounds = Bounds(nw, se); + final bounds = Bounds(nw.toPoint(), se.toPoint()); final bbox = (_versionNumber >= 1.3 && crs is Epsg4326) ? [bounds.min.y, bounds.min.x, bounds.max.y, bounds.max.x] : [bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y]; From 357badad62ba6cc5e3ccf1554e5cd988537c031f Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 00:42:11 -0600 Subject: [PATCH 30/51] convert to use size --- lib/src/gestures/map_interactive_viewer.dart | 4 +- lib/src/layer/circle_layer/circle_layer.dart | 2 +- lib/src/layer/polygon_layer/label.dart | 6 +-- lib/src/layer/polygon_layer/painter.dart | 3 +- .../layer/polygon_layer/polygon_layer.dart | 2 +- lib/src/layer/polyline_layer/painter.dart | 3 +- .../layer/polyline_layer/polyline_layer.dart | 2 +- .../internal_hit_detectable.dart | 3 +- .../shared/mobile_layer_transformer.dart | 8 ++-- .../tile_layer/tile_range_calculator.dart | 6 ++- lib/src/map/camera/camera.dart | 45 ++++++++++--------- lib/src/map/camera/camera_constraint.dart | 8 ++-- lib/src/map/camera/camera_fit.dart | 23 +++++----- .../map/controller/map_controller_impl.dart | 6 +-- lib/src/map/widget.dart | 2 +- lib/src/misc/offsets.dart | 2 +- test/map/camera/camera_constraint_test.dart | 4 +- 17 files changed, 69 insertions(+), 60 deletions(-) diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index 1884fd031..63234b3b2 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -729,9 +729,7 @@ class MapInteractiveViewerState extends State } final direction = details.velocity.pixelsPerSecond / magnitude; - final distance = (Offset.zero & - Size(_camera.nonRotatedSize.dx, _camera.nonRotatedSize.dy)) - .shortestSide; + final distance = (Offset.zero & _camera.nonRotatedSize).shortestSide; final flingOffset = _focalStartLocal - _lastFocalLocal; _flingAnimation = Tween( diff --git a/lib/src/layer/circle_layer/circle_layer.dart b/lib/src/layer/circle_layer/circle_layer.dart index 5f18146e1..8090fa582 100644 --- a/lib/src/layer/circle_layer/circle_layer.dart +++ b/lib/src/layer/circle_layer/circle_layer.dart @@ -36,7 +36,7 @@ class CircleLayer extends StatelessWidget { camera: camera, hitNotifier: hitNotifier, ), - size: Size(camera.size.dx, camera.size.dy), + size: camera.size, isComplex: true, ), ); diff --git a/lib/src/layer/polygon_layer/label.dart b/lib/src/layer/polygon_layer/label.dart index 65b9b99ba..39878c2ab 100644 --- a/lib/src/layer/polygon_layer/label.dart +++ b/lib/src/layer/polygon_layer/label.dart @@ -1,7 +1,7 @@ part of 'polygon_layer.dart'; void Function(Canvas canvas)? _buildLabelTextPainter({ - required Offset mapSize, + required Size mapSize, required Offset placementPoint, required ({Offset min, Offset max}) bounds, required TextPainter textPainter, @@ -18,10 +18,10 @@ void Function(Canvas canvas)? _buildLabelTextPainter({ // Currently this is only enabled when the map isn't rotated, since the placementOffset // is relative to the MobileLayerTransformer rather than in actual screen coordinates. if (rotationRad == 0) { - if (dx + width / 2 < 0 || dx - width / 2 > mapSize.dx) { + if (dx + width / 2 < 0 || dx - width / 2 > mapSize.width) { return null; } - if (dy + height / 2 < 0 || dy - height / 2 > mapSize.dy) { + if (dy + height / 2 < 0 || dy - height / 2 > mapSize.height) { return null; } } diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart index 03fd84d2c..e5e71f542 100644 --- a/lib/src/layer/polygon_layer/painter.dart +++ b/lib/src/layer/polygon_layer/painter.dart @@ -193,7 +193,8 @@ base class _PolygonPainter lastHash = null; } - final origin = camera.project(camera.center) - camera.size / 2; + final origin = + camera.project(camera.center) - camera.size.center(Offset.zero); // Main loop constructing batched fill and border paths from given polygons. for (int i = 0; i <= polygons.length - 1; i++) { diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index f048fe23c..34b289029 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -176,7 +176,7 @@ class _PolygonLayerState extends State> debugAltRenderer: widget.debugAltRenderer, hitNotifier: widget.hitNotifier, ), - size: Size(camera.size.dx, camera.size.dy), + size: camera.size, ), ); } diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index 38f1320e3..3aaed5bda 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -107,7 +107,8 @@ base class _PolylinePainter paint = Paint(); } - final origin = camera.project(camera.center) - camera.size / 2; + final origin = + camera.project(camera.center) - camera.size.center(Offset.zero); for (final projectedPolyline in polylines) { final polyline = projectedPolyline.polyline; diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 46b86b560..2a0cfe851 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -112,7 +112,7 @@ class _PolylineLayerState extends State> hitNotifier: widget.hitNotifier, minimumHitbox: widget.minimumHitbox, ), - size: Size(camera.size.dx, camera.size.dy), + size: camera.size, ), ); } diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index e73675af7..e2baca201 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -105,7 +105,8 @@ base mixin HitTestRequiresCameraOrigin? _pixelBounds; @@ -67,7 +67,7 @@ class MapCamera { /// rotation. When the rotation is zero this will equal [nonRotatedSize], /// otherwise it will be the size of the rectangle which contains this /// camera. - Offset get size => _cameraSize ??= calculateRotatedSize( + Size get size => _cameraSize ??= calculateRotatedSize( rotation, nonRotatedSize, ); @@ -75,7 +75,8 @@ class MapCamera { /// The offset of the top-left corner of the bounding rectangle of this /// camera. This will not equal the offset of the top-left visible pixel when /// the map is rotated. - Offset get pixelOrigin => _pixelOrigin ??= project(center, zoom) - size / 2; + Offset get pixelOrigin => + _pixelOrigin ??= project(center, zoom) - size.center(Offset.zero); /// The camera of the closest [FlutterMap] ancestor. If this is called from a /// context with no [FlutterMap] ancestor null, is returned. @@ -100,7 +101,7 @@ class MapCamera { required this.nonRotatedSize, this.minZoom, this.maxZoom, - Offset? size, + Size? size, Bounds? pixelBounds, LatLngBounds? bounds, Offset? pixelOrigin, @@ -121,7 +122,7 @@ class MapCamera { nonRotatedSize = kImpossibleSize; /// Returns a new instance of [MapCamera] with the given [nonRotatedSize]. - MapCamera withNonRotatedSize(Offset nonRotatedSize) { + MapCamera withNonRotatedSize(Size nonRotatedSize) { if (nonRotatedSize == this.nonRotatedSize) return this; return MapCamera( @@ -208,9 +209,9 @@ class MapCamera { /// Calculates the size of a bounding box which surrounds a box of size /// [nonRotatedSize] which is rotated by [rotation]. - static Offset calculateRotatedSize( + static Size calculateRotatedSize( double rotation, - Offset nonRotatedSize, + Size nonRotatedSize, ) { if (rotation == 0.0) return nonRotatedSize; @@ -218,11 +219,11 @@ class MapCamera { final cosAngle = math.cos(rotationRad).abs(); final sinAngle = math.sin(rotationRad).abs(); final width = - (nonRotatedSize.dx * cosAngle) + (nonRotatedSize.dy * sinAngle); + (nonRotatedSize.width * cosAngle) + (nonRotatedSize.height * sinAngle); final height = - (nonRotatedSize.dy * cosAngle) + (nonRotatedSize.dx * sinAngle); + (nonRotatedSize.height * cosAngle) + (nonRotatedSize.width * sinAngle); - return Offset(width, height); + return Size(width, height); } /// The current rotation value in radians @@ -256,7 +257,7 @@ class MapCamera { /// Calculates the pixel origin of this [MapCamera] at the given /// [center]/[zoom]. Offset getNewPixelOrigin(LatLng center, [double? zoom]) { - return (project(center, zoom) - (size / 2.0)).round(); + return (project(center, zoom) - size.center(Offset.zero)).round(); } /// Calculates the pixel bounds of this [MapCamera]. This value is cached. @@ -271,14 +272,15 @@ class MapCamera { halfSize = size / (scale * 2); } final pixelCenter = project(center, zoom).floor(); - return Bounds( - (pixelCenter - halfSize).toPoint(), (pixelCenter + halfSize).toPoint()); + return Bounds((pixelCenter - halfSize.bottomRight(Offset.zero)).toPoint(), + halfSize.bottomRight(pixelCenter).toPoint()); } /// This will convert a latLng to a position that we could use with a widget /// outside of FlutterMap layer space. Eg using a Positioned Widget. Offset latLngToScreenOffset(LatLng latLng) { - final nonRotatedPixelOrigin = project(center, zoom) - nonRotatedSize / 2.0; + final nonRotatedPixelOrigin = + project(center, zoom) - nonRotatedSize.center(Offset.zero); var point = crs.latLngToOffset(latLng, zoom); @@ -294,8 +296,8 @@ class MapCamera { /// Calculate the [LatLng] coordinates for a [localPoint]. LatLng offsetToLatLng(Offset localPoint) { final localPointCenterDistance = Offset( - (nonRotatedSize.dx / 2) - localPoint.dx, - (nonRotatedSize.dy / 2) - localPoint.dy, + (nonRotatedSize.width / 2) - localPoint.dx, + (nonRotatedSize.height / 2) - localPoint.dy, ); final mapCenter = crs.latLngToOffset(center, zoom); @@ -340,7 +342,8 @@ class MapCamera { /// [MapCamera] gets used. LatLng offsetToCrs(Offset offset, [double? zoom]) { final focalStartPt = project(center, zoom ?? this.zoom); - final point = (offset - (nonRotatedSize / 2.0)).rotate(rotationRad); + final point = + (offset - nonRotatedSize.center(Offset.zero)).rotate(rotationRad); final newCenterPt = focalStartPt + point; return unproject(newCenterPt, zoom ?? this.zoom); @@ -350,8 +353,8 @@ class MapCamera { /// visible at the given [cursorPos] with the zoom set to [zoom]. LatLng focusedZoomCenter(Offset cursorPos, double zoom) { // Calculate offset of mouse cursor from viewport center - final viewCenter = nonRotatedSize / 2; - final offset = (cursorPos - viewCenter).rotate(rotationRad); + final offset = + (cursorPos - nonRotatedSize.center(Offset.zero)).rotate(rotationRad); // Match new center coordinate to mouse cursor position final scale = getZoomScale(zoom, this.zoom); final newOffset = offset * (1.0 - 1.0 / scale); diff --git a/lib/src/map/camera/camera_constraint.dart b/lib/src/map/camera/camera_constraint.dart index 23a12866c..5283cf4ff 100644 --- a/lib/src/map/camera/camera_constraint.dart +++ b/lib/src/map/camera/camera_constraint.dart @@ -117,10 +117,10 @@ class ContainCamera extends CameraConstraint { // Find the limits for the map center which would keep the camera within the // [latLngBounds]. - final leftOkCenter = math.min(swPixel.dx, nePixel.dx) + halfSize.dx; - final rightOkCenter = math.max(swPixel.dx, nePixel.dx) - halfSize.dx; - final topOkCenter = math.min(swPixel.dy, nePixel.dy) + halfSize.dy; - final botOkCenter = math.max(swPixel.dy, nePixel.dy) - halfSize.dy; + final leftOkCenter = math.min(swPixel.dx, nePixel.dx) + halfSize.width; + final rightOkCenter = math.max(swPixel.dx, nePixel.dx) - halfSize.width; + final topOkCenter = math.min(swPixel.dy, nePixel.dy) + halfSize.height; + final botOkCenter = math.max(swPixel.dy, nePixel.dy) - halfSize.height; // Stop if we are zoomed out so far that the camera cannot be translated to // stay within [latLngBounds]. diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index cddd80c27..2b070f7de 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -140,9 +140,10 @@ class FitBounds extends CameraFit { ) { final nw = bounds.northWest; final se = bounds.southEast; - var size = camera.nonRotatedSize - pixelPadding; + var size = camera.nonRotatedSize - pixelPadding as Size; // Prevent negative size which results in NaN zoom value later on in the calculation - size = Offset(math.max(0, size.dx), math.max(0, size.dy)); + + size = Size(math.max(0, size.width), math.max(0, size.height)); var boundsSize = Bounds( camera.project(se, camera.zoom).toPoint(), camera.project(nw, camera.zoom).toPoint(), @@ -156,7 +157,8 @@ class FitBounds extends CameraFit { ); } - final scale = math.min(size.dx / boundsSize.x, size.dy / boundsSize.y); + final scale = + math.min(size.width / boundsSize.x, size.height / boundsSize.y); var boundsZoom = camera.getScaleZoom(scale); @@ -222,7 +224,7 @@ class FitInsideBounds extends CameraFit { final paddingTotalXY = paddingTL + paddingBR; final paddingOffset = (paddingBR - paddingTL) / 2; - final cameraSize = camera.nonRotatedSize - paddingTotalXY; + final cameraSize = camera.nonRotatedSize - paddingTotalXY as Size; final projectedBoundsSize = Bounds( camera.project(bounds.southEast, camera.zoom).toPoint(), @@ -231,8 +233,8 @@ class FitInsideBounds extends CameraFit { final scale = _rectInRotRectScale( angleRad: camera.rotationRad, - smallRectHalfWidth: cameraSize.dx / 2.0, - smallRectHalfHeight: cameraSize.dy / 2.0, + smallRectHalfWidth: cameraSize.width / 2.0, + smallRectHalfHeight: cameraSize.height / 2.0, bigRectHalfWidth: projectedBoundsSize.x / 2.0, bigRectHalfHeight: projectedBoundsSize.y / 2.0, ); @@ -460,9 +462,9 @@ class FitCoordinates extends CameraFit { MapCamera camera, Offset pixelPadding, ) { - var size = camera.nonRotatedSize - pixelPadding; + var size = camera.nonRotatedSize - pixelPadding as Size; // Prevent negative size which results in NaN zoom value later on in the calculation - size = Offset(math.max(0, size.dx), math.max(0, size.dy)); + size = Size(math.max(0, size.width), math.max(0, size.height)); final projectedPoints = [ for (final coord in coordinates) camera.project(coord) @@ -474,8 +476,9 @@ class FitCoordinates extends CameraFit { final boundsSize = rotatedBounds.size; - final scaleX = size.dx / boundsSize.x; - final scaleY = size.dy / boundsSize.y; + // TODO this could be replaced with Size.shortestSide + final scaleX = size.width / boundsSize.x; + final scaleY = size.height / boundsSize.y; final scale = math.min(scaleX, scaleY); var newZoom = camera.getScaleZoom(scale); diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 1e971e6ed..77a79ba31 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -313,7 +313,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> /// Set the widget size but don't emit a event to the event system. bool setNonRotatedSizeWithoutEmittingEvent( - Offset nonRotatedSize, + Size nonRotatedSize, ) { if (nonRotatedSize != MapCamera.kImpossibleSize && nonRotatedSize != camera.nonRotatedSize) { @@ -648,9 +648,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> _animationOffset = offset; _flingMapCenterStartPoint = camera.project(camera.center); - final distance = - (Offset.zero & Size(camera.nonRotatedSize.dx, camera.nonRotatedSize.dy)) - .shortestSide; + final distance = (Offset.zero & camera.nonRotatedSize).shortestSide; _flingAnimation = Tween( begin: begin, diff --git a/lib/src/map/widget.dart b/lib/src/map/widget.dart index 622333034..b1b5bbd70 100644 --- a/lib/src/map/widget.dart +++ b/lib/src/map/widget.dart @@ -141,7 +141,7 @@ class _FlutterMapStateContainer extends State } void _updateAndEmitSizeIfConstraintsChanged(BoxConstraints constraints) { - final nonRotatedSize = Offset( + final nonRotatedSize = Size( constraints.maxWidth, constraints.maxHeight, ); diff --git a/lib/src/misc/offsets.dart b/lib/src/misc/offsets.dart index 41b2f783a..372891b6c 100644 --- a/lib/src/misc/offsets.dart +++ b/lib/src/misc/offsets.dart @@ -67,7 +67,7 @@ List getOffsetsXY({ worldWidth, -worldWidth, ]; - final halfScreenWidth = camera.size.dx / 2; + final halfScreenWidth = camera.size.width / 2; final p = realPoints.elementAt(0); late double result; late double bestX; diff --git a/test/map/camera/camera_constraint_test.dart b/test/map/camera/camera_constraint_test.dart index fc5fd08b3..17c3e228c 100644 --- a/test/map/camera/camera_constraint_test.dart +++ b/test/map/camera/camera_constraint_test.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:latlong2/latlong.dart'; @@ -18,7 +20,7 @@ void main() { center: const LatLng(-90, -180), zoom: 1, rotation: 45, - nonRotatedSize: const Offset(200, 300), + nonRotatedSize: const Size(200, 300), ); final clamped = mapConstraint.constrain(camera)!; From 4e720dc35c178e036ef9ae292994f7b948e50880 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 01:03:04 -0600 Subject: [PATCH 31/51] migrate easy Bounds to Rect --- lib/src/layer/marker_layer/marker_layer.dart | 11 ++-- lib/src/map/camera/camera.dart | 23 +++++---- lib/src/map/camera/camera_fit.dart | 17 +++---- lib/src/misc/bounds.dart | 53 ++++++-------------- lib/src/misc/extensions.dart | 52 +++++++++++++++++++ test/core/bounds_test.dart | 24 --------- 6 files changed, 92 insertions(+), 88 deletions(-) diff --git a/lib/src/layer/marker_layer/marker_layer.dart b/lib/src/layer/marker_layer/marker_layer.dart index 0e0ef0cc4..1d74fc0f0 100644 --- a/lib/src/layer/marker_layer/marker_layer.dart +++ b/lib/src/layer/marker_layer/marker_layer.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -49,6 +47,7 @@ class MarkerLayer extends StatelessWidget { children: (List markers) sync* { for (final m in markers) { // Resolve real alignment + // TODO this can probably just be done with calls to Size, Offset, and Rect final left = 0.5 * m.width * ((m.alignment ?? alignment).x + 1); final top = 0.5 * m.height * ((m.alignment ?? alignment).y + 1); final right = m.width - left; @@ -58,10 +57,10 @@ class MarkerLayer extends StatelessWidget { final pxPoint = map.project(m.point); // Cull if out of bounds - if (!map.pixelBounds.containsPartialBounds( - Bounds( - Point(pxPoint.dx + left, pxPoint.dy - bottom), - Point(pxPoint.dx - right, pxPoint.dy + top), + if (!map.pixelBounds.overlaps( + Rect.fromPoints( + Offset(pxPoint.dx + left, pxPoint.dy - bottom), + Offset(pxPoint.dx - right, pxPoint.dy + top), ), )) { continue; diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index a5bc231b6..d45333209 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -48,7 +48,7 @@ class MapCamera { Size? _cameraSize; /// Lazily calculated field - Bounds? _pixelBounds; + Rect? _pixelBounds; /// Lazily calculated field LatLngBounds? _bounds; @@ -59,8 +59,8 @@ class MapCamera { /// This is the [LatLngBounds] corresponding to four corners of this camera. /// This takes rotation in to account. LatLngBounds get visibleBounds => _bounds ??= LatLngBounds( - unproject(pixelBounds.bottomLeft.toOffset(), zoom), - unproject(pixelBounds.topRight.toOffset(), zoom), + unproject(pixelBounds.bottomLeft, zoom), + unproject(pixelBounds.topRight, zoom), ); /// The size of bounding box of this camera taking in to account its @@ -102,7 +102,7 @@ class MapCamera { this.minZoom, this.maxZoom, Size? size, - Bounds? pixelBounds, + Rect? pixelBounds, LatLngBounds? bounds, Offset? pixelOrigin, }) : _cameraSize = size, @@ -261,19 +261,22 @@ class MapCamera { } /// Calculates the pixel bounds of this [MapCamera]. This value is cached. - Bounds get pixelBounds => + Rect get pixelBounds => _pixelBounds ?? (_pixelBounds = pixelBoundsAtZoom(zoom)); /// Calculates the pixel bounds of this [MapCamera] at the given [zoom]. - Bounds pixelBoundsAtZoom(double zoom) { - var halfSize = size / 2; + Rect pixelBoundsAtZoom(double zoom) { + Size cameraSize = size; if (zoom != this.zoom) { final scale = getZoomScale(this.zoom, zoom); - halfSize = size / (scale * 2); + cameraSize = size / (scale * 2); } final pixelCenter = project(center, zoom).floor(); - return Bounds((pixelCenter - halfSize.bottomRight(Offset.zero)).toPoint(), - halfSize.bottomRight(pixelCenter).toPoint()); + + return Rect.fromCenter( + center: pixelCenter, + width: cameraSize.width, + height: cameraSize.height); } /// This will convert a latLng to a position that we could use with a widget diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 2b070f7de..15a28ebe1 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -438,10 +438,9 @@ class FitCoordinates extends CameraFit { final projectedPoints = coordinates.map((coord) => camera.project(coord, newZoom)); - final rotatedPoints = - projectedPoints.map((point) => point.rotate(-camera.rotationRad)); - - final rotatedBounds = Bounds.containing(rotatedPoints); + final rotatedBounds = RectExtension.containing(projectedPoints + .map((point) => point.rotate(-camera.rotationRad)) + .toList()); // Apply padding final paddingOffset = (paddingBR - paddingTL) / 2; @@ -470,15 +469,15 @@ class FitCoordinates extends CameraFit { for (final coord in coordinates) camera.project(coord) ]; - final rotatedPoints = - projectedPoints.map((point) => point.rotate(-camera.rotationRad)); - final rotatedBounds = Bounds.containing(rotatedPoints); + final rotatedBounds = RectExtension.containing(projectedPoints + .map((point) => point.rotate(-camera.rotationRad)) + .toList()); final boundsSize = rotatedBounds.size; // TODO this could be replaced with Size.shortestSide - final scaleX = size.width / boundsSize.x; - final scaleY = size.height / boundsSize.y; + final scaleX = size.width / boundsSize.width; + final scaleY = size.height / boundsSize.height; final scale = math.min(scaleX, scaleY); var newZoom = camera.getScaleZoom(scale); diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index 307ce23ab..e3d849f28 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -42,23 +42,6 @@ class Bounds { /// minimum and [max] is actually the maximum. const Bounds.unsafe(this.min, this.max); - /// Create a [Bounds] as bounding box of a list of points. - static Bounds containing(Iterable points) { - var maxX = double.negativeInfinity; - var maxY = double.negativeInfinity; - var minX = double.infinity; - var minY = double.infinity; - - for (final point in points) { - maxX = math.max(point.dx, maxX); - minX = math.min(point.dx, minX); - maxY = math.max(point.dy, maxY); - minY = math.min(point.dy, minY); - } - - return Bounds.unsafe(Point(minX, minY), Point(maxX, maxY)); - } - /// Creates a new [Bounds] obtained by expanding the current ones with a new /// point. Bounds extend(Point point) { @@ -104,12 +87,20 @@ class Bounds { (b.max.y <= max.y); } - /// Checks if a part of the other [Bounds] is contained in this [Bounds]. - bool containsPartialBounds(Bounds b) { - return (b.min.x <= max.x) && - (b.max.x >= min.x) && - (b.min.y <= max.y) && - (b.max.y >= min.y); + /// Calculates the intersection of two Bounds. The return value will be null + /// if there is no intersection. The returned bounds may be zero size + /// (bottomLeft == topRight). + Bounds? intersect(Bounds b) { + final leftX = math.max(min.x, b.min.x); + final rightX = math.min(max.x, b.max.x); + final topY = math.max(min.y, b.min.y); + final bottomY = math.min(max.y, b.max.y); + + if (leftX <= rightX && topY <= bottomY) { + return Bounds.unsafe(Point(leftX, topY), Point(rightX, bottomY)); + } + + return null; } /// Checks if the line between the two coordinates is contained within the @@ -140,22 +131,6 @@ class Bounds { return false; } - /// Calculates the intersection of two Bounds. The return value will be null - /// if there is no intersection. The returned bounds may be zero size - /// (bottomLeft == topRight). - Bounds? intersect(Bounds b) { - final leftX = math.max(min.x, b.min.x); - final rightX = math.min(max.x, b.max.x); - final topY = math.max(min.y, b.min.y); - final bottomY = math.min(max.y, b.max.y); - - if (leftX <= rightX && topY <= bottomY) { - return Bounds.unsafe(Point(leftX, topY), Point(rightX, bottomY)); - } - - return null; - } - @override String toString() => 'Bounds($min, $max)'; } diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 6739dc05d..30efcfb60 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -37,3 +37,55 @@ extension OffsetExtension on Offset { /// returns new [Offset] where roundToDouble() is called on [dx] and [dy] independently Offset round() => Offset(dx.roundToDouble(), dy.roundToDouble()); } + +@internal +extension RectExtension on Rect { + + /// Create a [Rect] as bounding box of a list of points. + static Rect containing(List points) { + var maxX = double.negativeInfinity; + var maxY = double.negativeInfinity; + var minX = double.infinity; + var minY = double.infinity; + + for (final point in points) { + maxX = max(point.dx, maxX); + minX = min(point.dx, minX); + maxY = max(point.dy, maxY); + minY = min(point.dy, minY); + } + + return Rect.fromPoints(Offset(minX, minY), Offset(maxX, maxY)); + } + + /// Checks if the line between the two coordinates is contained within the + /// [Rect]. + bool aabbContainsLine(double x1, double y1, double x2, double y2) { + + + + // // Completely outside. + // if ((x1 <= min.x && x2 <= min.x) || + // (y1 <= min.y && y2 <= min.y) || + // (x1 >= max.x && x2 >= max.x) || + // (y1 >= max.y && y2 >= max.y)) { + // return false; + // } + + // final m = (y2 - y1) / (x2 - x1); + + // double y = m * (min.x - x1) + y1; + // if (y > min.y && y < max.y) return true; + + // y = m * (max.x - x1) + y1; + // if (y > min.y && y < max.y) return true; + + // double x = (min.y - y1) / m + x1; + // if (x > min.x && x < max.x) return true; + + // x = (max.y - y1) / m + x1; + // if (x > min.x && x < max.x) return true; + + return false; + } +} diff --git a/test/core/bounds_test.dart b/test/core/bounds_test.dart index b6539f10e..d4eaf61a7 100644 --- a/test/core/bounds_test.dart +++ b/test/core/bounds_test.dart @@ -261,30 +261,6 @@ void main() { isFalse); }); - test( - 'should contain compared bounds partially if at least one edge ' - 'overlaps within the bounds', () { - final bounds = - Bounds(const Point(101.1, 88.1), const Point(133.1, 60.3)); - - expect( - bounds.containsPartialBounds( - Bounds(const Point(200.22, 60.2), const Point(133.1, 60.3))), - isTrue); - }); - - test( - 'should NOT contain compared bounds partially if not a single edge ' - 'overlaps within the bounds', () { - final bounds = - Bounds(const Point(101.1, 88.1), const Point(133.1, 60.3)); - - expect( - bounds.containsPartialBounds( - Bounds(const Point(200.22, 60.2), const Point(133.2, 60.3))), - isFalse); - }); - test('should contain given point within the bounds', () { expect( Bounds(const Point(0, 50), const Point(50, 0)) From de371843ad537a691947a50a64f03fbae8fd1bd6 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 01:03:56 -0600 Subject: [PATCH 32/51] dart format . --- lib/src/misc/extensions.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 30efcfb60..5a0243a57 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -40,7 +40,6 @@ extension OffsetExtension on Offset { @internal extension RectExtension on Rect { - /// Create a [Rect] as bounding box of a list of points. static Rect containing(List points) { var maxX = double.negativeInfinity; @@ -61,9 +60,6 @@ extension RectExtension on Rect { /// Checks if the line between the two coordinates is contained within the /// [Rect]. bool aabbContainsLine(double x1, double y1, double x2, double y2) { - - - // // Completely outside. // if ((x1 <= min.x && x2 <= min.x) || // (y1 <= min.y && y2 <= min.y) || From b6d2d9557d3d957d674429224ce6733c242cb858 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 01:42:43 -0600 Subject: [PATCH 33/51] migrate most methods that use Bounds --- lib/src/geo/crs.dart | 17 ++- .../overlay_image_layer/overlay_image.dart | 33 +++--- .../layer/polyline_layer/polyline_layer.dart | 6 +- .../tile_layer/tile_bounds/tile_bounds.dart | 19 ++-- lib/src/layer/tile_layer/tile_range.dart | 19 ++-- .../tile_layer/tile_range_calculator.dart | 8 +- lib/src/map/camera/camera.dart | 2 +- lib/src/map/camera/camera_fit.dart | 27 +++-- lib/src/misc/bounds.dart | 36 ------ lib/src/misc/extensions.dart | 32 +++--- test/core/bounds_test.dart | 24 ---- .../tile_layer/tile_bounds/crs_fakes.dart | 2 +- .../tile_bounds/tile_bounds_at_zoom_test.dart | 5 +- .../tile_bounds/tile_bounds_test.dart | 3 +- test/layer/tile_layer/tile_range_test.dart | 104 +++++++++--------- 15 files changed, 137 insertions(+), 200 deletions(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 324fbb345..48c85be3f 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -67,7 +67,7 @@ abstract class Crs { double zoom(double scale) => math.log(scale / 256) / math.ln2; /// Rescales the bounds to a given zoom value. - Bounds? getProjectedBounds(double zoom); + Rect? getProjectedBounds(double zoom); /// Returns true if we want the world to be replicated, longitude-wise. bool get replicatesWorldLongitude => false; @@ -118,16 +118,16 @@ abstract class CrsWithStaticTransformation extends Crs { } @override - Bounds? getProjectedBounds(double zoom) { + Rect? getProjectedBounds(double zoom) { if (infinite) return null; final b = projection.bounds!; final s = scale(zoom); final (minx, miny) = _transformation.transform(b.min.x, b.min.y, s); final (maxx, maxy) = _transformation.transform(b.max.x, b.max.y, s); - return Bounds( - Point(minx, miny), - Point(maxx, maxy), + return Rect.fromPoints( + Offset(minx, miny), + Offset(maxx, maxy), ); } } @@ -293,7 +293,7 @@ class Proj4Crs extends Crs { /// Rescales the bounds to a given zoom value. @override - Bounds? getProjectedBounds(double zoom) { + Rect? getProjectedBounds(double zoom) { if (infinite) return null; final b = projection.bounds!; @@ -302,10 +302,7 @@ class Proj4Crs extends Crs { final transformation = _getTransformationByZoom(zoom); final (minx, miny) = transformation.transform(b.min.x, b.min.y, zoomScale); final (maxx, maxy) = transformation.transform(b.max.x, b.max.y, zoomScale); - return Bounds( - Point(minx, miny), - Point(maxx, maxy), - ); + return Rect.fromPoints(Offset(minx, miny), Offset(maxx, maxy)); } /// Zoom to Scale function. diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index 3c01ecb97..bf980b209 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -82,16 +82,16 @@ class OverlayImage extends BaseOverlayImage { final camera = MapCamera.of(context); // northWest is not necessarily upperLeft depending on projection - final bounds = Bounds( - (camera.project(this.bounds.northWest) - camera.pixelOrigin).toPoint(), - (camera.project(this.bounds.southEast) - camera.pixelOrigin).toPoint(), + final bounds = Rect.fromPoints( + camera.project(this.bounds.northWest) - camera.pixelOrigin, + camera.project(this.bounds.southEast) - camera.pixelOrigin, ); return Positioned( - left: bounds.topLeft.x, - top: bounds.topLeft.y, - width: bounds.size.x, - height: bounds.size.y, + left: bounds.topLeft.dx, + top: bounds.topLeft.dy, + width: bounds.size.width, + height: bounds.size.height, child: child, ); } @@ -145,13 +145,12 @@ class RotatedOverlayImage extends BaseOverlayImage { final pxTopRight = pxTopLeft - pxBottomLeft + pxBottomRight; /// update/enlarge bounds so the new corner points fit within - final bounds = Bounds(pxTopLeft.toPoint(), pxBottomRight.toPoint()) - .extend(pxTopRight.toPoint()) - .extend(pxBottomLeft.toPoint()); + final bounds = RectExtension.containing( + [pxTopLeft, pxBottomRight, pxTopRight, pxBottomLeft]); - final vectorX = (pxTopRight - pxTopLeft) / bounds.size.x; - final vectorY = (pxBottomLeft - pxTopLeft) / bounds.size.y; - final offset = pxTopLeft - bounds.topLeft.toOffset(); + final vectorX = (pxTopRight - pxTopLeft) / bounds.size.width; + final vectorY = (pxBottomLeft - pxTopLeft) / bounds.size.height; + final offset = pxTopLeft - bounds.topLeft; final a = vectorX.dx; final b = vectorX.dy; @@ -161,10 +160,10 @@ class RotatedOverlayImage extends BaseOverlayImage { final ty = offset.dy; return Positioned( - left: bounds.topLeft.x, - top: bounds.topLeft.y, - width: bounds.size.x, - height: bounds.size.y, + left: bounds.topLeft.dx, + top: bounds.topLeft.dy, + width: bounds.size.width, + height: bounds.size.height, child: Transform( transform: Matrix4(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1), filterQuality: filterQuality, diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart index 2a0cfe851..4ed0f0230 100644 --- a/lib/src/layer/polyline_layer/polyline_layer.dart +++ b/lib/src/layer/polyline_layer/polyline_layer.dart @@ -136,9 +136,9 @@ class _PolylineLayerState extends State> ); // segment is visible - final projBounds = Bounds( - projection.project(boundsAdjusted.southWest).toPoint(), - projection.project(boundsAdjusted.northEast).toPoint(), + final projBounds = Rect.fromPoints( + projection.project(boundsAdjusted.southWest), + projection.project(boundsAdjusted.northEast), ); final (xWest, _) = projection.projectXY(const LatLng(0, -180)); diff --git a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart index e0ac72a8a..4f116536e 100644 --- a/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart +++ b/lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart @@ -1,7 +1,8 @@ +import 'dart:ui'; + import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; -import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart'; @@ -87,13 +88,13 @@ class DiscreteTileBounds extends TileBounds { TileBoundsAtZoom _tileBoundsAtZoomImpl(int zoom) { final zoomDouble = zoom.toDouble(); - final Bounds pixelBounds; + final Rect pixelBounds; if (_latLngBounds == null) { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { - pixelBounds = Bounds( - crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble).toPoint(), - crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble).toPoint(), + pixelBounds = Rect.fromPoints( + crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble), + crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble), ); } @@ -127,13 +128,13 @@ class WrappedTileBounds extends TileBounds { WrappedTileBoundsAtZoom _tileBoundsAtZoomImpl(int zoom) { final zoomDouble = zoom.toDouble(); - final Bounds pixelBounds; + final Rect pixelBounds; if (_latLngBounds == null) { pixelBounds = crs.getProjectedBounds(zoomDouble)!; } else { - pixelBounds = Bounds( - crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble).toPoint(), - crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble).toPoint(), + pixelBounds = Rect.fromPoints( + crs.latLngToOffset(_latLngBounds!.southWest, zoomDouble), + crs.latLngToOffset(_latLngBounds!.northEast, zoomDouble), ); } diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index f98307093..b434b6714 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -3,7 +3,6 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter_map/src/misc/extensions.dart'; import 'package:meta/meta.dart'; /// A range of tiles, this is normally a [DiscreteTileRange] and sometimes @@ -31,11 +30,11 @@ class EmptyTileRange extends TileRange { const Iterable.empty(); } -Point _floor(Point point) => - Point(point.x.floor(), point.y.floor()); +Point _floor(Offset point) => + Point(point.dx.floor(), point.dy.floor()); -Point _ceil(Point point) => - Point(point.x.ceil(), point.y.ceil()); +Point _ceil(Offset point) => + Point(point.dx.ceil(), point.dy.ceil()); /// Every [TileRange] is a [DiscreteTileRange] if it's not an [EmptyTileRange]. @immutable @@ -50,16 +49,16 @@ class DiscreteTileRange extends TileRange { factory DiscreteTileRange.fromPixelBounds({ required int zoom, required int tileDimension, - required Bounds pixelBounds, + required Rect pixelBounds, }) { final Bounds bounds; - if (pixelBounds.min == pixelBounds.max) { - final minAndMax = _floor(pixelBounds.min / tileDimension); + if (pixelBounds.isEmpty) { + final minAndMax = _floor(pixelBounds.topLeft / tileDimension.toDouble()); bounds = Bounds(minAndMax, minAndMax); } else { bounds = Bounds( - _floor(pixelBounds.min / tileDimension), - _ceil(pixelBounds.max / tileDimension) - const Point(1, 1), + _floor(pixelBounds.topLeft / tileDimension.toDouble()), + _ceil(pixelBounds.bottomRight / tileDimension.toDouble()) - const Point(1, 1), ); } diff --git a/lib/src/layer/tile_layer/tile_range_calculator.dart b/lib/src/layer/tile_layer/tile_range_calculator.dart index 0490c7c6e..7fabfae67 100644 --- a/lib/src/layer/tile_layer/tile_range_calculator.dart +++ b/lib/src/layer/tile_layer/tile_range_calculator.dart @@ -40,7 +40,7 @@ class TileRangeCalculator { ); } - Bounds _calculatePixelBounds( + Rect _calculatePixelBounds( MapCamera camera, LatLng center, double viewingZoom, @@ -51,7 +51,9 @@ class TileRangeCalculator { final pixelCenter = camera.project(center, tileZoomDouble).floor(); final halfSize = camera.size / (scale * 2); - return Bounds((pixelCenter - halfSize.bottomRight(Offset.zero)).toPoint(), - (pixelCenter + halfSize.bottomRight(Offset.zero)).toPoint()); + return Rect.fromPoints( + pixelCenter - halfSize.bottomRight(Offset.zero), + pixelCenter + halfSize.bottomRight(Offset.zero), + ); } } diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index d45333209..fc90cfae1 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -248,7 +248,7 @@ class MapCamera { double getScaleZoom(double scale) => crs.zoom(scale * crs.scale(zoom)); /// Calculates the pixel bounds of this camera's [crs]. - Bounds? getPixelWorldBounds(double? zoom) => + Rect? getPixelWorldBounds(double? zoom) => crs.getProjectedBounds(zoom ?? this.zoom); /// Calculates the [Offset] from the [pos] to this camera's [pixelOrigin]. diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 15a28ebe1..d2222e49a 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -1,5 +1,4 @@ -import 'dart:math' as math hide Point; -import 'dart:math' show Point; +import 'dart:math' as math; import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -144,21 +143,21 @@ class FitBounds extends CameraFit { // Prevent negative size which results in NaN zoom value later on in the calculation size = Size(math.max(0, size.width), math.max(0, size.height)); - var boundsSize = Bounds( - camera.project(se, camera.zoom).toPoint(), - camera.project(nw, camera.zoom).toPoint(), + var boundsSize = Rect.fromPoints( + camera.project(se, camera.zoom), + camera.project(nw, camera.zoom), ).size; if (camera.rotation != 0.0) { final cosAngle = math.cos(camera.rotationRad).abs(); final sinAngle = math.sin(camera.rotationRad).abs(); - boundsSize = Point( - (boundsSize.x * cosAngle) + (boundsSize.y * sinAngle), - (boundsSize.y * cosAngle) + (boundsSize.x * sinAngle), + boundsSize = Size( + (boundsSize.width * cosAngle) + (boundsSize.width * sinAngle), + (boundsSize.height * cosAngle) + (boundsSize.height * sinAngle), ); } final scale = - math.min(size.width / boundsSize.x, size.height / boundsSize.y); + math.min(size.width / boundsSize.width, size.height / boundsSize.height); var boundsZoom = camera.getScaleZoom(scale); @@ -226,17 +225,17 @@ class FitInsideBounds extends CameraFit { final cameraSize = camera.nonRotatedSize - paddingTotalXY as Size; - final projectedBoundsSize = Bounds( - camera.project(bounds.southEast, camera.zoom).toPoint(), - camera.project(bounds.northWest, camera.zoom).toPoint(), + final projectedBoundsSize = Rect.fromPoints( + camera.project(bounds.southEast, camera.zoom), + camera.project(bounds.northWest, camera.zoom), ).size; final scale = _rectInRotRectScale( angleRad: camera.rotationRad, smallRectHalfWidth: cameraSize.width / 2.0, smallRectHalfHeight: cameraSize.height / 2.0, - bigRectHalfWidth: projectedBoundsSize.x / 2.0, - bigRectHalfHeight: projectedBoundsSize.y / 2.0, + bigRectHalfWidth: projectedBoundsSize.width / 2.0, + bigRectHalfHeight: projectedBoundsSize.height / 2.0, ); var newZoom = camera.getScaleZoom(1.0 / scale); diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index e3d849f28..432eb8418 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -79,14 +79,6 @@ class Bounds { (point.y <= max.y); } - /// Check if an other [Bounds] object is inside of the bounds. - bool containsBounds(Bounds b) { - return (b.min.x >= min.x) && - (b.max.x <= max.x) && - (b.min.y >= min.y) && - (b.max.y <= max.y); - } - /// Calculates the intersection of two Bounds. The return value will be null /// if there is no intersection. The returned bounds may be zero size /// (bottomLeft == topRight). @@ -103,34 +95,6 @@ class Bounds { return null; } - /// Checks if the line between the two coordinates is contained within the - /// [Bounds]. - bool aabbContainsLine(double x1, double y1, double x2, double y2) { - // Completely outside. - if ((x1 <= min.x && x2 <= min.x) || - (y1 <= min.y && y2 <= min.y) || - (x1 >= max.x && x2 >= max.x) || - (y1 >= max.y && y2 >= max.y)) { - return false; - } - - final m = (y2 - y1) / (x2 - x1); - - double y = m * (min.x - x1) + y1; - if (y > min.y && y < max.y) return true; - - y = m * (max.x - x1) + y1; - if (y > min.y && y < max.y) return true; - - double x = (min.y - y1) / m + x1; - if (x > min.x && x < max.x) return true; - - x = (max.y - y1) / m + x1; - if (x > min.x && x < max.x) return true; - - return false; - } - @override String toString() => 'Bounds($min, $max)'; } diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 5a0243a57..9bd2ab573 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -60,27 +60,27 @@ extension RectExtension on Rect { /// Checks if the line between the two coordinates is contained within the /// [Rect]. bool aabbContainsLine(double x1, double y1, double x2, double y2) { - // // Completely outside. - // if ((x1 <= min.x && x2 <= min.x) || - // (y1 <= min.y && y2 <= min.y) || - // (x1 >= max.x && x2 >= max.x) || - // (y1 >= max.y && y2 >= max.y)) { - // return false; - // } + // Completely outside. + if ((x1 <= left && x2 <= left) || + (y1 <= top && y2 <= top) || + (x1 >= right && x2 >= right) || + (y1 >= bottom && y2 >= bottom)) { + return false; + } - // final m = (y2 - y1) / (x2 - x1); + final m = (y2 - y1) / (x2 - x1); - // double y = m * (min.x - x1) + y1; - // if (y > min.y && y < max.y) return true; + double y = m * (left - x1) + y1; + if (y > top && y < bottom) return true; - // y = m * (max.x - x1) + y1; - // if (y > min.y && y < max.y) return true; + y = m * (right - x1) + y1; + if (y > top && y < bottom) return true; - // double x = (min.y - y1) / m + x1; - // if (x > min.x && x < max.x) return true; + double x = (top - y1) / m + x1; + if (x > left && x < right) return true; - // x = (max.y - y1) / m + x1; - // if (x > min.x && x < max.x) return true; + x = (bottom - y1) / m + x1; + if (x > left && x < right) return true; return false; } diff --git a/test/core/bounds_test.dart b/test/core/bounds_test.dart index d4eaf61a7..5616b49ec 100644 --- a/test/core/bounds_test.dart +++ b/test/core/bounds_test.dart @@ -237,30 +237,6 @@ void main() { }); group('contains', () { - test( - 'should contain compared bounds if they are completely within ' - 'the bounds', () { - final bounds = - Bounds(const Point(101.1, 88.1), const Point(133.1, 60.3)); - - expect( - bounds.containsBounds( - Bounds(const Point(110.1, 77.3), const Point(128.3, 65.5))), - isTrue); - }); - - test( - 'should NOT contain compared bounds if they are NOT completely ' - 'within the bounds', () { - final bounds = - Bounds(const Point(101.1, 88.1), const Point(133.1, 60.3)); - - expect( - bounds.containsBounds( - Bounds(const Point(110.1, 77.3), const Point(133.2, 65.5))), - isFalse); - }); - test('should contain given point within the bounds', () { expect( Bounds(const Point(0, 50), const Point(50, 0)) diff --git a/test/layer/tile_layer/tile_bounds/crs_fakes.dart b/test/layer/tile_layer/tile_bounds/crs_fakes.dart index 0a4c9d2a2..821d61efc 100644 --- a/test/layer/tile_layer/tile_bounds/crs_fakes.dart +++ b/test/layer/tile_layer/tile_bounds/crs_fakes.dart @@ -29,5 +29,5 @@ class FakeInfiniteCrs extends Crs { throw UnimplementedError(); @override - Bounds? getProjectedBounds(double zoom) => throw UnimplementedError(); + Rect? getProjectedBounds(double zoom) => throw UnimplementedError(); } diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart index fde35643f..94a8b84b0 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; @@ -9,11 +10,11 @@ void main() { group('TileBoundsAtZoom', () { const hugeCoordinate = TileCoordinates(999999999, 999999999, 0); final hugePoint = - Point(hugeCoordinate.x.toDouble(), hugeCoordinate.y.toDouble()); + Offset(hugeCoordinate.x.toDouble(), hugeCoordinate.y.toDouble()); final tileRangeWithHugeCoordinate = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 1, - pixelBounds: Bounds(hugePoint, hugePoint), + pixelBounds: Rect.fromPoints(hugePoint, hugePoint), ); DiscreteTileRange discreteTileRange( diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart index 1c2b2f531..9a96f3da3 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_test.dart @@ -4,7 +4,6 @@ import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; -import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:test/test.dart'; @@ -94,7 +93,7 @@ void main() { tileDimension: 256, latLngBounds: LatLngBounds( const LatLng(0, 0), - crs.offsetToLatLng(crs.getProjectedBounds(0)!.max.toOffset(), 0), + crs.offsetToLatLng(crs.getProjectedBounds(0)!.bottomRight, 0), ), ); diff --git a/test/layer/tile_layer/tile_range_test.dart b/test/layer/tile_layer/tile_range_test.dart index e010b1667..1a3162c8b 100644 --- a/test/layer/tile_layer/tile_range_test.dart +++ b/test/layer/tile_layer/tile_range_test.dart @@ -12,12 +12,12 @@ void main() { final tileRange1 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 1, - pixelBounds: Bounds(const Point(1, 1), const Point(2, 2)), + pixelBounds: Rect.fromPoints(const Offset(1, 1), const Offset(2, 2)), ); final tileRange2 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 1, - pixelBounds: Bounds(const Point(3, 3), const Point(4, 4)), + pixelBounds: Rect.fromPoints(const Offset(3, 3), const Offset(4, 4)), ); final emptyTileRange = tileRange1.intersect(tileRange2); @@ -35,9 +35,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(25, 25), - const Point(25, 25), + pixelBounds: Rect.fromPoints( + const Offset(25, 25), + const Offset(25, 25), ), ); @@ -49,9 +49,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(0, 0), - const Point(0.1, 0.1), + pixelBounds: Rect.fromPoints( + const Offset(0, 0), + const Offset(0.1, 0.1), ), ); @@ -63,9 +63,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(0, 0), - const Point(9.99, 9.99), + pixelBounds: Rect.fromPoints( + const Offset(0, 0), + const Offset(9.99, 9.99), ), ); @@ -77,9 +77,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(19.99, 19.99), - const Point(30.1, 30.1), + pixelBounds: Rect.fromPoints( + const Offset(19.99, 19.99), + const Offset(30.1, 30.1), ), ); @@ -101,9 +101,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(25, 25), - const Point(25, 25), + pixelBounds: Rect.fromPoints( + const Offset(25, 25), + const Offset(25, 25), ), ); @@ -128,18 +128,18 @@ void main() { final tileRange1 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(25, 25), - const Point(25, 25), + pixelBounds: Rect.fromPoints( + const Offset(25, 25), + const Offset(25, 25), ), ); final tileRange2 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(35, 35), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(35, 35), ), ); @@ -154,18 +154,18 @@ void main() { final tileRange1 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(25, 25), - const Point(35, 35), + pixelBounds: Rect.fromPoints( + const Offset(25, 25), + const Offset(35, 35), ), ); final tileRange2 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(45, 45), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(45, 45), ), ); @@ -182,18 +182,18 @@ void main() { final tileRange1 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(25, 25), - const Point(35, 35), + pixelBounds: Rect.fromPoints( + const Offset(25, 25), + const Offset(35, 35), ), ); final tileRange2 = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(15, 15), - const Point(45, 45), + pixelBounds: Rect.fromPoints( + const Offset(15, 15), + const Offset(45, 45), ), ); @@ -211,14 +211,14 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(45, 45), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(45, 45), ), ); - expect(tileRange.min, const Point(3, 3)); - expect(tileRange.max, const Point(4, 4)); + expect(tileRange.min, const Offset(3, 3)); + expect(tileRange.max, const Offset(4, 4)); }); group('center', () { @@ -226,9 +226,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(35, 35), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(35, 35), ), ); @@ -239,9 +239,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(45, 45), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(45, 45), ), ); @@ -252,9 +252,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 0, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(55, 55), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(55, 55), ), ); @@ -266,9 +266,9 @@ void main() { final tileRange = DiscreteTileRange.fromPixelBounds( zoom: 10, tileDimension: 10, - pixelBounds: Bounds( - const Point(35, 35), - const Point(35, 35), + pixelBounds: Rect.fromPoints( + const Offset(35, 35), + const Offset(35, 35), ), ); From 17d1e073bc2eb1e988a2c2e5b4807e0ad5e03cfe Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 01:43:01 -0600 Subject: [PATCH 34/51] dart format . --- lib/src/layer/tile_layer/tile_range.dart | 6 +++--- lib/src/map/camera/camera_fit.dart | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index b434b6714..76f834601 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -33,8 +33,7 @@ class EmptyTileRange extends TileRange { Point _floor(Offset point) => Point(point.dx.floor(), point.dy.floor()); -Point _ceil(Offset point) => - Point(point.dx.ceil(), point.dy.ceil()); +Point _ceil(Offset point) => Point(point.dx.ceil(), point.dy.ceil()); /// Every [TileRange] is a [DiscreteTileRange] if it's not an [EmptyTileRange]. @immutable @@ -58,7 +57,8 @@ class DiscreteTileRange extends TileRange { } else { bounds = Bounds( _floor(pixelBounds.topLeft / tileDimension.toDouble()), - _ceil(pixelBounds.bottomRight / tileDimension.toDouble()) - const Point(1, 1), + _ceil(pixelBounds.bottomRight / tileDimension.toDouble()) - + const Point(1, 1), ); } diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index d2222e49a..934f56521 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -156,8 +156,8 @@ class FitBounds extends CameraFit { ); } - final scale = - math.min(size.width / boundsSize.width, size.height / boundsSize.height); + final scale = math.min( + size.width / boundsSize.width, size.height / boundsSize.height); var boundsZoom = camera.getScaleZoom(scale); From 74e5ee49280b93379a885c30497c9148e1ffc053 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 01:43:41 -0600 Subject: [PATCH 35/51] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b37c702b..e06a2f0b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This CHANGELOG does not include every commit and/or PR - it is a hand picked sel Migration from `Point` class internally, but this also affects the external API. Migration Guide: -- any methods that previously required `Point` now require `Offset` as return values and parameters +- any methods that previously required `Point` now require `Offset`, `Size`, or `Rect` as return values and parameters - `pointToLatLng` -> `offsetToLatLng` - `PointExtension` and `OffsetToPointExtension` marked as internal - `MapController.rotateAroundPoint` now only accepts an Offset From b280465c87130003eaf088402b3a2f76c4893f95 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:01:39 -0600 Subject: [PATCH 36/51] more complete migration of Rect --- example/lib/pages/epsg3996_crs.dart | 6 ++--- lib/src/geo/crs.dart | 28 ++++++++++++------------ lib/src/layer/tile_layer/tile_range.dart | 6 ++--- lib/src/misc/extensions.dart | 27 +++++++++++++---------- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/example/lib/pages/epsg3996_crs.dart b/example/lib/pages/epsg3996_crs.dart index f2eb97e9b..acbcc984f 100644 --- a/example/lib/pages/epsg3996_crs.dart +++ b/example/lib/pages/epsg3996_crs.dart @@ -41,9 +41,9 @@ class EPSG3996PageState extends State { 128, ]; - final epsg3413Bounds = Bounds( - const Point(-4511619, -4511336), - const Point(4510883, 4510996), + final epsg3413Bounds = Rect.fromPoints( + const Offset(-4511619, -4511336), + const Offset(4510883, 4510996), ); maxZoom = resolutions.length - 1; diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 48c85be3f..97463a709 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -3,6 +3,7 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/src/misc/bounds.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart'; import 'package:proj4dart/proj4dart.dart' as proj4; @@ -123,8 +124,8 @@ abstract class CrsWithStaticTransformation extends Crs { final b = projection.bounds!; final s = scale(zoom); - final (minx, miny) = _transformation.transform(b.min.x, b.min.y, s); - final (maxx, maxy) = _transformation.transform(b.max.x, b.max.y, s); + final (minx, miny) = _transformation.transform(b.min.dx, b.min.dy, s); + final (maxx, maxy) = _transformation.transform(b.max.dx, b.max.dy, s); return Rect.fromPoints( Offset(minx, miny), Offset(maxx, maxy), @@ -222,7 +223,7 @@ class Proj4Crs extends Crs { required String code, required proj4.Projection proj4Projection, List>? origins, - Bounds? bounds, + Rect? bounds, List? scales, List? resolutions, }) { @@ -300,8 +301,8 @@ class Proj4Crs extends Crs { final zoomScale = scale(zoom); final transformation = _getTransformationByZoom(zoom); - final (minx, miny) = transformation.transform(b.min.x, b.min.y, zoomScale); - final (maxx, maxy) = transformation.transform(b.max.x, b.max.y, zoomScale); + final (minx, miny) = transformation.transform(b.min.dx, b.min.dy, zoomScale); + final (maxx, maxy) = transformation.transform(b.max.dx, b.max.dy, zoomScale); return Rect.fromPoints(Offset(minx, miny), Offset(maxx, maxy)); } @@ -369,7 +370,7 @@ class Proj4Crs extends Crs { @immutable abstract class Projection { /// The [Bounds] for the coordinates of this [Projection]. - final Bounds? bounds; + final Rect? bounds; /// Base constructor for the abstract [Projection] class that sets the /// required fields. @@ -441,10 +442,7 @@ abstract class Projection { } class _LonLat extends Projection { - static const _bounds = Bounds.unsafe( - Point(-180, -90), - Point(180, 90), - ); + static const _bounds = Rect.fromLTRB(-180, -90, 180, 90); const _LonLat() : super(_bounds); @@ -469,9 +467,11 @@ class SphericalMercator extends Projection { static const double _boundsD = r * math.pi; /// The constant Bounds of the [SphericalMercator] projection. - static const Bounds _bounds = Bounds.unsafe( - Point(-_boundsD, -_boundsD), - Point(_boundsD, _boundsD), + static const Rect _bounds = Rect.fromLTRB( + -_boundsD, + -_boundsD, + _boundsD, + _boundsD, ); /// Constant constructor for the [SphericalMercator] projection. @@ -515,7 +515,7 @@ class _Proj4Projection extends Projection { _Proj4Projection({ required this.proj4Projection, - required Bounds? bounds, + required Rect? bounds, }) : epsg4326 = proj4.Projection.WGS84, super(bounds); diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 76f834601..bbf81d379 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -3,6 +3,7 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/extensions.dart'; import 'package:meta/meta.dart'; /// A range of tiles, this is normally a [DiscreteTileRange] and sometimes @@ -56,9 +57,8 @@ class DiscreteTileRange extends TileRange { bounds = Bounds(minAndMax, minAndMax); } else { bounds = Bounds( - _floor(pixelBounds.topLeft / tileDimension.toDouble()), - _ceil(pixelBounds.bottomRight / tileDimension.toDouble()) - - const Point(1, 1), + _floor(pixelBounds.min / tileDimension.toDouble()), + _ceil(pixelBounds.max / tileDimension.toDouble()) - const Point(1, 1), ); } diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 9bd2ab573..ed147b258 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -1,14 +1,14 @@ -import 'dart:math'; +import 'dart:math' as math; import 'dart:ui'; import 'package:meta/meta.dart'; /// Extension methods for the math.[Point] class @internal -extension PointExtension on Point { +extension PointExtension on math.Point { /// Create a new [Point] where the [x] and [y] values are divided by [factor]. - Point operator /(num factor) { - return Point(x / factor, y / factor); + math.Point operator /(num factor) { + return math.Point(x / factor, y / factor); } /// Converts to offset @@ -19,13 +19,13 @@ extension PointExtension on Point { @internal extension OffsetExtension on Offset { /// Creates a [Point] representation of this offset. - Point toPoint() => Point(dx, dy); + math.Point toPoint() => math.Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by /// [radians]. Offset rotate(num radians) { - final cosTheta = cos(radians); - final sinTheta = sin(radians); + final cosTheta = math.cos(radians); + final sinTheta = math.sin(radians); final nx = (cosTheta * dx) + (sinTheta * dy); final ny = (cosTheta * dy) - (sinTheta * dx); return Offset(nx, ny); @@ -40,6 +40,7 @@ extension OffsetExtension on Offset { @internal extension RectExtension on Rect { + /// Create a [Rect] as bounding box of a list of points. static Rect containing(List points) { var maxX = double.negativeInfinity; @@ -48,10 +49,10 @@ extension RectExtension on Rect { var minY = double.infinity; for (final point in points) { - maxX = max(point.dx, maxX); - minX = min(point.dx, minX); - maxY = max(point.dy, maxY); - minY = min(point.dy, minY); + maxX = math.max(point.dx, maxX); + minX = math.min(point.dx, minX); + maxY = math.max(point.dy, maxY); + minY = math.min(point.dy, minY); } return Rect.fromPoints(Offset(minX, minY), Offset(maxX, maxY)); @@ -84,4 +85,8 @@ extension RectExtension on Rect { return false; } + + Offset get min => topLeft; + + Offset get max => bottomRight; } From a2d88a16c8a506a444f25da918344979ba8977f0 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:02:32 -0600 Subject: [PATCH 37/51] dart format --- lib/src/geo/crs.dart | 6 ++++-- lib/src/layer/tile_layer/tile_range.dart | 2 +- lib/src/misc/extensions.dart | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 97463a709..825bb34ce 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -301,8 +301,10 @@ class Proj4Crs extends Crs { final zoomScale = scale(zoom); final transformation = _getTransformationByZoom(zoom); - final (minx, miny) = transformation.transform(b.min.dx, b.min.dy, zoomScale); - final (maxx, maxy) = transformation.transform(b.max.dx, b.max.dy, zoomScale); + final (minx, miny) = + transformation.transform(b.min.dx, b.min.dy, zoomScale); + final (maxx, maxy) = + transformation.transform(b.max.dx, b.max.dy, zoomScale); return Rect.fromPoints(Offset(minx, miny), Offset(maxx, maxy)); } diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index bbf81d379..21f78b7bb 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -53,7 +53,7 @@ class DiscreteTileRange extends TileRange { }) { final Bounds bounds; if (pixelBounds.isEmpty) { - final minAndMax = _floor(pixelBounds.topLeft / tileDimension.toDouble()); + final minAndMax = _floor(pixelBounds.min / tileDimension.toDouble()); bounds = Bounds(minAndMax, minAndMax); } else { bounds = Bounds( diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index ed147b258..1cdeb1f2a 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -40,7 +40,6 @@ extension OffsetExtension on Offset { @internal extension RectExtension on Rect { - /// Create a [Rect] as bounding box of a list of points. static Rect containing(List points) { var maxX = double.negativeInfinity; From 57deeab695c73fcea661a84059c6f6d4a605f60e Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:13:32 -0600 Subject: [PATCH 38/51] convert Bounds to IntegerBounds and made internal most methods on integer bounds are not used --- lib/src/geo/crs.dart | 2 +- lib/src/layer/tile_layer/tile_range.dart | 12 +- .../tile_layer/wms_tile_layer_options.dart | 6 +- lib/src/misc/bounds.dart | 67 +++++----- test/core/bounds_test.dart | 116 +++++++++--------- .../tile_bounds/tile_bounds_at_zoom_test.dart | 2 +- .../tile_layer/tile_image_view_test.dart | 2 +- 7 files changed, 102 insertions(+), 105 deletions(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 825bb34ce..5672d6818 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -371,7 +371,7 @@ class Proj4Crs extends Crs { /// Inherit from this class if you want to create or implement your own CRS. @immutable abstract class Projection { - /// The [Bounds] for the coordinates of this [Projection]. + /// The [IntegerBounds] for the coordinates of this [Projection]. final Rect? bounds; /// Base constructor for the abstract [Projection] class that sets the diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 21f78b7bb..4e84757f3 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -40,7 +40,7 @@ Point _ceil(Offset point) => Point(point.dx.ceil(), point.dy.ceil()); @immutable class DiscreteTileRange extends TileRange { /// Bounds are inclusive - final Bounds _bounds; + final IntegerBounds _bounds; /// Create a new [DiscreteTileRange] by setting it's values. const DiscreteTileRange(super.zoom, this._bounds); @@ -51,12 +51,12 @@ class DiscreteTileRange extends TileRange { required int tileDimension, required Rect pixelBounds, }) { - final Bounds bounds; + final IntegerBounds bounds; if (pixelBounds.isEmpty) { final minAndMax = _floor(pixelBounds.min / tileDimension.toDouble()); - bounds = Bounds(minAndMax, minAndMax); + bounds = IntegerBounds(minAndMax, minAndMax); } else { - bounds = Bounds( + bounds = IntegerBounds( _floor(pixelBounds.min / tileDimension.toDouble()), _ceil(pixelBounds.max / tileDimension.toDouble()) - const Point(1, 1), ); @@ -95,7 +95,7 @@ class DiscreteTileRange extends TileRange { return DiscreteTileRange( zoom, - Bounds( + IntegerBounds( Point(math.max(min.x, minX), min.y), Point(math.min(max.x, maxX), max.y), ), @@ -110,7 +110,7 @@ class DiscreteTileRange extends TileRange { return DiscreteTileRange( zoom, - Bounds( + IntegerBounds( Point(min.x, math.max(min.y, minY)), Point(max.x, math.min(max.y, maxY)), ), diff --git a/lib/src/layer/tile_layer/wms_tile_layer_options.dart b/lib/src/layer/tile_layer/wms_tile_layer_options.dart index dd636097f..5c4c70de3 100644 --- a/lib/src/layer/tile_layer/wms_tile_layer_options.dart +++ b/lib/src/layer/tile_layer/wms_tile_layer_options.dart @@ -77,10 +77,10 @@ class WMSTileLayerOptions { crs.offsetToLatLng(sePoint.toOffset(), coords.z.toDouble()); final nw = crs.projection.project(nwCoords); final se = crs.projection.project(seCoords); - final bounds = Bounds(nw.toPoint(), se.toPoint()); + final bounds = Rect.fromPoints(nw, se); final bbox = (_versionNumber >= 1.3 && crs is Epsg4326) - ? [bounds.min.y, bounds.min.x, bounds.max.y, bounds.max.x] - : [bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y]; + ? [bounds.min.dy, bounds.min.dx, bounds.max.dy, bounds.max.dx] + : [bounds.min.dx, bounds.min.dy, bounds.max.dx, bounds.max.dy]; final buffer = StringBuffer(_encodedBaseUrl); buffer.write('&width=${retinaMode ? tileDimension * 2 : tileDimension}'); diff --git a/lib/src/misc/bounds.dart b/lib/src/misc/bounds.dart index 432eb8418..2a81209e7 100644 --- a/lib/src/misc/bounds.dart +++ b/lib/src/misc/bounds.dart @@ -8,17 +8,18 @@ import 'package:meta/meta.dart'; /// Rectangular bound delimited by orthogonal lines passing through two /// points. @immutable -class Bounds { - /// The edge of the bounds with the minimum x and y coordinate - final Point min; - - /// The edge of the bounds with the maximum x and y coordinate - final Point max; - - /// Create a [Bounds] instance in a safe way. - factory Bounds(Point a, Point b) { - final T minX; - final T maxX; +@internal +class IntegerBounds { + /// inthe edge of the bounds with the minimum x and y coordinate + final Point min; + + /// inthe edge of the bounds with the maximum x and y coordinate + final Point max; + + /// Create a [IntegerBounds] instance in a safe way. + factory IntegerBounds(Point a, Point b) { + final int minX; + final int maxX; if (a.x > b.x) { minX = b.x; maxX = a.x; @@ -26,8 +27,8 @@ class Bounds { minX = a.x; maxX = b.x; } - final T minY; - final T maxY; + final int minY; + final int maxY; if (a.y > b.y) { minY = b.y; maxY = a.y; @@ -35,61 +36,61 @@ class Bounds { minY = a.y; maxY = b.y; } - return Bounds.unsafe(Point(minX, minY), Point(maxX, maxY)); + return IntegerBounds.unsafe(Point(minX, minY), Point(maxX, maxY)); } - /// Create a [Bounds] instance **without** checking if [min] is actually the + /// Create a [IntegerBounds] instance **without** checking if [min] is actually the /// minimum and [max] is actually the maximum. - const Bounds.unsafe(this.min, this.max); + const IntegerBounds.unsafe(this.min, this.max); - /// Creates a new [Bounds] obtained by expanding the current ones with a new + /// Creates a new [IntegerBounds] obtained by expanding the current ones with a new /// point. - Bounds extend(Point point) { - return Bounds.unsafe( + IntegerBounds extend(Point point) { + return IntegerBounds.unsafe( Point(math.min(point.x, min.x), math.min(point.y, min.y)), Point(math.max(point.x, max.x), math.max(point.y, max.y)), ); } - /// This [Bounds] central point. - Offset get center => (min.toOffset() + max.toOffset()) / 2; + /// inthis [IntegerBounds] central point. + Offset get center => (min + max).toOffset() / 2; /// Bottom-Left corner's point. - Point get bottomLeft => Point(min.x, max.y); + Point get bottomLeft => Point(min.x, max.y); - /// Top-Right corner's point. - Point get topRight => Point(max.x, min.y); + /// intop-Right corner's point. + Point get topRight => Point(max.x, min.y); - /// Top-Left corner's point. - Point get topLeft => min; + /// intop-Left corner's point. + Point get topLeft => min; /// Bottom-Right corner's point. - Point get bottomRight => max; + Point get bottomRight => max; /// A point that contains the difference between the point's axis projections. - Point get size { + Point get size { return max - min; } /// Check if a [Point] is inside of the bounds. - bool contains(Point point) { + bool contains(Point point) { return (point.x >= min.x) && (point.x <= max.x) && (point.y >= min.y) && (point.y <= max.y); } - /// Calculates the intersection of two Bounds. The return value will be null - /// if there is no intersection. The returned bounds may be zero size + /// Calculates the intersection of two Bounds. inthe return value will be null + /// if there is no intersection. inthe returned bounds may be zero size /// (bottomLeft == topRight). - Bounds? intersect(Bounds b) { + IntegerBounds? intersect(IntegerBounds b) { final leftX = math.max(min.x, b.min.x); final rightX = math.min(max.x, b.max.x); final topY = math.max(min.y, b.min.y); final bottomY = math.min(max.y, b.max.y); if (leftX <= rightX && topY <= bottomY) { - return Bounds.unsafe(Point(leftX, topY), Point(rightX, bottomY)); + return IntegerBounds.unsafe(Point(leftX, topY), Point(rightX, bottomY)); } return null; diff --git a/test/core/bounds_test.dart b/test/core/bounds_test.dart index 5616b49ec..4808d1d96 100644 --- a/test/core/bounds_test.dart +++ b/test/core/bounds_test.dart @@ -10,7 +10,7 @@ void main() { test( 'should create bounds with minimum point equal to minimum argument ' 'if maximum argument point is positioned higher', () { - final bounds = Bounds(const Point(1, 2), const Point(3, 4)); + final bounds = IntegerBounds(const Point(1, 2), const Point(3, 4)); expect(bounds.min.x, equals(1.0)); expect(bounds.min.y, equals(2.0)); @@ -19,7 +19,7 @@ void main() { test( 'should create bounds with minimum point equal to maximum argument ' 'if maximum argument point is positioned lower', () { - final bounds = Bounds(const Point(3, 4), const Point(1, 2)); + final bounds = IntegerBounds(const Point(3, 4), const Point(1, 2)); expect(bounds.min.x, equals(1.0)); expect(bounds.min.y, equals(2.0)); @@ -28,7 +28,7 @@ void main() { test( 'should create bounds with maximum point equal to minimum argument ' 'if maximum argument point is positioned lower', () { - final bounds = Bounds(const Point(1, 2), const Point(0.01, 0.02)); + final bounds = IntegerBounds(const Point(1, 2), const Point(0, 0)); expect(bounds.max.x, equals(1.0)); expect(bounds.max.y, equals(2.0)); @@ -37,7 +37,7 @@ void main() { test( 'should create bounds with maximum point equal to maximum argument ' 'if maximum argument point is positioned higher', () { - final bounds = Bounds(const Point(0.01, 0.02), const Point(1, 2)); + final bounds = IntegerBounds(const Point(0, 0), const Point(1, 2)); expect(bounds.max.x, equals(1.0)); expect(bounds.max.y, equals(2.0)); @@ -45,42 +45,38 @@ void main() { test('should get center of bounds as a point with x position', () { expect( - Bounds(Point(5.5, randomDouble()), Point(3.3, randomDouble())) - .center - .dx, - equals(4.4)); + IntegerBounds(Point(5, randomInt()), Point(4, randomInt())).center.dx, + equals(4.5)); }); test('should get center of bounds as a point with y position', () { expect( - Bounds(Point(randomDouble(), 3.2), Point(randomDouble(), 6.6)) - .center - .dy, - equals(4.9)); + IntegerBounds(Point(randomInt(), 3), Point(randomInt(), 4)).center.dy, + equals(3.5)); }); test( 'should create bounds with size represented as point with position ' 'x based on distance between top left and bottom right corners', () { - final size = Bounds( - Point(1.1, randomDouble()), - Point(3.3, randomDouble()), + final size = IntegerBounds( + Point(1, randomInt()), + Point(3, randomInt()), ).size; // avoid float precision problems - expect(size.x.toStringAsPrecision(2), equals('2.2')); + expect(size.x, equals(2)); }); test( 'should create bounds with size represented as point with position ' 'y based on distance between top left and bottom right corners', () { - final size = Bounds( - Point(randomDouble(), 2.2), - Point(randomDouble(), 5.5), + final size = IntegerBounds( + Point(randomInt(), 2), + Point(randomInt(), 5), ).size; // avoid float precision problems - expect(size.y.toStringAsPrecision(2), equals('3.3')); + expect(size.y, equals(3)); }); group('corners', () { @@ -88,149 +84,149 @@ void main() { 'should create bounds with bottom left corner\'s x position ' 'using minimum point x position', () { expect( - Bounds(Point(2.2, randomDouble()), Point(1.1, randomDouble())) + IntegerBounds(Point(2, randomInt()), Point(1, randomInt())) .bottomLeft .x, - equals(1.1)); + equals(1)); }); test( 'should create bounds with bottom left corner\'s y position ' 'using maximum point y position', () { expect( - Bounds(Point(randomDouble(), 1), Point(randomDouble(), 5.5)) + IntegerBounds(Point(randomInt(), 1), Point(randomInt(), 5)) .bottomLeft .y, - equals(5.5)); + equals(5)); }); test( 'should create bounds with top right corner\'s x position ' 'using maximum point x position', () { expect( - Bounds(Point(1, randomDouble()), Point(8.8, randomDouble())) + IntegerBounds(Point(1, randomInt()), Point(8, randomInt())) .topRight .x, - equals(8.8)); + equals(8)); }); test( 'should create bounds with top right corner\'s y position ' 'using minimum point y position', () { expect( - Bounds(Point(randomDouble(), 9.9), Point(randomDouble(), 100)) + IntegerBounds(Point(randomInt(), 10), Point(randomInt(), 100)) .topRight .y, - equals(9.9)); + equals(10)); }); test( 'should create bounds with top left corner\'s x position ' 'using minimum point x position', () { expect( - Bounds(Point(1.1, randomDouble()), Point(2.2, randomDouble())) + IntegerBounds(Point(1, randomInt()), Point(2, randomInt())) .topLeft .x, - equals(1.1)); + equals(1)); }); test( 'should create bounds with top left corner\'s y position ' 'using minimum point y position', () { expect( - Bounds(Point(randomDouble(), 4.4), Point(randomDouble(), 3.3)) + IntegerBounds(Point(randomInt(), 4), Point(randomInt(), 3)) .topLeft .y, - equals(3.3)); + equals(3)); }); test( 'should create bounds with bottom right corner\'s x position ' 'using maximum point x position', () { expect( - Bounds(Point(5.5, randomDouble()), Point(4.4, randomDouble())) + IntegerBounds(Point(5, randomInt()), Point(4, randomInt())) .bottomRight .x, - equals(5.5)); + equals(5)); }); test( 'should create bounds with bottom right corner\'s y position ' 'using maximum point y position', () { expect( - Bounds(Point(randomDouble(), 101.3), Point(randomDouble(), 101.4)) + IntegerBounds(Point(randomInt(), 101), Point(randomInt(), 102)) .bottomRight .y, - equals(101.4)); + equals(102)); }); }); test('should be convertable to string', () { - expect(Bounds(const Point(1.1, 2.2), const Point(3.3, 4.4)).toString(), - equals('Bounds(Point(1.1, 2.2), Point(3.3, 4.4))')); + expect(IntegerBounds(const Point(1, 2), const Point(3, 4)).toString(), + equals('Bounds(Point(1, 2), Point(3, 4))')); }); group('extend', () { test('should create new bounds with updated minimum x position', () { final bounds = - Bounds(Point(-10.1, randomDouble()), Point(11.1, randomDouble())); - final extendedBounds = bounds.extend(Point(-13.3, randomDouble())); + IntegerBounds(Point(-10, randomInt()), Point(11, randomInt())); + final extendedBounds = bounds.extend(Point(-13, randomInt())); - expect(extendedBounds.min.x, -13.3); + expect(extendedBounds.min.x, -13); }); test('should create new bounds with updated minimum y position', () { final bounds = - Bounds(Point(randomDouble(), 3.5), Point(randomDouble(), 101.3)); - final extendedBounds = bounds.extend(Point(randomDouble(), 2.1)); + IntegerBounds(Point(randomInt(), 3), Point(randomInt(), 101)); + final extendedBounds = bounds.extend(Point(randomInt(), 2)); - expect(extendedBounds.min.y, equals(2.1)); + expect(extendedBounds.min.y, equals(2)); }); test('should create new bounds with updated maximum x position', () { final bounds = - Bounds(Point(4.5, randomDouble()), Point(16.3, randomDouble())); - final extendedBounds = bounds.extend(Point(18.9, randomDouble())); + IntegerBounds(Point(4, randomInt()), Point(16, randomInt())); + final extendedBounds = bounds.extend(Point(19, randomInt())); - expect(extendedBounds.max.x, equals(18.9)); + expect(extendedBounds.max.x, equals(19)); }); test('should create new bounds with updated maximum y position', () { final bounds = - Bounds(Point(randomDouble(), 3.5), Point(randomDouble(), 34.3)); - final extendedBounds = bounds.extend(Point(randomDouble(), 38.3)); + IntegerBounds(Point(randomInt(), 4), Point(randomInt(), 34)); + final extendedBounds = bounds.extend(Point(randomInt(), 38)); - expect(extendedBounds.max.y, equals(38.3)); + expect(extendedBounds.max.y, equals(38)); }); test('should create new bounds and keep existing minimum x position', () { final bounds = - Bounds(Point(-10.1, randomDouble()), Point(11.1, randomDouble())); - final extendedBounds = bounds.extend(Point(-7.7, randomDouble())); + IntegerBounds(Point(-10, randomInt()), Point(11, randomInt())); + final extendedBounds = bounds.extend(Point(-7, randomInt())); expect(extendedBounds.min.x, equals(bounds.min.x)); }); test('should create new bounds and keep existing minimum y position', () { final bounds = - Bounds(Point(randomDouble(), 3.3), Point(randomDouble(), 12.7)); - final extendedBounds = bounds.extend(Point(randomDouble(), 4.4)); + IntegerBounds(Point(randomInt(), 3), Point(randomInt(), 13)); + final extendedBounds = bounds.extend(Point(randomInt(), 4)); expect(extendedBounds.min.y, equals(bounds.min.y)); }); test('should create new bounds and keep existing maximum x position', () { final bounds = - Bounds(Point(-15.5, randomDouble()), Point(25.8, randomDouble())); - final extendedBounds = bounds.extend(Point(25.7, randomDouble())); + IntegerBounds(Point(-15, randomInt()), Point(26, randomInt())); + final extendedBounds = bounds.extend(Point(26, randomInt())); expect(extendedBounds.max.x, equals(bounds.max.x)); }); test('should create new bounds and keep existing maximum y position', () { final bounds = - Bounds(Point(randomDouble(), 0), Point(randomDouble(), 15.5)); - final extendedBounds = bounds.extend(Point(randomDouble(), 15.4)); + IntegerBounds(Point(randomInt(), 0), Point(randomInt(), 16)); + final extendedBounds = bounds.extend(Point(randomInt(), 15)); expect(extendedBounds.max.y, equals(bounds.max.y)); }); @@ -239,14 +235,14 @@ void main() { group('contains', () { test('should contain given point within the bounds', () { expect( - Bounds(const Point(0, 50), const Point(50, 0)) + IntegerBounds(const Point(0, 50), const Point(50, 0)) .contains(const Point(25, 25)), isTrue); }); test('should NOT contain given point within the bounds', () { expect( - Bounds(const Point(0, 50), const Point(50, 0)) + IntegerBounds(const Point(0, 50), const Point(50, 0)) .contains(const Point(51, 51)), isFalse); }); diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart index 94a8b84b0..83137bbce 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart @@ -21,7 +21,7 @@ void main() { int zoom, int minX, int minY, int maxX, int maxY) => DiscreteTileRange( zoom, - Bounds(Point(minX, minY), Point(maxX, maxY)), + IntegerBounds(Point(minX, minY), Point(maxX, maxY)), ); test('InfiniteTileBoundsAtZoom', () { diff --git a/test/layer/tile_layer/tile_image_view_test.dart b/test/layer/tile_layer/tile_image_view_test.dart index 00e7820a7..0c8859a4d 100644 --- a/test/layer/tile_layer/tile_image_view_test.dart +++ b/test/layer/tile_layer/tile_image_view_test.dart @@ -23,7 +23,7 @@ void main() { }) => DiscreteTileRange( zoom, - Bounds(Point(x1, y1), Point(x2, y2)), + IntegerBounds(Point(x1, y1), Point(x2, y2)), ); group('staleTiles', () { From 237d5f66236ea18317c6cf16c35b4a00c589ea4f Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:18:14 -0600 Subject: [PATCH 39/51] fix lints --- lib/flutter_map.dart | 1 - lib/src/gestures/map_interactive_viewer.dart | 4 +++- lib/src/layer/tile_layer/tile_range.dart | 1 + lib/src/map/controller/map_controller.dart | 4 ---- test/core/bounds_test.dart | 2 +- .../tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart | 1 + test/layer/tile_layer/tile_image_view_test.dart | 1 + test/layer/tile_layer/tile_range_test.dart | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/flutter_map.dart b/lib/flutter_map.dart index bea98ce16..60be3d81e 100644 --- a/lib/flutter_map.dart +++ b/lib/flutter_map.dart @@ -59,4 +59,3 @@ export 'package:flutter_map/src/map/options/cursor_keyboard_rotation.dart'; export 'package:flutter_map/src/map/options/interaction.dart'; export 'package:flutter_map/src/map/options/options.dart'; export 'package:flutter_map/src/map/widget.dart'; -export 'package:flutter_map/src/misc/bounds.dart'; diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index 63234b3b2..5b877f175 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -382,7 +382,9 @@ class MapInteractiveViewerState extends State ); if (_interactionOptions.cursorKeyboardRotationOptions.behaviour == - CursorRotationBehaviour.setNorth) _ckrClickDegrees = 0; + CursorRotationBehaviour.setNorth) { + _ckrClickDegrees = 0; + } } void _onPointerSignal(PointerSignalEvent pointerSignal) { diff --git a/lib/src/layer/tile_layer/tile_range.dart b/lib/src/layer/tile_layer/tile_range.dart index 4e84757f3..b7f2b90d8 100644 --- a/lib/src/layer/tile_layer/tile_range.dart +++ b/lib/src/layer/tile_layer/tile_range.dart @@ -3,6 +3,7 @@ import 'dart:math' show Point; import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/bounds.dart'; import 'package:flutter_map/src/misc/extensions.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/map/controller/map_controller.dart b/lib/src/map/controller/map_controller.dart index 0fb0f60fe..30466c3ae 100644 --- a/lib/src/map/controller/map_controller.dart +++ b/lib/src/map/controller/map_controller.dart @@ -86,10 +86,6 @@ abstract class MapController { /// /// See [rotate] to rotate the map around the current map center. /// - /// One, and only one, of [point] or [offset] must be defined: - /// * [point]: allows rotation around a screen-based point (in normal logical - /// pixels), where `Offset(0,0)` is the top-left of the map widget, and the - /// bottom right is `Offset(mapWidth, mapHeight)`. /// * [offset]: allows rotation around a screen-based offset (in normal logical /// pixels) from the map's center. For example, `Offset(100, 100)` will mean /// the point is the 100px down & 100px right from the center. diff --git a/test/core/bounds_test.dart b/test/core/bounds_test.dart index 4808d1d96..587517aa9 100644 --- a/test/core/bounds_test.dart +++ b/test/core/bounds_test.dart @@ -1,6 +1,6 @@ import 'dart:math'; -import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map/src/misc/bounds.dart'; import 'package:flutter_test/flutter_test.dart'; import '../helpers/core.dart'; diff --git a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart index 83137bbce..bfc334e61 100644 --- a/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart +++ b/test/layer/tile_layer/tile_bounds/tile_bounds_at_zoom_test.dart @@ -4,6 +4,7 @@ import 'dart:ui'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; +import 'package:flutter_map/src/misc/bounds.dart'; import 'package:test/test.dart'; void main() { diff --git a/test/layer/tile_layer/tile_image_view_test.dart b/test/layer/tile_layer/tile_image_view_test.dart index 0c8859a4d..99801dfd6 100644 --- a/test/layer/tile_layer/tile_image_view_test.dart +++ b/test/layer/tile_layer/tile_image_view_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/src/scheduler/ticker.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_image_view.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_range.dart'; +import 'package:flutter_map/src/misc/bounds.dart'; import 'package:test/test.dart'; import '../../test_utils/test_tile_image.dart'; diff --git a/test/layer/tile_layer/tile_range_test.dart b/test/layer/tile_layer/tile_range_test.dart index 1a3162c8b..7d0983ebb 100644 --- a/test/layer/tile_layer/tile_range_test.dart +++ b/test/layer/tile_layer/tile_range_test.dart @@ -50,7 +50,7 @@ void main() { zoom: 0, tileDimension: 10, pixelBounds: Rect.fromPoints( - const Offset(0, 0), + Offset.zero, const Offset(0.1, 0.1), ), ); @@ -64,7 +64,7 @@ void main() { zoom: 0, tileDimension: 10, pixelBounds: Rect.fromPoints( - const Offset(0, 0), + Offset.zero, const Offset(9.99, 9.99), ), ); From b2ed4f2587572a2dc7d08d3929e43d39f609fe7b Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:21:36 -0600 Subject: [PATCH 40/51] fix test --- test/layer/tile_layer/tile_range_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/layer/tile_layer/tile_range_test.dart b/test/layer/tile_layer/tile_range_test.dart index 7d0983ebb..c14a86556 100644 --- a/test/layer/tile_layer/tile_range_test.dart +++ b/test/layer/tile_layer/tile_range_test.dart @@ -217,8 +217,8 @@ void main() { ), ); - expect(tileRange.min, const Offset(3, 3)); - expect(tileRange.max, const Offset(4, 4)); + expect(tileRange.min, const Point(3, 3)); + expect(tileRange.max, const Point(4, 4)); }); group('center', () { From 0a8134bfca2538e0345244638b55be2dee02fb47 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:25:56 -0600 Subject: [PATCH 41/51] fix bug introduced in commit b6d2d9557d3d957d674429224ce6733c242cb858 https://github.com/fleaflet/flutter_map/pull/1996/commits/b6d2d9557d3d957d674429224ce6733c242cb858 --- lib/src/map/camera/camera_fit.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 934f56521..974177080 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -151,8 +151,8 @@ class FitBounds extends CameraFit { final cosAngle = math.cos(camera.rotationRad).abs(); final sinAngle = math.sin(camera.rotationRad).abs(); boundsSize = Size( - (boundsSize.width * cosAngle) + (boundsSize.width * sinAngle), - (boundsSize.height * cosAngle) + (boundsSize.height * sinAngle), + (boundsSize.width * cosAngle) + (boundsSize.height * sinAngle), + (boundsSize.height * cosAngle) + (boundsSize.width * sinAngle), ); } From 5e177e47e01a3d72a6addcbcd8525f2f069d3beb Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 02:27:49 -0600 Subject: [PATCH 42/51] fix lint --- lib/src/misc/extensions.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/misc/extensions.dart b/lib/src/misc/extensions.dart index 1cdeb1f2a..b6284efe1 100644 --- a/lib/src/misc/extensions.dart +++ b/lib/src/misc/extensions.dart @@ -3,10 +3,10 @@ import 'dart:ui'; import 'package:meta/meta.dart'; -/// Extension methods for the math.[Point] class +/// Extension methods for the [math.Point] class @internal extension PointExtension on math.Point { - /// Create a new [Point] where the [x] and [y] values are divided by [factor]. + /// Create a new [math.Point] where the [x] and [y] values are divided by [factor]. math.Point operator /(num factor) { return math.Point(x / factor, y / factor); } @@ -18,7 +18,7 @@ extension PointExtension on math.Point { /// Extension methods for [Offset] @internal extension OffsetExtension on Offset { - /// Creates a [Point] representation of this offset. + /// Creates a [math.Point] representation of this offset. math.Point toPoint() => math.Point(dx, dy); /// Create a new [Offset] whose [dx] and [dy] values are rotated clockwise by From 72f2fd2941f059045e501d141d604bb97b17829f Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:08:20 -0600 Subject: [PATCH 43/51] rename method --- lib/src/map/camera/camera.dart | 6 +++--- lib/src/map/controller/map_controller_impl.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/map/camera/camera.dart b/lib/src/map/camera/camera.dart index fc90cfae1..be88a7628 100644 --- a/lib/src/map/camera/camera.dart +++ b/lib/src/map/camera/camera.dart @@ -290,7 +290,7 @@ class MapCamera { final mapCenter = crs.latLngToOffset(center, zoom); if (rotation != 0.0) { - point = rotateOffset(mapCenter, point, counterRotation: false); + point = rotatePoint(mapCenter, point, counterRotation: false); } return point - nonRotatedPixelOrigin; @@ -307,7 +307,7 @@ class MapCamera { var point = mapCenter - localPointCenterDistance; if (rotation != 0.0) { - point = rotateOffset(mapCenter, point); + point = rotatePoint(mapCenter, point); } return crs.offsetToLatLng(point, zoom); @@ -317,7 +317,7 @@ class MapCamera { /// it needs to be reversed (pointToLatLng), and sometimes we want to use /// the same rotation to create a new position (latLngToScreenpoint). /// counterRotation just makes allowances this for this. - Offset rotateOffset( + Offset rotatePoint( Offset mapCenter, Offset point, { bool counterRotation = true, diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 77a79ba31..6c9014d1f 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -152,7 +152,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> if (offset != Offset.zero) { final newPoint = camera.project(newCenter, newZoom); center = camera.unproject( - camera.rotateOffset( + camera.rotatePoint( newPoint, newPoint - offset, ), From 8603d71e40a289dafac09c7900b7084c930ba6db Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:10:58 -0600 Subject: [PATCH 44/51] fix some nits --- example/lib/pages/screen_point_to_latlng.dart | 2 +- .../layer_interactivity/internal_hit_detectable.dart | 6 +++--- lib/src/map/camera/camera.dart | 10 ++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/example/lib/pages/screen_point_to_latlng.dart b/example/lib/pages/screen_point_to_latlng.dart index b6e550afb..2ddb8f484 100644 --- a/example/lib/pages/screen_point_to_latlng.dart +++ b/example/lib/pages/screen_point_to_latlng.dart @@ -94,7 +94,7 @@ class PointToLatlngPage extends State { } void updatePoint(BuildContext context) => setState(() => latLng = - mapController.camera.offsetToLatLng(Offset(_getPointX(context), pointY))); + mapController.camera.screenOffsetToLatLng(Offset(_getPointX(context), pointY))); double _getPointX(BuildContext context) => MediaQuery.sizeOf(context).width / 2; diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index e2baca201..0d21a5206 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -40,7 +40,7 @@ abstract base class HitDetectablePainter= 0; i--) { final element = elements.elementAt(i); @@ -96,7 +96,7 @@ base mixin HitTestRequiresCameraOrigin Date: Thu, 5 Dec 2024 10:22:08 -0600 Subject: [PATCH 45/51] Update lib/src/geo/crs.dart Co-authored-by: Luka S --- lib/src/geo/crs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index 5672d6818..b0ace472a 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -378,7 +378,7 @@ abstract class Projection { /// required fields. const Projection(this.bounds); - /// Converts a [LatLng] to a coordinates and returns them as [Point] object. + /// Converts a [LatLng] to a coordinates and returns them as an [Offset]. @nonVirtual Offset project(LatLng latlng) { final (x, y) = projectXY(latlng); From 7f82a71faa400d19d214baf599933c924a5ea505 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:22:27 -0600 Subject: [PATCH 46/51] Update lib/src/geo/crs.dart Co-authored-by: Luka S --- lib/src/geo/crs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index b0ace472a..eea55949b 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -52,7 +52,7 @@ abstract class Crs { /// scaled map point. (double, double) latLngToXY(LatLng latlng, double scale); - /// Similar to [latLngToXY] but converts the XY coordinates to a [Point]. + /// Similar to [latLngToXY] but converts the XY coordinates to an [Offset]. Offset latLngToOffset(LatLng latlng, double zoom) { final (x, y) = latLngToXY(latlng, scale(zoom)); return Offset(x, y); From 209eab70dea95b89e977c3363524bdbdf51680c0 Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:23:00 -0600 Subject: [PATCH 47/51] Update lib/src/geo/crs.dart Co-authored-by: Luka S --- lib/src/geo/crs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index eea55949b..fc5a4d7f1 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -371,7 +371,7 @@ class Proj4Crs extends Crs { /// Inherit from this class if you want to create or implement your own CRS. @immutable abstract class Projection { - /// The [IntegerBounds] for the coordinates of this [Projection]. + /// The bounds for the coordinates of this [Projection]. final Rect? bounds; /// Base constructor for the abstract [Projection] class that sets the From bdc16516bff8b57ed90ddac0758cb94abf09ddfe Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:26:15 -0600 Subject: [PATCH 48/51] dart format --- example/lib/pages/screen_point_to_latlng.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/example/lib/pages/screen_point_to_latlng.dart b/example/lib/pages/screen_point_to_latlng.dart index 2ddb8f484..3910191d1 100644 --- a/example/lib/pages/screen_point_to_latlng.dart +++ b/example/lib/pages/screen_point_to_latlng.dart @@ -93,8 +93,9 @@ class PointToLatlngPage extends State { ); } - void updatePoint(BuildContext context) => setState(() => latLng = - mapController.camera.screenOffsetToLatLng(Offset(_getPointX(context), pointY))); + void updatePoint(BuildContext context) => + setState(() => latLng = mapController.camera + .screenOffsetToLatLng(Offset(_getPointX(context), pointY))); double _getPointX(BuildContext context) => MediaQuery.sizeOf(context).width / 2; From fc3e5273a3b3dcc37cc6cb4ae006635494ab435c Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:31:42 -0600 Subject: [PATCH 49/51] rename project method --- lib/src/gestures/map_interactive_viewer.dart | 20 ++++++------- lib/src/layer/marker_layer/marker_layer.dart | 2 +- .../overlay_image_layer/overlay_image.dart | 10 +++---- lib/src/layer/polygon_layer/painter.dart | 2 +- lib/src/layer/polyline_layer/painter.dart | 2 +- lib/src/layer/scalebar/scalebar.dart | 4 +-- .../internal_hit_detectable.dart | 2 +- .../tile_layer/tile_range_calculator.dart | 2 +- lib/src/map/camera/camera.dart | 26 ++++++++-------- lib/src/map/camera/camera_constraint.dart | 8 ++--- lib/src/map/camera/camera_fit.dart | 30 +++++++++---------- .../map/controller/map_controller_impl.dart | 18 +++++------ 12 files changed, 63 insertions(+), 63 deletions(-) diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index 5b877f175..70572c1a6 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -631,16 +631,16 @@ class MapInteractiveViewerState extends State ScaleUpdateDetails details, double zoomAfterPinchZoom, ) { - final oldCenterPt = _camera.project(_camera.center, zoomAfterPinchZoom); + final oldCenterPt = _camera.projectAtZoom(_camera.center, zoomAfterPinchZoom); final newFocalLatLong = _camera.offsetToCrs(_focalStartLocal, zoomAfterPinchZoom); - final newFocalPt = _camera.project(newFocalLatLong, zoomAfterPinchZoom); - final oldFocalPt = _camera.project(_focalStartLatLng, zoomAfterPinchZoom); + final newFocalPt = _camera.projectAtZoom(newFocalLatLong, zoomAfterPinchZoom); + final oldFocalPt = _camera.projectAtZoom(_focalStartLatLng, zoomAfterPinchZoom); final zoomDifference = oldFocalPt - newFocalPt; final moveDifference = _rotateOffset(_focalStartLocal - _lastFocalLocal); final newCenterPt = oldCenterPt + zoomDifference + moveDifference; - return _camera.unproject(newCenterPt, zoomAfterPinchZoom); + return _camera.unprojectAtZoom(newCenterPt, zoomAfterPinchZoom); } void _handleScalePinchRotate( @@ -654,15 +654,15 @@ class MapInteractiveViewerState extends State if (_rotationStarted) { final rotationDiff = currentRotation - _lastRotation; - final oldCenterPt = _camera.project(_camera.center); + final oldCenterPt = _camera.projectAtZoom(_camera.center); final rotationCenter = - _camera.project(_camera.offsetToCrs(_lastFocalLocal)); + _camera.projectAtZoom(_camera.offsetToCrs(_lastFocalLocal)); final vector = oldCenterPt - rotationCenter; final rotatedVector = vector.rotate(degrees2Radians * rotationDiff); final newCenter = rotationCenter + rotatedVector; widget.controller.moveAndRotateRaw( - _camera.unproject(newCenter), + _camera.unprojectAtZoom(newCenter), _camera.zoom, _camera.rotation + rotationDiff, offset: Offset.zero, @@ -882,11 +882,11 @@ class MapInteractiveViewerState extends State _startListeningForAnimationInterruptions(); } - final newCenterPoint = _camera.project(_mapCenterStart) + + final newCenterPoint = _camera.projectAtZoom(_mapCenterStart) + _flingAnimation.value.rotate(_camera.rotationRad); final LatLng newCenter; if (!_camera.crs.replicatesWorldLongitude) { - newCenter = _camera.unproject(newCenterPoint); + newCenter = _camera.unprojectAtZoom(newCenterPoint); } else { final Offset bestCenterPoint; final double worldSize = _camera.crs.scale(_camera.zoom); @@ -899,7 +899,7 @@ class MapInteractiveViewerState extends State } else { bestCenterPoint = newCenterPoint; } - newCenter = _camera.unproject(bestCenterPoint); + newCenter = _camera.unprojectAtZoom(bestCenterPoint); } widget.controller.moveRaw( diff --git a/lib/src/layer/marker_layer/marker_layer.dart b/lib/src/layer/marker_layer/marker_layer.dart index 1d74fc0f0..2d6c7c369 100644 --- a/lib/src/layer/marker_layer/marker_layer.dart +++ b/lib/src/layer/marker_layer/marker_layer.dart @@ -54,7 +54,7 @@ class MarkerLayer extends StatelessWidget { final bottom = m.height - top; // Perform projection - final pxPoint = map.project(m.point); + final pxPoint = map.projectAtZoom(m.point); // Cull if out of bounds if (!map.pixelBounds.overlaps( diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index bf980b209..56f3b516c 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -83,8 +83,8 @@ class OverlayImage extends BaseOverlayImage { // northWest is not necessarily upperLeft depending on projection final bounds = Rect.fromPoints( - camera.project(this.bounds.northWest) - camera.pixelOrigin, - camera.project(this.bounds.southEast) - camera.pixelOrigin, + camera.projectAtZoom(this.bounds.northWest) - camera.pixelOrigin, + camera.projectAtZoom(this.bounds.southEast) - camera.pixelOrigin, ); return Positioned( @@ -135,10 +135,10 @@ class RotatedOverlayImage extends BaseOverlayImage { }) { final camera = MapCamera.of(context); - final pxTopLeft = camera.project(topLeftCorner) - camera.pixelOrigin; + final pxTopLeft = camera.projectAtZoom(topLeftCorner) - camera.pixelOrigin; final pxBottomRight = - camera.project(bottomRightCorner) - camera.pixelOrigin; - final pxBottomLeft = camera.project(bottomLeftCorner) - camera.pixelOrigin; + camera.projectAtZoom(bottomRightCorner) - camera.pixelOrigin; + final pxBottomLeft = camera.projectAtZoom(bottomLeftCorner) - camera.pixelOrigin; /// calculate pixel coordinate of top-right corner by calculating the /// vector from bottom-left to top-left and adding it to bottom-right diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart index e5e71f542..22cfc2f35 100644 --- a/lib/src/layer/polygon_layer/painter.dart +++ b/lib/src/layer/polygon_layer/painter.dart @@ -194,7 +194,7 @@ base class _PolygonPainter } final origin = - camera.project(camera.center) - camera.size.center(Offset.zero); + camera.projectAtZoom(camera.center) - camera.size.center(Offset.zero); // Main loop constructing batched fill and border paths from given polygons. for (int i = 0; i <= polygons.length - 1; i++) { diff --git a/lib/src/layer/polyline_layer/painter.dart b/lib/src/layer/polyline_layer/painter.dart index 3aaed5bda..44bf498b0 100644 --- a/lib/src/layer/polyline_layer/painter.dart +++ b/lib/src/layer/polyline_layer/painter.dart @@ -108,7 +108,7 @@ base class _PolylinePainter } final origin = - camera.project(camera.center) - camera.size.center(Offset.zero); + camera.projectAtZoom(camera.center) - camera.size.center(Offset.zero); for (final projectedPolyline in polylines) { final polyline = projectedPolyline.polyline; diff --git a/lib/src/layer/scalebar/scalebar.dart b/lib/src/layer/scalebar/scalebar.dart index 8ec22a5bc..477b6e146 100644 --- a/lib/src/layer/scalebar/scalebar.dart +++ b/lib/src/layer/scalebar/scalebar.dart @@ -69,7 +69,7 @@ class Scalebar extends StatelessWidget { // calculate the scalebar width in pixels final latLngCenter = camera.center; - final offsetCenter = camera.project(latLngCenter); + final offsetCenter = camera.projectAtZoom(latLngCenter); final absLat = latLngCenter.latitude.abs(); double index = camera.zoom - length.value; @@ -88,7 +88,7 @@ class Scalebar extends StatelessWidget { if (latLngOffset.longitude < latLngCenter.longitude) { latLngOffset = dst.offset(latLngCenter, metricDst.toDouble(), 270); } - final offsetDistance = camera.project(latLngOffset); + final offsetDistance = camera.projectAtZoom(latLngOffset); final label = metricDst < 1000 ? '$metricDst m' diff --git a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart index 0d21a5206..b59135d7a 100644 --- a/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart +++ b/lib/src/layer/shared/layer_interactivity/internal_hit_detectable.dart @@ -106,7 +106,7 @@ base mixin HitTestRequiresCameraOrigin _bounds ??= LatLngBounds( - unproject(pixelBounds.bottomLeft, zoom), - unproject(pixelBounds.topRight, zoom), + unprojectAtZoom(pixelBounds.bottomLeft, zoom), + unprojectAtZoom(pixelBounds.topRight, zoom), ); /// The size of bounding box of this camera taking in to account its @@ -76,7 +76,7 @@ class MapCamera { /// camera. This will not equal the offset of the top-left visible pixel when /// the map is rotated. Offset get pixelOrigin => - _pixelOrigin ??= project(center, zoom) - size.center(Offset.zero); + _pixelOrigin ??= projectAtZoom(center, zoom) - size.center(Offset.zero); /// The camera of the closest [FlutterMap] ancestor. If this is called from a /// context with no [FlutterMap] ancestor null, is returned. @@ -231,12 +231,12 @@ class MapCamera { /// Calculates point value for the given [latlng] using this camera's /// [crs] and [zoom] (or the provided [zoom]). - Offset project(LatLng latlng, [double? zoom]) => + Offset projectAtZoom(LatLng latlng, [double? zoom]) => crs.latLngToOffset(latlng, zoom ?? this.zoom); /// Calculates the [LatLng] for the given [point] using this camera's /// [crs] and [zoom] (or the provided [zoom]). - LatLng unproject(Offset point, [double? zoom]) => + LatLng unprojectAtZoom(Offset point, [double? zoom]) => crs.offsetToLatLng(point, zoom ?? this.zoom); /// Calculates the scale for a zoom from [fromZoom] to [toZoom] using this @@ -252,12 +252,12 @@ class MapCamera { crs.getProjectedBounds(zoom ?? this.zoom); /// Calculates the [Offset] from the [pos] to this camera's [pixelOrigin]. - Offset getOffsetFromOrigin(LatLng pos) => project(pos) - pixelOrigin; + Offset getOffsetFromOrigin(LatLng pos) => projectAtZoom(pos) - pixelOrigin; /// Calculates the pixel origin of this [MapCamera] at the given /// [center]/[zoom]. Offset getNewPixelOrigin(LatLng center, [double? zoom]) { - return (project(center, zoom) - size.center(Offset.zero)).round(); + return (projectAtZoom(center, zoom) - size.center(Offset.zero)).round(); } /// Calculates the pixel bounds of this [MapCamera]. This value is cached. @@ -271,7 +271,7 @@ class MapCamera { final scale = getZoomScale(this.zoom, zoom); cameraSize = size / (scale * 2); } - final pixelCenter = project(center, zoom).floor(); + final pixelCenter = projectAtZoom(center, zoom).floor(); return Rect.fromCenter( center: pixelCenter, @@ -283,7 +283,7 @@ class MapCamera { /// outside of FlutterMap layer space. Eg using a Positioned Widget. Offset latLngToScreenOffset(LatLng latLng) { final nonRotatedPixelOrigin = - project(center, zoom) - nonRotatedSize.center(Offset.zero); + projectAtZoom(center, zoom) - nonRotatedSize.center(Offset.zero); var point = crs.latLngToOffset(latLng, zoom); @@ -342,12 +342,12 @@ class MapCamera { /// zoom level. If [zoom] is not provided the current zoom level of the /// [MapCamera] gets used. LatLng offsetToCrs(Offset offset, [double? zoom]) { - final focalStartPt = project(center, zoom ?? this.zoom); + final focalStartPt = projectAtZoom(center, zoom ?? this.zoom); final point = (offset - nonRotatedSize.center(Offset.zero)).rotate(rotationRad); final newCenterPt = focalStartPt + point; - return unproject(newCenterPt, zoom ?? this.zoom); + return unprojectAtZoom(newCenterPt, zoom ?? this.zoom); } /// Calculate the center point which would keep the same point of the map @@ -359,8 +359,8 @@ class MapCamera { // Match new center coordinate to mouse cursor position final scale = getZoomScale(zoom, this.zoom); final newOffset = offset * (1.0 - 1.0 / scale); - final mapCenter = project(center); - final newCenter = unproject(mapCenter + newOffset); + final mapCenter = projectAtZoom(center); + final newCenter = unprojectAtZoom(mapCenter + newOffset); return newCenter; } diff --git a/lib/src/map/camera/camera_constraint.dart b/lib/src/map/camera/camera_constraint.dart index 5283cf4ff..06a4f3cf8 100644 --- a/lib/src/map/camera/camera_constraint.dart +++ b/lib/src/map/camera/camera_constraint.dart @@ -110,8 +110,8 @@ class ContainCamera extends CameraConstraint { final testZoom = camera.zoom; final testCenter = camera.center; - final nePixel = camera.project(bounds.northEast, testZoom); - final swPixel = camera.project(bounds.southWest, testZoom); + final nePixel = camera.projectAtZoom(bounds.northEast, testZoom); + final swPixel = camera.projectAtZoom(bounds.southWest, testZoom); final halfSize = camera.size / 2; @@ -126,7 +126,7 @@ class ContainCamera extends CameraConstraint { // stay within [latLngBounds]. if (leftOkCenter > rightOkCenter || topOkCenter > botOkCenter) return null; - final centerPix = camera.project(testCenter, testZoom); + final centerPix = camera.projectAtZoom(testCenter, testZoom); final newCenterPix = Offset( centerPix.dx.clamp(leftOkCenter, rightOkCenter), centerPix.dy.clamp(topOkCenter, botOkCenter), @@ -135,7 +135,7 @@ class ContainCamera extends CameraConstraint { if (newCenterPix == centerPix) return camera; return camera.withPosition( - center: camera.unproject(newCenterPix, testZoom), + center: camera.unprojectAtZoom(newCenterPix, testZoom), ); } diff --git a/lib/src/map/camera/camera_fit.dart b/lib/src/map/camera/camera_fit.dart index 974177080..939c6351f 100644 --- a/lib/src/map/camera/camera_fit.dart +++ b/lib/src/map/camera/camera_fit.dart @@ -111,8 +111,8 @@ class FitBounds extends CameraFit { if (maxZoom != null) newZoom = math.min(maxZoom!, newZoom); final paddingOffset = (paddingBR - paddingTL) / 2; - final swPoint = camera.project(bounds.southWest, newZoom); - final nePoint = camera.project(bounds.northEast, newZoom); + final swPoint = camera.projectAtZoom(bounds.southWest, newZoom); + final nePoint = camera.projectAtZoom(bounds.northEast, newZoom); final Offset projectedCenter; if (camera.rotation != 0.0) { @@ -126,7 +126,7 @@ class FitBounds extends CameraFit { projectedCenter = (swPoint + nePoint) / 2 + paddingOffset; } - final center = camera.unproject(projectedCenter, newZoom); + final center = camera.unprojectAtZoom(projectedCenter, newZoom); return camera.withPosition( center: center, zoom: newZoom, @@ -144,8 +144,8 @@ class FitBounds extends CameraFit { size = Size(math.max(0, size.width), math.max(0, size.height)); var boundsSize = Rect.fromPoints( - camera.project(se, camera.zoom), - camera.project(nw, camera.zoom), + camera.projectAtZoom(se, camera.zoom), + camera.projectAtZoom(nw, camera.zoom), ).size; if (camera.rotation != 0.0) { final cosAngle = math.cos(camera.rotationRad).abs(); @@ -226,8 +226,8 @@ class FitInsideBounds extends CameraFit { final cameraSize = camera.nonRotatedSize - paddingTotalXY as Size; final projectedBoundsSize = Rect.fromPoints( - camera.project(bounds.southEast, camera.zoom), - camera.project(bounds.northWest, camera.zoom), + camera.projectAtZoom(bounds.southEast, camera.zoom), + camera.projectAtZoom(bounds.northWest, camera.zoom), ).size; final scale = _rectInRotRectScale( @@ -272,20 +272,20 @@ class FitInsideBounds extends CameraFit { required Offset paddingOffset, }) { if (camera.rotation == 0.0) { - final swPoint = camera.project(bounds.southWest, newZoom); - final nePoint = camera.project(bounds.northEast, newZoom); + final swPoint = camera.projectAtZoom(bounds.southWest, newZoom); + final nePoint = camera.projectAtZoom(bounds.northEast, newZoom); final projectedCenter = (swPoint + nePoint) / 2 + paddingOffset; - final newCenter = camera.unproject(projectedCenter, newZoom); + final newCenter = camera.unprojectAtZoom(projectedCenter, newZoom); return newCenter; } // Handle rotation - final projectedCenter = camera.project(bounds.center, newZoom); + final projectedCenter = camera.projectAtZoom(bounds.center, newZoom); final rotatedCenter = projectedCenter.rotate(-camera.rotationRad); final adjustedCenter = rotatedCenter + paddingOffset; final derotatedAdjustedCenter = adjustedCenter.rotate(camera.rotationRad); - final newCenter = camera.unproject(derotatedAdjustedCenter, newZoom); + final newCenter = camera.unprojectAtZoom(derotatedAdjustedCenter, newZoom); return newCenter; } @@ -435,7 +435,7 @@ class FitCoordinates extends CameraFit { if (maxZoom != null) newZoom = math.min(maxZoom!, newZoom); final projectedPoints = - coordinates.map((coord) => camera.project(coord, newZoom)); + coordinates.map((coord) => camera.projectAtZoom(coord, newZoom)); final rotatedBounds = RectExtension.containing(projectedPoints .map((point) => point.rotate(-camera.rotationRad)) @@ -448,7 +448,7 @@ class FitCoordinates extends CameraFit { // Undo the rotation final unrotatedNewCenter = rotatedNewCenter.rotate(camera.rotationRad); - final newCenter = camera.unproject(unrotatedNewCenter, newZoom); + final newCenter = camera.unprojectAtZoom(unrotatedNewCenter, newZoom); return camera.withPosition( center: newCenter, @@ -465,7 +465,7 @@ class FitCoordinates extends CameraFit { size = Size(math.max(0, size.width), math.max(0, size.height)); final projectedPoints = [ - for (final coord in coordinates) camera.project(coord) + for (final coord in coordinates) camera.projectAtZoom(coord) ]; final rotatedBounds = RectExtension.containing(projectedPoints diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index 6c9014d1f..f9acb983a 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -150,8 +150,8 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> // Algorithm thanks to https://github.com/tlserver/flutter_map_location_marker LatLng center = newCenter; if (offset != Offset.zero) { - final newPoint = camera.project(newCenter, newZoom); - center = camera.unproject( + final newPoint = camera.projectAtZoom(newCenter, newZoom); + center = camera.unprojectAtZoom( camera.rotatePoint( newPoint, newPoint - offset, @@ -245,13 +245,13 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> final rotationDiff = degree - camera.rotation; final rotationCenter = - (camera.project(camera.center) + offset!).rotate(camera.rotationRad); + (camera.projectAtZoom(camera.center) + offset!).rotate(camera.rotationRad); return ( moveSuccess: moveRaw( - camera.unproject( + camera.unprojectAtZoom( rotationCenter + - (camera.project(camera.center) - rotationCenter) + (camera.projectAtZoom(camera.center) - rotationCenter) .rotate(degrees2Radians * rotationDiff), ), camera.zoom, @@ -373,10 +373,10 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> /// To be called when an ongoing drag movement updates. void dragUpdated(MapEventSource source, Offset offset) { - final oldCenterPt = camera.project(camera.center); + final oldCenterPt = camera.projectAtZoom(camera.center); final newCenterPt = oldCenterPt + offset; - final newCenter = camera.unproject(newCenterPt); + final newCenter = camera.unprojectAtZoom(newCenterPt); moveRaw( newCenter, @@ -646,7 +646,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> _animationHasGesture = hasGesture; _animationOffset = offset; - _flingMapCenterStartPoint = camera.project(camera.center); + _flingMapCenterStartPoint = camera.projectAtZoom(camera.center); final distance = (Offset.zero & camera.nonRotatedSize).shortestSide; @@ -715,7 +715,7 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> final newCenterPoint = _flingMapCenterStartPoint + _flingAnimation!.value.rotate(camera.rotationRad); moveRaw( - camera.unproject(newCenterPoint), + camera.unprojectAtZoom(newCenterPoint), camera.zoom, hasGesture: _animationHasGesture, source: MapEventSource.flingAnimationController, From 2d9a42db290b7e9bfb1a313ea2d1df727bfc9c6f Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:40:25 -0600 Subject: [PATCH 50/51] dart format . --- lib/src/gestures/map_interactive_viewer.dart | 9 ++++++--- lib/src/layer/overlay_image_layer/overlay_image.dart | 3 ++- lib/src/map/controller/map_controller_impl.dart | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/src/gestures/map_interactive_viewer.dart b/lib/src/gestures/map_interactive_viewer.dart index 70572c1a6..46da7b911 100644 --- a/lib/src/gestures/map_interactive_viewer.dart +++ b/lib/src/gestures/map_interactive_viewer.dart @@ -631,11 +631,14 @@ class MapInteractiveViewerState extends State ScaleUpdateDetails details, double zoomAfterPinchZoom, ) { - final oldCenterPt = _camera.projectAtZoom(_camera.center, zoomAfterPinchZoom); + final oldCenterPt = + _camera.projectAtZoom(_camera.center, zoomAfterPinchZoom); final newFocalLatLong = _camera.offsetToCrs(_focalStartLocal, zoomAfterPinchZoom); - final newFocalPt = _camera.projectAtZoom(newFocalLatLong, zoomAfterPinchZoom); - final oldFocalPt = _camera.projectAtZoom(_focalStartLatLng, zoomAfterPinchZoom); + final newFocalPt = + _camera.projectAtZoom(newFocalLatLong, zoomAfterPinchZoom); + final oldFocalPt = + _camera.projectAtZoom(_focalStartLatLng, zoomAfterPinchZoom); final zoomDifference = oldFocalPt - newFocalPt; final moveDifference = _rotateOffset(_focalStartLocal - _lastFocalLocal); diff --git a/lib/src/layer/overlay_image_layer/overlay_image.dart b/lib/src/layer/overlay_image_layer/overlay_image.dart index 56f3b516c..703e7550b 100644 --- a/lib/src/layer/overlay_image_layer/overlay_image.dart +++ b/lib/src/layer/overlay_image_layer/overlay_image.dart @@ -138,7 +138,8 @@ class RotatedOverlayImage extends BaseOverlayImage { final pxTopLeft = camera.projectAtZoom(topLeftCorner) - camera.pixelOrigin; final pxBottomRight = camera.projectAtZoom(bottomRightCorner) - camera.pixelOrigin; - final pxBottomLeft = camera.projectAtZoom(bottomLeftCorner) - camera.pixelOrigin; + final pxBottomLeft = + camera.projectAtZoom(bottomLeftCorner) - camera.pixelOrigin; /// calculate pixel coordinate of top-right corner by calculating the /// vector from bottom-left to top-left and adding it to bottom-right diff --git a/lib/src/map/controller/map_controller_impl.dart b/lib/src/map/controller/map_controller_impl.dart index f9acb983a..b0b8ad951 100644 --- a/lib/src/map/controller/map_controller_impl.dart +++ b/lib/src/map/controller/map_controller_impl.dart @@ -244,8 +244,8 @@ class MapControllerImpl extends ValueNotifier<_MapControllerState> } final rotationDiff = degree - camera.rotation; - final rotationCenter = - (camera.projectAtZoom(camera.center) + offset!).rotate(camera.rotationRad); + final rotationCenter = (camera.projectAtZoom(camera.center) + offset!) + .rotate(camera.rotationRad); return ( moveSuccess: moveRaw( From fa244a77d9b02ae519edc2dba46dbfe140f240dc Mon Sep 17 00:00:00 2001 From: mootw Date: Thu, 5 Dec 2024 10:43:33 -0600 Subject: [PATCH 51/51] fix unused import --- lib/src/geo/crs.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/geo/crs.dart b/lib/src/geo/crs.dart index fc5a4d7f1..914131730 100644 --- a/lib/src/geo/crs.dart +++ b/lib/src/geo/crs.dart @@ -2,7 +2,6 @@ import 'dart:math' as math hide Point; import 'dart:math' show Point; import 'dart:ui'; -import 'package:flutter_map/src/misc/bounds.dart'; import 'package:flutter_map/src/misc/extensions.dart'; import 'package:latlong2/latlong.dart'; import 'package:meta/meta.dart';