- andar equilibraod separado del calculo

- comienzo de penalizacoin en 200m
- centrado de origen
This commit is contained in:
2026-07-29 14:45:59 +02:00
parent 8a75c583ca
commit 6145fb635a
11 changed files with 404 additions and 101 deletions

View File

@@ -48,6 +48,7 @@ public partial class PlanificadorRutas : ComponentBase
// CONFIG // CONFIG
private const double FactorPenalizacionDistanciaPiePorDefecto = 1.35; private const double FactorPenalizacionDistanciaPiePorDefecto = 1.35;
private const double ParametroPenalizacionDistanciaPieMetrosPorDefecto = 200.0;
private const double CoeficienteEsfuerzoAlturaPorDefecto = 8.2; private const double CoeficienteEsfuerzoAlturaPorDefecto = 8.2;
private const double UmbralPendienteSubidaRutaPorDefecto = 2.0; private const double UmbralPendienteSubidaRutaPorDefecto = 2.0;
private const double UmbralPendienteBajadaRutaPorDefecto = 5.0; private const double UmbralPendienteBajadaRutaPorDefecto = 5.0;
@@ -56,12 +57,12 @@ public partial class PlanificadorRutas : ComponentBase
private double _velocidadPieKmH = 3.6; private double _velocidadPieKmH = 3.6;
private double _factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto; private double _factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto;
private double _parametroPenalizacionDistanciaPieMetros = 100.0; private double _parametroPenalizacionDistanciaPieMetros = ParametroPenalizacionDistanciaPieMetrosPorDefecto;
private double _coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto; private double _coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
private double _pesoTransbordoRankingMinutos = 4.0; private double _pesoTransbordoRankingMinutos = 4.0;
private double _factorEquilibradoAndarBus = 12.0; private double _factorEquilibradoAndarBus = 12.0;
private string _factorPenalizacionDistanciaPieTextoEdicion = "1.35"; private string _factorPenalizacionDistanciaPieTextoEdicion = "1.35";
private string _parametroPenalizacionDistanciaPieTextoEdicion = "100"; private string _parametroPenalizacionDistanciaPieTextoEdicion = "200";
private string _coeficienteEsfuerzoAlturaTextoEdicion = "8.20"; private string _coeficienteEsfuerzoAlturaTextoEdicion = "8.20";
private string _pesoTransbordoRankingTextoEdicion = "4,0"; private string _pesoTransbordoRankingTextoEdicion = "4,0";
private string _factorEquilibradoAndarBusTextoEdicion = "12"; private string _factorEquilibradoAndarBusTextoEdicion = "12";
@@ -461,21 +462,47 @@ public partial class PlanificadorRutas : ComponentBase
/// <summary> /// <summary>
/// Construye paradas for variante. /// Construye el payload JS de paradas de una variante.
/// </summary> /// </summary>
private static List<object> BuildStopsDesdeParadas(IEnumerable<Parada> paradas) private List<object> BuildStopsForVariante(InfoVariante v)
{ {
var paradasOrdenadas = paradas.ToList(); if (v?.CodigosParadas is null || v.CodigosParadas.Count == 0)
var stops = new List<object>(paradasOrdenadas.Count); return new List<object>();
for (var indice = 0; indice < paradasOrdenadas.Count; indice++)
return BuildStopsParaRangoVariante(v, 0, v.CodigosParadas.Count - 1);
}
/// <summary>
/// Construye el payload JS de paradas recorridas por un tramo concreto.
/// </summary>
private List<object> BuildStopsForTramoBus(TramoBus tramo)
{ {
var parada = paradasOrdenadas[indice]; if (tramo?.Variante?.CodigosParadas is null || tramo.Variante.CodigosParadas.Count == 0)
return new List<object>();
var ultimoIndice = tramo.Variante.CodigosParadas.Count - 1;
var inicio = Math.Clamp(Math.Min(tramo.IndiceInicio, tramo.IndiceFin), 0, ultimoIndice);
var fin = Math.Clamp(Math.Max(tramo.IndiceInicio, tramo.IndiceFin), 0, ultimoIndice);
return BuildStopsParaRangoVariante(tramo.Variante, inicio, fin);
}
private List<object> BuildStopsParaRangoVariante(InfoVariante variante, int inicio, int fin)
{
var stops = new List<object>();
var codigosVistos = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for (var indice = inicio; indice <= fin; indice++)
{
var codigo = variante.CodigosParadas[indice];
if (!codigosVistos.Add(codigo) || !_paradaByCode.TryGetValue(codigo, out var parada))
continue;
stops.Add(new stops.Add(new
{ {
lat = parada.Latitud, lat = parada.Latitud,
lon = parada.Longitud, lon = parada.Longitud,
code = parada.Codigo, code = parada.Codigo,
bearing = CalcularRumboParada(paradasOrdenadas, indice) bearing = CalcularRumboParada(variante, indice)
}); });
} }
@@ -483,21 +510,121 @@ public partial class PlanificadorRutas : ComponentBase
} }
/// <summary> /// <summary>
/// Calcula el sentido de marcha hacia la siguiente parada; en la terminal conserva el rumbo de llegada. /// Obtiene la tangente local de la geometria real al salir de la parada.
/// En la terminal usa la tangente de llegada del ultimo trayecto.
/// </summary> /// </summary>
private static double? CalcularRumboParada(IReadOnlyList<Parada> paradas, int indice) private double? CalcularRumboParada(InfoVariante variante, int indiceParada)
{ {
var actual = paradas[indice]; var idsTrayectos = variante.Variante?.IdsTrayectos;
for (var siguiente = indice + 1; siguiente < paradas.Count; siguiente++) if (idsTrayectos is not null)
{ {
var rumbo = CalcularRumboGrados(actual, paradas[siguiente]); if (indiceParada >= 0 &&
indiceParada < idsTrayectos.Count &&
RedBusServicio.Trayectos.TryGetValue(idsTrayectos[indiceParada], out var trayectoSalida))
{
var rumboSalida = CalcularRumboGeometriaTrayecto(trayectoSalida.Posiciones, desdeInicio: true);
if (rumboSalida is not null)
return rumboSalida;
}
var indiceTrayectoLlegada = indiceParada - 1;
if (indiceTrayectoLlegada >= 0 &&
indiceTrayectoLlegada < idsTrayectos.Count &&
RedBusServicio.Trayectos.TryGetValue(idsTrayectos[indiceTrayectoLlegada], out var trayectoLlegada))
{
var rumboLlegada = CalcularRumboGeometriaTrayecto(trayectoLlegada.Posiciones, desdeInicio: false);
if (rumboLlegada is not null)
return rumboLlegada;
}
}
return CalcularRumboParadaPorCoordenadas(variante, indiceParada);
}
private static double? CalcularRumboGeometriaTrayecto(
IReadOnlyList<double[]> posiciones,
bool desdeInicio)
{
var puntos = posiciones
.Where(punto =>
punto is { Length: >= 2 } &&
double.IsFinite(punto[0]) &&
double.IsFinite(punto[1]))
.ToList();
if (puntos.Count < 2)
return null;
const double distanciaMinimaRumboMetros = 3.0;
double? rumboCorto = null;
if (desdeInicio)
{
var origen = puntos[0];
for (var indice = 1; indice < puntos.Count; indice++)
{
var destino = puntos[indice];
var rumbo = CalcularRumboGrados(origen[0], origen[1], destino[0], destino[1]);
if (rumbo is null)
continue;
rumboCorto ??= rumbo;
if (CalcularDistanciaMetros(origen[0], origen[1], destino[0], destino[1]) >= distanciaMinimaRumboMetros)
return rumbo;
}
}
else
{
var destino = puntos[^1];
for (var indice = puntos.Count - 2; indice >= 0; indice--)
{
var origen = puntos[indice];
var rumbo = CalcularRumboGrados(origen[0], origen[1], destino[0], destino[1]);
if (rumbo is null)
continue;
rumboCorto ??= rumbo;
if (CalcularDistanciaMetros(origen[0], origen[1], destino[0], destino[1]) >= distanciaMinimaRumboMetros)
return rumbo;
}
}
return rumboCorto;
}
private double? CalcularRumboParadaPorCoordenadas(InfoVariante variante, int indice)
{
if (indice < 0 ||
indice >= variante.CodigosParadas.Count ||
!_paradaByCode.TryGetValue(variante.CodigosParadas[indice], out var actual))
{
return null;
}
for (var siguiente = indice + 1; siguiente < variante.CodigosParadas.Count; siguiente++)
{
if (!_paradaByCode.TryGetValue(variante.CodigosParadas[siguiente], out var paradaSiguiente))
continue;
var rumbo = CalcularRumboGrados(
actual.Latitud,
actual.Longitud,
paradaSiguiente.Latitud,
paradaSiguiente.Longitud);
if (rumbo is not null) if (rumbo is not null)
return rumbo; return rumbo;
} }
for (var anterior = indice - 1; anterior >= 0; anterior--) for (var anterior = indice - 1; anterior >= 0; anterior--)
{ {
var rumbo = CalcularRumboGrados(paradas[anterior], actual); if (!_paradaByCode.TryGetValue(variante.CodigosParadas[anterior], out var paradaAnterior))
continue;
var rumbo = CalcularRumboGrados(
paradaAnterior.Latitud,
paradaAnterior.Longitud,
actual.Latitud,
actual.Longitud);
if (rumbo is not null) if (rumbo is not null)
return rumbo; return rumbo;
} }
@@ -505,19 +632,23 @@ public partial class PlanificadorRutas : ComponentBase
return null; return null;
} }
private static double? CalcularRumboGrados(Parada origen, Parada destino) private static double? CalcularRumboGrados(
double latitudOrigenGrados,
double longitudOrigenGrados,
double latitudDestinoGrados,
double longitudDestinoGrados)
{ {
if (!double.IsFinite(origen.Latitud) || if (!double.IsFinite(latitudOrigenGrados) ||
!double.IsFinite(origen.Longitud) || !double.IsFinite(longitudOrigenGrados) ||
!double.IsFinite(destino.Latitud) || !double.IsFinite(latitudDestinoGrados) ||
!double.IsFinite(destino.Longitud)) !double.IsFinite(longitudDestinoGrados))
{ {
return null; return null;
} }
var latitudOrigen = origen.Latitud * Math.PI / 180.0; var latitudOrigen = latitudOrigenGrados * Math.PI / 180.0;
var latitudDestino = destino.Latitud * Math.PI / 180.0; var latitudDestino = latitudDestinoGrados * Math.PI / 180.0;
var diferenciaLongitud = (destino.Longitud - origen.Longitud) * Math.PI / 180.0; var diferenciaLongitud = (longitudDestinoGrados - longitudOrigenGrados) * Math.PI / 180.0;
var y = Math.Sin(diferenciaLongitud) * Math.Cos(latitudDestino); var y = Math.Sin(diferenciaLongitud) * Math.Cos(latitudDestino);
var x = Math.Cos(latitudOrigen) * Math.Sin(latitudDestino) - var x = Math.Cos(latitudOrigen) * Math.Sin(latitudDestino) -
Math.Sin(latitudOrigen) * Math.Cos(latitudDestino) * Math.Cos(diferenciaLongitud); Math.Sin(latitudOrigen) * Math.Cos(latitudDestino) * Math.Cos(diferenciaLongitud);
@@ -529,33 +660,6 @@ public partial class PlanificadorRutas : ComponentBase
return (rumbo + 360.0) % 360.0; return (rumbo + 360.0) % 360.0;
} }
/// <summary>
/// Construye las paradas visibles recorridas por una variante completa.
/// </summary>
private List<Parada> BuildParadasForVariante(InfoVariante v)
{
var stops = new List<Parada>(v?.CodigosParadas?.Count ?? 0);
if (v?.CodigosParadas is null) return stops;
var codigosVistos = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var cod in v.CodigosParadas)
{
if (!codigosVistos.Add(cod))
continue;
if (_paradaByCode.TryGetValue(cod, out var parada))
stops.Add(parada);
}
return stops;
}
/// <summary>
/// Construye el payload JS de paradas de una variante.
/// </summary>
private List<object> BuildStopsForVariante(InfoVariante v)
=> BuildStopsDesdeParadas(BuildParadasForVariante(v));
/// <summary> /// <summary>
/// Construye las paradas visibles recorridas por un tramo concreto de bus. /// Construye las paradas visibles recorridas por un tramo concreto de bus.
/// </summary> /// </summary>
@@ -1061,14 +1165,16 @@ public partial class PlanificadorRutas : ComponentBase
/// <summary> /// <summary>
/// Ajusta rutas js. /// Ajusta rutas js.
/// </summary> /// </summary>
private async Task FitRoutesJsAsync(IReadOnlyList<double[]>? coordenadas = null) private async Task FitRoutesJsAsync(
IReadOnlyList<double[]>? coordenadas = null,
double[]? centroPreferido = null)
{ {
try try
{ {
if (coordenadas is null) if (coordenadas is null && centroPreferido is null)
await JS.InvokeVoidAsync("rt.fitRoutes"); await JS.InvokeVoidAsync("rt.fitRoutes");
else else
await JS.InvokeVoidAsync("rt.fitRoutes", coordenadas); await JS.InvokeVoidAsync("rt.fitRoutes", coordenadas, centroPreferido);
} }
catch { } catch { }
} }
@@ -1267,11 +1373,19 @@ public partial class PlanificadorRutas : ComponentBase
var parametros = CrearParametrosPenalizacionActuales(); var parametros = CrearParametrosPenalizacionActuales();
var distanciaCorregidaBase = alternativa.EsSoloAPie IEnumerable<double> distanciasPiePorTramo = alternativa.EsSoloAPie
? UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaSoloAPie, parametros) ? new[] { alternativa.DistanciaSoloAPie }
: UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieInicioAprox, parametros) : alternativa.DistanciasPiePorTramoAprox.Count > 0
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieTransbordosAprox, parametros) ? alternativa.DistanciasPiePorTramoAprox
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieFinAprox, parametros); : new[]
{
alternativa.DistanciaPieInicioAprox,
alternativa.DistanciaPieTransbordosAprox,
alternativa.DistanciaPieFinAprox
};
var distanciaCorregidaBase = UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaTotalMetros(
distanciasPiePorTramo,
parametros);
var esfuerzoExtra = double.IsFinite(alternativa.EsfuerzoExtraPendienteMetros) var esfuerzoExtra = double.IsFinite(alternativa.EsfuerzoExtraPendienteMetros)
? Math.Max(0, alternativa.EsfuerzoExtraPendienteMetros) ? Math.Max(0, alternativa.EsfuerzoExtraPendienteMetros)
: 0; : 0;
@@ -1391,12 +1505,19 @@ public partial class PlanificadorRutas : ComponentBase
alternativa.DistanciaSoloAPie); alternativa.DistanciaSoloAPie);
} }
var distanciasPiePorTramo = alternativa.DistanciasPiePorTramoAprox.Count > 0
? alternativa.DistanciasPiePorTramoAprox.ToArray()
: new[]
{
alternativa.DistanciaPieInicioAprox,
alternativa.DistanciaPieTransbordosAprox,
alternativa.DistanciaPieFinAprox
};
return UtilidadesTransitoDbus.CalcularCosteConPenalizacionPieSegundos( return UtilidadesTransitoDbus.CalcularCosteConPenalizacionPieSegundos(
duracionReal, duracionReal,
parametros, parametros,
alternativa.DistanciaPieInicioAprox, distanciasPiePorTramo);
alternativa.DistanciaPieTransbordosAprox,
alternativa.DistanciaPieFinAprox);
} }
/// <summary> /// <summary>

