Skip to content

Commit

Permalink
simplify before culling
Browse files Browse the repository at this point in the history
  • Loading branch information
mootw committed Jan 5, 2024
1 parent 145cbcc commit 5adede5
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 29 deletions.
25 changes: 24 additions & 1 deletion example/lib/pages/polyline.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_example/misc/tile_providers.dart';
Expand Down Expand Up @@ -102,6 +104,20 @@ class _PolylinePageState extends State<PolylinePage> {
),
};

final randomWalk = <LatLng>[const LatLng(44.861294, 13.845086)];

@override
void initState() {
super.initState();
final random = Random(1234);
for (int i = 1; i < 100000; i++) {
final lat = (random.nextDouble() - 0.5) * 0.001;
final lon = (random.nextDouble() - 0.6) * 0.001;
randomWalk.add(LatLng(
randomWalk[i - 1].latitude + lat, randomWalk[i - 1].longitude + lon));
}
}

List<Polyline>? hoverLines;

@override
Expand Down Expand Up @@ -158,7 +174,14 @@ class _PolylinePageState extends State<PolylinePage> {
),
child: PolylineLayer(
hitNotifier: hitNotifier,
polylines: polylines.keys.followedBy(hoverLines ?? []).toList(),
polylines: [
Polyline(
points: randomWalk,
strokeWidth: 3,
color: Colors.deepOrange,
),
...polylines.keys.followedBy(hoverLines ?? []).toList()
],
),
),
),
Expand Down
76 changes: 48 additions & 28 deletions lib/src/layer/polyline_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class PolylineLayer extends StatelessWidget {
/// otherwise, points within the radial distance of the threshold value are merged. (Also called radial distance simplification)
/// radial distance is faster, but does not preserve the shape of the original line as well as Douglas Peucker
final bool simplificationHighQuality;

/// A notifier to notify when a hit is detected over a/multiple [Polyline]s
///
/// To listen for hits, wrap the layer in a standard hit detector widget, such
Expand Down Expand Up @@ -151,8 +152,32 @@ class PolylineLayer extends StatelessWidget {

final renderedLines = <Polyline>[];


final possiblySimplifiedPolylines = <Polyline>[];
if (simplificationTolerance != null) {
possiblySimplifiedPolylines.addAll(polylines.map((polyline) => Polyline(
points: simplify(
polyline.points,
simplificationTolerance! /
math.pow(2, mapCamera.zoom.floorToDouble()),
highestQuality: simplificationHighQuality),
borderColor: polyline.borderColor,
borderStrokeWidth: polyline.borderStrokeWidth,
color: polyline.color,
colorsStop: polyline.colorsStop,
gradientColors: polyline.gradientColors,
isDotted: polyline.isDotted,
strokeCap: polyline.strokeCap,
strokeJoin: polyline.strokeJoin,
strokeWidth: polyline.strokeWidth,
useStrokeWidthInMeter: polyline.useStrokeWidthInMeter,
)));
} else {
possiblySimplifiedPolylines.addAll(polylines);
}

if (polylineCullingMargin == null) {
renderedLines.addAll(polylines);
renderedLines.addAll(possiblySimplifiedPolylines);
} else {
final bounds = mapCamera.visibleBounds;
final margin =
Expand All @@ -165,7 +190,7 @@ class PolylineLayer extends StatelessWidget {
LatLng(math.min(90, bounds.northEast.latitude + margin),
math.min(180, bounds.northEast.longitude + margin)));

for (final polyline in polylines) {
for (final polyline in possiblySimplifiedPolylines) {
// Gradiant poylines do not render identically and cannot be easily segmented
if (polyline.gradientColors != null) {
renderedLines.add(polyline);
Expand Down Expand Up @@ -242,18 +267,18 @@ class PolylineLayer extends StatelessWidget {
}

return MobileLayerTransformer(
child: CustomPaint(
painter: _PolylinePainter(
polylines: renderedLines,
simplificationHighQuality: simplificationHighQuality,
simplificationTolerance: simplificationTolerance,
camera: mapCamera,
hitNotifier: hitNotifier,
minimumHitbox: minimumHitbox,
),
size: Size(mapCamera.size.x, mapCamera.size.y),
isComplex: true,
));
child: CustomPaint(
painter: _PolylinePainter(
polylines: renderedLines,
simplificationHighQuality: simplificationHighQuality,
simplificationTolerance: simplificationTolerance,
camera: mapCamera,
hitNotifier: hitNotifier,
minimumHitbox: minimumHitbox,
),
size: Size(mapCamera.size.x, mapCamera.size.y),
isComplex: true,
));
}
}

Expand All @@ -273,23 +298,18 @@ class _PolylinePainter extends CustomPainter {
int get hash => _hash ??= Object.hashAll(polylines);
int? _hash;

_PolylinePainter({required this.polylines,
required this.camera, this.simplificationTolerance,
required this.simplificationHighQuality, required this.hitNotifier,
required this.minimumHitbox})
_PolylinePainter(
{required this.polylines,
required this.camera,
this.simplificationTolerance,
required this.simplificationHighQuality,
required this.hitNotifier,
required this.minimumHitbox})
: bounds = camera.visibleBounds;

List<Offset> getOffsets(Offset origin, List<LatLng> points) {
final List<LatLng> simplifiedPoints;
if (simplificationTolerance != null) {
simplifiedPoints = simplify(points,
simplificationTolerance! / math.pow(2, camera.zoom.floorToDouble()),
highestQuality: simplificationHighQuality);
} else {
simplifiedPoints = points;
}
return List.generate(simplifiedPoints.length, (index) {
return getOffset(origin, simplifiedPoints[index]);
return List.generate(points.length, (index) {
return getOffset(origin, points[index]);
}, growable: false);
}

Expand Down

0 comments on commit 5adede5

Please sign in to comment.