From 7061660e7d475fe3ed016858a49a0c9b7ba10c18 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Fri, 21 Nov 2025 10:53:03 +0100 Subject: Show path from bus position to terminus --- .../Controllers/VigoController.cs | 34 ++++++++++++++++++++++ .../Services/ShapeTraversalService.cs | 30 +++++++++++++++---- .../Types/ConsolidatedCirculation.cs | 2 ++ 3 files changed, 61 insertions(+), 5 deletions(-) (limited to 'src/Costasdev.Busurbano.Backend') diff --git a/src/Costasdev.Busurbano.Backend/Controllers/VigoController.cs b/src/Costasdev.Busurbano.Backend/Controllers/VigoController.cs index 6423c2f..f1f5f4a 100644 --- a/src/Costasdev.Busurbano.Backend/Controllers/VigoController.cs +++ b/src/Costasdev.Busurbano.Backend/Controllers/VigoController.cs @@ -46,6 +46,38 @@ public class VigoController : ControllerBase } } + [HttpGet("GetShape")] + public async Task GetShape( + [FromQuery] string shapeId, + [FromQuery] int startPointIndex = 0 + ) + { + // Include a significant number of previous points to ensure continuity and context + // Backtrack 50 points to cover any potential gaps or dense point sequences + var adjustedStartIndex = Math.Max(0, startPointIndex - 50); + var path = await _shapeService.GetShapePathAsync(shapeId, adjustedStartIndex); + if (path == null) + { + return NotFound(); + } + + // Convert to GeoJSON LineString + var coordinates = path.Select(p => new[] { p.Longitude, p.Latitude }).ToList(); + + var geoJson = new + { + type = "Feature", + geometry = new + { + type = "LineString", + coordinates = coordinates + }, + properties = new { } + }; + + return Ok(geoJson); + } + [HttpGet("GetStopTimetable")] public async Task GetStopTimetable( [FromQuery] int stopId, @@ -278,6 +310,7 @@ public class VigoController : ControllerBase Minutes = (int)(closestCirculation.CallingDateTime()!.Value - now).TotalMinutes, TripId = closestCirculation.TripId, ServiceId = closestCirculation.ServiceId, + ShapeId = closestCirculation.ShapeId, }, RealTime = new RealTimeData { @@ -316,6 +349,7 @@ public class VigoController : ControllerBase Minutes = (int)(sched.CallingDateTime()!.Value - now).TotalMinutes, TripId = sched.TripId, ServiceId = sched.ServiceId, + ShapeId = sched.ShapeId, }, RealTime = null }); diff --git a/src/Costasdev.Busurbano.Backend/Services/ShapeTraversalService.cs b/src/Costasdev.Busurbano.Backend/Services/ShapeTraversalService.cs index bded78b..37b76ee 100644 --- a/src/Costasdev.Busurbano.Backend/Services/ShapeTraversalService.cs +++ b/src/Costasdev.Busurbano.Backend/Services/ShapeTraversalService.cs @@ -60,6 +60,23 @@ public class ShapeTraversalService } } + public async Task?> GetShapePathAsync(string shapeId, int startIndex) + { + var shape = await LoadShapeAsync(shapeId); + if (shape == null) return null; + + var result = new List(); + // Ensure startIndex is within bounds + if (startIndex < 0) startIndex = 0; + if (startIndex >= shape.Points.Count) return result; + + for (int i = startIndex; i < shape.Points.Count; i++) + { + result.Add(TransformToLatLng(shape.Points[i])); + } + return result; + } + /// /// Calculates the bus position by reverse-traversing the shape from the stop location /// @@ -78,13 +95,15 @@ public class ShapeTraversalService int closestPointIndex = FindClosestPointIndex(shape.Points, stopLocation); // Traverse backwards from the closest point to find the position at the given distance - var (busPoint, forwardPoint) = TraverseBackwards(shape.Points.ToArray(), closestPointIndex, distanceMeters); + var (busPoint, forwardIndex) = TraverseBackwards(shape.Points.ToArray(), closestPointIndex, distanceMeters); if (busPoint == null) { return null; } + var forwardPoint = shape.Points[forwardIndex]; + // Compute orientation in EPSG:25829 (meters): 0°=North, 90°=East (azimuth) var dx = forwardPoint.X - busPoint.X; // Easting difference var dy = forwardPoint.Y - busPoint.Y; // Northing difference @@ -94,19 +113,20 @@ public class ShapeTraversalService // Transform from EPSG:25829 (meters) to EPSG:4326 (lat/lng) var pos = TransformToLatLng(busPoint); pos.OrientationDegrees = (int)Math.Round(bearing); + pos.ShapeIndex = forwardIndex; return pos; } /// /// Traverses backwards along the shape from a starting point by the specified distance /// - private (Epsg25829 point, Epsg25829 forward) TraverseBackwards(Epsg25829[] shapePoints, int startIndex, double distanceMeters) + private (Epsg25829 point, int forwardIndex) TraverseBackwards(Epsg25829[] shapePoints, int startIndex, double distanceMeters) { if (startIndex <= 0) { // Already at the beginning, return the first point var forwardIdx = Math.Min(1, shapePoints.Length - 1); - return (shapePoints[0], shapePoints[forwardIdx]); + return (shapePoints[0], forwardIdx); } double remainingDistance = distanceMeters; @@ -123,7 +143,7 @@ public class ShapeTraversalService var ratio = remainingDistance / segmentDistance; var interpolated = InterpolatePoint(shapePoints[currentIndex], shapePoints[currentIndex - 1], ratio); // Forward direction is towards the stop (increasing index direction) - return (interpolated, shapePoints[currentIndex]); + return (interpolated, currentIndex); } remainingDistance -= segmentDistance; @@ -131,7 +151,7 @@ public class ShapeTraversalService } // We've reached the beginning of the shape - var fwd = shapePoints[Math.Min(1, shapePoints.Length - 1)]; + var fwd = Math.Min(1, shapePoints.Length - 1); return (shapePoints[0], fwd); } diff --git a/src/Costasdev.Busurbano.Backend/Types/ConsolidatedCirculation.cs b/src/Costasdev.Busurbano.Backend/Types/ConsolidatedCirculation.cs index a21aa60..2ac3206 100644 --- a/src/Costasdev.Busurbano.Backend/Types/ConsolidatedCirculation.cs +++ b/src/Costasdev.Busurbano.Backend/Types/ConsolidatedCirculation.cs @@ -23,6 +23,7 @@ public class ScheduleData public required int Minutes { get; set; } public required string ServiceId { get; set; } public required string TripId { get; set; } + public string? ShapeId { get; set; } } public class Position @@ -30,4 +31,5 @@ public class Position public required double Latitude { get; set; } public required double Longitude { get; set; } public int OrientationDegrees { get; set; } + public int ShapeIndex { get; set; } } -- cgit v1.3