MobilApp/lib/core/geometry_measure.dart

106 lines
2.2 KiB
Dart

import 'dart:math';
import 'package:latlong2/latlong.dart';
class GeometryMeasure {
static final Distance _distance = const Distance();
static double lineLengthMeters(List<LatLng> points) {
if (points.length < 2) return 0.0;
double sum = 0.0;
for (var i = 1; i < points.length; i++) {
sum += _distance.as(
LengthUnit.Meter,
points[i - 1],
points[i],
);
}
return sum;
}
static double polygonAreaSquareMeters(List<LatLng> points) {
final polygon = _normalizedPolygon(points);
if (polygon.length < 3) return 0.0;
final origin = _centroid(polygon);
final projected =
polygon.map((p) => _projectToLocalMeters(p, origin)).toList();
double area = 0.0;
for (var i = 0; i < projected.length; i++) {
final j = (i + 1) % projected.length;
area += projected[i].x * projected[j].y - projected[j].x * projected[i].y;
}
return area.abs() / 2.0;
}
static List<LatLng> _normalizedPolygon(List<LatLng> source) {
final points = List<LatLng>.from(source);
if (points.length < 2) return points;
final first = points.first;
final last = points.last;
final closeDistance = _distance.as(
LengthUnit.Meter,
first,
last,
);
if (closeDistance < 0.01) {
points.removeLast();
}
return points;
}
static LatLng _centroid(List<LatLng> points) {
double lat = 0.0;
double lon = 0.0;
for (final p in points) {
lat += p.latitude;
lon += p.longitude;
}
return LatLng(
lat / points.length,
lon / points.length,
);
}
static _Point2D _projectToLocalMeters(
LatLng point,
LatLng origin,
) {
const earthRadius = 6378137.0;
final latRad = point.latitude * pi / 180.0;
final lonRad = point.longitude * pi / 180.0;
final originLatRad = origin.latitude * pi / 180.0;
final originLonRad = origin.longitude * pi / 180.0;
final x = earthRadius * (lonRad - originLonRad) * cos(originLatRad);
final y = earthRadius * (latRad - originLatRad);
return _Point2D(x, y);
}
}
class _Point2D {
final double x;
final double y;
const _Point2D(this.x, this.y);
}