/// /// Copyright (c) 2020 Sensus Slovensko a.s. /// using System; using System.Diagnostics; using System.Collections.Generic; namespace SchematicDrawing { public class Graph { public bool Completed; IList nodes; GNode startNode; int secondaryStartNodesCount; MinHeap minHeap; GNode currentNode; public Graph() { nodes = new List(); startNode = null; secondaryStartNodesCount = 0; minHeap = new MinHeap(); Completed = false; } public void Clear() { nodes.Clear(); startNode = null; secondaryStartNodesCount = 0; Completed = false; } /// /// Add a node to the list of graph nodes /// /// Graph node public void AddNode(GNode node, bool isStartNode = false, bool isSecondaryStartNode = false) { if (isStartNode && startNode == null) { startNode = node; nodes.Insert(0, node); } else if (isStartNode || isSecondaryStartNode) { secondaryStartNodesCount++; nodes.Insert(startNode != null ? 1 : 0, node); } else { nodes.Add(node); } } /// /// Add an edge to the list of edges of node1. /// /// Node 1 (start) /// NOde 2 (end) /// Default distance (when closed) /// Way the route affects this edge /// Added graph edge public GEdge AddEdge(GNode node1, GNode node2, int defaultDist, RouteCouple routeCouple = RouteCouple.None) { GEdge gedge = new GEdge(node1, node2, defaultDist, routeCouple); node1.AddEdge(gedge); return gedge; } /// /// Run Dijkstra shortest path algorithm to determine schematic drawing coloring /// public void RunDijkstraAlgo() { if (nodes == null || startNode == null) return; /// Reset all nodes minHeap.ResetAndBuild(nodes, secondaryStartNodesCount); currentNode = minHeap.ExtractMinNode(); do { /// Consider all unvisited neighbors of the current node foreach (var e in currentNode.Edges) { int distViaCurrNode = (e.Dist == int.MaxValue) ? int.MaxValue : currentNode.Dist + e.Dist; if (distViaCurrNode < e.EndNode.Dist) { e.EndNode.Dist = distViaCurrNode; minHeap.SiftUp(e.EndNode.HeapIx); } } currentNode = minHeap.ExtractMinNode(); } while (currentNode.Dist < int.MaxValue && currentNode != null); } } }