Ejemplo n.º 1
0
 /// <summary>
 /// Rebuilds the vertex index.
 /// </summary>
 public void RebuildVertexIndex()
 {
     _vertexIndex = new QuadTree <GeoCoordinate, uint>();
     for (uint vertex = 0; vertex <= _graph.VertexCount; vertex++)
     {
         float latitude, longitude;
         if (_graph.GetVertex(vertex, out latitude, out longitude))
         {
             _vertexIndex.Add(new GeoCoordinate(latitude, longitude),
                              vertex);
         }
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Switches the data around for the two given vertices.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        /// <param name="graph"></param>
        /// <param name="vertex1"></param>
        /// <param name="vertex2"></param>
        public static void Switch <TEdgeData>(this GraphBase <TEdgeData> graph, uint vertex1, uint vertex2)
            where TEdgeData : struct, IGraphEdgeData
        {
            // get all existing data.
            var   edges1 = new List <Edge <TEdgeData> >(graph.GetEdges(vertex1));
            var   edges2 = new List <Edge <TEdgeData> >(graph.GetEdges(vertex2));
            float vertex1Latitude, vertex1Longitude;

            graph.GetVertex(vertex1, out vertex1Latitude, out vertex1Longitude);
            float vertex2Latitude, vertex2Longitude;

            graph.GetVertex(vertex2, out vertex2Latitude, out vertex2Longitude);

            // remove all edges.
            graph.RemoveEdges(vertex1);
            graph.RemoveEdges(vertex2);

            // update location.
            graph.SetVertex(vertex1, vertex2Latitude, vertex2Longitude);
            graph.SetVertex(vertex2, vertex1Latitude, vertex1Longitude);

            // add edges again.
            foreach (var edge in edges1)
            {
                // update existing data.
                if (edge.Neighbour == vertex1)
                {
                    edge.Neighbour = vertex2;
                }
                else if (edge.Neighbour == vertex2)
                {
                    edge.Neighbour = vertex1;
                }
                graph.AddEdge(vertex2, edge.Neighbour, edge.EdgeData, edge.Intermediates);
            }
            foreach (var edge in edges2)
            {
                // update existing data.
                if (edge.Neighbour == vertex1)
                {
                    edge.Neighbour = vertex2;
                }
                else if (edge.Neighbour == vertex2)
                {
                    edge.Neighbour = vertex1;
                }
                graph.AddEdge(vertex1, edge.Neighbour, edge.EdgeData, edge.Intermediates);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the hibert distance for n and the given vertex.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        /// <param name="graph"></param>
        /// <param name="n"></param>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public static ulong HilbertDistance <TEdgeData>(this GraphBase <TEdgeData> graph, int n, uint vertex)
            where TEdgeData : struct, IGraphEdgeData
        {
            float latitude, longitude;

            graph.GetVertex(vertex, out latitude, out longitude);
            return(OsmSharp.Math.Algorithms.HilbertCurve.HilbertDistance(latitude, longitude, n));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns the hibert distance for n and the given vertex.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        /// <param name="graph"></param>
        /// <param name="n"></param>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public static long HilbertDistance <TEdgeData>(this GraphBase <TEdgeData> graph, int n, uint vertex)
            where TEdgeData : struct, IGraphEdgeData
        {
            float latitude, longitude;

            if (!graph.GetVertex(vertex, out latitude, out longitude))
            {
                throw new Exception(string.Format("Vertex {0} does not exist in graph.", vertex));
            }
            return(HilbertCurve.HilbertDistance(latitude, longitude, n));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns all hibert distances for n.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        /// <returns></returns>
        public static long[] HilbertDistances <TEdgeData>(this GraphBase <TEdgeData> graph, int n)
            where TEdgeData : struct, IGraphEdgeData
        {
            var distances = new long[graph.VertexCount];

            for (uint vertex = 1; vertex <= graph.VertexCount; vertex++)
            {
                float latitude, longitude;
                graph.GetVertex(vertex, out latitude, out longitude);
                distances[vertex - 1] = HilbertCurve.HilbertDistance(latitude, longitude, n);
            }
            return(distances);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Searches the graph for nearby vertices assuming it has been sorted.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        public static List <uint> SearchHilbert <TEdgeData>(this GraphBase <TEdgeData> graph, int n, float latitude, float longitude,
                                                            float offset)
            where TEdgeData : struct, IGraphEdgeData
        {
            var targets = HilbertCurve.HilbertDistances(
                System.Math.Max(latitude - offset, -90),
                System.Math.Max(longitude - offset, -180),
                System.Math.Min(latitude + offset, 90),
                System.Math.Min(longitude + offset, 180), n);

            targets.Sort();
            var vertices = new List <uint>();

            var   targetIdx = 0;
            var   vertex1 = (uint)1;
            var   vertex2 = (uint)graph.VertexCount;
            float vertexLat, vertexLon;

            while (targetIdx < targets.Count)
            {
                uint vertex;
                int  count;
                if (GraphExtensions.SearchHilbert(graph, targets[targetIdx], n, vertex1, vertex2, out vertex, out count))
                {         // the search was successful.
                    while (count > 0)
                    {     // there have been vertices found.
                        if (graph.GetVertex((uint)vertex + (uint)(count - 1), out vertexLat, out vertexLon))
                        { // the vertex was found.
                            if (System.Math.Abs(latitude - vertexLat) < offset &&
                                System.Math.Abs(longitude - vertexLon) < offset)
                            { // within offset.
                                vertices.Add((uint)vertex + (uint)(count - 1));
                            }
                        }
                        count--;
                    }

                    // update vertex1.
                    vertex1 = vertex;
                }

                // move to next target.
                targetIdx++;
            }
            return(vertices);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Copies all data from the given graph.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        /// <param name="copyTo"></param>
        /// <param name="copyFrom"></param>
        public static void CopyFrom <TEdgeData>(this GraphBase <TEdgeData> copyTo, GraphBase <TEdgeData> copyFrom)
            where TEdgeData : struct, IGraphEdgeData
        {
            float latitude, longitude;

            for (uint vertex = 1; vertex <= copyFrom.VertexCount; vertex++)
            {
                copyFrom.GetVertex(vertex, out latitude, out longitude);
                uint newVertex = copyTo.AddVertex(latitude, longitude);
                if (newVertex != vertex)
                {
                    throw new Exception("Graph should be empty when copy new data to it.");
                }
            }

            for (uint vertex = 1; vertex <= copyFrom.VertexCount; vertex++)
            {
                var edges = new List <Edge <TEdgeData> >(copyFrom.GetEdges(vertex));
                foreach (var edge in edges)
                {
                    copyTo.AddEdge(vertex, edge.Neighbour, edge.EdgeData, edge.Intermediates);
                }
            }
        }
 /// <summary>
 /// Returns true if a given vertex is in the graph.
 /// </summary>
 /// <returns></returns>
 public override bool GetVertex(uint id, out float latitude, out float longitude)
 {
     return(_graph.GetVertex(id, out latitude, out longitude));
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Switches the locations around for the two given vertices.
        /// </summary>
        /// <typeparam name="TEdgeData"></typeparam>
        public static void Switch <TEdgeData>(this GraphBase <TEdgeData> graph, uint vertex1, uint vertex2,
                                              IDictionary <uint, List <uint> > reverse)
            where TEdgeData : struct, IGraphEdgeData
        {
            if (graph.IsDirected && reverse == null)
            {
                throw new ArgumentException("Cannot switch two vertices on a directed graph without it's reverse index.");
            }

            if (vertex1 == vertex2)
            { // switching identical vertices (?).
                return;
            }

            float vertex1Latitude, vertex1Longitude;

            graph.GetVertex(vertex1, out vertex1Latitude, out vertex1Longitude);
            float vertex2Latitude, vertex2Longitude;

            graph.GetVertex(vertex2, out vertex2Latitude, out vertex2Longitude);

            // update location.
            graph.SetVertex(vertex1, vertex2Latitude, vertex2Longitude);
            graph.SetVertex(vertex2, vertex1Latitude, vertex1Longitude);

            // switch and update edges, this is easy!
            var edges1 = new List <Edge <TEdgeData> >();

            foreach (var edge in graph.GetEdges(vertex1))
            {
                edges1.Add(new Edge <TEdgeData>()
                {
                    EdgeData      = edge.EdgeData,
                    Neighbour     = edge.Neighbour,
                    Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>(
                        edge.Intermediates.ToSimpleArray()) : null
                });
            }
            var edges2 = new List <Edge <TEdgeData> >();

            foreach (var edge in graph.GetEdges(vertex2))
            {
                edges2.Add(new Edge <TEdgeData>()
                {
                    EdgeData      = edge.EdgeData,
                    Neighbour     = edge.Neighbour,
                    Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>(
                        edge.Intermediates.ToSimpleArray()) : null
                });
            }

            graph.RemoveEdges(vertex1);
            graph.RemoveEdges(vertex2);

            foreach (var edge in edges1)
            { // update existing data.
                var neighbour    = edge.Neighbour;
                var newNeighbour = edge.Neighbour;
                if (newNeighbour == vertex2)
                {
                    newNeighbour = vertex1;
                }
                graph.AddEdge(vertex2, newNeighbour, edge.EdgeData, edge.Intermediates);

                if (reverse != null)
                { // update reverse set if present.
                    List <uint> neighbours = null;
                    if (reverse.TryGetValue(neighbour, out neighbours))
                    { // remove.
                        neighbours.Remove(vertex1);
                        reverse[neighbour] = neighbours;
                    }
                    if (reverse.TryGetValue(newNeighbour, out neighbours))
                    { // add.
                        neighbours.Add(vertex2);
                    }
                    else
                    { // add new.
                        neighbours = new List <uint>();
                        neighbours.Add(vertex2);
                    }
                    reverse[newNeighbour] = neighbours;
                }
            }
            foreach (var edge in edges2)
            { // update existing data.
                var neighbour    = edge.Neighbour;
                var newNeighbour = edge.Neighbour;
                if (newNeighbour == vertex1)
                {
                    newNeighbour = vertex2;
                }
                graph.AddEdge(vertex1, newNeighbour, edge.EdgeData, edge.Intermediates);

                if (reverse != null)
                { // update reverse set if present.
                    List <uint> neighbours = null;
                    if (reverse.TryGetValue(neighbour, out neighbours))
                    { // remove.
                        neighbours.Remove(vertex2);
                        reverse[neighbour] = neighbours;
                    }
                    if (reverse.TryGetValue(newNeighbour, out neighbours))
                    { // add.
                        neighbours.Add(vertex1);
                    }
                    else
                    { // add new.
                        neighbours = new List <uint>();
                        neighbours.Add(vertex1);
                    }
                    reverse[newNeighbour] = neighbours;
                }
            }

            if (graph.IsDirected)
            { // in a directed graph, there is more work to be done.
                var         toUpdateSet = new HashSet <uint>();
                List <uint> neighbours1 = null;
                if (reverse.TryGetValue(vertex1, out neighbours1))
                {
                    for (var i = 0; i < neighbours1.Count; i++)
                    {
                        if (neighbours1[i] == vertex2)
                        {
                            neighbours1[i] = vertex1;
                        }
                        else
                        {
                            toUpdateSet.Add(neighbours1[i]);
                        }
                    }
                    reverse[vertex1] = neighbours1;
                }
                List <uint> neighbours2 = null;
                if (reverse.TryGetValue(vertex2, out neighbours2))
                {
                    for (var i = 0; i < neighbours2.Count; i++)
                    {
                        if (neighbours2[i] == vertex1)
                        {
                            neighbours2[i] = vertex2;
                        }
                        else
                        {
                            toUpdateSet.Add(neighbours2[i]);
                        }
                    }
                    reverse[vertex2] = neighbours2;
                }

                // switch reverses.
                if (neighbours2 == null)
                {
                    reverse.Remove(vertex1);
                }
                else
                {
                    reverse[vertex1] = neighbours2;
                }
                if (neighbours1 == null)
                {
                    reverse.Remove(vertex2);
                }
                else
                {
                    reverse[vertex2] = neighbours1;
                }

                // update all edges in these vertices.
                var updatedEdges = new List <Edge <TEdgeData> >();
                foreach (var toUpdate in toUpdateSet)
                {
                    updatedEdges.Clear();

                    foreach (var edge in graph.GetEdges(toUpdate))
                    {
                        if (edge.Neighbour == vertex1)
                        {
                            updatedEdges.Add(new Edge <TEdgeData>()
                            {
                                EdgeData      = edge.EdgeData,
                                Neighbour     = vertex2,
                                Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>(
                                    edge.Intermediates.ToSimpleArray()) : null
                            });
                        }
                        else if (edge.Neighbour == vertex2)
                        {
                            updatedEdges.Add(new Edge <TEdgeData>()
                            {
                                EdgeData      = edge.EdgeData,
                                Neighbour     = vertex1,
                                Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>(
                                    edge.Intermediates.ToSimpleArray()) : null
                            });
                        }
                    }

                    graph.RemoveEdge(toUpdate, vertex1);
                    graph.RemoveEdge(toUpdate, vertex2);

                    foreach (var updatedEdge in updatedEdges)
                    {
                        graph.AddEdge(toUpdate, updatedEdge.Neighbour, updatedEdge.EdgeData, updatedEdge.Intermediates);
                    }
                }
            }
        }