MIF_E31231027/smart_cycling/lib/utils/navigation_helper.dart

68 lines
2.3 KiB
Dart

import 'dart:math' as math;
import 'package:latlong2/latlong.dart';
class NavigationHelper {
static const Distance _distanceCalculator = Distance();
/// Menghitung jarak antara dua titik dalam meter
static double calculateDistance(LatLng p1, LatLng p2) {
return _distanceCalculator.as(LengthUnit.Meter, p1, p2);
}
/// Menghitung bearing (sudut) antara dua titik (0-360 derajat)
static double calculateBearing(LatLng p1, LatLng p2) {
double lat1 = p1.latitude * math.pi / 180;
double lon1 = p1.longitude * math.pi / 180;
double lat2 = p2.latitude * math.pi / 180;
double lon2 = p2.longitude * math.pi / 180;
double dLon = lon2 - lon1;
double y = math.sin(dLon) * math.cos(lat2);
double x = math.cos(lat1) * math.sin(lat2) -
math.sin(lat1) * math.cos(lat2) * math.cos(dLon);
double radians = math.atan2(y, x);
return (radians * 180 / math.pi + 360) % 360;
}
/// Menghitung jarak terdekat dari titik ke sebuah segmen garis (Cross Track Distance)
static double getDistanceToSegment(LatLng p, LatLng s1, LatLng s2) {
final double l2 = math.pow(calculateDistance(s1, s2), 2).toDouble();
if (l2 == 0) return calculateDistance(p, s1);
// Proyeksi titik ke garis
double t = ((p.latitude - s1.latitude) * (s2.latitude - s1.latitude) +
(p.longitude - s1.longitude) * (s2.longitude - s1.longitude)) /
(math.pow(s2.latitude - s1.latitude, 2) +
math.pow(s2.longitude - s1.longitude, 2));
t = math.max(0, math.min(1, t));
LatLng projection = LatLng(
s1.latitude + t * (s2.latitude - s1.latitude),
s1.longitude + t * (s2.longitude - s1.longitude),
);
return calculateDistance(p, projection);
}
/// Menentukan apakah ada belokan tajam di titik tertentu pada rute
static String? detectManeuver(List<LatLng> points, int index) {
if (index <= 0 || index >= points.length - 1) return null;
double bearing1 = calculateBearing(points[index - 1], points[index]);
double bearing2 = calculateBearing(points[index], points[index + 1]);
double diff = (bearing2 - bearing1 + 360) % 360;
if (diff > 180) diff -= 360;
if (diff > 25 && diff < 160) {
return "Belok Kanan";
} else if (diff < -25 && diff > -160) {
return "Belok Kiri";
}
return null;
}
}