View File

@@ -432,16 +432,29 @@ public partial class PlanificadorRutas
if (!await AsegurarHistorialLocalCargadoAsync()) if (!await AsegurarHistorialLocalCargadoAsync())
return; return;
var item = _historialLocal.FirstOrDefault(x => x.Id == id); var indiceEliminado = _historialLocal.FindIndex(x => x.Id == id);
if (item is null) if (indiceEliminado < 0)
return; return;
_historialLocal.Remove(item); var estabaSeleccionado = _historialLocalSeleccionadoId == id;
_historialLocal.RemoveAt(indiceEliminado);
if (_historialLocalSeleccionadoId == id)
_historialLocalSeleccionadoId = string.Empty;
await PersistirHistorialLocalAsync(); await PersistirHistorialLocalAsync();
if (estabaSeleccionado)
{
if (_historialLocal.Count == 0)
{
_historialLocalSeleccionadoId = string.Empty;
}
else
{
var siguiente = _historialLocal[Math.Min(indiceEliminado, _historialLocal.Count - 1)];
await AplicarRegistroHistorialAsync(siguiente);
SeleccionarHistorialLocal(siguiente.Id);
}
}
MostrarMensajeHistorial("Combinacion eliminada del historial personal."); MostrarMensajeHistorial("Combinacion eliminada del historial personal.");
} }
@@ -473,6 +486,8 @@ public partial class PlanificadorRutas
{ {
try try
{ {
var indiceEliminado = _historialCompartido.FindIndex(x => x.Id == id);
var estabaSeleccionado = _historialCompartidoSeleccionadoId == id;
var ok = await HistorialRutasCompartidoService.EliminarAsync(id); var ok = await HistorialRutasCompartidoService.EliminarAsync(id);
if (!ok) if (!ok)
{ {
@@ -481,9 +496,22 @@ public partial class PlanificadorRutas
} }
await CargarHistorialCompartidoAsync(); await CargarHistorialCompartidoAsync();
_historialCompartido.RemoveAll(x => x.Id == id);
if (_historialCompartidoSeleccionadoId == id) if (estabaSeleccionado)
{
if (_historialCompartido.Count == 0)
{
_historialCompartidoSeleccionadoId = string.Empty; _historialCompartidoSeleccionadoId = string.Empty;
}
else
{
var indiceSiguiente = Math.Clamp(indiceEliminado, 0, _historialCompartido.Count - 1);
var siguiente = _historialCompartido[indiceSiguiente];
await AplicarRegistroHistorialAsync(siguiente);
SeleccionarHistorialCompartido(siguiente.Id);
}
}
MostrarMensajeHistorial("Combinacion eliminada del historial compartido."); MostrarMensajeHistorial("Combinacion eliminada del historial compartido.");
} }

View File

@@ -1204,7 +1204,7 @@ public partial class PlanificadorRutas : ComponentBase
private bool _elevPopupMinimizado = false; private bool _elevPopupMinimizado = false;
private const string _versionApp = "(v-20260727a)"; private const string _versionApp = "(v-20260728a)";
private double? _paradaElevG; private double? _paradaElevG;

View File

@@ -192,7 +192,10 @@ public partial class PlanificadorRutas
? FactorPenalizacionDistanciaPiePorDefecto ? FactorPenalizacionDistanciaPiePorDefecto
: factor; : factor;
if (config.ParametroPenalizacionDistanciaPieMetros is { } parametro && double.IsFinite(parametro)) if (config.ParametroPenalizacionDistanciaPieMetros is { } parametro && double.IsFinite(parametro))
_parametroPenalizacionDistanciaPieMetros = parametro; _parametroPenalizacionDistanciaPieMetros =
Math.Abs(parametro - 100.0) < 0.0001
? ParametroPenalizacionDistanciaPieMetrosPorDefecto
: parametro;
if (config.CoeficienteEsfuerzoAltura is { } coeficienteAltura && double.IsFinite(coeficienteAltura)) if (config.CoeficienteEsfuerzoAltura is { } coeficienteAltura && double.IsFinite(coeficienteAltura))
_coeficienteEsfuerzoAltura = _coeficienteEsfuerzoAltura =
Math.Abs(coeficienteAltura - 1.6) < 0.0001 || Math.Abs(coeficienteAltura - 1.6) < 0.0001 ||
@@ -315,7 +318,7 @@ public partial class PlanificadorRutas
_maxTransbordosPermitidos = 3; _maxTransbordosPermitidos = 3;
_factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto; _factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto;
_parametroPenalizacionDistanciaPieMetros = 100.0; _parametroPenalizacionDistanciaPieMetros = ParametroPenalizacionDistanciaPieMetrosPorDefecto;
_coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto; _coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
_pesoTransbordoRankingMinutos = 4.0; _pesoTransbordoRankingMinutos = 4.0;
_factorEquilibradoAndarBus = 12.0; _factorEquilibradoAndarBus = 12.0;
@@ -365,7 +368,7 @@ public partial class PlanificadorRutas
_maxTransbordosPermitidos = 3; _maxTransbordosPermitidos = 3;
_factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto; _factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto;
_parametroPenalizacionDistanciaPieMetros = 100.0; _parametroPenalizacionDistanciaPieMetros = ParametroPenalizacionDistanciaPieMetrosPorDefecto;
_coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto; _coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
_pesoTransbordoRankingMinutos = 4.0; _pesoTransbordoRankingMinutos = 4.0;
_factorEquilibradoAndarBus = 12.0; _factorEquilibradoAndarBus = 12.0;

View File

@@ -463,7 +463,7 @@ public partial class PlanificadorRutas : ComponentBase
await CerrarPopupsAsync(); await CerrarPopupsAsync();
ThrowIfPintadoObsoleto(versionPintado); ThrowIfPintadoObsoleto(versionPintado);
await FitRoutesJsAsync(); await FitRoutesJsAsync(centroPreferido: _coordenadasOrigen);
ThrowIfPintadoObsoleto(versionPintado); ThrowIfPintadoObsoleto(versionPintado);
StateHasChanged(); StateHasChanged();
} }
@@ -505,7 +505,7 @@ public partial class PlanificadorRutas : ComponentBase
if (paradasTramo.Count == 0) if (paradasTramo.Count == 0)
continue; continue;
var stops = BuildStopsDesdeParadas(paradasTramo); var stops = BuildStopsForTramoBus(tramo);
var id = $"route_stops_{indice}_{tramo.Variante.Linea.Codigo}_{tramo.Variante.CodigoItinerario}_{NormalizarSentidoCodigo(tramo.Variante.Sentido?.Codigo)}"; var id = $"route_stops_{indice}_{tramo.Variante.Linea.Codigo}_{tramo.Variante.CodigoItinerario}_{NormalizarSentidoCodigo(tramo.Variante.Sentido?.Codigo)}";
var color = ColorCssDesdeVariante(tramo.Variante); var color = ColorCssDesdeVariante(tramo.Variante);

