public static Graph Dijkstra(Graph graph, gVertex origin, gVertex destination, Graph tempGraph = null) { MinPriorityQ <gVertex, double> Q = new MinPriorityQ <gVertex, double>(); graph.vertices.ForEach(v => Q.Add(v, Double.PositiveInfinity)); //If tempGraph is not null, means graph doesn't contain origin and/or destination vertices. if (graph.Contains(origin)) { Q.UpdateValue(origin, 0); } else { Q.Add(origin, 0); } if (!graph.Contains(destination)) { Q.Add(destination, Double.PositiveInfinity); } Dictionary <gVertex, gVertex> ParentVertices = new Dictionary <gVertex, gVertex>(); List <gVertex> S = new List <gVertex>(); while (Q.Size > 0) { double minDistance = Q.PeekValue(); gVertex vertex = Q.Take(); S.Add(vertex); if (vertex.Equals(destination)) { break; } List <gEdge> edges = new List <gEdge>(); edges.AddRange(graph.GetVertexEdges(vertex)); if (tempGraph != null && tempGraph.edges.Any()) { edges.AddRange(tempGraph.GetVertexEdges(vertex)); } foreach (gEdge e in edges) { gVertex w = e.GetVertexPair(vertex); double newLength = minDistance + e.Length; if (!S.Contains(w) && newLength < Q.GetValue(w)) { Q.UpdateValue(w, newLength); //dist[w] = newLength; ParentVertices[w] = vertex; } } } Graph path = new Graph(); gVertex dest = destination; while (dest != origin) { gVertex parent = ParentVertices[dest]; path.AddEdge(new gEdge(dest, parent)); dest = parent; } return(path); }
/// <summary> /// /// </summary> /// <param name="centre"></param> /// <param name="baseGraph"></param> /// <param name="origin"></param> /// <param name="destination"></param> /// <param name="singleVertices"></param> /// <param name="scan"></param> /// <returns name="visibleVertices">List of vertices visible from the analysed vertex</returns> public static List <gVertex> VisibleVertices( gVertex centre, Graph baseGraph, gVertex origin = null, gVertex destination = null, List <gVertex> singleVertices = null, bool halfScan = true, bool reducedGraph = true, bool maxVisibility = false) { #region Initialize variables and sort vertices List <gEdge> edges = baseGraph.edges; List <gVertex> vertices = baseGraph.vertices; if (origin != null) { vertices.Add(origin); } if (destination != null) { vertices.Add(destination); } if (singleVertices != null) { vertices.AddRange(singleVertices); } gVertex maxVertex = vertices.OrderByDescending(v => v.DistanceTo(centre)).First(); double maxDistance = centre.DistanceTo(maxVertex) * 1.5; //vertices = vertices.OrderBy(v => Point.RadAngle(centre.point, v.point)).ThenBy(v => centre.DistanceTo(v)).ToList(); vertices = gVertex.OrderByRadianAndDistance(vertices, centre); #endregion #region Initialize openEdges //Initialize openEdges with any intersection edges on the half line //from centre to maxDistance on the XAxis List <EdgeKey> openEdges = new List <EdgeKey>(); double xMax = Math.Abs(centre.X) + 1.5 * maxDistance; gEdge halfEdge = gEdge.ByStartVertexEndVertex(centre, gVertex.ByCoordinates(xMax, centre.Y, centre.Z)); foreach (gEdge e in edges) { if (e.Contains(centre)) { continue; } if (halfEdge.Intersects(e)) { if (e.StartVertex.OnEdge(halfEdge)) { continue; } if (e.EndVertex.OnEdge(halfEdge)) { continue; } EdgeKey k = new EdgeKey(halfEdge, e); Core.List.AddItemSorted(openEdges, k); } } #endregion List <gVertex> visibleVertices = new List <gVertex>(); gVertex prev = null; bool prevVisible = false; for (var i = 0; i < vertices.Count; i++) { gVertex vertex = vertices[i]; if (vertex.Equals(centre) || vertex.Equals(prev)) { continue; } // v == to centre or to previous when updating graph //Check only half of vertices as eventually they will become 'v' if (halfScan && gVertex.RadAngle(centre, vertex) > Math.PI) { break; } //Removing clock wise edges incident on v if (openEdges.Count > 0 && baseGraph.graph.ContainsKey(vertex)) { foreach (gEdge edge in baseGraph.graph[vertex]) { int orientation = gVertex.Orientation(centre, vertex, edge.GetVertexPair(vertex)); if (orientation == -1) { EdgeKey k = new EdgeKey(centre, vertex, edge); int index = Core.List.Bisect(openEdges, k) - 1; index = (index < 0) ? openEdges.Count - 1 : index; if (openEdges.Count > 0 && openEdges.ElementAt(index).Equals(k)) { openEdges.RemoveAt(index); } } } } //Checking if p is visible from p. bool isVisible = false; //No collinear vertices if (prev == null || gVertex.Orientation(centre, prev, vertex) != 0 || !prev.OnEdge(centre, vertex)) { if (openEdges.Count == 0) { isVisible = true; } else if (!EdgeIntersect(centre, vertex, openEdges[0].Edge)) { isVisible = true; } } //For collinear vertices, if previous was not visible, vertex is not either else if (!prevVisible) { isVisible = false; } //For collinear vertices, if prev was visible need to check that //the edge from prev to vertex does not intersect with any open edge else { isVisible = true; foreach (EdgeKey k in openEdges) { //if (!k.edge.Contains(prev) && EdgeIntersect(prev, vertex, k.edge)) if (EdgeIntersect(prev, vertex, k.Edge) && !k.Edge.Contains(prev)) { isVisible = false; break; } } // If visible (doesn't intersect any open edge) and edge 'prev-vertex' // is in any polygon, vertex is visible if it belongs to a external boundary if (isVisible && EdgeInPolygon(prev, vertex, baseGraph, maxDistance)) { isVisible = IsBoundaryVertex(vertex, baseGraph); } // If still visible (not inside polygon or is boundary vertex), // if not on 'centre-prev' edge means there is a gap between prev and vertex if (isVisible && !vertex.OnEdge(centre, prev)) { isVisible = !IsBoundaryVertex(vertex, baseGraph); } } //If vertex is visible and centre belongs to any polygon, checks //if the visible edge is interior to its polygon if (isVisible && centre.polygonId >= 0 && !baseGraph.GetAdjecentVertices(centre).Contains(vertex)) { if (IsBoundaryVertex(centre, baseGraph) && IsBoundaryVertex(vertex, baseGraph)) { isVisible = EdgeInPolygon(centre, vertex, baseGraph, maxDistance); } else { isVisible = !EdgeInPolygon(centre, vertex, baseGraph, maxDistance); } } prev = vertex; prevVisible = isVisible; if (isVisible) { // Check reducedGraph if vertices belongs to different polygons if (reducedGraph && centre.polygonId != vertex.polygonId) { bool isOriginExtreme = true; bool isTargetExtreme = true; // For reduced graphs, it is checked if the edge is extrem or not. // For an edge to be extreme, the edges coincident at the start and end vertex // will have the same orientation (both clock or counter-clock wise) // Vertex belongs to a polygon if (centre.polygonId >= 0 && !IsBoundaryVertex(centre, baseGraph)) { var orientationsOrigin = baseGraph.GetAdjecentVertices(centre).Select(otherVertex => gVertex.Orientation(vertex, centre, otherVertex)).ToList(); isOriginExtreme = orientationsOrigin.All(o => o == orientationsOrigin.First()); } if (vertex.polygonId >= 0 && !IsBoundaryVertex(vertex, baseGraph)) { var orientationsTarget = baseGraph.GetAdjecentVertices(vertex).Select(otherVertex => gVertex.Orientation(centre, vertex, otherVertex)).ToList(); isTargetExtreme = orientationsTarget.All(o => o == orientationsTarget.First()); } if (isTargetExtreme || isOriginExtreme) { visibleVertices.Add(vertex); } } else { visibleVertices.Add(vertex); } } if (baseGraph.Contains(vertex)) { foreach (gEdge e in baseGraph.graph[vertex]) { if (!e.Contains(centre) && gVertex.Orientation(centre, vertex, e.GetVertexPair(vertex)) == 1) { EdgeKey k = new EdgeKey(centre, vertex, e); Core.List.AddItemSorted(openEdges, k); } } } if (isVisible && maxVisibility && vertex.polygonId >= 0) { List <gVertex> vertexPairs = baseGraph.GetAdjecentVertices(vertex); int firstOrientation = gVertex.Orientation(centre, vertex, vertexPairs[0]); int secondOrientation = gVertex.Orientation(centre, vertex, vertexPairs[1]); //if both edges lie on the same side of the centre-vertex edge or one of them is colinear if (firstOrientation == secondOrientation || firstOrientation == 0 || secondOrientation == 0) { gVertex rayVertex = vertex.Translate(gVector.ByTwoVertices(centre, vertex), maxDistance); gEdge rayEdge = gEdge.ByStartVertexEndVertex(centre, rayVertex); gVertex projectionVertex = null; foreach (EdgeKey ek in openEdges) { gBase intersection = rayEdge.Intersection(ek.Edge); if (intersection != null && intersection is gVertex && !(intersection as gVertex).Equals(vertex)) { projectionVertex = intersection as gVertex; break; } } if (projectionVertex != null) { // if edges are before rayEdge, projection Vertex goes after vertex if (firstOrientation == -1 || secondOrientation == -1) { visibleVertices.Add(projectionVertex); } else { visibleVertices.Insert(visibleVertices.Count - 1, projectionVertex); } } } } } return(visibleVertices); }