コード例 #1
0
        /// <summary>
        /// Calculates the distance to one of the vertices on the edge this router point is on.
        /// </summary>
        /// <returns></returns>
        public static float DistanceTo(this RouterPoint point, RouterDb routerDb, uint vertex)
        {
            var geometricEdge  = routerDb.Network.GeometricGraph.GetEdge(point.EdgeId);
            var edgeDistance   = routerDb.Network.GeometricGraph.Length(geometricEdge);
            var offsetDistance = edgeDistance * ((float)point.Offset / (float)ushort.MaxValue);

            if (geometricEdge.From == vertex)
            { // offset = distance.
                return(offsetDistance);
            }
            else if (geometricEdge.To == vertex)
            { // offset = 100 - distance.
                return(edgeDistance - offsetDistance);
            }
            throw new ArgumentOutOfRangeException(string.Format("Vertex {0} is not part of edge {1}.",
                                                                vertex, point.EdgeId));
        }
コード例 #2
0
        /// <summary>
        /// Snaps to an edge closest to the given coordinates.
        /// </summary>
        /// <param name="routerDb">The router db.</param>
        /// <param name="longitude">The longitude.</param>
        /// <param name="latitude">The latitude.</param>
        /// <param name="maxOffsetInMeter">The maximum offset in meter.</param>
        /// <param name="profile">The profile to snap for.</param>
        /// <returns>The snap point.</returns>
        public static Result <SnapPoint> Snap(this RouterDb routerDb, double longitude, double latitude, float maxOffsetInMeter = 1000,
                                              Profile profile = null)
        {
            ProfileHandler profileHandler = null;

            if (profile != null)
            {
                profileHandler = routerDb.GetProfileHandler(profile);
            }

            var offset = 100;

            while (offset < maxOffsetInMeter)
            {
                // calculate search box.
                var offsets         = (new Coordinate(longitude, latitude)).OffsetWithDistances(maxOffsetInMeter);
                var latitudeOffset  = System.Math.Abs(latitude - offsets.Latitude);
                var longitudeOffset = System.Math.Abs(longitude - offsets.Longitude);
                var box             = (longitude - longitudeOffset, latitude - latitudeOffset, longitude + longitudeOffset,
                                       latitude + latitudeOffset);

                // make sure data is loaded.
                routerDb.DataProvider?.TouchBox(box);

                // snap to closest edge.
                var snapPoint = routerDb.SnapInBox(box, (eEnum) =>
                {
                    if (profileHandler == null)
                    {
                        return(true);
                    }

                    profileHandler.MoveTo(eEnum);
                    var canStop = profileHandler.CanStop;

                    return(canStop);
                });
                if (snapPoint.EdgeId != uint.MaxValue)
                {
                    return(snapPoint);
                }

                offset *= 2;
            }
            return(new Result <SnapPoint>($"Could not snap to location: {longitude},{latitude}"));
        }
コード例 #3
0
        /// <summary>
        /// Gets the get restriction function for the given profile.
        /// </summary>
        /// <param name="db">The router db.</param>
        /// <param name="profile">The vehicle profile.</param>
        /// <param name="first">When true, only restrictions starting with given vertex, when false only restrictions ending with given vertex already reversed, when null all restrictions are returned.</param>
        public static Func <uint, IEnumerable <uint[]> > GetGetRestrictions(this RouterDb db, Profiles.Profile profile, bool?first)
        {
            var vehicleTypes = new List <string>(profile.VehicleType);

            vehicleTypes.Insert(0, string.Empty);
            return((vertex) =>
            {
                var restrictionList = new List <uint[]>();
                for (var i = 0; i < vehicleTypes.Count; i++)
                {
                    RestrictionsDb restrictionsDb;
                    if (db.TryGetRestrictions(vehicleTypes[i], out restrictionsDb))
                    {
                        var enumerator = restrictionsDb.GetEnumerator();
                        if (enumerator.MoveTo(vertex))
                        {
                            while (enumerator.MoveNext())
                            {
                                if (first.HasValue && first.Value)
                                {
                                    if (enumerator[0] == vertex)
                                    {
                                        restrictionList.Add(enumerator.ToArray());
                                    }
                                }
                                else if (first.HasValue && !first.Value)
                                {
                                    if (enumerator[(int)enumerator.Count - 1] == vertex)
                                    {
                                        var array = enumerator.ToArray();
                                        array.Reverse();
                                        restrictionList.Add(array);
                                    }
                                }
                                else
                                {
                                    restrictionList.Add(enumerator.ToArray());
                                }
                            }
                        }
                    }
                }
                return restrictionList;
            });
        }
