Skip to content

Commit

Permalink
perf!: remove unnecessary rounding and surrounding features, and prod…
Browse files Browse the repository at this point in the history
…uce less garbage (fleaflet#1714)
  • Loading branch information
ignatz committed Nov 5, 2023
1 parent 0758979 commit 0dc3fa9
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 116 deletions.
53 changes: 23 additions & 30 deletions lib/src/geo/crs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,8 @@ abstract class Crs {
/// Converts a point on the sphere surface (with a certain zoom) in a
/// map point.
Point<double> latLngToPoint(LatLng latlng, double zoom) {
try {
final projectedPoint = projection.project(latlng);
final scale = this.scale(zoom);
return transformation.transform(projectedPoint, scale);
} catch (_) {
return const Point(0, 0);
}
final projectedPoint = projection.project(latlng);
return transformation.transform(projectedPoint, scale(zoom));
}

/// Converts a map point to the sphere coordinate (at a certain zoom).
Expand Down Expand Up @@ -114,7 +109,7 @@ class Epsg3857 extends Earth {
@override
final Transformation transformation;

static const num _scale = 0.5 / (math.pi * SphericalMercator.r);
static const double _scale = 0.5 / (math.pi * SphericalMercator.r);

const Epsg3857()
: projection = const SphericalMercator(),
Expand Down Expand Up @@ -183,7 +178,7 @@ class Proj4Crs extends Crs {
required String code,
required proj4.Projection proj4Projection,
Transformation? transformation,
List<Point>? origins,
List<Point<double>>? origins,
Bounds<double>? bounds,
List<double>? scales,
List<double>? resolutions,
Expand Down Expand Up @@ -230,15 +225,11 @@ class Proj4Crs extends Crs {
/// map point.
@override
Point<double> latLngToPoint(LatLng latlng, double zoom) {
try {
final projectedPoint = projection.project(latlng);
final scale = this.scale(zoom);
final transformation = _getTransformationByZoom(zoom);

return transformation.transform(projectedPoint, scale);
} catch (_) {
return const Point(0, 0);
}
final projectedPoint = projection.project(latlng);
final scale = this.scale(zoom);
final transformation = _getTransformationByZoom(zoom);

return transformation.transform(projectedPoint, scale);
}

/// Converts a map point to the sphere coordinate (at a certain zoom).
Expand Down Expand Up @@ -313,14 +304,15 @@ class Proj4Crs extends Crs {

/// returns Transformation object based on zoom
Transformation _getTransformationByZoom(double zoom) {
if (null == _transformations) {
final transformations = _transformations;
if (transformations == null || transformations.isEmpty) {
return transformation;
}

final iZoom = zoom.round();
final lastIdx = _transformations!.length - 1;
final lastIdx = transformations.length - 1;

return _transformations![iZoom > lastIdx ? lastIdx : iZoom];
return transformations[iZoom > lastIdx ? lastIdx : iZoom];
}
}

Expand Down Expand Up @@ -369,7 +361,7 @@ class _LonLat extends Projection {
@override
LatLng unproject(Point point) {
return LatLng(
inclusiveLat(point.y as double), inclusiveLng(point.x as double));
inclusiveLat(point.y.toDouble()), inclusiveLng(point.x.toDouble()));
}
}

Expand All @@ -391,12 +383,13 @@ class SphericalMercator extends Projection {
@override
Point<double> project(LatLng latlng) {
const d = math.pi / 180;
const max = maxLatitude;
final lat = math.max(math.min(max, latlng.latitude), -max);
final lat = latlng.latitude.clamp(-maxLatitude, maxLatitude);
final sin = math.sin(lat * d);

return Point(
r * latlng.longitude * d, r * math.log((1 + sin) / (1 - sin)) / 2);
r * d * latlng.longitude,
r / 2 * math.log((1 + sin) / (1 - sin)),
);
}

@override
Expand Down Expand Up @@ -434,18 +427,18 @@ class _Proj4Projection extends Projection {
@override
LatLng unproject(Point point) {
final point2 = proj4Projection.transform(
epsg4326, proj4.Point(x: point.x as double, y: point.y as double));
epsg4326, proj4.Point(x: point.x.toDouble(), y: point.y.toDouble()));

return LatLng(inclusiveLat(point2.y), inclusiveLng(point2.x));
}
}

@immutable
class Transformation {
final num a;
final num b;
final num c;
final num d;
final double a;
final double b;
final double c;
final double d;

const Transformation(this.a, this.b, this.c, this.d);

Expand Down
3 changes: 1 addition & 2 deletions lib/src/layer/marker_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_map/src/layer/general/mobile_layer_transformer.dart';
import 'package:flutter_map/src/map/camera/camera.dart';
import 'package:flutter_map/src/misc/bounds.dart';
import 'package:flutter_map/src/misc/point_extensions.dart';
import 'package:latlong2/latlong.dart';

/// A container for a [child] widget located at a geographic coordinate [point]
Expand Down Expand Up @@ -126,7 +125,7 @@ class MarkerLayer extends StatelessWidget {
)) continue;

// Apply map camera to marker position
final pos = pxPoint.subtract(map.pixelOrigin);
final pos = pxPoint - map.pixelOrigin;

yield Positioned(
key: m.key,
Expand Down
14 changes: 6 additions & 8 deletions lib/src/layer/overlay_image_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class OverlayImage extends BaseOverlayImage {
}) {
// northWest is not necessarily upperLeft depending on projection
final bounds = Bounds<double>(
camera.project(this.bounds.northWest).subtract(camera.pixelOrigin),
camera.project(this.bounds.southEast).subtract(camera.pixelOrigin),
camera.project(this.bounds.northWest) - camera.pixelOrigin,
camera.project(this.bounds.southEast) - camera.pixelOrigin,
);

return Positioned(
Expand Down Expand Up @@ -111,12 +111,10 @@ class RotatedOverlayImage extends BaseOverlayImage {
required Image child,
required MapCamera camera,
}) {
final pxTopLeft =
camera.project(topLeftCorner).subtract(camera.pixelOrigin);
final pxTopLeft = camera.project(topLeftCorner) - camera.pixelOrigin;
final pxBottomRight =
camera.project(bottomRightCorner).subtract(camera.pixelOrigin);
final pxBottomLeft =
camera.project(bottomLeftCorner).subtract(camera.pixelOrigin);
camera.project(bottomRightCorner) - camera.pixelOrigin;
final pxBottomLeft = camera.project(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
Expand All @@ -129,7 +127,7 @@ class RotatedOverlayImage extends BaseOverlayImage {

final vectorX = (pxTopRight - pxTopLeft) / bounds.size.x;
final vectorY = (pxBottomLeft - pxTopLeft) / bounds.size.y;
final offset = pxTopLeft.subtract(bounds.topLeft);
final offset = pxTopLeft - bounds.topLeft;

final a = vectorX.x;
final b = vectorX.y;
Expand Down
32 changes: 20 additions & 12 deletions lib/src/layer/polygon_layer/polygon_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter_map/src/geo/latlng_bounds.dart';
import 'package:flutter_map/src/layer/general/mobile_layer_transformer.dart';
import 'package:flutter_map/src/layer/polygon_layer/label.dart';
import 'package:flutter_map/src/map/camera/camera.dart';
import 'package:flutter_map/src/misc/point_extensions.dart';
import 'package:latlong2/latlong.dart' hide Path; // conflict with Path from UI

enum PolygonLabelPlacement {
Expand Down Expand Up @@ -160,20 +161,24 @@ class PolygonPainter extends CustomPainter {

int? _hash;

({Offset min, Offset max}) getBounds(Polygon polygon) {
({Offset min, Offset max}) getBounds(Offset origin, Polygon polygon) {
final bbox = polygon.boundingBox;
return (
min: map.getOffsetFromOrigin(bbox.southWest),
max: map.getOffsetFromOrigin(bbox.northEast),
min: getOffset(origin, bbox.southWest),
max: getOffset(origin, bbox.northEast),
);
}

List<Offset> getOffsets(List<LatLng> points) {
Offset getOffset(Offset origin, LatLng point) {
// Critically create as little garbage as possible. This is called on every frame.
final projected = map.project(point);
return Offset(projected.x - origin.dx, projected.y - origin.dy);
}

List<Offset> getOffsets(Offset origin, List<LatLng> points) {
return List.generate(
points.length,
(index) {
return map.getOffsetFromOrigin(points[index]);
},
(index) => getOffset(origin, points[index]),
growable: false,
);
}
Expand Down Expand Up @@ -213,12 +218,14 @@ class PolygonPainter extends CustomPainter {
lastHash = null;
}

final origin = (map.project(map.center) - map.size / 2).toOffset();

// Main loop constructing batched fill and border paths from given polygons.
for (final polygon in polygons) {
if (polygon.points.isEmpty) {
continue;
}
final offsets = getOffsets(polygon.points);
final offsets = getOffsets(origin, polygon.points);

// The hash is based on the polygons visual properties. If the hash from
// the current and the previous polygon no longer match, we need to flush
Expand Down Expand Up @@ -248,7 +255,7 @@ class PolygonPainter extends CustomPainter {

final holeOffsetsList = List<List<Offset>>.generate(
holePointsList.length,
(i) => getOffsets(holePointsList[i]),
(i) => getOffsets(origin, holePointsList[i]),
growable: false,
);

Expand All @@ -274,7 +281,7 @@ class PolygonPainter extends CustomPainter {
final painter = buildLabelTextPainter(
mapSize: map.size,
placementPoint: map.getOffsetFromOrigin(polygon.labelPosition),
bounds: getBounds(polygon),
bounds: getBounds(origin, polygon),
textPainter: polygon.textPainter!,
rotationRad: map.rotationRad,
rotate: polygon.rotateLabel,
Expand All @@ -301,8 +308,9 @@ class PolygonPainter extends CustomPainter {
if (textPainter != null) {
final painter = buildLabelTextPainter(
mapSize: map.size,
placementPoint: map.getOffsetFromOrigin(polygon.labelPosition),
bounds: getBounds(polygon),
placementPoint:
map.project(polygon.labelPosition).toOffset() - origin,
bounds: getBounds(origin, polygon),
textPainter: textPainter,
rotationRad: map.rotationRad,
rotate: polygon.rotateLabel,
Expand Down
23 changes: 16 additions & 7 deletions lib/src/layer/polyline_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_map/src/geo/latlng_bounds.dart';
import 'package:flutter_map/src/layer/general/mobile_layer_transformer.dart';
import 'package:flutter_map/src/map/camera/camera.dart';
import 'package:flutter_map/src/misc/point_extensions.dart';
import 'package:latlong2/latlong.dart';

class Polyline {
Expand Down Expand Up @@ -97,13 +98,19 @@ class PolylinePainter extends CustomPainter {

int? _hash;

List<Offset> getOffsets(List<LatLng> points) {
return List.generate(points.length, (index) {
return getOffset(points[index]);
}, growable: false);
Offset getOffset(Offset origin, LatLng point) {
// Critically create as little garbage as possible. This is called on every frame.
final projected = map.project(point);
return Offset(projected.x - origin.dx, projected.y - origin.dy);
}

Offset getOffset(LatLng point) => map.getOffsetFromOrigin(point);
List<Offset> getOffsets(Offset origin, List<LatLng> points) {
return List.generate(
points.length,
(index) => getOffset(origin, points[index]),
growable: false,
);
}

@override
void paint(Canvas canvas, Size size) {
Expand Down Expand Up @@ -144,8 +151,10 @@ class PolylinePainter extends CustomPainter {
paint = Paint();
}

final origin = map.project(map.center).toOffset() - map.size.toOffset() / 2;

for (final polyline in polylines) {
final offsets = getOffsets(polyline.points);
final offsets = getOffsets(origin, polyline.points);
if (offsets.isEmpty) {
continue;
}
Expand All @@ -167,7 +176,7 @@ class PolylinePainter extends CustomPainter {
polyline.strokeWidth,
180,
);
final delta = firstOffset - getOffset(r);
final delta = firstOffset - getOffset(origin, r);

strokeWidth = delta.distance;
} else {
Expand Down
5 changes: 2 additions & 3 deletions lib/src/layer/tile_layer/tile_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import 'package:flutter_map/src/layer/tile_layer/tile_update_transformer.dart';
import 'package:flutter_map/src/map/camera/camera.dart';
import 'package:flutter_map/src/map/controller/map_controller.dart';
import 'package:flutter_map/src/misc/bounds.dart';
import 'package:flutter_map/src/misc/point_extensions.dart';
import 'package:http/retry.dart';
import 'package:logger/logger.dart';

Expand Down Expand Up @@ -533,8 +532,8 @@ class _TileLayerState extends State<TileLayer> with TickerProviderStateMixin {
);

final currentPixelOrigin = Point<double>(
map.pixelOrigin.x.toDouble(),
map.pixelOrigin.y.toDouble(),
map.pixelOrigin.x,
map.pixelOrigin.y,
);

_tileScaleCalculator.clearCacheUnlessZoomMatches(map.zoom);
Expand Down
5 changes: 2 additions & 3 deletions lib/src/layer/tile_layer/wms_tile_layer_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ class WMSTileLayerOptions {
}

String getUrl(TileCoordinates coords, int tileSize, bool retinaMode) {
final tileSizePoint = Point(tileSize, tileSize);
final nwPoint = coords.scaleBy(tileSizePoint);
final sePoint = nwPoint + tileSizePoint;
final nwPoint = coords * tileSize;
final sePoint = nwPoint + Point<int>(tileSize, tileSize);
final nwCoords = crs.pointToLatLng(nwPoint, coords.z.toDouble());
final seCoords = crs.pointToLatLng(sePoint, coords.z.toDouble());
final nw = crs.projection.project(nwCoords);
Expand Down
Loading

0 comments on commit 0dc3fa9

Please sign in to comment.