Example #1
0
        private static Route.Meta[] ReadShapeMeta(dynamic token)
        {
            var dArray     = token.First;
            var shapeMetas = new Route.Meta[dArray.Count];

            for (var i = 0; i < dArray.Count; i++)
            {
                var dItem = dArray[i];
                shapeMetas[i] = new Route.Meta();
                foreach (var token1 in dItem)
                {
                    switch (token1.Name)
                    {
                    case "Shape":
                        shapeMetas[i].Shape = token1.Value;
                        break;

                    case "Attributes":
                        shapeMetas[i].Attributes = ReadAttributes(token1);
                        break;
                    }
                }
            }

            return(shapeMetas);
        }
Example #2
0
        /// <summary>
        /// Adds instructions as attributes to route.
        /// </summary>
        public static void AddInstructions(this Route route, IEnumerable <Instruction> instructions)
        {
            var metas = new Dictionary <int, Route.Meta>();

            foreach (var meta in route.ShapeMeta)
            {
                metas.Add(meta.Shape, meta);
            }

            foreach (var instruction in instructions)
            {
                var        shapeIndex = instruction.Shape;
                Route.Meta shapeMeta;
                if (!metas.TryGetValue(shapeIndex, out shapeMeta))
                {
                    shapeMeta = new Route.Meta()
                    {
                        Attributes = new AttributeCollection(),
                        Shape      = shapeIndex
                    };
                    float distance, time;
                    route.DistanceAndTimeAt(shapeIndex, out distance, out time);
                    shapeMeta.Distance = distance;
                    shapeMeta.Time     = time;

                    metas.Add(shapeIndex, shapeMeta);
                }

                shapeMeta.Attributes.AddOrReplace("instruction", instruction.Text);
                shapeMeta.Attributes.AddOrReplace("instruction_type", instruction.Type);
            }
        }
Example #3
0
        /// <summary>
        /// Constructor of the InstructionProperties.
        /// </summary>
        /// <param name="Instruction">The instruction to convert to a GeoJsonFeature.</param>
        /// <param name="Next">The next instruction.</param>
        /// <param name="route">The Route object.</param>
        public InstructionProperties(Instruction Instruction, Instruction Next, Route route)
        {
            this.type        = "Feature";
            this.properties  = new Dictionary <string, string> ();
            this.geometry    = new GeoJsonPoint(route.Shape[Instruction.Shape]);
            this.Instruction = Instruction;

            properties.Add("instruction", Instruction.Text);
            Route.Meta meta = route.ShapeMetaFor(Instruction.Shape);

            properties.Add("colour", Instruction.GetAttribute("cyclecolour", route));
            properties.Add("ref", Instruction.GetAttribute("cycleref", route));

            float time;
            float dist;

            route.DistanceAndTimeAt(Instruction.Shape, out dist, out time);
            properties.Add("distance", dist.ToString(new CultureInfo("en-US")));

            properties.Add("type", Instruction.Type);

            if (Next != null)
            {
                Route.Meta nextMeta = route.ShapeMetaFor(Next.Shape);
                properties.Add("nextColour", Next.GetAttribute("cyclecolour", route));
                properties.Add("nextRef", Next.GetAttribute("cycleref", route));

                if (Instruction.Type != "start" && Instruction.Type != "stop")
                {
                    this.Angle = route.RelativeDirectionAt(Instruction.Shape);
                    properties.Add("angle", Angle.Direction.ToString());
                }
            }
        }