コード例 #4
0
        /// <summary>
        /// Writes a linestring-geometry for the edge currently in the enumerator.
        /// </summary>
        private static void WriteEdge(this RouterDb db, JsonWriter jsonWriter, RoutingNetwork.EdgeEnumerator edgeEnumerator)
        {
            var edgeAttributes = new Itinero.Attributes.AttributeCollection(db.EdgeMeta.Get(edgeEnumerator.Data.MetaId));

            edgeAttributes.AddOrReplace(db.EdgeProfiles.Get(edgeEnumerator.Data.Profile));

            var shape = db.Network.GetShape(edgeEnumerator.Current);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Feature", true, false);
            jsonWriter.WritePropertyName("geometry", false);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "LineString", true, false);
            jsonWriter.WritePropertyName("coordinates", false);
            jsonWriter.WriteArrayOpen();

            foreach (var coordinate in shape)
            {
                jsonWriter.WriteArrayOpen();
                jsonWriter.WriteArrayValue(coordinate.Longitude.ToInvariantString());
                jsonWriter.WriteArrayValue(coordinate.Latitude.ToInvariantString());
                jsonWriter.WriteArrayClose();
            }

            jsonWriter.WriteArrayClose();
            jsonWriter.WriteClose();

            jsonWriter.WritePropertyName("properties");
            jsonWriter.WriteOpen();
            if (edgeAttributes != null)
            {
                foreach (var attribute in edgeAttributes)
                {
                    jsonWriter.WriteProperty(attribute.Key, attribute.Value, true, true);
                }
            }
            jsonWriter.WriteProperty("edgeid", edgeEnumerator.Id.ToInvariantString());
            jsonWriter.WriteProperty("vertex1", edgeEnumerator.From.ToInvariantString());
            jsonWriter.WriteProperty("vertex2", edgeEnumerator.To.ToInvariantString());
            jsonWriter.WriteClose();

            jsonWriter.WriteClose();
        }
コード例 #5
0
        /// <summary>
        /// Builds an edge path from a path consisiting of only vertices.
        /// </summary>
        public static EdgePath <T> BuildEdgePath <T>(this RouterDb routerDb, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, List <uint> vertexPath)
            where T : struct
        {
            if (vertexPath == null || vertexPath.Count == 0)
            {
                return(null);
            }

            var path = new EdgePath <T>(vertexPath[0]);
            var i    = 1;

            if (path.Vertex == Constants.NO_VERTEX)
            { // add first router point segment from source.
                path = source.EdgePathTo(routerDb, weightHandler, vertexPath[1]);
                i    = 2;
            }

            var edgeEnumerator = routerDb.Network.GeometricGraph.Graph.GetEdgeEnumerator();

            for (; i < vertexPath.Count; i++)
            {
                var vertex = vertexPath[i];
                if (vertex == Constants.NO_VERTEX)
                {
                    if (i != vertexPath.Count - 1)
                    {
                        throw new Exception("Invalid data found in vertex path: a non-vertex id was found at an invalid location.");
                    }
                    var toTarget = target.EdgePathTo(routerDb, weightHandler, path.Vertex, true);
                    path = new EdgePath <T>(toTarget.Vertex, weightHandler.Add(toTarget.Weight, path.Weight), toTarget.Edge, path);
                    break;
                }
                T   weight;
                var best = edgeEnumerator.FindBestEdge(weightHandler, path.Vertex, vertexPath[i], out weight);
                if (best == Constants.NO_EDGE)
                {
                    throw new Exception(string.Format("Cannot build vertex path, edge {0} -> {1} not found.", path.Vertex, vertexPath[i]));
                }

                path = new EdgePath <T>(vertexPath[i], weightHandler.Add(weight, path.Weight), best, path);
            }
            return(path);
        }
