52 lines
1.4 KiB
Text
52 lines
1.4 KiB
Text
import 'package:latlong2/latlong.dart';
|
|
|
|
class GpsSmoothing {
|
|
static List<LatLng> douglasPeucker(List<LatLng> points, double epsilon) {
|
|
if (points.length < 3) return points;
|
|
|
|
final first = points.first;
|
|
final last = points.last;
|
|
|
|
double maxDistance = 0;
|
|
int index = 0;
|
|
|
|
for (int i = 1; i < points.length - 1; i++) {
|
|
final d = _perpendicularDistance(points[i], first, last);
|
|
if (d > maxDistance) {
|
|
maxDistance = d;
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
if (maxDistance > epsilon) {
|
|
final left = douglasPeucker(points.sublist(0, index + 1), epsilon);
|
|
final right = douglasPeucker(points.sublist(index, points.length), epsilon);
|
|
|
|
return [...left, ...right.skip(1)];
|
|
} else {
|
|
return [first, last];
|
|
}
|
|
}
|
|
|
|
static double _perpendicularDistance(LatLng p, LatLng start, LatLng end) {
|
|
final x = p.longitude;
|
|
final y = p.latitude;
|
|
final x1 = start.longitude;
|
|
final y1 = start.latitude;
|
|
final x2 = end.longitude;
|
|
final y2 = end.latitude;
|
|
|
|
final dx = x2 - x1;
|
|
final dy = y2 - y1;
|
|
|
|
if (dx == 0 && dy == 0) {
|
|
return ((x - x1) * (x - x1) + (y - y1) * (y - y1)).abs();
|
|
}
|
|
|
|
final t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
|
|
final projX = x1 + t * dx;
|
|
final projY = y1 + t * dy;
|
|
|
|
return ((x - projX) * (x - projX) + (y - projY) * (y - projY)).abs();
|
|
}
|
|
}
|