Example #4
0
        public void TestProjectOne()
        {
            var route = new Route()
            {
                Shape = new Coordinate[]
                {
                    new Coordinate()
                    {
                        Latitude  = 51.268977112538806f,
                        Longitude = 4.800424575805664f
                    },
                    new Coordinate()
                    {
                        Latitude  = 51.26830584177533f,
                        Longitude = 4.8006391525268555f
                    },
                    new Coordinate()
                    {
                        Latitude  = 51.267768818104585f,
                        Longitude = 4.801325798034667f
                    },
                    new Coordinate()
                    {
                        Latitude  = 51.26674845584085f,
                        Longitude = 4.801068305969238f
                    },
                    new Coordinate()
                    {
                        Latitude  = 51.26551325015766f,
                        Longitude = 4.801154136657715f
                    }
                },
                ShapeMeta = new Route.Meta[]
                {
                    new Route.Meta()
                    {
                        Shape = 0
                    },
                    new Route.Meta()
                    {
                        Shape    = 2,
                        Distance = 100,
                        Time     = 60
                    },
                    new Route.Meta()
                    {
                        Shape    = 4,
                        Distance = 200,
                        Time     = 120
                    }
                },
                Attributes    = new AttributeCollection(),
                TotalDistance = 200,
                TotalTime     = 120
            };

            // calculate actual distance/times.
            Route.Meta previousMeta = null;
            foreach (var meta in route.ShapeMeta)
            {
                meta.Distance = 0;
                meta.Time     = 0;

                if (previousMeta != null)
                {
                    for (var s = previousMeta.Shape; s < meta.Shape; s++)
                    {
                        meta.Distance = meta.Distance + Coordinate.DistanceEstimateInMeter(
                            route.Shape[s], route.Shape[s + 1]);
                    }

                    meta.Time = meta.Distance / 16.6667f; // 60km/h
                }

                previousMeta = meta;
            }
            route.TotalDistance = route.ShapeMeta[route.ShapeMeta.Length - 1].Distance;
            route.TotalTime     = route.ShapeMeta[route.ShapeMeta.Length - 1].Time;

            float      time, distance;
            int        shape;
            Coordinate projected;

            Assert.IsTrue(route.ProjectOn(new Coordinate(51.26856092582056f, 4.800623059272766f), out projected, out shape, out distance, out time));
            Assert.AreEqual(0, shape);
            Assert.IsTrue(time > route.ShapeMeta[0].Time);
            Assert.IsTrue(time < route.ShapeMeta[1].Time);

            Assert.IsTrue(route.ProjectOn(new Coordinate(51.26795342069926f, 4.801229238510132f), out projected, out shape, out distance, out time));
            Assert.AreEqual(1, shape);
            Assert.IsTrue(time > route.ShapeMeta[0].Time);
            Assert.IsTrue(time < route.ShapeMeta[1].Time);

            Assert.IsTrue(route.ProjectOn(new Coordinate(51.26712438141587f, 4.801207780838013f), out projected, out shape, out distance, out time));
            Assert.AreEqual(2, shape);
            Assert.IsTrue(time > route.ShapeMeta[1].Time);
            Assert.IsTrue(time < route.ShapeMeta[2].Time);

            Assert.IsTrue(route.ProjectOn(new Coordinate(51.26610064830449f, 4.801395535469055f), out projected, out shape, out distance, out time));
            Assert.AreEqual(3, shape);
            Assert.IsTrue(time > route.ShapeMeta[1].Time);
            Assert.IsTrue(time < route.ShapeMeta[2].Time);
        }
Example #5
0
        /// <summary>
        /// Adds the shape point between from and to and the target location itself.
        /// </summary>
        private void Add(uint from, uint to, uint next)
        {
            if (from == Constants.NO_VERTEX &&
                _source.IsVertex())
            { // replace from with the vertex.
                from = _source.VertexId(_routerDb);

                if (from == to)
                { // nothing to be done.
                    return;
                }
            }
            if (next == Constants.NO_VERTEX &&
                _target.IsVertex())
            { // replace next with the vertex.
                next = _target.VertexId(_routerDb);

                //if (to == next)
                //{ // nothing to be done.
                //    return;
                //}
            }


            // get shapepoints and edge.
            var         shape          = new List <Coordinate>(0);
            RoutingEdge edge           = null;
            Coordinate? targetLocation = null;
            var         distance       = 0f;
            var         direction      = true;

            if (from == Constants.NO_VERTEX &&
                to == Constants.NO_VERTEX)
            {     // from is the source and to is the target.
                if (_source.EdgeId != _target.EdgeId)
                { // a route inside one edge but source and target do not match.
                    this.ErrorMessage = "Target and source have to be on the same vertex with a route with only virtual vertices.";
                    return;
                }
                shape          = _source.ShapePointsTo(_routerDb, _target);
                distance       = _source.DistanceTo(_routerDb, _target);
                edge           = _routerDb.Network.GetEdge(_source.EdgeId);
                targetLocation = _target.Location();
                shape.Add(targetLocation.Value);
            }
            else if (from == Constants.NO_VERTEX)
            { // from is the source and to is a regular vertex.
                edge = _routerDb.Network.GetEdge(_source.EdgeId);
                var toOnEdge = _routerDb.Network.CreateRouterPointForVertex(to,
                                                                            edge.GetOther(to));
                shape          = _source.ShapePointsTo(_routerDb, toOnEdge);
                distance       = _source.DistanceTo(_routerDb, toOnEdge);
                targetLocation = _routerDb.Network.GetVertex(to);
                shape.Add(targetLocation.Value);
            }
            else if (to == Constants.NO_VERTEX)
            { // from is a regular vertex and to is the target.
                edge = _routerDb.Network.GetEdge(_target.EdgeId);
                var fromOnEdge = _routerDb.Network.CreateRouterPointForVertex(from,
                                                                              edge.GetOther(from));
                shape          = fromOnEdge.ShapePointsTo(_routerDb, _target);
                distance       = fromOnEdge.DistanceTo(_routerDb, _target);
                targetLocation = _target.Location();
                shape.Add(targetLocation.Value);
            }
            else
            { // both are just regular vertices.
                edge      = _routerDb.Network.GetEdgeEnumerator(from).First(x => x.To == to);
                direction = !edge.DataInverted;
                if (this.AddShorcut(edge))
                {
                    return;
                }

                distance = edge.Data.Distance;
                var shapeEnumerable = edge.Shape;
                if (shapeEnumerable != null)
                {
                    if (edge.DataInverted)
                    {
                        shapeEnumerable = shapeEnumerable.Reverse();
                    }
                    shape.AddRange(shapeEnumerable);
                }
                targetLocation = _routerDb.Network.GetVertex(to);
                shape.Add(targetLocation.Value);
            }

            // get edge details.
            var profile = _routerDb.EdgeProfiles.Get(edge.Data.Profile);
            var speed   = this._profile.Speed(profile);
            var time    = 0f;

            if (speed.Value != 0)
            {
                time = distance / speed.Value;
            }
            var meta       = _routerDb.EdgeMeta.Get(edge.Data.MetaId);
            var attributes = new AttributeCollection(meta);

            attributes.AddOrReplace(profile);
            attributes.AddOrReplace("profile", _profile.FullName);

            // add shape and meta.
            _shape.AddRange(shape);
            var previousMeta = _shapeMeta[_shapeMeta.Count - 1];
            var shapeMeta    = new Route.Meta()
            {
                Shape               = _shape.Count - 1,
                Attributes          = attributes,
                AttributesDirection = direction
            };

            shapeMeta.Distance = distance + previousMeta.Distance;
            shapeMeta.Time     = time + previousMeta.Time;
            _shapeMeta.Add(shapeMeta);

            // add sidestreets.
            if (to != Constants.NO_VERTEX)
            {
                _branches.AddBranches(_routerDb, _shape.Count - 1, to, edge.Id, next);
            }
        }
