cambio foco elemento compartido

poner km en los tramos de bus
line 16 oscurecida
flechas de sentido en las paradas
This commit is contained in:
2026-07-28 08:17:04 +02:00
parent f2e0b59faa
commit 8a75c583ca
8 changed files with 231 additions and 87 deletions

View File

@@ -465,13 +465,70 @@ public partial class PlanificadorRutas : ComponentBase
/// </summary>
private static List<object> BuildStopsDesdeParadas(IEnumerable<Parada> paradas)
{
var stops = new List<object>();
foreach (var parada in paradas)
stops.Add(new { lat = parada.Latitud, lon = parada.Longitud, code = parada.Codigo });
var paradasOrdenadas = paradas.ToList();
var stops = new List<object>(paradasOrdenadas.Count);
for (var indice = 0; indice < paradasOrdenadas.Count; indice++)
{
var parada = paradasOrdenadas[indice];
stops.Add(new
{
lat = parada.Latitud,
lon = parada.Longitud,
code = parada.Codigo,
bearing = CalcularRumboParada(paradasOrdenadas, indice)
});
}
return stops;
}
/// <summary>
/// Calcula el sentido de marcha hacia la siguiente parada; en la terminal conserva el rumbo de llegada.
/// </summary>
private static double? CalcularRumboParada(IReadOnlyList<Parada> paradas, int indice)
{
var actual = paradas[indice];
for (var siguiente = indice + 1; siguiente < paradas.Count; siguiente++)
{
var rumbo = CalcularRumboGrados(actual, paradas[siguiente]);
if (rumbo is not null)
return rumbo;
}
for (var anterior = indice - 1; anterior >= 0; anterior--)
{
var rumbo = CalcularRumboGrados(paradas[anterior], actual);
if (rumbo is not null)
return rumbo;
}
return null;
}
private static double? CalcularRumboGrados(Parada origen, Parada destino)
{
if (!double.IsFinite(origen.Latitud) ||
!double.IsFinite(origen.Longitud) ||
!double.IsFinite(destino.Latitud) ||
!double.IsFinite(destino.Longitud))
{
return null;
}
var latitudOrigen = origen.Latitud * Math.PI / 180.0;
var latitudDestino = destino.Latitud * Math.PI / 180.0;
var diferenciaLongitud = (destino.Longitud - origen.Longitud) * Math.PI / 180.0;
var y = Math.Sin(diferenciaLongitud) * Math.Cos(latitudDestino);
var x = Math.Cos(latitudOrigen) * Math.Sin(latitudDestino) -
Math.Sin(latitudOrigen) * Math.Cos(latitudDestino) * Math.Cos(diferenciaLongitud);
if (Math.Abs(x) < 1e-12 && Math.Abs(y) < 1e-12)
return null;
var rumbo = Math.Atan2(y, x) * 180.0 / Math.PI;
return (rumbo + 360.0) % 360.0;
}
/// <summary>
/// Construye las paradas visibles recorridas por una variante completa.
/// </summary>

View File

