/// <summary> /// 查找直达路线。 /// </summary> /// <param name="startNode">开始节点。</param> /// <param name="endNode">结束节点。</param> /// <returns>乘车路线。</returns> private MetroPath FindDirectPath(MetroNode startNode, MetroNode endNode) { MetroPath path = new MetroPath(); var startLines = startNode.Links.Select(c => c.Line).Distinct().ToList(); var endLines = endNode.Links.Select(c => c.Line).Distinct().ToList(); var lines = startLines.Where(c => endLines.Contains(c)).ToList(); if (lines.Count == 0) { return(path); } //查找直达路线 List <MetroPath> pathList = new List <MetroPath>(); foreach (var line in lines) { pathList.AddRange(FindShortestPaths(startNode, endNode, line)); } //挑选最短路线 return(GetShortestPath(pathList)); }
/// <summary> /// 合并路线。 /// </summary> /// <exception cref="ArgumentNullException">如果path为空引用,则跑出该异常。</exception> public MetroPath Merge(MetroPath path) { if (path == null) { throw new ArgumentNullException("path"); } MetroPath newPath = new MetroPath(); newPath.Links.AddRange(this.Links); newPath.Links.AddRange(path.Links); return(newPath); }
/// <summary> /// 最佳一条新的Link,并返回一条新的路线。 /// </summary> /// <exception cref="ArgumentNullException">如果link为空引用,则跑出该异常。</exception> public MetroPath Append(MetroLink link) { if (link == null) { throw new ArgumentNullException("link"); } MetroPath newPath = new MetroPath(); newPath.Links.AddRange(this.Links); newPath.Links.Add(link); return(newPath); }
/// <summary> /// 从指定的路线列表中挑选一个最短的路线。 /// </summary> /// <param name="pathList"></param> /// <returns></returns> private MetroPath GetShortestPath(List <MetroPath> pathList) { MetroPath minPath = new MetroPath(); int minLength = int.MaxValue; foreach (var item in pathList) { if (item.Links.Count < minLength) { minLength = item.Links.Count; minPath = item; } } return(minPath); }
/// <summary> /// 查找乘车路线。 /// </summary> /// <param name="startNodeName">起点的名称。</param> /// <param name="endNodeName">终点的名称。</param> public void FindPath(string startNodeName, string endNodeName) { if (!this.Graph.Nodes.Contains(startNodeName)) { return; } if (!this.Graph.Nodes.Contains(endNodeName)) { return; } this.StartNode = this.Graph.Nodes[startNodeName]; this.EndNode = this.Graph.Nodes[endNodeName]; this.CurPath = FindPath(this.StartNode, this.EndNode); Invalidate(); }
/// <summary> /// 重写OnMouseUp方法。 /// </summary> /// <param name="e"></param> protected override void OnMouseUp(MouseEventArgs e) { //选择起点或终点 var node = GetNodeAt(e.Location); if (node != null && node.Name != "1" && node.Name != "2" && node.Name != "3") { if (this.StartNode == null) { this.StartNode = node; } else { this.EndNode = node; //查找乘车线路 Cursor.Current = Cursors.WaitCursor; try { m_curPath = FindPath(this.StartNode, this.EndNode); } finally { Cursor.Current = Cursors.Default; } } } else if (Distance(e.Location, m_mouseDownPoint) < 3)//是否发生拖拽 { this.StartNode = this.EndNode = null; this.CurPath.Links.Clear(); if (CurPath.Links.Count > 0) { this.BackColor = Color.White; } else { this.BackColor = Color.WhiteSmoke; } } Invalidate(); }
/// <summary> /// 查找指定两个节点之间的最短路径。 /// </summary> /// <param name="startNode">开始节点。</param> /// <param name="endNode">结束节点。</param> /// <param name="line">目标线路(为null表示不限制线路)。</param> /// <returns>乘车路线列表。</returns> private List <MetroPath> FindShortestPaths(MetroNode startNode, MetroNode endNode, MetroLine line) { List <MetroPath> pathtList = new List <MetroPath>(); if (startNode == endNode) { return(pathtList); } //路径队列,用于遍历路径 Queue <MetroPath> pathQueue = new Queue <MetroPath>(); pathQueue.Enqueue(new MetroPath()); while (pathQueue.Count > 0) { var path = pathQueue.Dequeue(); //如果已经超过最短路径,则直接返回 if (pathtList.Count > 0 && path.Links.Count > pathtList[0].Links.Count) { continue; } //路径的最后一个节点 MetroNode prevNode = path.Links.Count > 0 ? path.Links[path.Links.Count - 1].From : null; MetroNode lastNode = path.Links.Count > 0 ? path.Links[path.Links.Count - 1].To : startNode; //继续寻找后续节点 //int Gx_min = int.MaxValue; //int Gx; foreach (var link in lastNode.Links.Where(c => c.To != prevNode && (line == null || c.Line == line))) { /*Gx = Math.Abs(link.To.X - endNode.X) + Math.Abs(link.To.Y - endNode.Y) + 500 * path.Links.Count; * * if (Gx < Gx_min) * Gx_min = Gx; * else * continue;*/ if (link.Weight == 2) { continue; } if (link.To == endNode) { MetroPath newPath = path.Append(link); if (pathtList.Count == 0 || newPath.Links.Count == pathtList[0].Links.Count) {//找到一条路径 pathtList.Add(newPath); } else if (newPath.Links.Count < pathtList[0].Links.Count) {//找到一条更短的路径 pathtList.Clear(); pathtList.Add(newPath); } else { break; //更长的路径没有意义 } } else if (!path.ContainsNode(link.To)) { pathQueue.Enqueue(path.Append(link)); } link.Weight = 2; } } return(pathtList); }
/// <summary> /// 查找乘车路线。 /// </summary> /// <param name="startNode">起点。</param> /// <param name="endNode">终点。</param> /// <returns>乘车路线。</returns> public MetroPath FindPath(MetroNode startNode, MetroNode endNode) { MetroPath path = new MetroPath(); if (startNode == null || endNode == null) { return(path); } if (startNode == endNode) { return(path); } foreach (var item in this.Graph.Nodes) { foreach (var link in item.Links) { link.Weight = 3; } } //如果起点和终点拥有共同线路,则查找直达路线 path = FindDirectPath(startNode, endNode); if (path.Links.Count > 0) { return(path); } //如果起点和终点拥有一个共同的换乘站点,则查找一次换乘路线 //path = FindOneTransferPath(startNode, endNode); //if (path.Links.Count > 0) return path; //查找路径最短的乘车路线 var pathList = FindShortestPaths(startNode, endNode, null); //查找换乘次数最少的一条路线 int minTransfers = int.MaxValue; foreach (var item in pathList) { var curTransfers = item.Transfers; if (curTransfers < minTransfers) { minTransfers = curTransfers; path = item; } } if (CurPath.Links.Count > 0) { this.BackColor = Color.White; } else { this.BackColor = Color.WhiteSmoke; } return(path); }