//Функция найдет и удалит указанную связь из списка static Boolean delete_exist_line(Connection _con, List<Connection> _cons) { Boolean result = false; int i = _cons.Count - 1; if (i >= 0) do { if ((_con.p1 == _cons[i].p1 && _con.p2 == _cons[i].p2) || (_con.p1 == _cons[i].p2 && _con.p2 == _cons[i].p1)) { result = true; _cons.RemoveAt(i); } i--; } while (result == false && i >= 0); return result; }
//Функция начертит граф static void print_graph(Graph _g, Connection _cr_con, Connection _path, PictureBox _paint) { Bitmap bmp = new Bitmap(_paint.Width, _paint.Height); Graphics _gr = Graphics.FromImage(bmp); _gr.Clear(Color.White); foreach (S_point _p in _g.Nodes) { _gr.FillEllipse(Brushes.Black, _p.pnt.X - 4, _p.pnt.Y - 4, 8, 8); _gr.DrawString(_p.name, new Font("Arial", 8), Brushes.Black, _p.pnt.X-6, _p.pnt.Y + 8); } foreach(Connection _c in _g.Lines) _gr.DrawLine(new Pen(Color.Black), _c.p1, _c.p2); if (_cr_con.p1 != new Point(0, 0)) _gr.DrawEllipse(new Pen(Color.Turquoise),_cr_con.p1.X-8, _cr_con.p1.Y-8, 16, 16); if (_path.p1 != new Point(0, 0)) _gr.DrawEllipse(new Pen(Color.Red), _path.p1.X - 8, _path.p1.Y - 8, 16, 16); if (_path.p2 != new Point(0, 0)) _gr.DrawEllipse(new Pen(Color.Red), _path.p2.X - 8, _path.p2.Y - 8, 16, 16); _paint.Image = bmp; }
/* * Обработка клика мышкой по полю для рисования, выполняет различные действия в зависимости от режима * в режиме point проставляет по клику ноды * в режиме line создает связи между нодами * в режиме path устанавливает точки, между которыми будет рассчитываться кратчайший путь */ private void Canvas_MouseClick(object sender, MouseEventArgs e) { S_point pnt = new S_point(new Point(e.X, e.Y),0,point_name_man.Text); switch ((Canvas.Tag as String)) { case "point": S_point p = delete_exist_point(pnt.pnt, grph.Nodes); if (p == null) { grph.Nodes.Add(pnt); point_name_man.Text = ""; } else delete_node(p, grph.Lines); break; case "line": int i=0; if (grph.Nodes.Count > 1) { do { if (check_point(pnt.pnt, grph.Nodes[i].pnt)) pnt = grph.Nodes[i]; i++; } while (i < grph.Nodes.Count && pnt != grph.Nodes[i - 1]); if (pnt != grph.Nodes[i - 1]) break; if (cr_con.p1 == new Point(0, 0)) cr_con.p1 = pnt.pnt; else { if (cr_con.p1 == pnt.pnt) cr_con.p1 = new Point(0, 0); else { cr_con.p2 = pnt.pnt; cr_con.cost = calc_cost(cr_con.p1, cr_con.p2); if (!delete_exist_line(cr_con, grph.Lines)) grph.Lines.Add(cr_con); cr_con = new Connection(new Point(0, 0), new Point(0, 0), 0); } } } else System.Windows.Forms.MessageBox.Show("Ошибка:\n" + "Перед созданием граней создайте хотя бы 2 вершины графа.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case "path": i = 0; if (grph.Nodes.Count > 1) { do { p = grph.Nodes[i]; i++; if (check_point(p.pnt, pnt.pnt)) pnt = p; } while (pnt != p && i < grph.Nodes.Count); if (p == pnt) if (start_end.p1 == pnt.pnt || start_end.p2 == pnt.pnt) { if (start_end.p1 == pnt.pnt) start_end.p1 = new Point(0, 0); else start_end.p2 = new Point(0, 0); } else if (start_end.p1 == new Point(0, 0)) start_end.p1 = pnt.pnt; else if (start_end.p2 == new Point(0, 0)) start_end.p2 = pnt.pnt; } else System.Windows.Forms.MessageBox.Show("Ошибка:\n" + "Перед этим действием нужно создать хотя бы 2 вершины.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); break; } print_graph(grph, cr_con, start_end, Canvas); }
//Исследуемый граф //Функция поиска кратчайшего пути, возвращает грани, которые можно вывести на экран static List<Connection> get_path( Connection _start_end, //Начальная и конечная точки Graph _g) { //Список вершин графа со стоимостью List<S_point> ch_pnts = new List<S_point>(); foreach (S_point p in _g.Nodes) ch_pnts.Add(new S_point(p.pnt,0,p.name)); List<Connection> result = new List<Connection>(); double fin_cost = 0; //Сформируем начальный путь snake first = new snake(get_pathes(_start_end.p1, _g.Lines), 0); first.head = _start_end.p1; List<snake> snakes = new List<snake>(); snakes.Add(first); /* * Цикл формирует все возможные пути. Когда будет найден первый путь до конечной точки, будет назначена цена пути. * Оставшиеся пути будут продолжать формироваться до тех пор, пока стоимость каждого из них не превысит * стоимость уже найденного пути. */ do { int i = snakes.Count-1; if (snakes.Count > 0) do { int j = snakes[i].pathes.Count-1; if (snakes[i].pathes.Count>0) do { Point cur_pnt = new Point(); double tmp_cost = snakes[i].cost + snakes[i].pathes[j].cost; if (snakes[i].pathes[j].p1 == snakes[i].head) cur_pnt = snakes[i].pathes[j].p2; else cur_pnt = snakes[i].pathes[j].p1; if ((get_s_point(cur_pnt, ch_pnts).cost > tmp_cost || get_s_point(cur_pnt, ch_pnts).cost == 0) && (tmp_cost<fin_cost || fin_cost==0)) { if (cur_pnt == _start_end.p2 && (fin_cost > tmp_cost || fin_cost==0)) { fin_cost = tmp_cost; result = snakes[i].body; result.Add(snakes[i].pathes[j]); } else if (cur_pnt != snakes[i].neck) { snake tmp_snake = new snake(get_pathes(cur_pnt, _g.Lines), tmp_cost); foreach (Connection c in snakes[i].body) tmp_snake.body.Add(c); tmp_snake.body.Add(snakes[i].pathes[j]); tmp_snake.neck = snakes[i].head; tmp_snake.head = cur_pnt; set_s_point_cost(cur_pnt, tmp_cost, ch_pnts); snakes.Add(tmp_snake); } } snakes[i].pathes.RemoveAt(j); j--; } while(j>=0); snakes.RemoveAt(i); i--; } while(i>=0); } while (snakes.Count!=0); return result; }