public Tuple <List <PointF>, float, float> CalculatePathBetweenVertices(GraphVertex vertex1, GraphVertex vertex2, RouteCalculationMode mode) { //Реализация алгоритма Дейкстры на основе очереди с приоритетом (Heap) int n = vertices.Count; float[] d = new float[n]; int[] p = new int[n]; for (int i = 0; i < n; i++) { d[i] = float.MaxValue; p[i] = -1; } d[vertex1.Id] = 0; var queue = new SimplePriorityQueue <int, float>(); queue.Enqueue(vertex1.Id, 0); while (queue.Count > 0) { int v = queue.Dequeue(); for (int i = 0; i < vertices[v].Edges.Count; i++) { int to = vertices[v].Edges[i].Vert2.Id; //если нужен самый короткий путь - минимизируем длину пути. //если нужен самый быстрый - минимизируем время (длина/скорость). float len = (mode == RouteCalculationMode.ShortRoute) ? (vertices[v].Edges[i].Length) : (vertices[v].Edges[i].Time); if (d[v] + len < d[to]) { d[to] = d[v] + len; p[to] = v; if (!queue.TryUpdatePriority(to, d[to])) { queue.Enqueue(to, d[to]); } } } } if (p[vertex2.Id] == -1) { //не нашли путь throw new Exception(); } // восстанавливаем путь int currentPoint = vertex2.Id; var vertPath = new List <int>(); while (currentPoint != -1) { vertPath.Add(currentPoint); currentPoint = p[currentPoint]; } vertPath.Reverse(); var edgePath = new List <GraphEdge>(); for (int i = 0; i < vertPath.Count - 1; i++) { var vert1 = vertices[vertPath[i]]; var vert2 = vertices[vertPath[i + 1]]; var edge = vert1.Edges.First(e => e.Vert2.Id == vert2.Id); edgePath.Add(edge); } List <PointF> wktPath = edgePath.SelectMany(e => e.Shape).ToList(); float length = edgePath.Sum(edge => edge.Length); float time = edgePath.Sum(edge => edge.Time); return(new Tuple <List <PointF>, float, float>(wktPath, length, time)); }
public RouteCalculationCheckpointResult CalculatePathBetweenPoints(PointF startPoint, PointF finishPoint, RouteCalculationMode mode) { //TO-DO: Искать не ближайшую точку дороги, а наиболее удобную. //TO-DO: Обработать кейс, когда nearStart и nearFinish окажутся одинаковыми var nearStart = this.GetNearVertex(startPoint); var nearFinish = this.GetNearVertex(finishPoint); var calcResult = CalculatePathBetweenVertices(nearStart, nearFinish, mode); if (calcResult.Item1.First() != startPoint) { calcResult.Item1.Insert(0, startPoint); } if (calcResult.Item1.Last() != finishPoint) { calcResult.Item1.Add(finishPoint); } // Length и Time маршрута учитывают только движение по дорогам // и не учитывают время и длину маршрута до ближайшей точки дороги var result = new RouteCalculationCheckpointResult { StartPoint = startPoint, FinishPoint = finishPoint, WKTPath = calcResult.Item1, Length = calcResult.Item2, Time = calcResult.Item3 }; return(result); }
public RouteCalculationResult Calculate(PointF startPoint, List <PointF> checkpoints, RouteCalculationMode mode = RouteCalculationMode.ShortRoute) { var result = new RouteCalculationResult { Mode = mode }; var graph = RoadGraph.getInstance(); var list = new List <List <Tuple <PointF, PointF> > >(); foreach (var checkpoint in checkpoints) { var localResult = graph.CalculatePathBetweenPoints(startPoint, checkpoint, mode); result.Checkpoints.Add(localResult); result.TotalLength += localResult.Length; result.TotalTime += localResult.Time; startPoint = checkpoint; } return(result); }