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 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; } }