private static Segment CalculateDirectRoute(RealLifeProfile p, WithLocation <TransferMetric> precalculator, Stop fromStop, Stop toStop) { var directJourneyTime = uint.MaxValue; if (DistanceEstimate.DistanceEstimateInMeter( fromStop.Latitude, fromStop.Longitude, toStop.Latitude, toStop.Longitude) > p.WalksGenerator.Range()) { return(null); } precalculator.CalculateDirectJourney() ?.TryGetValue((fromStop.Id, toStop.Id), out directJourneyTime); if (directJourneyTime == uint.MaxValue) { return(null); } var(coordinates, generator, license) = JourneyTranslator.GetCoordinatesFor(p.WalksGenerator, fromStop, toStop); var departure = new TimedLocation(new Location(fromStop), null, 0); var arrival = new TimedLocation(new Location(toStop), null, 0); return(new Segment(departure, arrival, generator, coordinates, directJourneyTime, license)); }
public static RealLifeProfile CreateProfile( this OperatorSet operatorSet, string from, string to, string walksGeneratorDescription, uint internalTransferTime = 180, double searchFactor = 2.5, uint minimalSearchTimeSeconds = 2 * 60 * 60, bool allowCancelled = false, uint maxNumberOfTransfers = uint.MaxValue ) { var stops = operatorSet.GetStopsReader().AddOsmReader(); stops.MoveTo(from); var fromId = stops.Id; stops.MoveTo(to); var toId = stops.Id; var walksGenerator = State.GlobalState.OtherModeBuilder.Create( walksGeneratorDescription, new List <StopId> { fromId }, new List <StopId> { toId } ); var internalTransferGenerator = new InternalTransferGenerator(internalTransferTime); var maxDistance = uint.MaxValue; foreach (var op in operatorSet.Operators) { maxDistance = Math.Min(maxDistance, op.MaxSearch); } if (walksGenerator.Range() > maxDistance) { throw new ArgumentException( $"Search range too high: with the chosen operators, at most {maxDistance}m is allowed"); } var searchFunction = RealLifeProfile.DefaultSearchLengthSearcher(searchFactor, TimeSpan.FromSeconds(minimalSearchTimeSeconds)); return(new RealLifeProfile( operatorSet, internalTransferGenerator, walksGenerator, allowCancelled, maxNumberOfTransfers, searchFunction )); }
BuildJourneys(this RealLifeProfile p, string @from, string to, DateTime?departure, DateTime?arrival, bool multipleOptions, Dictionary <string, string> logMessage) { if (departure == null && arrival == null) { throw new ArgumentException( "At least one date should be given, either departure time or arrival time (or both)"); } departure = departure?.ToUniversalTime(); arrival = arrival?.ToUniversalTime(); var reader = p.OperatorSet.GetStopsReader(); var osmIndex = reader.DatabaseIndexes().Max() + 1u; var stopsReader = StopsReaderAggregator.CreateFrom(new List <IStopsReader> { reader, new OsmLocationStopReader(osmIndex, true), }).UseCache(); // We cache here only for this request- only case cache will be missed is around the new stop locations // Calculate the first and last miles, in order to // 1) Detect impossible routes // 2) cache them stopsReader.MoveTo(from); var fromStop = new Stop(stopsReader); stopsReader.MoveTo(to); var toStop = new Stop(stopsReader); p.DetectFirstMileWalks(stopsReader, fromStop, osmIndex, false, "departure"); p.DetectFirstMileWalks(stopsReader, toStop, osmIndex, true, "arrival"); var precalculator = p.OperatorSet.All() .SelectProfile(p) .SetStopsReader(stopsReader) .SelectStops(from, to); var directRoute = CalculateDirectRoute(p, precalculator, fromStop, toStop); WithTime <TransferMetric> calculator; if (departure == null) { // Departure time is null // We calculate one with a latest arrival scan search calculator = precalculator.SelectTimeFrame(arrival.Value.AddDays(-1), arrival.Value); // This will set the time frame correctly var latest = calculator .CalculateLatestDepartureJourney(tuple => tuple.journeyStart - p.SearchLengthCalculator(tuple.journeyStart, tuple.journeyEnd)); if (!multipleOptions) { return(new List <Journey <TransferMetric> > { latest }, directRoute, latest.Root.Time.FromUnixTime(), latest.Time.FromUnixTime()); } } else if (arrival == null || !multipleOptions) { calculator = precalculator.SelectTimeFrame(departure.Value, departure.Value.AddDays(1)); // We do an earliest arrival search in a timewindow of departure time -> latest arrival time (eventually with arrival + 1 day) // This scan is extended for some time, in order to have both // - the automatically calculated latest arrival time // - an isochrone line in order to optimize later on var earliestArrivalJourney = calculator.CalculateEarliestArrivalJourney( tuple => tuple.journeyStart + p.SearchLengthCalculator(tuple.journeyStart, tuple.journeyEnd)); if (earliestArrivalJourney == null) { return(new List <Journey <TransferMetric> >(), directRoute, DateTime.MaxValue, DateTime.MinValue); } logMessage.Add("earliestArrivalJourney:departure", earliestArrivalJourney.Root.Time.FromUnixTime().ToString("s")); logMessage.Add("earliestArrivalJourney:arrival", earliestArrivalJourney.Time.FromUnixTime().ToString("s")); if (!multipleOptions) { return(new List <Journey <TransferMetric> > { earliestArrivalJourney }, directRoute, earliestArrivalJourney.Root.Time.FromUnixTime(), earliestArrivalJourney.Time.FromUnixTime()); } } else { calculator = precalculator.SelectTimeFrame(departure.Value, arrival.Value); // Perform isochrone to speed up 'all journeys' calculator.CalculateIsochroneFrom(); } // We lower the max number of transfers to speed up calculations // p.ApplyMaxNumberOfTransfers(); logMessage.Add("searchTime:pcs:start", calculator.Start.ToString("s")); logMessage.Add("searchTime:pcs:end", calculator.End.ToString("s")); return(calculator.CalculateAllJourneys(), directRoute, calculator.Start, calculator.End); }