public static async Task <StopDistanceResult> GetNearestStop(GeoCoordinate center) { await nearestStopLock.WaitAsync(); if (nearestStopTime < DateTime.Now - TimeSpan.FromMinutes(1)) { LastNearestStop = await calculateNearestStop(center); nearestStopTime = DateTime.Now; } nearestStopLock.Release(); return(LastNearestStop); }
public static async Task <IEnumerable <StopDistanceResult> > WalkDistances(Stop sourceStop, IEnumerable <Stop> targetStops) { var unknownStops = new List <Stop>(); var result = new List <StopDistanceResult>(); double walkingSpeed = WalkingSpeed(); var sourceTransfers = sourceStop.Transfers.ToArray(); foreach (Stop currentStop in targetStops) { if (currentStop.Coordinate == sourceStop.Coordinate) { result.Add(new StopDistanceResult { Stop = currentStop, EstimatedDuration = TimeSpan.Zero, DistanceInMeters = 0.0 }); } else { Transfer matchingTransfer = sourceTransfers.FirstOrDefault(t => t.Target.Coordinate == currentStop.Coordinate); if (matchingTransfer != null) { var entry = new StopDistanceResult { Stop = currentStop, EstimatedDuration = TimeSpan.FromSeconds(matchingTransfer.Distance / walkingSpeed), DistanceInMeters = (double)matchingTransfer.Distance }; result.Add(entry); AddToCache(sourceStop.Coordinate, currentStop.Coordinate, new Direction { EstimatedDuration = entry.EstimatedDuration, DistanceInMeters = entry.DistanceInMeters }); } else { unknownStops.Add(currentStop); } } } result.AddRange(await WalkDistances(sourceStop.Coordinate, unknownStops)); return(result); }
private static async Task <StopDistanceResult> calculateNearestStop(GeoCoordinate center) { StopDistanceResult result = null; if (center != null) { var stops = TransitBaseComponent.Current.Stops .Where(s => s.StraightLineDistanceTo(center.Latitude, center.Longitude) < 2000) .Select(s => new { Stop = s, Distance = s.StraightLineDistanceTo(center.Latitude, center.Longitude) }) .OrderBy(x => x.Distance) .ToList(); StopDistanceResult prevResult = new StopDistanceResult { DistanceInMeters = double.MaxValue }; while (stops.Count > 0) { var minDistance = stops.First().Distance; var nextStops = stops.TakeWhile(s => s.Distance < minDistance + 200.0).ToList(); stops.RemoveRange(0, nextStops.Count); var results = await WalkDistances(center, nextStops.Select(x => x.Stop)); var minResult = results.Concat(new StopDistanceResult[] { prevResult }).MinBy(r => r.DistanceInMeters); if (stops.Count == 0 || minResult.DistanceInMeters <= stops.First().Distance) { result = minResult; break; } else { prevResult = minResult; } } } return(result); }