コード例 #6
0
        /// <summary>
        /// Calculates the edge path between this router point and the given router point.
        /// </summary>
        /// <param name="point">The source point.</param>
        /// <param name="db">The router db.</param>
        /// <param name="weightHandler">The weight handler.</param>
        /// <param name="target">The target point.</param>
        /// <param name="backward">Forces the direction on the edge to travel in.</param>
        public static EdgePath <T> EdgePathTo <T>(this RouterPoint point, RouterDb db, WeightHandler <T> weightHandler, RouterPoint target, bool backward = false)
            where T : struct
        {
            if (point.EdgeId != target.EdgeId)
            {
                throw new ArgumentException("Target point must be part of the same edge.");
            }

            if (point.Offset == target.Offset)
            { // two points are identical, path of length '0'.
                return(new EdgePath <T>(point.VertexId(db)));
            }

            var forward = point.Offset < target.Offset;

            if (forward && backward)
            { // forward travel is required but backward travel is requested.
                return(null);
            }

            var edge     = db.Network.GetEdge(point.EdgeId);
            var distance = ((float)System.Math.Abs((int)point.Offset - (int)target.Offset) / (float)ushort.MaxValue) *
                           edge.Data.Distance;
            Factor factor;
            var    weight = weightHandler.Calculate(edge.Data.Profile, distance, out factor);

            if (factor.Value <= 0)
            { // not possible to travel here.
                return(null);
            }
            if (factor.Direction == 0 ||
                (forward && factor.Direction == 1) ||
                (!forward && factor.Direction == 2))
            { // ok, directions match.
                if (forward)
                {
                    return(new EdgePath <T>(target.VertexId(db), weight, point.EdgeId + 1, new EdgePath <T>(point.VertexId(db))));
                }
                return(new EdgePath <T>(target.VertexId(db), weight, -point.EdgeId - 1, new EdgePath <T>(point.VertexId(db))));
            }
            return(null);
        }
コード例 #7
0
 /// <summary>
 /// Calculates the edge path between this router point and the given router point.
 /// </summary>
 /// <param name="point">The source point.</param>
 /// <param name="db">The router db.</param>
 /// <param name="weightHandler">The weight handler.</param>
 /// <param name="sourceForward">The source forward flag, true if forward, false if backward, null if don't care.</param>
 /// <param name="target">The target point.</param>
 /// <param name="targetForward">The target forward flag, true if forward, false if backward, null if don't care.</param>
 public static EdgePath <T> EdgePathTo <T>(this RouterPoint point, RouterDb db, WeightHandler <T> weightHandler, bool?sourceForward, RouterPoint target, bool?targetForward)
     where T : struct
 {
     if (!sourceForward.HasValue && !targetForward.HasValue)
     {
         return(point.EdgePathTo(db, weightHandler, target));
     }
     if (sourceForward.HasValue && targetForward.HasValue)
     {
         if (sourceForward.Value != targetForward.Value)
         { // impossible route inside one edge.
             return(null);
         }
     }
     if (sourceForward.HasValue)
     {
         return(point.EdgePathTo(db, weightHandler, target, !sourceForward.Value));
     }
     return(point.EdgePathTo(db, weightHandler, target, !targetForward.Value));
 }
コード例 #8
0
        /// <summary>
        /// Returns one attribute collection containing both the profile and meta tags.
        /// </summary>
        public static IAttributeCollection GetProfileAndMeta(this RouterDb db, uint profileId, uint meta)
        {
            var tags = new AttributeCollection();

            var metaTags = db.EdgeMeta.Get(meta);

            if (metaTags != null)
            {
                tags.AddOrReplace(metaTags);
            }

            var profileTags = db.EdgeProfiles.Get(profileId);

            if (profileTags != null)
            {
                tags.AddOrReplace(profileTags);
            }

            return(tags);
        }
コード例 #9
0
        /// <summary>
        /// Calculates the shape points along the way from this router point to one of it's vertices.
        /// </summary>
        public static List <Coordinate> ShapePointsTo(this RouterPoint point, RouterDb routerDb, uint vertex)
        {
            List <Coordinate> points = null;
            var geometricEdge        = routerDb.Network.GeometricGraph.GetEdge(point.EdgeId);
            var edgeDistance         = routerDb.Network.GeometricGraph.Length(geometricEdge);
            var offsetDistance       = edgeDistance * ((float)point.Offset / (float)ushort.MaxValue);

            if (geometricEdge.From == vertex)
            { // offset = distance.
                points = routerDb.Network.GeometricGraph.GetShape(geometricEdge, vertex, offsetDistance);
                points.Reverse();
                return(points);
            }
            else if (geometricEdge.To == vertex)
            { // offset = 100 - distance.
                points = routerDb.Network.GeometricGraph.GetShape(geometricEdge, vertex, edgeDistance - offsetDistance);
                points.Reverse();
                return(points);
            }
            throw new ArgumentOutOfRangeException(string.Format("Vertex {0} is not part of edge {1}.",
                                                                vertex, point.EdgeId));
        }