Example #6
0
        /// <summary>
        /// Executes the route build step.
        /// </summary>
        /// <returns></returns>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            if (!_search.HasRun)
            {
                throw new InvalidOperationException("Cannot build a route before the search was executed.");
            }
            if (!_search.HasSucceeded)
            {
                throw new InvalidOperationException("Cannot build a route when the search did not succeed.");
            }

            var stops = new List <Tuple <uint, StopProfile> >();
            var trips = new List <uint?>();

            var connectionEnumerator = _search.Db.GetConnectionsEnumerator(Data.DefaultSorting.DepartureTime);
            var stopEnumerator       = _search.Db.GetStopsEnumerator();
            var tripEnumerator       = _search.Db.GetTripsEnumerator();

            // get best target stop.
            var targetProfiles   = _search.ArrivalProfiles;
            var targetProfileIdx = _search.GetBest(targetProfiles, 10 * 60);
            var targetStop       = _search.ArrivalStops[targetProfileIdx];

            // build route along that target.
            var profiles   = _search.GetStopProfiles(targetStop);
            var profileIdx = profiles.GetLeastTransfers();

            stops.Add(new Tuple <uint, StopProfile>(targetStop, profiles[profileIdx]));
            while (!profiles[profileIdx].IsFirst)
            {
                var previousStopId = uint.MaxValue;
                if (profiles[profileIdx].IsConnection)
                { // this profile represent an arrival via a connection, add the trip and move down to where
                    // the trip was boarded.
                    connectionEnumerator.MoveTo(profiles[profileIdx].PreviousConnectionId);
                    trips.Add(connectionEnumerator.TripId);

                    // get trip status.
                    var tripStatus = _search.GetTripStatus(connectionEnumerator.TripId);
                    previousStopId = tripStatus.StopId;

                    // get next profiles.
                    profiles   = _search.GetStopProfiles(previousStopId);
                    profileIdx = profiles.GetLeastTransfers();

                    // when the next also has a connection this is a transfer.
                    if (profiles[profileIdx].IsConnection)
                    { // move to connection and check it out.
                        stops.Add(new Tuple <uint, StopProfile>(previousStopId, new StopProfile()
                        {
                            PreviousStopId = previousStopId,
                            Seconds        = tripStatus.DepartureTime
                        }));
                        trips.Add(null);
                    }

                    // check for a difference in departure time and arrival time of the profile.
                    // if there is a difference insert a waiting period.
                    if (!profiles[profileIdx].IsConnection &&
                        profiles[profileIdx].Seconds != connectionEnumerator.DepartureTime)
                    { // this is a waiting period.
                        stops.Add(new Tuple <uint, StopProfile>(previousStopId, new StopProfile()
                        {
                            PreviousStopId = previousStopId,
                            Seconds        = tripStatus.DepartureTime
                        }));
                        trips.Add(null);
                    }

                    // add stop.
                    stops.Add(new Tuple <uint, StopProfile>(previousStopId, profiles[profileIdx]));
                }
                else if (profiles[profileIdx].IsTransfer)
                { // this profile respresent an arrival via a transfers from a given stop.
                    trips.Add(null);
                    previousStopId = profiles[profileIdx].PreviousStopId;

                    // get next profiles.
                    profiles   = _search.GetStopProfiles(previousStopId);
                    profileIdx = profiles.GetLeastTransfers();

                    // add stop.
                    stops.Add(new Tuple <uint, StopProfile>(previousStopId, profiles[profileIdx]));
                }
                else
                { // no previous connection or stop or first, what is this?
                    throw new Exception("A profile was found as part of the path that is not a transfer, connection or first.");
                }
            }

            // reverse stops/connections.
            stops.Reverse();
            trips.Reverse();

            if (_intermediateStops)
            { // expand trips.
                for (var i = 0; i < trips.Count; i++)
                {
                    if (trips[i].HasValue)
                    { // there is a trip, expand it.
                        var lastStop  = stops[i + 1].Item1;
                        var firstStop = stops[i].Item1;
                        if (!stops[i + 1].Item2.IsConnection)
                        {
                            throw new Exception("Last stop of a trip is not a connection, it should be.");
                        }
                        var connection = stops[i + 1].Item2.PreviousConnectionId;
                        connectionEnumerator.MoveTo(connection);
                        var firstI = i;
                        while (true)
                        { // add departure stop of connection if it doesn't equal the first stop.
                            if (firstStop == connectionEnumerator.DepartureStop)
                            {
                                break;
                            }
                            if (!connectionEnumerator.MoveToPreviousConnection())
                            {
                                throw new Exception("There has to be a previous stop, have not reached the first stop for this trip yet.");
                            }
                            stops.Insert(firstI + 1, new Tuple <uint, StopProfile>(connectionEnumerator.ArrivalStop, new StopProfile()
                            {
                                PreviousConnectionId = connectionEnumerator.Id,
                                Seconds = connectionEnumerator.ArrivalTime
                            }));
                            trips.Insert(i, trips[i].Value);
                            i++;
                        }
                    }
                }
            }

            // set the duration.
            _duration = stops[stops.Count - 1].Item2.Seconds -
                        stops[0].Item2.Seconds;

            // keep stops.
            _stops = new List <uint>();
            for (var i = 0; i < stops.Count; i++)
            {
                _stops.Add(stops[i].Item1);
            }

            // convert the stop and connection sequences into an actual route.
            // _route = new Route();
            var routeShape      = new List <Coordinate>();
            var routeShapeMetas = new List <Route.Meta>();
            var routeStops      = new List <Route.Stop>();

            // get the first stop.
            if (!stopEnumerator.MoveTo(stops[0].Item1))
            {
                throw new Exception(string.Format("Stop {0} not found.", stops[0].Item1));
            }
            routeShape.Add(new Coordinate(stopEnumerator.Latitude, stopEnumerator.Longitude));
            var attributes = new AttributeCollection();

            attributes.AddOrReplace(Constants.TimeOfDayKey, stops[0].Item2.Seconds.ToInvariantString());
            routeShapeMetas.Add(new Route.Meta()
            {
                Attributes = attributes,
                Shape      = 0
            });
            var stopAttributes = _search.Db.StopAttributes.Get(stopEnumerator.MetaId);

            routeStops.Add(new Route.Stop()
            {
                Shape      = 0,
                Attributes = stopAttributes,
                Coordinate = new Coordinate(stopEnumerator.Latitude, stopEnumerator.Longitude)
            });

            var departureTime = stops[0].Item2.Seconds;

            for (int idx = 1; idx < stops.Count; idx++)
            {
                // get the next ...->trip->stop->... pair.
                var trip = trips[idx - 1];
                if (!stopEnumerator.MoveTo(stops[idx].Item1))
                {
                    throw new Exception(string.Format("Stop {0} not found.", stops[0].Item1));
                }

                // add shapepoints between stops if present.
                var shapePoints = _search.Db.ShapesDb.Get(stops[idx - 1].Item1, stops[idx].Item1);
                if (shapePoints != null)
                {
                    foreach (var shapePoint in shapePoints)
                    {
                        routeShape.Add(new Coordinate(shapePoint.Latitude, shapePoint.Longitude));
                    }
                }

                // add stop shapepoint.
                routeShape.Add(new Coordinate(stopEnumerator.Latitude, stopEnumerator.Longitude));

                // add stop.
                stopAttributes = _search.Db.StopAttributes.Get(stopEnumerator.MetaId);
                routeStops.Add(new Route.Stop()
                {
                    Shape      = routeShape.Count - 1,
                    Attributes = stopAttributes,
                    Coordinate = new Coordinate(stopEnumerator.Latitude, stopEnumerator.Longitude)
                });

                // add timing info.
                attributes = new AttributeCollection();
                attributes.AddOrReplace(Constants.TimeOfDayKey, stops[idx].Item2.Seconds.ToInvariantString());

                // get route information.
                if (trip == null)
                {
                    if (idx == 1)
                    { // first trip null is waiting period.
                        var meta = new Route.Meta()
                        {
                            Shape      = routeShape.Count - 1,
                            Attributes = attributes
                        };
                        meta.Time    = stops[idx].Item2.Seconds - departureTime;
                        meta.Profile = Constants.WaitProfile;
                        routeShapeMetas.Add(meta);
                    }
                    else if (routeShapeMetas[routeShapeMetas.Count - 1].Profile == Constants.TransferProfile)
                    { // a waiting period.
                        var meta = new Route.Meta()
                        {
                            Shape      = routeShape.Count - 1,
                            Attributes = attributes
                        };
                        meta.Time    = stops[idx].Item2.Seconds - departureTime;
                        meta.Profile = Constants.WaitProfile;
                        routeShapeMetas.Add(meta);
                    }
                    else
                    { // a regular transfer.
                        var meta = new Route.Meta()
                        {
                            Shape      = routeShape.Count - 1,
                            Attributes = attributes
                        };
                        meta.Time    = stops[idx].Item2.Seconds - departureTime;
                        meta.Profile = Constants.TransferProfile;
                        routeShapeMetas.Add(meta);
                    }
                }
                else
                {
                    if (!tripEnumerator.MoveTo(trip.Value))
                    {
                        throw new Exception(string.Format("Trip {0} not found.", connectionEnumerator.TripId));
                    }

                    attributes.AddOrReplaceWithPrefix("trip_", _search.Db.TripAttributes.Get(tripEnumerator.MetaId));
                    attributes.AddOrReplaceWithPrefix("agency_", _search.Db.AgencyAttributes.Get(tripEnumerator.AgencyId));

                    var meta = new Route.Meta()
                    {
                        Shape      = routeShape.Count - 1,
                        Attributes = attributes
                    };
                    meta.Time    = stops[idx].Item2.Seconds - departureTime;
                    meta.Profile = Constants.VehicleProfile;
                    routeShapeMetas.Add(meta);
                }
            }

            // build actual route.
            _route           = new Route();
            _route.Shape     = routeShape.ToArray();
            _route.ShapeMeta = routeShapeMetas.ToArray();
            _route.Stops     = routeStops.ToArray();
            if (_route.ShapeMeta.Length > 0)
            {
                _route.TotalDistance = _route.ShapeMeta[_route.ShapeMeta.Length - 1].Distance;
                _route.TotalTime     = _route.ShapeMeta[_route.ShapeMeta.Length - 1].Time;
            }

            this.HasSucceeded = true;
        }
