예제 #1
0
        protected List <Node> GetNeighbours(AlgorithmData data, Node current)
        {
            List <Node> neighbours = new List <Node>();

            foreach (var edge in data.allEdges)
            {
                if (edge.nodeFrom == current)
                {
                    neighbours.Add(edge.nodeTo);
                }
                else if (edge.nodeTo == current)
                {
                    neighbours.Add(edge.nodeFrom);
                }
            }
            return(neighbours);
        }
예제 #2
0
        public AlgorithmData ConvertVisualsToData()
        {
            AlgorithmData data = new AlgorithmData();

            var visualNodes = FindObjectsOfType <VisualNode>();

            data.allNodes = new List <Node>();
            foreach (var visualNode in visualNodes)
            {
                Node newNode = new Node();
                data.allNodes.Add(newNode);
                if (visualNode.isStartNode)
                {
                    data.startNode = newNode;
                }
                if (visualNode.isEndNode)
                {
                    data.endNode = newNode;
                }
                visualNodeToNodeDict[visualNode] = newNode;
                nodeToVisualNodeDict[newNode]    = visualNode;
            }

            var visualEdges = FindObjectOfType <EdgeMaker>().visualEdges;

            data.allEdges = new List <Edge>();
            foreach (var visualEdge in visualEdges)
            {
                Edge newEdge = new Edge();
                data.allEdges.Add(newEdge);

                newEdge.nodeFrom = visualNodeToNodeDict[visualEdge.nodeFrom];
                newEdge.nodeTo   = visualNodeToNodeDict[visualEdge.nodeTo];

                visualEdgeToEdgeDict[visualEdge] = newEdge;
                edgeToVisualEdgeDict[newEdge]    = visualEdge;
            }

            return(data);
        }
예제 #3
0
        protected override IEnumerator PerformAlgorithmCO(AlgorithmData data)
        {
            bool result = false;

            Queue <Node> queue        = new Queue <Node>();
            List <Node>  visitedNodes = new List <Node>();

            queue.Enqueue(data.startNode);
            visitedNodes.Add(data.startNode);
            while (queue.Count > 0)
            {
                Node current = queue.Dequeue();

                converter.SelectNode(current);
                yield return(new WaitForSeconds(0.05f));

                if (current == data.endNode)
                {
                    Debug.Log("WE FOUND THE END NODE!");
                    result = true;
                    break;
                }

                List <Node> neighbours = GetNeighbours(data, current);
                foreach (var neighbour in neighbours)
                {
                    if (!visitedNodes.Contains(neighbour))
                    {
                        queue.Enqueue(neighbour);
                        visitedNodes.Add(neighbour);
                    }
                }
            }

            if (result == false)
            {
                Debug.Log("We could not find a path to the end node.");
            }
        }
예제 #4
0
        protected override IEnumerator PerformAlgorithmCO(AlgorithmData data)
        {
            List <Node> unvisitedNodes = new List <Node>();      // nodes we need to check

            // Initialise all nodes to infinity and put them in the unvisited list
            foreach (var node in data.allNodes)
            {
                unvisitedNodes.Add(node);
                node.pathWeight = Mathf.Infinity;
            }

            // Initialise the start node
            Node current = data.startNode;

            data.startNode.pathWeight = 0;
            converter.SelectNode(current);

            while (true)
            {
                List <Node> neighbours = GetNeighbours(data, current);
                foreach (var neighbour in neighbours)
                {
                    if (unvisitedNodes.Contains(neighbour))
                    {
                        float tentativeWeight = current.pathWeight + 1;     // 1 is the weight of the segment connecting the two nodes

                        // we compare the tentative weight with the one we already set for that neighbour
                        if (tentativeWeight < neighbour.pathWeight)
                        {
                            neighbour.pathWeight = tentativeWeight;
                        }
                    }
                }

                // we remove the visited node
                unvisitedNodes.Remove(current);

                // let's check whether we finished the path
                if (current == data.endNode)
                {
                    Debug.Log("WE FOUND THE SHORTEST PATH " + current.pathWeight);
                    break;
                }


                // let's choose the node with the minimum weight
                float minWeight = Mathf.Infinity;
                foreach (var node in unvisitedNodes)
                {
                    if (node.pathWeight < minWeight)
                    {
                        minWeight = node.pathWeight;
                        current   = node;
                    }
                }

                converter.SelectNode(current, new Color(current.pathWeight / 15f, 1 - current.pathWeight / 15f, 0));
                yield return(new WaitForSeconds(0.05f));
            }

            // Find the shortest path
            List <Node> shortestPath = new List <Node>();

            shortestPath.Add(data.endNode);
            current = data.endNode;
            converter.SelectNode(current, new Color(0f, 0f, 1f));
            while (true)
            {
                // Find the lowest weight neighbour (which is the one that will take me to the start node at minimum cost)
                float minWeight    = Mathf.Infinity;
                Node  minNeighbour = null;
                foreach (var neighbour in GetNeighbours(data, current))
                {
                    if (neighbour.pathWeight < minWeight)
                    {
                        minWeight    = neighbour.pathWeight;
                        minNeighbour = neighbour;
                    }
                }

                shortestPath.Add(minNeighbour);

                current = minNeighbour;
                converter.SelectNode(current, new Color(0f, 0f, 1f));
                yield return(new WaitForSeconds(0.05f));

                if (current == data.startNode)
                {
                    break;
                }
            }
        }
