findNearestRouteIndex method
Finds the route index whose polyline is closest to tapLocation.
Uses screen-space Web Mercator projection to measure distance in pure screen pixels (default 48.0px touch target radius). This ensures 100% tap accuracy across all zoom levels and platforms without DPI discrepancies.
Implementation
int findNearestRouteIndex(
LatLng tapLocation, {
double maxDistanceMeters = 35.0,
double? zoom,
double touchRadiusPixels = 56.0,
}) {
if (_currentRoutes.isEmpty) return -1;
final effectiveZoom = (zoom != null && zoom > 0)
? zoom
: (_controller.cameraPosition?.zoom ?? 12.0);
final tapPx = _latLngToMercatorPixels(tapLocation, effectiveZoom);
// Calculate minimum pixel distance from tap to each route
final routePixelDistances = List<double>.filled(
_currentRoutes.length,
double.infinity,
);
for (int i = 0; i < _currentRoutes.length; i++) {
final geom = _currentRoutes[i].geometry;
if (geom.length < 2) continue;
var prevPx = _latLngToMercatorPixels(geom[0], effectiveZoom);
for (int j = 1; j < geom.length; j++) {
final nextPx = _latLngToMercatorPixels(geom[j], effectiveZoom);
// Fast bounding box reject
final minX = math.min(prevPx.x, nextPx.x) - touchRadiusPixels;
final maxX = math.max(prevPx.x, nextPx.x) + touchRadiusPixels;
final minY = math.min(prevPx.y, nextPx.y) - touchRadiusPixels;
final maxY = math.max(prevPx.y, nextPx.y) + touchRadiusPixels;
if (tapPx.x >= minX &&
tapPx.x <= maxX &&
tapPx.y >= minY &&
tapPx.y <= maxY) {
final d = _pointToSegmentDistancePixels(tapPx, prevPx, nextPx);
if (d < routePixelDistances[i]) {
routePixelDistances[i] = d;
}
}
prevPx = nextPx;
}
}
// 1. Check for alternative routes within touch radius
int? bestAltIndex;
double bestAltDist = double.infinity;
for (int i = 0; i < _currentRoutes.length; i++) {
if (i != _selectedRouteIndex &&
routePixelDistances[i] <= touchRadiusPixels) {
if (routePixelDistances[i] < bestAltDist) {
bestAltDist = routePixelDistances[i];
bestAltIndex = i;
}
}
}
final selectedDist =
(_selectedRouteIndex >= 0 &&
_selectedRouteIndex < routePixelDistances.length)
? routePixelDistances[_selectedRouteIndex]
: double.infinity;
// 2. If ANY alternative route was hit within touch target, SWITCH TO IT!
// On touchscreens, when multiple routes run in close proximity (parallel roads/forks),
// the user's finger covers both lines. The user's explicit intent when tapping the route
// bundle in preview mode is to select the alternative route.
if (bestAltIndex != null) {
return bestAltIndex;
}
// 3. If only the selected route was hit:
if (selectedDist <= touchRadiusPixels) {
return _selectedRouteIndex;
}
return -1;
}