snapToRoute static method
Implementation
static Map<String, dynamic> snapToRoute(
LatLng gpsPos,
List<LatLng> geometry, {
double? userBearing,
}) {
if (geometry.isEmpty) return {};
if (geometry.length == 1) {
return {
'snappedPos': geometry.first,
'segmentIndex': 0,
'distanceTraveled': 0.0,
'offRouteDistance': haversineDistance(gpsPos, geometry.first),
};
}
double minDistance = double.infinity;
int bestIndex = 0;
LatLng bestSnapped = geometry.first;
for (int i = 0; i < geometry.length - 1; i++) {
final p1 = geometry[i];
final p2 = geometry[i + 1];
final snapped = nearestPointOnSegment(gpsPos, p1, p2);
double dist = haversineDistance(gpsPos, snapped);
if (userBearing != null && haversineDistance(p1, p2) > 1.0) {
final roadBearing = computeBearing(p1, p2);
final diffRad = (userBearing - roadBearing) * math.pi / 180.0;
final dotProduct = math.cos(diffRad);
final penalty = (1.0 - dotProduct) * 40.0; // Up to 80m penalty
dist += penalty;
}
if (dist < minDistance) {
minDistance = dist;
bestIndex = i;
bestSnapped = snapped;
}
}
double totalDist = 0.0;
for (int i = 0; i < bestIndex; i++) {
totalDist += haversineDistance(geometry[i], geometry[i + 1]);
}
totalDist += haversineDistance(geometry[bestIndex], bestSnapped);
final trueOffRouteDist = haversineDistance(gpsPos, bestSnapped);
return {
'snappedPos': bestSnapped,
'segmentIndex': bestIndex,
'distanceTraveled': totalDist,
'offRouteDistance': trueOffRouteDist,
};
}