View File

@@ -20,6 +20,7 @@ public sealed class AlternativaRuta
public double DistanciaPieFinAprox { get; set; } public double DistanciaPieFinAprox { get; set; }
public double DistanciaPieTotalAprox => public double DistanciaPieTotalAprox =>
DistanciaPieInicioAprox + DistanciaPieTransbordosAprox + DistanciaPieFinAprox; DistanciaPieInicioAprox + DistanciaPieTransbordosAprox + DistanciaPieFinAprox;
public List<double> DistanciasPiePorTramoAprox { get; set; } = new();
public List<double[,]> LineasPieCalculoElevacion { get; set; } = new(); public List<double[,]> LineasPieCalculoElevacion { get; set; } = new();
public double EsfuerzoExtraPendienteMetros { get; set; } public double EsfuerzoExtraPendienteMetros { get; set; }

View File

@@ -24,7 +24,7 @@ public sealed class ParametrosPlanificadorRuta
public int MargenTransbordoSegundos { get; set; } = 120; public int MargenTransbordoSegundos { get; set; } = 120;
public int SegundosPorParadaBus { get; set; } = 30; public int SegundosPorParadaBus { get; set; } = 30;
public double FactorPenalizacionDistanciaPie { get; set; } = 1.35; public double FactorPenalizacionDistanciaPie { get; set; } = 1.35;
public double ParametroPenalizacionDistanciaPieMetros { get; set; } = 100.0; public double ParametroPenalizacionDistanciaPieMetros { get; set; } = 200.0;
public double PesoTransbordoRankingMinutos { get; set; } = 4.0; public double PesoTransbordoRankingMinutos { get; set; } = 4.0;
public double FactorEquilibradoAndarBus { get; set; } = 12.0; public double FactorEquilibradoAndarBus { get; set; } = 12.0;

