Newer
Older
Traffic-Simulator / Assets / Scripts / Car / Route.cs
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Route {
    public Node start, end;
    public List<Road> roads = new List<Road>();
    public bool isValid = false;

    public Route(Node start, Node end) {
        this.start = start;
        this.end = end;
        if (start.roads.Count == 0) {
            return;
        }
        Dictionary<Node, Node> cameFrom = new Dictionary<Node, Node>();
        cameFrom[start] = null;
        Dictionary<Node, float> travelDistance = new Dictionary<Node, float>();
        travelDistance.Add(start, 0f);
        Dictionary<Node, float> totalDistance = new Dictionary<Node, float>();
        totalDistance.Add(start, (start.position-end.position).magnitude);
        HashSet<Node> openNodes = new HashSet<Node>();
        openNodes.Add(start);

        while (openNodes.Count > 0) {
            Node currentNode = null;
            float currentMinTotalDistance = float.PositiveInfinity;
            foreach (Node node in openNodes) {
                float distance = totalDistance[node];
                if (distance < currentMinTotalDistance) {
                    currentMinTotalDistance = distance;
                    currentNode = node;
                }
            }
            if (currentNode == end) {
                while (cameFrom[currentNode] != null) {
                    roads.Add(currentNode.roads.Find(it => it.nodes.Contains(cameFrom[currentNode])));
                    currentNode = cameFrom[currentNode];
                }
                roads.Reverse();
                isValid = true;
                return;
            }
            openNodes.Remove(currentNode);
            foreach (Road road in currentNode.roads) {
                if (road.nodes[0] != currentNode) {
                    continue;
                }
                Node neighbour = road.nodes[1];
                float neighbourTravelDistance = totalDistance[currentNode] + (currentNode.position - neighbour.position).magnitude;
                if ((!travelDistance.ContainsKey(neighbour)) || neighbourTravelDistance < travelDistance[neighbour]) {
                    cameFrom[neighbour] = currentNode;
                    travelDistance[neighbour] = neighbourTravelDistance;
                    totalDistance[neighbour] = neighbourTravelDistance + (neighbour.position - end.position).magnitude;
                    if (!openNodes.Contains(neighbour)) {
                        openNodes.Add(neighbour);
                    }
                }
            }
        }
    }
}