コード例 #10
0
        /// <summary>
        /// Generates an edge path for the given edge.
        /// </summary>
        public static EdgePath <T> GetPathForEdge <T>(this RouterDb routerDb, WeightHandler <T> weightHandler, RoutingEdge edge, bool edgeForward, bool asSource)
            where T : struct
        {
            var weight = weightHandler.Calculate(edge.Data.Profile, edge.Data.Distance);

            if (asSource)
            {
                if (edgeForward)
                {
                    return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From)));
                }
                return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To)));
            }
            else
            {
                if (edgeForward)
                {
                    return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To)));
                }
                return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From)));
            }
        }
コード例 #11
0
        /// <summary>
        /// Determines the direction from the given angle, true meaning forward relative to the edge in the routerpoint, false backwards.
        /// </summary>
        /// <param name="routerPoint">The router point.</param>
        /// <param name="routerDb">The router db.</param>
        /// <param name="angle">The angle in degrees relative to the longitudinal lines.</param>
        /// <param name="diffLimit">The diff limit when the angle is smaller than this we consider it the same direction.</param>
        /// <returns>True when forward, false when backward, null when direction couldn't be determined (outside of difflimit for example).</returns>
        public static bool?DirectionFromAngle(this RouterPoint routerPoint, RouterDb routerDb, float?angle, float diffLimit = 90)
        {
            if (diffLimit <= 0 || diffLimit > 90)
            {
                throw new ArgumentOutOfRangeException(nameof(diffLimit), "Expected to be in range ]0, 90].");
            }
            if (routerDb == null)
            {
                throw new ArgumentNullException(nameof(routerDb));
            }
            if (routerPoint == null)
            {
                throw new ArgumentNullException(nameof(routerPoint));
            }
            if (angle == null)
            {
                return(null);
            }

            angle = (float)Tools.NormalizeDegrees(angle.Value);
            var edgeAngle = routerPoint.Angle(routerDb.Network);

            if (edgeAngle == null)
            {
                return(null);                   // no angle could be determined, for example on extremely short edges.
            }
            var diff = System.Math.Abs(Itinero.LocalGeo.Tools.SmallestDiffDegrees(angle.Value, edgeAngle.Value));

            if (diff < diffLimit)
            { // forward, angle is close to that of the edge.
                return(true);
            }
            if (180 - diff < diffLimit)
            { // backward, angle is close to the anti-direction of the edge.
                return(false);
            }
            return(null);
        }
コード例 #12
0
        /// <summary>
        /// Writes a point-geometry for the given vertex.
        /// </summary>
        private static void WriteVertex(this RouterDb db, JsonWriter jsonWriter, uint vertex)
        {
            var coordinate = db.Network.GetVertex(vertex);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Feature", true, false);
            jsonWriter.WritePropertyName("geometry", false);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Point", true, false);
            jsonWriter.WritePropertyName("coordinates", false);
            jsonWriter.WriteArrayOpen();
            jsonWriter.WriteArrayValue(coordinate.Longitude.ToInvariantString());
            jsonWriter.WriteArrayValue(coordinate.Latitude.ToInvariantString());
            jsonWriter.WriteArrayClose();
            jsonWriter.WriteClose();

            jsonWriter.WritePropertyName("properties");
            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("id", vertex.ToInvariantString());
            jsonWriter.WriteClose();

            jsonWriter.WriteClose();
        }
コード例 #13
0
 internal RouterDbEdgeEnumerator(RouterDb routerDb, EdgeEnumerator edgeEnumerator)
 {
     _routerDb       = routerDb ?? throw new ArgumentNullException(nameof(routerDb));
     _edgeEnumerator = edgeEnumerator ?? throw new ArgumentNullException(nameof(edgeEnumerator));;
 }
コード例 #14
0
 /// <summary>
 /// Returns true if this db contains complex restrictions for the given profile.
 /// </summary>
 public static bool HasComplexRestrictions(this RouterDb db, Profiles.Profile profile)
 {
     return(db.HasComplexRestrictions(profile.VehicleType));
 }
コード例 #15
0
        /// <summary>
        /// Returns true if this db contains restrictions for the given vehicle type.
        /// </summary>
        public static bool HasRestrictions(this RouterDb db, string vehicleType)
        {
            RestrictionsDb restrictions;

            return(db.TryGetRestrictions(vehicleType, out restrictions));
        }
コード例 #16
0
 /// <summary>
 /// Deserializes a database from the given stream.
 /// </summary>
 public static RouterDb Deserialize(Stream stream)
 {
     return(RouterDb.Deserialize(stream, null));
 }
