Пример #1
0
        /// <summary>
        /// 查找一次中转的路线。
        /// </summary>
        /// <param name="startNode">开始节点。</param>
        /// <param name="endNode">结束节点。</param>
        /// <returns>乘车路线。</returns>
        private MetroPath FindOneTransferPath(MetroNode startNode, MetroNode endNode)
        {
            List <MetroPath> pathList = new List <MetroPath>();

            foreach (var startLine in startNode.Links.Select(c => c.Line).Distinct())
            {
                foreach (var endLine in endNode.Links.Select(c => c.Line).Where(c => c != startLine).Distinct())
                {
                    //两条线路的中转站
                    foreach (var transferNode in this.Graph.GetTransferNodes(startLine, endLine))
                    {
                        //起点到中转站的直达路线
                        var startDirectPathList = FindShortestPaths(startNode, transferNode, startLine);

                        //中转站到终点的直达路线
                        var endDirectPathList = FindShortestPaths(transferNode, endNode, endLine);

                        //合并两条直达路线
                        foreach (var startDirectPath in startDirectPathList)
                        {
                            foreach (var endDirectPath in endDirectPathList)
                            {
                                var directPath = startDirectPath.Merge(endDirectPath);
                                pathList.Add(directPath);
                            }
                        }
                    }
                }
            }

            //挑选最短路线
            return(GetShortestPath(pathList));
        }
Пример #2
0
        /// <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));
        }
Пример #3
0
        /// <summary>
        /// 判断是否包含指定的站点。
        /// </summary>
        /// <exception cref="ArgumentNullException">如果node为空引用,则跑出该异常。</exception>
        public bool ContainsNode(MetroNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            return(Links.FirstOrDefault(c => c.From == node || c.To == node) != null);
        }
Пример #4
0
        /// <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;
        }
Пример #5
0
        /// <summary>
        /// 绘制地铁站点。
        /// </summary>
        /// <param name="g">绘图图面。</param>
        /// <param name="node">地铁站点。</param>
        private void PaintNode(Graphics g, MetroNode node)
        {
            if (node.Name != "1" && node.Name != "2" && node.Name != "3")
            {
                //绘制站点圆圈
                Color color = node.Links.Count > 2 ? Color.Black : node.Links[0].Line.Color;
                var   rect  = GetNodeRect(node);
                g.FillEllipse(Brushes.White, rect);
                using (Pen pen = new Pen(color))
                {
                    g.DrawEllipse(pen, rect);
                }
                if (node.Links.Count > 2)
                {
                    Point p = new Point(node.X - 4, node.Y - 4);
                    //g.DrawString("C", Font, Brushes.Red, p);

                    var startNodeImage = Properties.Resources.Trans;
                    g.DrawImage(startNodeImage, node.X - 10, node.Y - 10);
                }

                //绘制站点名称
                var   sz = g.MeasureString(node.Name, this.Font).ToSize();
                Point pt = new Point(node.X - sz.Width / 2, node.Y + (rect.Height >> 1) + 4);
                g.DrawString(node.Name, new Font("微软雅黑", 9, FontStyle.Bold), Brushes.Black, pt);
            }

            if (node.Name == "2")
            {
                Color color = node.Links.Count > 2 ? Color.Black : node.Links[0].Line.Color;
                var   rect  = GetNodeRect(node);
                //g.FillEllipse(Brushes.White, rect);
                using (Pen pen = new Pen(color))
                {
                    //g.DrawEllipse(pen, rect);
                    g.FillEllipse(new SolidBrush(color), node.X - 2, node.Y - 2, 8, 8);
                }
            }
        }
Пример #6
0
        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;
        }
Пример #7
0
        /// <summary>
        /// 获取地铁站点的矩形区域。
        /// </summary>
        /// <param name="node">地铁站点。</param>
        /// <returns></returns>
        private Rectangle GetNodeRect(MetroNode node)
        {
            int r = node.Links.Count > 2 ? 7 : 5;

            return(new Rectangle(node.X - r, node.Y - r, (r << 1) + 1, (r << 1) + 1));
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }