lecheminvert.tech/server/utils/estimate.ts

49 lines
1.7 KiB
TypeScript
Raw Normal View History

import { EMISSION_FACTORS } from '#shared/emissions'
import type { Coord } from '#shared/types'
const TRAIN_AVG_KMH = 90
/**
* Distance a vol d oiseau entre deux points geographiques en km.
* Formule de Haversine, rayon terrestre moyen 6371 km.
*/
function haversineKm(a: { lat: number, lon: number }, b: { lat: number, lon: number }): number {
const toRad = (d: number) => (d * Math.PI) / 180
const R = 6371
const dLat = toRad(b.lat - a.lat)
const dLon = toRad(b.lon - a.lon)
const s = Math.sin(dLat / 2) ** 2
+ Math.cos(toRad(a.lat)) * Math.cos(toRad(b.lat)) * Math.sin(dLon / 2) ** 2
return 2 * R * Math.asin(Math.sqrt(s))
}
/**
* Fabrique une estimation train quand Transitous ne couvre pas le trajet.
* Distance vol d oiseau x 1.2 pour approximer le detour ferroviaire,
* vitesse pratique moyenne 90 km/h (compromis TGV/TER), facteur ADEME train
* generique. C est un ordre de grandeur, pas un horaire.
*/
export function estimateTrainTrip(
from: { lat: number, lon: number },
to: { lat: number, lon: number },
) {
const straightKm = haversineKm(from, to)
// Facteur 1.2 : les voies ferrees suivent rarement une ligne droite.
const distanceKm = Math.round(straightKm * 1.2 * 10) / 10
const durationMin = Math.round((distanceKm / TRAIN_AVG_KMH) * 60)
const co2Grams = Math.round(distanceKm * EMISSION_FACTORS.train)
// Geometrie ligne droite [depart, arrivee] pour que la carte affiche
// quelque chose de coherent avec l estimation textuelle.
const geometry: Coord[] = [[from.lon, from.lat], [to.lon, to.lat]]
return {
mode: 'train' as const,
distanceKm,
durationMin,
co2Grams,
geometry,
estimated: true,
}
}