コード例 #17
0
        /// <summary>
        /// Creates a new contracted graph and adds it to the router db for the given profile.
        /// </summary>
        public static void AddContracted <T>(this RouterDb db, Profiles.Profile profile, WeightHandler <T> weightHandler, bool forceEdgeBased = false)
            where T : struct
        {
            // create the raw directed graph.
            ContractedDb contractedDb = null;

            if (!forceEdgeBased)
            {     // check if there are complex restrictions in the routerdb forcing edge-based contraction.
                if (db.HasComplexRestrictions(profile))
                { // there are complex restrictions, use edge-based contraction, the only way to support these in a contracted graph.
                    forceEdgeBased = true;
                }
            }

            lock (db)
            {
                if (forceEdgeBased)
                { // edge-based is needed when complex restrictions found.
                    var contracted           = new DirectedDynamicGraph(weightHandler.DynamicSize);
                    var directedGraphBuilder = new Itinero.Algorithms.Contracted.EdgeBased.DirectedGraphBuilder <T>(db.Network.GeometricGraph.Graph, contracted,
                                                                                                                    weightHandler);
                    directedGraphBuilder.Run();

                    // contract the graph.
                    var priorityCalculator = new Itinero.Algorithms.Contracted.EdgeBased.EdgeDifferencePriorityCalculator <T>(contracted, weightHandler,
                                                                                                                              new Itinero.Algorithms.Contracted.EdgeBased.Witness.DykstraWitnessCalculator <T>(weightHandler, 4, 64));
                    priorityCalculator.DifferenceFactor = 5;
                    priorityCalculator.DepthFactor      = 5;
                    priorityCalculator.ContractedFactor = 8;
                    var hierarchyBuilder = new Itinero.Algorithms.Contracted.EdgeBased.HierarchyBuilder <T>(contracted, priorityCalculator,
                                                                                                            new Itinero.Algorithms.Contracted.EdgeBased.Witness.DykstraWitnessCalculator <T>(weightHandler, int.MaxValue, 64), weightHandler, db.GetGetRestrictions(profile, null));
                    hierarchyBuilder.Run();

                    contractedDb = new ContractedDb(contracted);
                }
                else
                { // vertex-based is ok when no complex restrictions found.
                    var contracted           = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size, weightHandler.MetaSize);
                    var directedGraphBuilder = new DirectedGraphBuilder <T>(db.Network.GeometricGraph.Graph, contracted, weightHandler);
                    directedGraphBuilder.Run();

                    // contract the graph.
                    var priorityCalculator = new EdgeDifferencePriorityCalculator(contracted,
                                                                                  new DykstraWitnessCalculator(int.MaxValue));
                    priorityCalculator.DifferenceFactor = 5;
                    priorityCalculator.DepthFactor      = 5;
                    priorityCalculator.ContractedFactor = 8;
                    var hierarchyBuilder = new HierarchyBuilder <T>(contracted, priorityCalculator,
                                                                    new DykstraWitnessCalculator(int.MaxValue), weightHandler);
                    hierarchyBuilder.Run();

                    contractedDb = new ContractedDb(contracted);
                }
            }

            // add the graph.
            lock (db)
            {
                db.AddContracted(profile, contractedDb);
            }
        }
コード例 #18
0
 /// <summary>
 /// Returns true if the given profile is supported.
 /// </summary>
 public static bool Supports(this RouterDb db, Profiles.Profile profile)
 {
     return(db.Supports(profile.Parent.Name));
 }
コード例 #19
0
 /// <summary>
 /// Gets all features inside the given bounding box and writes them as a geojson string.
 /// </summary>
 public static void WriteGeoJson(this RouterDb db, Stream stream, float minLatitude, float minLongitude,
                                 float maxLatitude, float maxLongitude, bool includeEdges = true, bool includeVertices = true)
 {
     db.WriteGeoJson(new StreamWriter(stream), minLatitude, minLongitude, maxLatitude, maxLongitude, includeEdges, includeVertices);
 }
コード例 #20
0
 /// <summary>
 /// Returns the location on the network.
 /// </summary>
 public static Coordinate LocationOnNetwork(this RouterPoint point, RouterDb db)
 {
     return(db.LocationOnNetwork(point.EdgeId, point.Offset));
 }