View File

@@ -714,13 +714,16 @@ public sealed class BuscadorRutasTemporalesDbus
}; };
var duracionEstimada = Math.Max(0, (estadoDestino.Llegada - instanteSalida).TotalSeconds) + destino.TiempoAPie; var duracionEstimada = Math.Max(0, (estadoDestino.Llegada - instanteSalida).TotalSeconds) + destino.TiempoAPie;
var distanciasPieTransbordos = ObtenerDistanciasPieTransbordos(estadoDestino);
var distanciasPiePorTramo = ConstruirDistanciasPiePorTramo(
origen.DistanciaAPie,
distanciasPieTransbordos,
destino.DistanciaAPie);
var puntuacionCoste = UtilidadesTransitoDbus.CalcularCosteConPenalizacionesRankingSegundos( var puntuacionCoste = UtilidadesTransitoDbus.CalcularCosteConPenalizacionesRankingSegundos(
duracionEstimada, duracionEstimada,
parametros, parametros,
numeroTransbordos, numeroTransbordos,
origen.DistanciaAPie, distanciasPiePorTramo.ToArray());
estadoDestino.DistanciaPieTransbordos,
destino.DistanciaAPie);
var resultado = new ResultadoBusquedaRutaBusDbus var resultado = new ResultadoBusquedaRutaBusDbus
{ {
@@ -731,6 +734,7 @@ public sealed class BuscadorRutasTemporalesDbus
DistanciaPieFin = destino.DistanciaAPie, DistanciaPieFin = destino.DistanciaAPie,
TiempoPieFin = destino.TiempoAPie, TiempoPieFin = destino.TiempoAPie,
DistanciaPieTransbordos = estadoDestino.DistanciaPieTransbordos, DistanciaPieTransbordos = estadoDestino.DistanciaPieTransbordos,
DistanciasPieTransbordosPorTramo = distanciasPieTransbordos,
TiempoEsperaInicialSegundos = estadoDestino.TiempoEsperaInicialSegundos, TiempoEsperaInicialSegundos = estadoDestino.TiempoEsperaInicialSegundos,
TiempoEsperaTransbordosSegundos = estadoDestino.TiempoEsperaTransbordosSegundos, TiempoEsperaTransbordosSegundos = estadoDestino.TiempoEsperaTransbordosSegundos,
DuracionEstimadaSegundos = duracionEstimada, DuracionEstimadaSegundos = duracionEstimada,
@@ -816,10 +820,12 @@ public sealed class BuscadorRutasTemporalesDbus
ParametrosPlanificadorRuta parametros) ParametrosPlanificadorRuta parametros)
{ {
var distanciaBus = Math.Max(0, resultado.RutaBus.DistanciaTotalBus); var distanciaBus = Math.Max(0, resultado.RutaBus.DistanciaTotalBus);
var distanciaAndando = var distanciaAndando = UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaTotalMetros(
UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieInicio, parametros) ConstruirDistanciasPiePorTramo(
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieTransbordos, parametros) resultado.DistanciaPieInicio,
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieFin, parametros); resultado.DistanciasPieTransbordosPorTramo,
resultado.DistanciaPieFin),
parametros);
var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus) var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus)
? Math.Max(0, parametros.FactorEquilibradoAndarBus) ? Math.Max(0, parametros.FactorEquilibradoAndarBus)
: 12.0; : 12.0;
@@ -830,6 +836,45 @@ public sealed class BuscadorRutasTemporalesDbus
: double.PositiveInfinity; : double.PositiveInfinity;
} }
private static List<double> ObtenerDistanciasPieTransbordos(EstadoBusquedaParadaDbus estadoDestino)
{
var distancias = new List<double>();
var cursor = estadoDestino;
while (cursor is not null)
{
if (cursor.Movimiento is MovimientoPieTransbordoDbus movimiento &&
double.IsFinite(movimiento.DistanciaMetros) &&
movimiento.DistanciaMetros > 0)
{
distancias.Add(movimiento.DistanciaMetros);
}
cursor = cursor.EstadoAnterior;
}
distancias.Reverse();
return distancias;
}
private static List<double> ConstruirDistanciasPiePorTramo(
double distanciaInicio,
IEnumerable<double> distanciasTransbordos,
double distanciaFin)
{
var distancias = new List<double>();
AgregarDistancia(distanciaInicio);
foreach (var distancia in distanciasTransbordos)
AgregarDistancia(distancia);
AgregarDistancia(distanciaFin);
return distancias;
void AgregarDistancia(double distancia)
{
if (double.IsFinite(distancia) && distancia > 0)
distancias.Add(distancia);
}
}
private static double CalcularDistanciaBusEstado(EstadoBusquedaParadaDbus estadoDestino) private static double CalcularDistanciaBusEstado(EstadoBusquedaParadaDbus estadoDestino)
{ {
var distancia = 0.0; var distancia = 0.0;
@@ -1345,6 +1390,11 @@ public sealed class ResultadoBusquedaRutaBusDbus
/// </summary> /// </summary>
public double DistanciaPieTransbordos { get; init; } public double DistanciaPieTransbordos { get; init; }
/// <summary>
/// Distancias peatonales de cada transbordo, sin agregarlas antes de penalizarlas.
/// </summary>
public IReadOnlyList<double> DistanciasPieTransbordosPorTramo { get; init; } = Array.Empty<double>();
/// <summary> /// <summary>
/// Espera inicial acumulada. /// Espera inicial acumulada.
/// </summary> /// </summary>

View File

@@ -295,6 +295,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
DistanciaPieInicioAprox = candidataBus.DistanciaPieInicio, DistanciaPieInicioAprox = candidataBus.DistanciaPieInicio,
DistanciaPieFinAprox = candidataBus.DistanciaPieFin, DistanciaPieFinAprox = candidataBus.DistanciaPieFin,
DistanciaPieTransbordosAprox = candidataBus.DistanciaPieTransbordos, DistanciaPieTransbordosAprox = candidataBus.DistanciaPieTransbordos,
DistanciasPiePorTramoAprox = ConstruirDistanciasPiePorTramo(candidataBus),
TiempoPieInicio = candidataBus.TiempoPieInicio, TiempoPieInicio = candidataBus.TiempoPieInicio,
TiempoPieFin = candidataBus.TiempoPieFin, TiempoPieFin = candidataBus.TiempoPieFin,
TiempoEsperaInicialSegundos = candidataBus.TiempoEsperaInicialSegundos, TiempoEsperaInicialSegundos = candidataBus.TiempoEsperaInicialSegundos,
@@ -992,6 +993,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
DistanciaPieFin = destino.DistanciaAPie, DistanciaPieFin = destino.DistanciaAPie,
TiempoPieFin = destino.TiempoAPie, TiempoPieFin = destino.TiempoAPie,
DistanciaPieTransbordos = transferencia.DistanciaMetros, DistanciaPieTransbordos = transferencia.DistanciaMetros,
DistanciasPieTransbordosPorTramo = new[] { transferencia.DistanciaMetros },
TiempoEsperaInicialSegundos = esperaInicial, TiempoEsperaInicialSegundos = esperaInicial,
TiempoEsperaTransbordosSegundos = esperaTotalTransbordos, TiempoEsperaTransbordosSegundos = esperaTotalTransbordos,
DuracionEstimadaSegundos = duracionTotal, DuracionEstimadaSegundos = duracionTotal,
@@ -1343,6 +1345,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
DistanciaPieFin = baseRuta.DistanciaPieFin, DistanciaPieFin = baseRuta.DistanciaPieFin,
TiempoPieFin = baseRuta.TiempoPieFin, TiempoPieFin = baseRuta.TiempoPieFin,
DistanciaPieTransbordos = baseRuta.DistanciaPieTransbordos, DistanciaPieTransbordos = baseRuta.DistanciaPieTransbordos,
DistanciasPieTransbordosPorTramo = baseRuta.DistanciasPieTransbordosPorTramo.ToArray(),
TiempoEsperaInicialSegundos = esperaInicial, TiempoEsperaInicialSegundos = esperaInicial,
TiempoEsperaTransbordosSegundos = baseRuta.TiempoEsperaTransbordosSegundos, TiempoEsperaTransbordosSegundos = baseRuta.TiempoEsperaTransbordosSegundos,
DuracionEstimadaSegundos = duracionTotal, DuracionEstimadaSegundos = duracionTotal,
@@ -1350,9 +1353,10 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
duracionTotal, duracionTotal,
parametros, parametros,
numeroTransbordos, numeroTransbordos,
ConstruirDistanciasPiePorTramo(
origen.DistanciaAPie, origen.DistanciaAPie,
baseRuta.DistanciaPieTransbordos, ObtenerDistanciasPieTransbordosPorTramo(baseRuta),
baseRuta.DistanciaPieFin), baseRuta.DistanciaPieFin).ToArray()),
RutaBus = ruta RutaBus = ruta
}; };
@@ -1518,9 +1522,9 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
var distanciaAndando = parametros is null var distanciaAndando = parametros is null
? Math.Max(0, resultado.DistanciaPieTotal) ? Math.Max(0, resultado.DistanciaPieTotal)
: UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieInicio, parametros) : UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaTotalMetros(
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieTransbordos, parametros) ConstruirDistanciasPiePorTramo(resultado),
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(resultado.DistanciaPieFin, parametros); parametros);
var factor = parametros is not null && double.IsFinite(parametros.FactorEquilibradoAndarBus) var factor = parametros is not null && double.IsFinite(parametros.FactorEquilibradoAndarBus)
? Math.Max(0, parametros.FactorEquilibradoAndarBus) ? Math.Max(0, parametros.FactorEquilibradoAndarBus)
: 12.0; : 12.0;
@@ -1531,6 +1535,42 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
: double.PositiveInfinity; : double.PositiveInfinity;
} }
private static List<double> ConstruirDistanciasPiePorTramo(ResultadoBusquedaRutaBusDbus resultado)
=> ConstruirDistanciasPiePorTramo(
resultado.DistanciaPieInicio,
ObtenerDistanciasPieTransbordosPorTramo(resultado),
resultado.DistanciaPieFin);
private static IReadOnlyList<double> ObtenerDistanciasPieTransbordosPorTramo(
ResultadoBusquedaRutaBusDbus resultado)
{
if (resultado.DistanciasPieTransbordosPorTramo.Count > 0)
return resultado.DistanciasPieTransbordosPorTramo;
return double.IsFinite(resultado.DistanciaPieTransbordos) && resultado.DistanciaPieTransbordos > 0
? new[] { resultado.DistanciaPieTransbordos }
: Array.Empty<double>();
}
private static List<double> ConstruirDistanciasPiePorTramo(
double distanciaInicio,
IEnumerable<double> distanciasTransbordos,
double distanciaFin)
{
var distancias = new List<double>();
AgregarDistancia(distanciaInicio);
foreach (var distancia in distanciasTransbordos)
AgregarDistancia(distancia);
AgregarDistancia(distanciaFin);
return distancias;
void AgregarDistancia(double distancia)
{
if (double.IsFinite(distancia) && distancia > 0)
distancias.Add(distancia);
}
}
private static bool DebeBuscarTransbordosRobustos( private static bool DebeBuscarTransbordosRobustos(
IReadOnlyList<ResultadoBusquedaRutaBusDbus> candidatasBus, IReadOnlyList<ResultadoBusquedaRutaBusDbus> candidatasBus,
IReadOnlyList<ParadaCandidata> candidatasOrigen, IReadOnlyList<ParadaCandidata> candidatasOrigen,
@@ -2033,6 +2073,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
ProveedorRuta = "v1", ProveedorRuta = "v1",
LineaSoloAPie = osrm.linea, LineaSoloAPie = osrm.linea,
LineasPieCalculoElevacion = new List<double[,]> { osrm.linea }, LineasPieCalculoElevacion = new List<double[,]> { osrm.linea },
DistanciasPiePorTramoAprox = new List<double> { osrm.distancia },
DistanciaSoloAPie = osrm.distancia, DistanciaSoloAPie = osrm.distancia,
DuracionSoloAPie = duracion, DuracionSoloAPie = duracion,
DuracionTotalAproxSegundos = duracion, DuracionTotalAproxSegundos = duracion,
@@ -2052,6 +2093,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
ProveedorRuta = "v2", ProveedorRuta = "v2",
LineaSoloAPie = valhalla.linea, LineaSoloAPie = valhalla.linea,
LineasPieCalculoElevacion = new List<double[,]> { valhalla.linea }, LineasPieCalculoElevacion = new List<double[,]> { valhalla.linea },
DistanciasPiePorTramoAprox = new List<double> { valhalla.distancia },
DistanciaSoloAPie = valhalla.distancia, DistanciaSoloAPie = valhalla.distancia,
DuracionSoloAPie = duracion, DuracionSoloAPie = duracion,
DuracionTotalAproxSegundos = duracion, DuracionTotalAproxSegundos = duracion,
@@ -2091,6 +2133,23 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
}); });
} }
private static void AgregarDistanciaPiePorTramo(AlternativaRuta alternativa, double distanciaMetros)
{
if (double.IsFinite(distanciaMetros) && distanciaMetros > 0)
alternativa.DistanciasPiePorTramoAprox.Add(distanciaMetros);
}
private static void AcumularDistanciaPieEnPrimerTramo(AlternativaRuta alternativa, double distanciaMetros)
{
if (!double.IsFinite(distanciaMetros) || distanciaMetros <= 0)
return;
if (alternativa.DistanciasPiePorTramoAprox.Count == 0)
alternativa.DistanciasPiePorTramoAprox.Add(distanciaMetros);
else
alternativa.DistanciasPiePorTramoAprox[0] += distanciaMetros;
}
/// <summary> /// <summary>
/// Recalcula una alternativa de bus usando caminatas exactas y horarios reales. /// Recalcula una alternativa de bus usando caminatas exactas y horarios reales.
/// </summary> /// </summary>
@@ -2105,6 +2164,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
return double.PositiveInfinity; return double.PositiveInfinity;
alternativa.LineasPieCalculoElevacion.Clear(); alternativa.LineasPieCalculoElevacion.Clear();
alternativa.DistanciasPiePorTramoAprox.Clear();
alternativa.EsfuerzoExtraPendienteMetros = 0; alternativa.EsfuerzoExtraPendienteMetros = 0;
var tramosBus = alternativa.AlternativaBus.Tramos; var tramosBus = alternativa.AlternativaBus.Tramos;
@@ -2155,6 +2215,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
alternativa.DistanciaPieInicioAprox = acceso.distancia > 0 alternativa.DistanciaPieInicioAprox = acceso.distancia > 0
? acceso.distancia ? acceso.distancia
: UtilidadesTransitoDbus.CalcularDistanciaMetros(origenLatLon[0], origenLatLon[1], paradaInicioBus.Latitud, paradaInicioBus.Longitud); : UtilidadesTransitoDbus.CalcularDistanciaMetros(origenLatLon[0], origenLatLon[1], paradaInicioBus.Latitud, paradaInicioBus.Longitud);
AgregarDistanciaPiePorTramo(alternativa, alternativa.DistanciaPieInicioAprox);
alternativa.TiempoPieInicio = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(alternativa.DistanciaPieInicioAprox, parametros); alternativa.TiempoPieInicio = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(alternativa.DistanciaPieInicioAprox, parametros);
total += alternativa.TiempoPieInicio; total += alternativa.TiempoPieInicio;
cursor = UtilidadesTransitoDbus.AddSecondsSafe(cursor, alternativa.TiempoPieInicio); cursor = UtilidadesTransitoDbus.AddSecondsSafe(cursor, alternativa.TiempoPieInicio);
@@ -2229,10 +2290,12 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
{ {
alternativa.DistanciaPieInicioAprox += distanciaTransferencia; alternativa.DistanciaPieInicioAprox += distanciaTransferencia;
alternativa.TiempoPieInicio += UtilidadesTransitoDbus.EstimarDuracionPieSegundos(distanciaTransferencia, parametros); alternativa.TiempoPieInicio += UtilidadesTransitoDbus.EstimarDuracionPieSegundos(distanciaTransferencia, parametros);
AcumularDistanciaPieEnPrimerTramo(alternativa, distanciaTransferencia);
} }
else else
{ {
alternativa.DistanciaPieTransbordosAprox += distanciaTransferencia; alternativa.DistanciaPieTransbordosAprox += distanciaTransferencia;
AgregarDistanciaPiePorTramo(alternativa, distanciaTransferencia);
} }
var duracionTransferencia = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(distanciaTransferencia, parametros); var duracionTransferencia = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(distanciaTransferencia, parametros);
@@ -2345,6 +2408,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
alternativa.DistanciaPieFinAprox = salidaFinal.distancia > 0 alternativa.DistanciaPieFinAprox = salidaFinal.distancia > 0
? salidaFinal.distancia ? salidaFinal.distancia
: UtilidadesTransitoDbus.CalcularDistanciaMetros(puntoUltimaLlegada[0], puntoUltimaLlegada[1], destinoLatLon[0], destinoLatLon[1]); : UtilidadesTransitoDbus.CalcularDistanciaMetros(puntoUltimaLlegada[0], puntoUltimaLlegada[1], destinoLatLon[0], destinoLatLon[1]);
AgregarDistanciaPiePorTramo(alternativa, alternativa.DistanciaPieFinAprox);
alternativa.TiempoPieFin = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(alternativa.DistanciaPieFinAprox, parametros); alternativa.TiempoPieFin = UtilidadesTransitoDbus.EstimarDuracionPieSegundos(alternativa.DistanciaPieFinAprox, parametros);
total += alternativa.TiempoPieFin; total += alternativa.TiempoPieFin;
@@ -2462,6 +2526,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
DistanciaPieFin = candidataBase.DistanciaPieFin, DistanciaPieFin = candidataBase.DistanciaPieFin,
TiempoPieFin = candidataBase.TiempoPieFin, TiempoPieFin = candidataBase.TiempoPieFin,
DistanciaPieTransbordos = candidataBase.DistanciaPieTransbordos, DistanciaPieTransbordos = candidataBase.DistanciaPieTransbordos,
DistanciasPieTransbordosPorTramo = candidataBase.DistanciasPieTransbordosPorTramo.ToArray(),
TiempoEsperaInicialSegundos = esperaInicial, TiempoEsperaInicialSegundos = esperaInicial,
TiempoEsperaTransbordosSegundos = candidataBase.TiempoEsperaTransbordosSegundos, TiempoEsperaTransbordosSegundos = candidataBase.TiempoEsperaTransbordosSegundos,
DuracionEstimadaSegundos = duracionEstimada, DuracionEstimadaSegundos = duracionEstimada,
@@ -2469,9 +2534,10 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
duracionEstimada, duracionEstimada,
parametros, parametros,
rutaDirecta.NumeroTransbordos, rutaDirecta.NumeroTransbordos,
ConstruirDistanciasPiePorTramo(
origenDirecto.DistanciaAPie, origenDirecto.DistanciaAPie,
candidataBase.DistanciaPieTransbordos, ObtenerDistanciasPieTransbordosPorTramo(candidataBase),
candidataBase.DistanciaPieFin), candidataBase.DistanciaPieFin).ToArray()),
RutaBus = rutaDirecta RutaBus = rutaDirecta
}; };
@@ -3156,9 +3222,22 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
private static double CalcularDistanciaAndandoCorregidaMetros( private static double CalcularDistanciaAndandoCorregidaMetros(
AlternativaRuta alternativa, AlternativaRuta alternativa,
ParametrosPlanificadorRuta parametros) ParametrosPlanificadorRuta parametros)
=> UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieInicioAprox, parametros) => UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaTotalMetros(
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieTransbordosAprox, parametros) ObtenerDistanciasPiePorTramo(alternativa),
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieFinAprox, parametros); parametros);
private static IReadOnlyList<double> ObtenerDistanciasPiePorTramo(AlternativaRuta alternativa)
{
if (alternativa.DistanciasPiePorTramoAprox.Count > 0)
return alternativa.DistanciasPiePorTramoAprox;
return ConstruirDistanciasPiePorTramo(
alternativa.DistanciaPieInicioAprox,
alternativa.DistanciaPieTransbordosAprox > 0
? new[] { alternativa.DistanciaPieTransbordosAprox }
: Array.Empty<double>(),
alternativa.DistanciaPieFinAprox);
}
private static double DuracionVisibleOrdenacion(AlternativaRuta alternativa) private static double DuracionVisibleOrdenacion(AlternativaRuta alternativa)
=> double.IsFinite(alternativa.DuracionTotalAproxSegundos) => double.IsFinite(alternativa.DuracionTotalAproxSegundos)
@@ -3355,9 +3434,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
alternativa.DuracionTotalAproxSegundos, alternativa.DuracionTotalAproxSegundos,
parametros, parametros,
alternativa.NumeroTransbordosReales, alternativa.NumeroTransbordosReales,
alternativa.DistanciaPieInicioAprox, ObtenerDistanciasPiePorTramo(alternativa).ToArray());
alternativa.DistanciaPieTransbordosAprox,
alternativa.DistanciaPieFinAprox);
} }
/// <summary> /// <summary>