Example #7
0
        /// <summary>
        /// Exectes the actual run of the algorithm.
        /// </summary>
        protected override void DoRun()
        {
            if (_route.Shape == null ||
                _route.Shape.Length == 0 ||
                _route.ShapeMeta == null ||
                _route.ShapeMeta.Length == 0)
            {
                return;
            }

            _aggregatedRoute = new Route();
            if (_route.Attributes != null)
            {
                _aggregatedRoute.Attributes = new AttributeCollection(_route.Attributes);
            }
            _aggregatedRoute.Shape = _route.Shape.Clone() as Coordinate[];
            if (_route.Stops != null)
            {
                _aggregatedRoute.Stops = new Route.Stop[_route.Stops.Length];
                for (var s = 0; s < _route.Stops.Length; s++)
                {
                    _aggregatedRoute.Stops[s] = _route.Stops[s].Clone();
                }
            }
            if (_route.Branches != null)
            {
                _aggregatedRoute.Branches = new Route.Branch[_route.Branches.Length];
                for (var s = 0; s < _route.Branches.Length; s++)
                {
                    _aggregatedRoute.Branches[s] = _route.Branches[s].Clone();
                }
            }

            Route.Meta current = null;
            var        metas   = new List <Route.Meta>();

            if (_route.ShapeMeta[0].Shape == 0)
            {
                metas.Add(_route.ShapeMeta[0].Clone());
            }
            for (int i = 1; i < _route.ShapeMeta.Length; i++)
            {
                // try to aggregate.
                if (current == null)
                { // there is no current yet, set it.
                    current = _route.ShapeMeta[i].Clone();
                }
                else
                {                                                              // try to merge the current segment with the next one.
                    var aggregated = _aggregate(current, _route.ShapeMeta[i]); // expecting an already new object.
                    if (aggregated == null)
                    {                                                          // the current segment could not be merged with the next, add it to the final route.
                        metas.Add(current);

                        current = _route.ShapeMeta[i].Clone();
                    }
                    else
                    {                                                 // keep the aggregated as current.
                        aggregated.Shape = _route.ShapeMeta[i].Shape; // make sure to set the shape-index correctly.
                        current          = aggregated;
                    }
                }
            }

            if (current != null)
            { // add the final segment.
                metas.Add(current);
            }

            _aggregatedRoute.ShapeMeta = metas.ToArray();

            this.HasSucceeded = true;
        }