private void BtnAddLineC_Click(object sender, EventArgs e) { MetroLine NewLine = new MetroLine(); foreach (var line in metroGraphView1.Graph.Lines) { if (this.colorDialog1.Color == line.Color || this.colorDialog1.Color == Color.White) { MessageBox.Show("该路线颜色已经存在,请重新选取哦ฅʕ•̫͡•ʔฅ"); return; } if (this.TxtLineName.Text.ToString() == line.Name.ToString()) { MessageBox.Show("该路线名已经存在,请重新命名哦ฅʕ•̫͡•ʔฅ"); return; } } NewLine.Name = this.TxtLineName.Text.ToString(); NewLine.Color = this.colorDialog1.Color; metroGraphView1.Graph.Lines.Add(NewLine); CobNodeLine.Items.Add(NewLine.Name); //metroGraphView1.SaveToFile(Application.StartupPath + "\\MetroGraph.xml"); MessageBox.Show("添加成功\\(0^◇^0)/"); this.BtnAdd.Visible = true; this.BtnMetroHelp.Visible = true; this.BtnSave.Visible = true; this.PnlAddLine.Visible = false; this.PnlAddNode.Visible = false; metroGraphView1.Invalidate(); this.CobPreNode.Text = ""; this.CobNexNode.Text = ""; this.TxtNodeName.Text = ""; this.TxtNodeX.Text = ""; this.TxtNodeY.Text = ""; this.TxtLineName.Text = ""; this.CobNodeLine.Text = ""; this.colorDialog1.Reset(); this.LabNexXY.Text = ""; this.LabPreXY.Text = ""; }
/// <summary> /// 构造函数。 /// </summary> /// <param name="line">所属线路。</param> /// <param name="from">来源站点。</param> /// <param name="to">目标站点。</param> /// <exception cref="ArgumentNullException">如果from或to为空引用,则抛出该异常。</exception> public MetroLink(MetroLine line, MetroNode from, MetroNode to) { if (line == null) { throw new ArgumentNullException("line"); } if (from == null) { throw new ArgumentNullException("from"); } if (to == null) { throw new ArgumentNullException("to"); } m_line = line; m_from = from; m_to = to; }
/// <summary> /// 获取指定两个线路的中转站。 /// </summary> /// <param name="line1">线路1。</param> /// <param name="line2">线路2。</param> /// <returns>中转站。</returns> /// <exception cref="ArgumentNullException">如果line1或line2为空引用,则抛出该异常。</exception> public IEnumerable <MetroNode> GetTransferNodes(MetroLine line1, MetroLine line2) { if (line1 == null) { throw new ArgumentNullException("line1"); } if (line2 == null) { throw new ArgumentNullException("line2"); } if (line1 == line2) { yield break; } foreach (var node in this.Nodes.Where(c => c.Links.Count > 2 && c.Links.Exists(k => k.Line == line1) && c.Links.Exists(k => k.Line == line2))) { yield return(node); } }
private void BtnAddNodeC_Click(object sender, EventArgs e) { try { bool IsDouLine1 = false; bool IsDouLine2 = false; MetroNode NewNode = new MetroNode(); MetroNode PreNode = new MetroNode(); MetroNode NexNode = new MetroNode(); String Prename = (CobPreNode.Text.ToString() == "海伦路" && CobNexNode.Text.ToString() == "宝山路") || (CobPreNode.Text.ToString() == "宝山路" && CobNexNode.Text.ToString() == "海伦路") ? "3" : CobPreNode.Text.ToString(); String Nexname = (CobPreNode.Text.ToString() == "海伦路" && CobNexNode.Text.ToString() == "宝山路") || (CobPreNode.Text.ToString() == "宝山路" && CobNexNode.Text.ToString() == "海伦路") ? "2" : CobNexNode.Text.ToString(); foreach (var node in metroGraphView1.Graph.Nodes) { if (node.Name == Prename) { PreNode = node; } if (node.Name == Nexname) { NexNode = node; } } NewNode.Name = this.TxtNodeName.Text.ToString(); NewNode.X = (CobPreNode.Text.ToString() == "海伦路" && CobNexNode.Text.ToString() == "宝山路") || (CobPreNode.Text.ToString() == "宝山路" && CobNexNode.Text.ToString() == "海伦路") ? 2033 : int.Parse(this.TxtNodeX.Text.ToString()); NewNode.Y = (CobPreNode.Text.ToString() == "海伦路" && CobNexNode.Text.ToString() == "宝山路") || (CobPreNode.Text.ToString() == "宝山路" && CobNexNode.Text.ToString() == "海伦路") ? 750 : int.Parse(this.TxtNodeY.Text.ToString()); if ((Math.Abs(NewNode.X - PreNode.X) > 200 || Math.Abs(NewNode.Y - PreNode.Y) > 200 || Math.Abs(NewNode.X - NexNode.X) > 200 || Math.Abs(NewNode.Y - NexNode.Y) > 200) && (PreNode.Name != "" && NexNode.Name != "")) { MessageBox.Show("距离太远了哦,请重新设定坐标(´▽`ʃ♡ƪ)"); this.TxtNodeX.Text = ""; this.TxtNodeY.Text = ""; return; } for (int i = 0; i < PreNode.Links.Count; i++) { if (PreNode.Links[i].Flag == 1 && PreNode.Links.Count > 3) { IsDouLine1 = true; } } for (int i = 0; i < NexNode.Links.Count; i++) { if (NexNode.Links[i].Flag == 1 && NexNode.Links.Count > 3) { IsDouLine2 = true; } } if (!IsDouLine2 || !IsDouLine1) { MetroLine NewLine = new MetroLine(); foreach (var line in metroGraphView1.Graph.Lines) { if (line.Name == CobNodeLine.Text.ToString()) { NewLine = line; } } if (!((CobPreNode.Text == "" || CobPreNode.Text == null) && NexNode.Links.Count <= 1)) { MetroLink NewLink = new MetroLink(NewLine, NewNode, PreNode); NewLink.Weight = 3; NewNode.Links.Add(NewLink); NewLink.Flag = 0; } if (!((CobNexNode.Text == "" || CobNexNode.Text == null) && PreNode.Links.Count <= 1)) { MetroLink NewLink = new MetroLink(NewLine, NewNode, NexNode); NewLink.Flag = 0; NewLink.Weight = 3; NewNode.Links.Add(NewLink); } if (!((CobPreNode.Text == "" || CobPreNode.Text == null) && NexNode.Links.Count <= 1)) { for (int i = 0; i < PreNode.Links.Count; i++) { if (PreNode.Links[i].To.Name == NexNode.Name) { PreNode.Links.RemoveAt(i); } } } PreNode.Links.Add(new MetroLink(NewLine, PreNode, NewNode)); if (!((CobNexNode.Text == "" || CobNexNode.Text == null) && PreNode.Links.Count <= 1)) { for (int i = 0; i < NexNode.Links.Count; i++) { if (NexNode.Links[i].To.Name == PreNode.Name) { NexNode.Links.RemoveAt(i); } } } NexNode.Links.Add(new MetroLink(NewLine, NexNode, NewNode)); metroGraphView1.Graph.Nodes.Add(NewNode); } else { for (int i = 0; i < PreNode.Links.Count; i++) { if (PreNode.Links[i].To.Name == NexNode.Name) { MetroLine NewLine = new MetroLine(); NewLine = PreNode.Links[i].Line; MetroLink NewLink = new MetroLink(NewLine, PreNode, NewNode); NewLink.Flag = PreNode.Links[i].Flag; MetroLink SNewLink = new MetroLink(NewLine, NewNode, NexNode); SNewLink.Flag = PreNode.Links[i].Flag; SNewLink.Weight = 3; NewNode.Links.Add(SNewLink); PreNode.Links.RemoveAt(i); PreNode.Links.Add(NewLink); } } for (int i = 0; i < NexNode.Links.Count; i++) { if (NexNode.Links[i].To.Name == PreNode.Name) { MetroLine NewLine = new MetroLine(); NewLine = NexNode.Links[i].Line; MetroLink NewLink = new MetroLink(NewLine, NexNode, NewNode); NewLink.Flag = NexNode.Links[i].Flag; MetroLink SNewLink = new MetroLink(NewLine, NewNode, PreNode); SNewLink.Flag = NexNode.Links[i].Flag; SNewLink.Weight = 3; NewNode.Links.Add(SNewLink); NexNode.Links.RemoveAt(i); NexNode.Links.Add(NewLink); } } metroGraphView1.Graph.Nodes.Add(NewNode); } //metroGraphView1.SaveToFile(Application.StartupPath + "\\MetroGraph.xml"); metroGraphView1.Invalidate(); this.CobPreNode.Text = ""; this.CobNexNode.Text = ""; this.TxtNodeName.Text = ""; this.TxtNodeX.Text = ""; this.TxtNodeY.Text = ""; this.TxtLineName.Text = ""; this.CobNodeLine.Text = ""; this.colorDialog1.Reset(); this.LabNexXY.Text = ""; this.LabPreXY.Text = ""; } catch { MessageBox.Show("请检查是否有误哦(✿◕‿◕✿)"); return; } this.PnlAddNode.Visible = false; this.BtnMetroHelp.Visible = true; this.BtnAdd.Visible = true; this.BtnSave.Visible = true; }
private void PicBoxList_Paint(object sender, PaintEventArgs e) { int ListBox_x = 25; int ListBox_y = 50; int ListBox_width = 250; Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; //绘制路线站点名称 int y = ListBox_y + WheelHeight; int count = 0; MetroLine preLine = null; MetroLine nexLine = null; Point preP = new Point(0, 0); Point nexP = new Point(0, 0); //绘制界面 Draw(new Rectangle(60, y - 30, 200, 50), g, 18, false, Color.Wheat, Color.Wheat); g.DrawString("换乘路线", new Font("微软雅黑", 10, FontStyle.Bold), Brushes.Black, 100, y - 25); foreach (var link in metroGraphView1.CurPath.Links) { count++; if (link.From.Name == "2" || link.From.Name == "1") { continue; } var sz = g.MeasureString(link.From.Name, this.Font); if (link.From.Name == "3" && metroGraphView1.EndNode.Name.ToString() != link.To.Name.ToString()) { continue; } if (link.From.Name == "3" && metroGraphView1.EndNode.Name.ToString() == link.To.Name.ToString()) { y += 25; g.FillRectangle(new SolidBrush(Color.FromArgb(144, 183, 213)), ListBox_x + 10, y, ListBox_width - 20, 25); g.DrawEllipse(new Pen(link.Line.Color, 5), ListBox_x - 5, y + 8, 8, 8); g.DrawString(link.To.Name, new Font("微软雅黑", 10, FontStyle.Bold), Brushes.Black, ListBox_x + 10, y - sz.Height / 2 + 10); nexP = new Point(ListBox_x - 1, y + 8); g.DrawLine(new Pen(link.Line.Color, 3), preP, nexP); continue; } if (count % 2 == 1) { preLine = link.Line; } else if (count % 2 == 0) { nexLine = link.Line; } if (preLine != nexLine) { y += 25; g.FillRectangle(new SolidBrush(Color.FromArgb(144, 183, 213)), ListBox_x + 10, y, ListBox_width - 20, 25); g.DrawEllipse(new Pen(link.Line.Color, 5), ListBox_x - 5, y + 8, 8, 8); g.DrawString(link.From.Name, new Font("微软雅黑", 10, FontStyle.Bold), Brushes.Black, ListBox_x + 10, y - sz.Height / 2 + 10); } else { y += 20; g.DrawString(link.From.Name, new Font("微软雅黑", 8, FontStyle.Bold), Brushes.Black, ListBox_x + 10, y - sz.Height / 2 + 10); } if (count % 2 == 1) { preP = new Point(ListBox_x - 1, y + 8); } else if (count % 2 == 0) { nexP = new Point(ListBox_x - 1, y + 8); } if (nexP.Y != 0) { g.DrawLine(new Pen(preLine.Color, 3), preP, nexP); } if (count == metroGraphView1.CurPath.Links.Count) { y += 25; g.FillRectangle(new SolidBrush(Color.FromArgb(144, 183, 213)), ListBox_x + 10, y, ListBox_width - 20, 25); g.DrawEllipse(new Pen(link.Line.Color, 5), ListBox_x - 5, y + 8, 8, 8); g.DrawString(link.To.Name, new Font("微软雅黑", 10, FontStyle.Bold), Brushes.Black, ListBox_x + 10, y - sz.Height / 2 + 10); nexP = new Point(ListBox_x - 1, y + 8); g.DrawLine(new Pen(link.Line.Color, 3), preP, nexP); } } if (PicBoxList.Visible == true && !IsFirst) { ListHeight = y - ListBox_y; IsFirst = true; } }
/// <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); }