예제 #5
0
 protected abstract IEnumerator PerformAlgorithmCO(AlgorithmData data);
예제 #6
0
        protected override IEnumerator PerformAlgorithmCO(AlgorithmData data)
        {
            List <Node> unvisitedNodes = new List <Node>();      // nodes we need to check

            // Initialise all nodes to infinity and put them in the unvisited list
            foreach (var node in data.allNodes)
            {
                unvisitedNodes.Add(node);
                node.pathWeight      = Mathf.Infinity;
                node.tentativeWeight = Mathf.Infinity;
            }

            // Initialise the start node
            Node current = data.startNode;

            data.startNode.pathWeight = 0;
            converter.SelectNode(current);

            while (true)
            {
                List <Node> neighbours = GetNeighbours(data, current);
                foreach (var neighbour in neighbours)
                {
                    if (unvisitedNodes.Contains(neighbour))
                    {
                        float pathWeight = current.pathWeight + segmentWeight;  // segmentWeight is the weight of the segment connecting the two nodes

                        // A* magic here!
                        // we also add a heuristic "h" estimate of the remaining cost
                        // we use distance as an heuristic
                        float distance = (converter.nodeToVisualNodeDict[neighbour].transform.position
                                          - converter.nodeToVisualNodeDict[data.endNode].transform.position).sqrMagnitude;
                        float heuristicWeight = distance * heuristicFactor;

                        float tentativeWeight = pathWeight + heuristicWeight;

                        Debug.Log("Tot: " + tentativeWeight + " Path: " + pathWeight + " Heur: " + heuristicWeight);

                        // we compare the tentative weight with the one we already set for that neighbour
                        if (tentativeWeight < neighbour.tentativeWeight)
                        {
                            neighbour.tentativeWeight = tentativeWeight;
                        }

                        if (pathWeight < neighbour.pathWeight)
                        {
                            neighbour.pathWeight = pathWeight;
                        }
                    }
                }

                // we remove the visited node
                unvisitedNodes.Remove(current);

                // let's check whether we finished the path
                if (current == data.endNode)
                {
                    Debug.Log("WE FOUND THE SHORTEST PATH " + current.pathWeight);
                    break;
                }


                // let's choose the node with the minimum weight
                float minWeight = Mathf.Infinity;
                foreach (var node in unvisitedNodes)
                {
                    if (node.tentativeWeight < minWeight)
                    {
                        minWeight = node.tentativeWeight;
                        current   = node;
                    }
                }

                converter.SelectNode(current, new Color(current.tentativeWeight / 15f, 1 - current.tentativeWeight / 15f, 0));
                yield return(new WaitForSeconds(0.05f));
            }

            // Find the shortest path
            List <Node> shortestPath = new List <Node>();

            shortestPath.Add(data.endNode);
            current = data.endNode;
            converter.SelectNode(current, new Color(0f, 0f, 1f));
            while (true)
            {
                // Find the lowest weight neighbour (which is the one that will take me to the start node at minimum cost)
                float minWeight    = Mathf.Infinity;
                Node  minNeighbour = null;
                foreach (var neighbour in GetNeighbours(data, current))
                {
                    if (neighbour.pathWeight < minWeight)
                    {
                        minWeight    = neighbour.pathWeight;
                        minNeighbour = neighbour;
                    }
                }

                shortestPath.Add(minNeighbour);

                current = minNeighbour;
                converter.SelectNode(current, new Color(0f, 0f, 1f));
                yield return(new WaitForSeconds(0.05f));

                if (current == data.startNode)
                {
                    break;
                }
            }
        }