/// <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); } }
/// <summary> /// Builds the reverse index for a directed graph. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <returns></returns> public static IDictionary <uint, List <uint> > BuildReverse <TEdgeData>(this GraphBase <TEdgeData> graph) where TEdgeData : struct, IGraphEdgeData { if (!graph.IsDirected) { throw new ArgumentException("Building a reverse index for a non-directed graph is not supported."); } var reverse = new Dictionary <uint, List <uint> >(); for (uint vertex = 1; vertex <= graph.VertexCount; vertex++) { foreach (var edge in graph.GetEdges(vertex)) { var to = edge.Neighbour; List <uint> neighbours; if (!reverse.TryGetValue(to, out neighbours)) { // create an entry here. neighbours = new List <uint>(); } neighbours.Add(vertex); reverse[to] = neighbours; // explicitly set again because this may be another kind of dictionary soon. } } return(reverse); }
/// <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 the edge enumerator for the given vertex. /// </summary> /// <param name="vertexId"></param> /// <returns></returns> public override EdgeEnumerator <TEdgeData> GetEdges(uint vertexId) { return(_graph.GetEdges(vertexId)); }
/// <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); } } } }