View File

@@ -316,7 +316,7 @@ internal static class UtilidadesTransitoDbus
: 1.35; : 1.35;
var parametroBaseMetros = double.IsFinite(parametros.ParametroPenalizacionDistanciaPieMetros) var parametroBaseMetros = double.IsFinite(parametros.ParametroPenalizacionDistanciaPieMetros)
? Math.Abs(parametros.ParametroPenalizacionDistanciaPieMetros) ? Math.Abs(parametros.ParametroPenalizacionDistanciaPieMetros)
: 100.0; : 200.0;
if (parametroBaseMetros <= 0) if (parametroBaseMetros <= 0)
parametroBaseMetros = 1.0; parametroBaseMetros = 1.0;
@@ -325,6 +325,22 @@ internal static class UtilidadesTransitoDbus
return Math.Max(distanciaMetros, corregida); return Math.Max(distanciaMetros, corregida);
} }
/// <summary>
/// Aplica la correccion a cada tramo peatonal por separado y suma los resultados.
/// </summary>
public static double CalcularDistanciaPieCorregidaTotalMetros(
IEnumerable<double> distanciasPieMetros,
ParametrosPlanificadorRuta parametros)
{
var total = 0.0;
foreach (var distancia in distanciasPieMetros)
total += CalcularDistanciaPieCorregidaMetros(distancia, parametros);
return double.IsFinite(total) && total >= 0
? total
: double.PositiveInfinity;
}
/// <summary> /// <summary>
/// Calcula un coste interno que penaliza de forma progresiva la caminata sin cambiar el tiempo real. /// Calcula un coste interno que penaliza de forma progresiva la caminata sin cambiar el tiempo real.
/// </summary> /// </summary>

View File

@@ -322,7 +322,7 @@ window.rt.drawRoute = function (id, coords, options) {
} }
}; };
window.rt.fitRoutes = function (coords) { window.rt.fitRoutes = function (coords, preferredCenter) {
const map = window.__rtLeafletMap; const map = window.__rtLeafletMap;
if (!map || !window.L) return false; if (!map || !window.L) return false;
@@ -364,7 +364,14 @@ window.rt.fitRoutes = function (coords) {
const geometryBounds = window.L.latLngBounds(points); const geometryBounds = window.L.latLngBounds(points);
if (!geometryBounds.isValid()) return false; if (!geometryBounds.isValid()) return false;
map.panTo(geometryBounds.getCenter(), { const center = Array.isArray(preferredCenter)
&& preferredCenter.length >= 2
&& Number.isFinite(Number(preferredCenter[0]))
&& Number.isFinite(Number(preferredCenter[1]))
? window.L.latLng(Number(preferredCenter[0]), Number(preferredCenter[1]))
: geometryBounds.getCenter();
map.panTo(center, {
animate: true, animate: true,
duration: 0.35 duration: 0.35
}); });