コード例 #21
0
        /// <summary>
        /// Converts the router point to paths leading to the closest 2 vertices.
        /// </summary>
        public static EdgePath <T>[] ToEdgePaths <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource)
            where T : struct
        {
            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            float  distance;
            ushort profileId;

            EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profileId);
            Factor factor;
            var    edgeWeight = weightHandler.Calculate(profileId, distance, out factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            {     // bidirectional.
                if (offset == 0)
                { // the first part is just the first vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From),
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                    });
                }
                else if (offset == 1)
                { // the second path it just the second vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To)),
                        new EdgePath <T>(edge.To)
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>()),
                    new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway.
                if (asSource)
                {
                    if (offset == 1)
                    { // just return the to-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To)
                        });
                    }
                    if (offset == 0)
                    { // return both, we are at the from-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.From),
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                        });
                    }
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                if (offset == 0)
                { // just return the from vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From)
                    });
                }
                if (offset == 1)
                { // return both, we are at the to-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To),
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To))
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else
            { // edge is backward oneway.
                if (!asSource)
                {
                    if (offset == 1)
                    { // just return the to-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To)
                        });
                    }
                    if (offset == 0)
                    { // return both, we are at the from-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.From),
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                        });
                    }
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                if (offset == 0)
                { // just return the from-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From)
                    });
                }
                if (offset == 1)
                { // return both, we are at the to-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To),
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To))
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
        }
コード例 #22
0
 /// <summary>
 /// Creates a new contracted graph and adds it to the router db for the given profile.
 /// </summary>
 public static void AddContracted(this RouterDb db, Profiles.Profile profile, bool forceEdgeBased = false)
 {
     db.AddContracted <float>(profile, profile.DefaultWeightHandlerCached(db), forceEdgeBased);
 }
コード例 #23
0
        /// <summary>
        /// Creates a new router point.
        /// </summary>
        public static RouterPoint CreateRouterPoint(this RouterDb routerDb, uint edgeId, ushort offset)
        {
            var location = routerDb.LocationOnNetwork(edgeId, offset);

            return(new RouterPoint(location.Latitude, location.Longitude, edgeId, offset));
        }
コード例 #24
0
        /// <summary>
        /// Writes geojson describing the given routerpoint.
        /// </summary>
        internal static void WriteGeoJson(this RouterPoint routerPoint, TextWriter writer, RouterDb db)
        {
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            var jsonWriter = new JsonWriter(writer);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "FeatureCollection", true, false);
            jsonWriter.WritePropertyName("features", false);
            jsonWriter.WriteArrayOpen();

            var edgeEnumerator = db.Network.GetEdgeEnumerator();

            edgeEnumerator.MoveToEdge(routerPoint.EdgeId);

            db.WriteEdge(jsonWriter, edgeEnumerator);

            db.WriteVertex(jsonWriter, edgeEnumerator.From);
            db.WriteVertex(jsonWriter, edgeEnumerator.To);

            // write location on network.
            var coordinate = routerPoint.LocationOnNetwork(db);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Feature", true, false);
            jsonWriter.WritePropertyName("geometry", false);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Point", true, false);
            jsonWriter.WritePropertyName("coordinates", false);
            jsonWriter.WriteArrayOpen();
            jsonWriter.WriteArrayValue(coordinate.Longitude.ToInvariantString());
            jsonWriter.WriteArrayValue(coordinate.Latitude.ToInvariantString());
            jsonWriter.WriteArrayClose();
            jsonWriter.WriteClose();

            jsonWriter.WritePropertyName("properties");
            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "location_on_network", true);
            jsonWriter.WriteProperty("offset", routerPoint.Offset.ToInvariantString());
            jsonWriter.WriteClose();

            jsonWriter.WriteClose();

            // write original location.
            coordinate = routerPoint.Location();
            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Feature", true, false);
            jsonWriter.WritePropertyName("geometry", false);

            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "Point", true, false);
            jsonWriter.WritePropertyName("coordinates", false);
            jsonWriter.WriteArrayOpen();
            jsonWriter.WriteArrayValue(coordinate.Longitude.ToInvariantString());
            jsonWriter.WriteArrayValue(coordinate.Latitude.ToInvariantString());
            jsonWriter.WriteArrayClose();
            jsonWriter.WriteClose();

            jsonWriter.WritePropertyName("properties");
            jsonWriter.WriteOpen();
            jsonWriter.WriteProperty("type", "original_location", true);
            jsonWriter.WriteClose();

            jsonWriter.WriteClose();


            jsonWriter.WriteArrayClose();
            jsonWriter.WriteClose();
        }
コード例 #25
0
        internal RouterDbEdgeEnumerator(RouterDb routerDb)
        {
            _routerDb = routerDb ?? throw new ArgumentNullException(nameof(routerDb));

            _enumerator = _routerDb.Network.GetEnumerator();
        }