@@ -29,6 +29,7 @@ public partial class PlanificadorRutas
private bool _mostrarHistorialRutas = false;
private bool _refrescandoHistorialCompartido = false;
private bool _omitirRegistroHistorialEnSiguienteCalculo = false;
private bool _aplicandoRegistroHistorial = false;
private string? _historialCompartidoPendienteEliminarId;
private ConfiguracionLocalPlanificador? _configuracionTemporalPreviaHistorial;
private Task<bool>? _tareaCargaHistorialLocal;
@@ -181,7 +182,8 @@ public partial class PlanificadorRutas
{
_historialLocal.Clear();
_historialLocal.AddRange(items);
_historialLocalSeleccionadoId = _historialLocal.FirstOrDefault()?.Id ?? string.Empty;
if (!_historialLocal.Any(x => x.Id == _historialLocalSeleccionadoId))
_historialLocalSeleccionadoId = string.Empty;
_historialLocalCargado = true;
}
@@ -232,7 +234,7 @@ public partial class PlanificadorRutas
}
if (!_historialCompartido.Any(x => x.Id == _historialCompartidoSeleccionadoId))
_historialCompartidoSeleccionadoId = _historialCompartido[0].Id;
_historialCompartidoSeleccionadoId = string.Empty;
}
catch (Exception)
{
@@ -332,13 +334,12 @@ public partial class PlanificadorRutas
while (_historialLocal.Count > MaxItemsHistorialLocal)
_historialLocal.RemoveAt(_historialLocal.Count - 1);
_historialLocalSeleccionadoId = existente.Id;
await PersistirHistorialLocalAsync();
}
private async Task CargarHistorialLocalSeleccionadoAsync()
private async Task CargarHistorialLocalAsync(string id)
{
var item = _historialLocal.FirstOrDefault(x => x.Id == _historialLocalSeleccionadoId);
var item = _historialLocal.FirstOrDefault(x => x.Id == id);
if (item is null)
{
MostrarMensajeHistorial("No encuentro esa combinacion en tu historial personal.", esError: true);
@@ -346,18 +347,13 @@ public partial class PlanificadorRutas
}
await AplicarRegistroHistorialAsync(item);
SeleccionarHistorialLocal(id);
MostrarMensajeHistorial("Combinacion personal cargada.");
}
private async Task CargarHistorialLocalAsync(string id)
private async Task CargarHistorialCompartidoAsync(string id)
{
_historialLocalSeleccionadoId = id;
await CargarHistorialLocalSeleccionadoAsync();
}
private async Task CargarHistorialCompartidoSeleccionadoAsync()
{
var item = _historialCompartido.FirstOrDefault(x => x.Id == _historialCompartidoSeleccionadoId);
var item = _historialCompartido.FirstOrDefault(x => x.Id == id);
if (item is null)
{
MostrarMensajeHistorial("No encuentro esa combinacion en el historial compartido.", esError: true);
@@ -365,13 +361,26 @@ public partial class PlanificadorRutas
}
await AplicarRegistroHistorialAsync(item);
SeleccionarHistorialCompartido(id);
MostrarMensajeHistorial("Combinación compartida cargada.");
}
private async Task CargarHistorialCompartidoAsync(string id)
private void SeleccionarHistorialLocal(string id)
{
_historialLocalSeleccionadoId = id;
_historialCompartidoSeleccionadoId = string.Empty;
}
private void SeleccionarHistorialCompartido(string id)
{
_historialLocalSeleccionadoId = string.Empty;
_historialCompartidoSeleccionadoId = id;
await CargarHistorialCompartidoSeleccionadoAsync();
}
private void LimpiarSeleccionHistorial()
{
_historialLocalSeleccionadoId = string.Empty;
_historialCompartidoSeleccionadoId = string.Empty;
}
private async Task CompartirEscenarioActualAsync()
@@ -387,9 +396,8 @@ public partial class PlanificadorRutas
try
{
var guardado = await HistorialRutasCompartidoService.GuardarAsync(actual);
await HistorialRutasCompartidoService.GuardarAsync(actual);
await CargarHistorialCompartidoAsync();
_historialCompartidoSeleccionadoId = guardado.Id;
MostrarMensajeHistorial("Combinacion enviada al historial compartido.");
}
catch (Exception)
@@ -400,7 +408,6 @@ public partial class PlanificadorRutas
private async Task CompartirHistorialLocalAsync(string id)
{
_historialLocalSeleccionadoId = id;
var item = _historialLocal.FirstOrDefault(x => x.Id == id);
if (item is null)
{
@@ -410,9 +417,8 @@ public partial class PlanificadorRutas
try
{
var guardado = await HistorialRutasCompartidoService.GuardarAsync(item);
await HistorialRutasCompartidoService.GuardarAsync(item);
await CargarHistorialCompartidoAsync();
_historialCompartidoSeleccionadoId = guardado.Id;
MostrarMensajeHistorial("Combinacion enviada al historial compartido.");
}
catch (Exception)
@@ -433,7 +439,7 @@ public partial class PlanificadorRutas
_historialLocal.Remove(item);
if (_historialLocalSeleccionadoId == id)
_historialLocalSeleccionadoId = _historialLocal.FirstOrDefault()?.Id ?? string.Empty;
_historialLocalSeleccionadoId = string.Empty;
await PersistirHistorialLocalAsync();
MostrarMensajeHistorial("Combinacion eliminada del historial personal.");
@@ -477,7 +483,7 @@ public partial class PlanificadorRutas
await CargarHistorialCompartidoAsync();
if (_historialCompartidoSeleccionadoId == id)
_historialCompartidoSeleccionadoId = _historialCompartido.FirstOrDefault()?.Id ?? string.Empty;
_historialCompartidoSeleccionadoId = string.Empty;
MostrarMensajeHistorial("Combinacion eliminada del historial compartido.");
}
@@ -488,6 +494,9 @@ public partial class PlanificadorRutas
}
private async Task AplicarRegistroHistorialAsync(RegistroHistorialRuta item)
{
_aplicandoRegistroHistorial = true;
try
{
CapturarConfiguracionTemporalAntesDeHistorial();
@@ -545,6 +554,11 @@ public partial class PlanificadorRutas
await SincronizarMarcadoresOrigenDestinoJsAsync();
await CalcularRutaCompletaAsync();
}
finally
{
_aplicandoRegistroHistorial = false;
}
}
private void CapturarConfiguracionTemporalAntesDeHistorial()
{

View File

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

View File

@@ -1552,6 +1552,9 @@ public partial class PlanificadorRutas : ComponentBase
if (_mapa is null || _coordenadasOrigen is null || _coordenadasDestino is null)
return;
if (!_aplicandoRegistroHistorial)
LimpiarSeleccionHistorial();
var cronometroCalculo = System.Diagnostics.Stopwatch.StartNew();
_panelRutasMovilContraido = _mostrarBuscadorMapa;

View File

@@ -859,6 +859,13 @@ public partial class PlanificadorRutas : ComponentBase
DateTime? depT = null;
DateTime? arrT = null;
double distanciaTramo = 0;
for (int p = 1; p < lineaGeom.GetLength(0); p++)
{
distanciaTramo += CalcularDistanciaMetros(
lineaGeom[p - 1, 0], lineaGeom[p - 1, 1],
lineaGeom[p, 0], lineaGeom[p, 1]);
}
if (_usarHorariosTeoricos && _horariosOk)
{
@@ -957,21 +964,13 @@ public partial class PlanificadorRutas : ComponentBase
Descripcion = CapitalizarPalabrasClave(
$"{HHmm(depT.Value)} -> {HHmm(arrT.Value)} - Linea {codLineaItinSentidoMostrado} ({infoVariante.Linea.Nombre})."
),
DistanciaMetros = 0,
DistanciaMetros = distanciaTramo,
DuracionSegundos = durBus,
VarianteBus = infoVariante
});
}
else
{
double distanciaTramo = 0;
for (int p = 1; p < lineaGeom.GetLength(0); p++)
{
distanciaTramo += CalcularDistanciaMetros(
lineaGeom[p - 1, 0], lineaGeom[p - 1, 1],
lineaGeom[p, 0], lineaGeom[p, 1]);
}
int paradasTramo = ContarParadasRecorridas(tramo);
double extraParadasSeg = paradasTramo * Math.Max(0, _segundosPorParadaBus);
double duracionBusSegundos = EstimarDuracionBusSegundos(distanciaTramo) + extraParadasSeg;

View File

@@ -8,6 +8,7 @@ namespace RutasDBUS.Servicios.RedBus;
public class RedBusServicio : IRedBusServicio
{
private const string ColorVisualLinea16Argb = "FF5AAED6";
private const string ColorVisualLinea40Argb = "FF9A7B00";
private readonly OpcionesRedBus _opciones;
private readonly ILogger<RedBusServicio> _logger;
@@ -143,7 +144,9 @@ public class RedBusServicio : IRedBusServicio
private static void AjustarColorVisualLinea(LineaBus linea)
{
if (string.Equals(linea.Codigo, "40", StringComparison.OrdinalIgnoreCase))
if (string.Equals(linea.Codigo, "16", StringComparison.OrdinalIgnoreCase))
linea.ColorArgb = ColorVisualLinea16Argb;
else if (string.Equals(linea.Codigo, "40", StringComparison.OrdinalIgnoreCase))
linea.ColorArgb = ColorVisualLinea40Argb;
}

View File

@@ -1755,6 +1755,47 @@ html, body {
border: none;
}
.rt-stop-direction-icon {
border: 0;
background: transparent;
pointer-events: none;
}
.rt-stop-direction-arrow {
position: absolute;
top: 50%;
left: 50%;
width: 10px;
height: 12px;
transform: translate(-50%, -50%) rotate(var(--stop-bearing, 0deg));
transform-origin: 50% 50%;
filter: drop-shadow(0 0 1px #0f172a) drop-shadow(0 1px 0 #0f172a);
}
.rt-stop-direction-arrow::before {
content: "";
position: absolute;
top: 0;
left: 50%;
width: 0;
height: 0;
transform: translateX(-50%);
border-right: 3px solid transparent;
border-bottom: 6px solid #f8fafc;
border-left: 3px solid transparent;
}
.rt-stop-direction-arrow::after {
content: "";
position: absolute;
top: 5px;
left: 4px;
width: 2px;
height: 6px;
border-radius: 1px;
background: #f8fafc;
}
.rt-arrow {
position: relative;
transform-origin: 50% 50%;

View File

@@ -894,7 +894,32 @@ window.rt.ensureItStopsLayer = function () {
return true;
};
// stops: [{lat, lon}]
window.rt.addStopDirectionMarker = function (group, stop, pane, radius) {
if (!group || !stop || !window.L) return;
const bearing = Number(stop.bearing);
const lat = Number(stop.lat);
const lon = Number(stop.lon);
if (!Number.isFinite(bearing) || !Number.isFinite(lat) || !Number.isFinite(lon)) return;
const size = Math.max(14, Number(radius || 7) * 2);
const icon = window.L.divIcon({
className: "rt-stop-direction-icon",
html: `<span class="rt-stop-direction-arrow" style="--stop-bearing:${bearing}deg"></span>`,
iconSize: [size, size],
iconAnchor: [size / 2, size / 2]
});
window.L.marker([lat, lon], {
pane,
icon,
interactive: false,
keyboard: false,
zIndexOffset: 1000
}).addTo(group);
};
// stops: [{lat, lon, code, bearing}]
window.rt.toggleItStops = function (id, stops, options) {
if (!window.rt.ensureItStopsLayer()) return;
@@ -944,6 +969,7 @@ window.rt.toggleItStops = function (id, stops, options) {
}
m.addTo(group);
window.rt.addStopDirectionMarker(group, s, "rtStopsPane", radius);
}
}
@@ -1021,6 +1047,7 @@ window.rt.drawRouteStops = function (id, stops, options) {
}
m.addTo(group);
window.rt.addStopDirectionMarker(group, s, "rtRouteStopsPane", radius);
}
group.addTo(window.rt._routeStopsLayer);