Cómo calculamos distancia y tiempo a pie sin usar Google Maps
Cómo estimamos distancia y tiempo caminando en una ciudad caminable como La Plata usando la fórmula de Haversine, evitando Google Maps, reduciendo costos y manteniendo nuestra app basada en ubicación rápida, simple y confiable.
Un enfoque pragmático para una ciudad caminable como La Plata
Cuando estás desarrollando una app basada en la ubicación, Google Maps suele sentirse como la solución por defecto. Distancias, tiempos de viaje, rutas — parece la opción más segura.
Ese también fue nuestro primer impulso.
Pero mientras construíamos Entre Diagonales, una app de turismo gamificado enfocada en la ciudad de La Plata, Argentina, descubrimos algo importante:
La forma en que una ciudad está diseñada importa más de lo que uno cree al momento de elegir cómo calcular distancias.
Por qué La Plata cambia el problema
La Plata no es una ciudad típica.
Fue diseñada desde cero a fines del siglo XIX con un plan urbano único:
- Un sistema de cuadrícula estricta
- Plazas grandes y distribuidas de forma uniforme
- Avenidas diagonales que atraviesan la ciudad
- Cuadras cortas y distancias predecibles
La mayoría de los recorridos turísticos en La Plata:
- Son altamente caminables
- Cubren distancias relativamente cortas
- Se mueven de plaza en plaza, de monumento en monumento
En este contexto, la precisión de ruteo a nivel de calle deja de ser necesaria.
Lo que realmente necesitábamos responder eran tres preguntas simples:
- ¿Qué tan lejos está la próxima parada?
- ¿Cuánto tiempo llevará llegar caminando?
- ¿El usuario está lo suficientemente cerca como para interactuar con este punto?
El verdadero problema que queríamos resolver
Dentro de la app mostramos constantemente información como:
- Distancia a la siguiente parada del recorrido
- Tiempo estimado caminando
- Validaciones por proximidad para desbloquear desafíos
Estos cálculos ocurren muchas veces por sesión, para cada usuario.
Usar Google Directions o la Distance Matrix API hubiera implicado:
- 💸 Llamadas pagas a la API
- 🚫 Límites de cuota
- ⏱️ Mayor latencia
- 🔗 Dependencia de un servicio externo
Para una ciudad compacta y caminable como La Plata, esto se sentía excesivo.
No todo necesita rutas reales
Google Maps brilla cuando necesitás:
- Navegación paso a paso
- Rutas con información de tráfico
- Trayectos largos o complejos
Pero si tu interfaz solo necesita decir:
“Estás a unos 350 metros — ~5 minutos caminando”
…existe un enfoque mucho más simple.
Ahí es donde entra Haversine.
Haversine: distancia sin APIs
La fórmula de Haversine calcula la distancia entre dos puntos de latitud y longitud, teniendo en cuenta la curvatura de la Tierra.
Para nuestro caso de uso, fue un encaje perfecto:
- ✅ Sin llamadas a APIs externas
- ✅ Se ejecuta completamente en el cliente
- ✅ Extremadamente rápida
- ✅ Costo cero
- ✅ Funciona offline
Acá una implementación simplificada en TypeScript:
type LatLng = { latitude: number; longitude: number };
const toRad = (value: number) => (value * Math.PI) / 180;
export const getDistanceInMeters = (a: LatLng, b: LatLng): number => {
const dLat = toRad(b.latitude - a.latitude);
const dLon = toRad(b.longitude - a.longitude);
const lat1 = toRad(a.latitude);
const lat2 = toRad(b.latitude);
const sinDLat = Math.sin(dLat / 2);
const sinDLon = Math.sin(dLon / 2);
const h =
sinDLat * sinDLat +
Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon;
const c = 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
const R = 6371000; // Radio de la Tierra en metros
return R * c;
};
Esto nos da la distancia en línea recta entre dos puntos.
En una ciudad como La Plata — donde las diagonales muchas veces acortan los caminos — esta aproximación resulta sorprendentemente precisa para distancias caminando.
De la distancia al tiempo caminando
La distancia sola no es tan útil para los usuarios.
El tiempo sí lo es.
Definimos una velocidad promedio de caminata razonable:
export const WALK_SPEED_KMH = 4.8;
export const WALK_SPEED_M_PER_MIN = (WALK_SPEED_KMH * 1000) / 60;
Luego calculamos el tiempo estimado caminando:
export const estimateWalkMinutes = (meters: number) =>
Math.ceil(meters / WALK_SPEED_M_PER_MIN);
Esto nos permite mostrar mensajes naturales y fáciles de entender como:
“450 m · ~6 min caminando”
Algo que se siente intuitivo y confiable para quienes recorren la ciudad a pie.
Dónde brilla este enfoque en Entre Diagonales
Esta lógica impulsa varias funcionalidades clave de la app:
- Tarjetas de “próxima parada” durante un recorrido
- Pantallas de progreso mostrando los puntos que siguen
- Reglas basadas en distancia para evitar trampas
- Ordenamiento inteligente de paradas en zonas compactas
Todo esto funciona sin una sola request a una API externa.
Los beneficios que obtuvimos de inmediato
Al evitar Google Maps para estos cálculos, ganamos:
- ⚡ Respuesta instantánea — sin demoras de red
- 💰 Costo cero por usuario — sin facturas de API
- 📴 Compatibilidad offline — funciona sin internet
- 🧩 Arquitectura más simple — menos complejidad
- 🧠 Reglas más fáciles de razonar basadas en distancia
¿Es perfectamente preciso? No — y está bien.
Haversine calcula distancia en línea recta, no el recorrido exacto por las calles.
En muchas ciudades, eso podría ser una limitación importante.
Pero en La Plata — con su trazado en cuadrícula, diagonales y distancias cortas — la diferencia es lo suficientemente pequeña como para ser irrelevante en:
- Estimaciones de distancia
- Feedback en la interfaz
- Mecánicas de juego
- Indicadores de progreso
Cuando necesitamos navegación precisa paso a paso, seguimos usando un servicio de mapas.
Simplemente no lo usamos para todo.
Reflexión final
Una de las mayores enseñanzas de esta decisión fue:
Las buenas decisiones técnicas dependen de la ciudad, el producto y la experiencia de usuario — no solo de las herramientas disponibles.
Para una ciudad caminable como La Plata, un enfoque matemático liviano resultó ser más eficiente, más barato y más fácil de mantener que un servicio completo de ruteo.
Si estás construyendo una app basada en ubicación para ciudades compactas y amigables para peatones, Haversine puede ser todo lo que necesites.
La mejor solución no siempre es la más compleja.