コード例 #26
0
        /// <summary>
        /// Deserializes a database from the given stream.
        /// </summary>
        public static RouterDb Deserialize(Stream stream, RouterDbProfile profile)
        {
            // deserialize all basic data.
            // version1: OsmSharp.Routing state of layout.
            // version2: Added ShortcutsDbs.
            // version3: Add advanced profile serialization.
            // version4: Added missing restriction dbs.
            var version = stream.ReadByte();

            if (version != 1 && version != 2 && version != 3 && version != 4)
            {
                throw new Exception(string.Format("Cannot deserialize routing db: Invalid version #: {0}.", version));
            }

            var guidBytes = new byte[16];

            stream.Read(guidBytes, 0, 16);
            var guid = new Guid(guidBytes);

            var supportedVehicleInstances = new List <Vehicle>();

            if (version <= 2)
            { // just contains vehicle names.
                var supportedVehicles = stream.ReadWithSizeStringArray();
                foreach (var vehicleName in supportedVehicles)
                {
                    Profile vehicleProfile;
                    if (Profile.TryGet(vehicleName, out vehicleProfile))
                    {
                        supportedVehicleInstances.Add(vehicleProfile.Parent);
                    }
                    else
                    {
                        Itinero.Logging.Logger.Log("RouterDb", Logging.TraceEventType.Warning, "Vehicle with name {0} was not found, register all vehicle profiles before deserializing the router db.",
                                                   vehicleName);
                    }
                }
            }
            else
            { // contains the full vehicles.
                var lengthBytes = new byte[4];
                stream.Read(lengthBytes, 0, 4);
                var size = BitConverter.ToInt32(lengthBytes, 0);
                for (var i = 0; i < size; i++)
                {
                    var vehicle = Vehicle.Deserialize(stream);
                    supportedVehicleInstances.Add(vehicle);
                    vehicle.Register();
                }
            }

            var metaDb        = stream.ReadWithSizeAttributesCollection();
            var shorcutsCount = (int)0;

            if (version >= 2)
            { // when version < 1 there are no shortcuts and thus no shortcut count.
                shorcutsCount = stream.ReadByte();
            }
            var contractedCount = stream.ReadByte();

            var restrictionDbCount = 0;

            if (version >= 4)
            {
                restrictionDbCount = stream.ReadByte();
            }

            var profiles = AttributesIndex.Deserialize(new LimitedStream(stream), true);
            var meta     = AttributesIndex.Deserialize(new LimitedStream(stream), true);
            var network  = RoutingNetwork.Deserialize(stream, profile == null ? null : profile.RoutingNetworkProfile);

            // create router db.
            var routerDb = new RouterDb(guid, network, profiles, meta, metaDb, supportedVehicleInstances.ToArray());

            // read all shortcut dbs.
            for (var i = 0; i < shorcutsCount; i++)
            {
                var shortcutsName = stream.ReadWithSizeString();
                var shorcutsDb    = ShortcutsDb.Deserialize(stream);
                routerDb._shortcutsDbs[shortcutsName] = shorcutsDb;
            }

            // read all contracted versions.
            for (var i = 0; i < contractedCount; i++)
            {
                var profileName = stream.ReadWithSizeString();
                var contracted  = ContractedDb.Deserialize(stream, profile == null ? null : profile.ContractedDbProfile);
                routerDb._contracted[profileName] = contracted;
            }

            // read all restriction dbs.
            for (var i = 0; i < restrictionDbCount; i++)
            {
                var restrictionDbName = stream.ReadWithSizeString();
                var restrictionDb     = RestrictionsDb.Deserialize(stream, profile == null ? null : profile.RestrictionDbProfile);
                routerDb._restrictionDbs[restrictionDbName] = restrictionDb;
            }

            return(routerDb);
        }
コード例 #27
0
        /// <summary>
        /// Adds the router point as a vertex.
        /// </summary>
        public static uint[] AddAsVertices(this RouterDb routerDb, RouterPoint[] points)
        {
            if (routerDb.HasContracted)
            {
                throw new InvalidOperationException("Cannot add new vertices to a routerDb with contracted versions of the network.");
            }

            var edges = new HashSet <uint>();

            for (var i = 0; i < points.Length; i++)
            {
                var point = points[i];
                if (edges.Contains(point.EdgeId))
                {
                    point = null;
                }
                else
                {
                    edges.Add(point.EdgeId);
                }
            }

            var newVertices = new uint[points.Length];
            var newEdges    = new List <EdgeToSplit>();

            for (var i = 0; i < points.Length; i++)
            {
                var point = points[i];

                if (point == null)
                { // there was a duplicate edge.
                    newVertices[i] = Constants.NO_VERTEX;
                    newEdges.Add(null);
                    continue;
                }

                if (point.IsVertex())
                { // the router point is already a vertex.
                    newVertices[i] = point.VertexId(routerDb);
                    newEdges.Add(null);
                    continue;
                }

                // add a new vertex at the router point location.
                var location = point.LocationOnNetwork(routerDb);

                // add two new edges.
                var edge      = routerDb.Network.GetEdge(point.EdgeId);
                var shapeFrom = point.ShapePointsTo(routerDb, edge.From);
                shapeFrom.Reverse(); // we need this shape from edge.From -> vertex.
                var shapeTo      = point.ShapePointsTo(routerDb, edge.To);
                var distanceFrom = point.DistanceTo(routerDb, edge.From);
                var distanceTo   = point.DistanceTo(routerDb, edge.To);

                // register new edge.
                newEdges.Add(new EdgeToSplit()
                {
                    Coordinate   = location,
                    From         = edge.From,
                    To           = edge.To,
                    DistanceFrom = distanceFrom,
                    DistanceTo   = distanceTo,
                    ShapeFrom    = shapeFrom,
                    ShapeTo      = shapeTo,
                    MetaId       = edge.Data.MetaId,
                    Profile      = edge.Data.Profile
                });
            }

            for (var i = 0; i < newEdges.Count; i++)
            {
                var edgeToSplit = newEdges[i];
                if (edgeToSplit == null)
                {
                    continue;
                }

                // remove original edge.
                routerDb.Network.RemoveEdges(edgeToSplit.From, edgeToSplit.To);

                // add vertex.
                var vertex = routerDb.Network.VertexCount;
                routerDb.Network.AddVertex(vertex, edgeToSplit.Coordinate.Latitude, edgeToSplit.Coordinate.Longitude);

                // add two new pieces.
                routerDb.Network.AddEdge(edgeToSplit.From, vertex, new Data.Network.Edges.EdgeData()
                {
                    Distance = edgeToSplit.DistanceFrom,
                    MetaId   = edgeToSplit.MetaId,
                    Profile  = edgeToSplit.Profile
                }, edgeToSplit.ShapeFrom);
                routerDb.Network.AddEdge(vertex, edgeToSplit.To, new Data.Network.Edges.EdgeData()
                {
                    Distance = edgeToSplit.DistanceTo,
                    MetaId   = edgeToSplit.MetaId,
                    Profile  = edgeToSplit.Profile
                }, edgeToSplit.ShapeTo);

                newVertices[i] = vertex;
            }

            return(newVertices);
        }
コード例 #28
0
        /// <summary>
        /// Converts the router point to paths leading to the closest 2 vertices.
        /// </summary>
        public static EdgePath <T>[] ToEdgePaths <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource, bool?forward)
            where T : struct
        {
            if (forward == null)
            { // don't-care direction, use default implementation.
                return(point.ToEdgePaths(routerDb, weightHandler, asSource));
            }

            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            float  distance;
            ushort profileId;

            EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profileId);
            Factor factor;
            var    edgeWeight = weightHandler.Calculate(profileId, distance, out factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            { // bidirectional.
                if (forward.Value)
                {
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway.
                if (asSource)
                {
                    if (forward.Value)
                    {
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                        });
                    }
                    return(new EdgePath <T> [0]);
                }
                if (forward.Value)
                {
                    return(new EdgePath <T> [0]);
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else
            { // edge is backward oneway.
                if (!asSource)
                {
                    if (forward.Value)
                    {
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                        });
                    }
                    return(new EdgePath <T> [0]);
                }
                if (forward.Value)
                {
                    return(new EdgePath <T> [0]);
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
        }
コード例 #29
0
        /// <summary>
        /// Creates a router point for the given edge.
        /// </summary>
        public static RouterPoint CreateRouterPointForEdge(this RouterDb routerDb, long directedEdgeId, bool atStart)
        {
            var edge = routerDb.Network.GetEdge(directedEdgeId);

            return(routerDb.CreateRouterPointForEdge(edge, directedEdgeId > 0, atStart));
        }
コード例 #30
0
        /// <summary>
        /// Creates a new router.
        /// </summary>
        public Router(RouterDb db)
        {
            _db = db;

            this.VerifyAllStoppable = false;
        }