/// <summary> /// Performs the visit part of Depth First Search /// Reference: DFS Algorithm taken from introduction to algorithms book, page 604 /// </summary> /// <param name="nodes">List of nodes</param> /// <param name="n">Node to visit</param> /// <param name="time">Time taken to visit node</param> /// <returns></returns> private int DFSVisit(List <DFSNode> nodes, DFSNode n, int time) { // Increment time, assign discovered time (n.DiscoverTime) and new color to node // Gray = Visited, but isn't finished with this node yet time++; n.DiscoverTime = time; n.Color = DFSNode.Colors.Grey; foreach (var edge in _edges[n.Node]) { // Get the first node, which is pointed to by the current node. Other ordering could also be used var dfsNode = nodes.First(dfsnode => dfsnode.Node == edge.In); if (dfsNode.Color == DFSNode.Colors.White) { time = DFSVisit(nodes, dfsNode, time); } } // We've finished visiting this node, and is able to set the color to black // and set the finish time (v.FinisedTime) n.Color = DFSNode.Colors.Black; time++; n.FinishedTime = time; return(time); }
public override void FindPath(Vector2 startPosition, Vector2 targetPosition) { // Start stopwatch. stopwatch.Restart(); stopwatch.Start(); // Find start and end node positions. DFSNode startNode = (DFSNode)grid.NodeFromWorldPoint(startPosition); DFSNode targetNode = (DFSNode)grid.NodeFromWorldPoint(targetPosition); // Initalise Lists & HastSets. List <DFSNode> visitedSet = new List <DFSNode>(); List <DFSNode> order = new List <DFSNode>(); Stack <DFSNode> openSet = new Stack <DFSNode>(); startNode.History = new List <DFSNode>(); visitedSet.Add(startNode); openSet.Push(startNode); // Add starting node to open set, we start searching from here. while (openSet.Count > 0) // While there are nodes in the open set, loop. { DFSNode currentNode = openSet.Pop(); if (!order.Contains(currentNode)) { order.Add(currentNode); } foreach (DFSNode neighbourNode in grid.GetNeighbours(currentNode)) // Loop over each neighbour of the current node. { if (!neighbourNode.Walkable || visitedSet.Contains(neighbourNode)) // If the neighbour is not walkable, or has already been sorted into the closed set... { continue; } neighbourNode.History = new List <DFSNode>(currentNode.History); neighbourNode.History.Add(currentNode); visitedSet.Add(neighbourNode); openSet.Push(neighbourNode); if (!order.Contains(neighbourNode)) { order.Add(neighbourNode); } if (neighbourNode == targetNode) // If we have reached the target node... { neighbourNode.History.Add(neighbourNode); RetracePath(targetNode, order.ConvertAll(x => (Node)x)); openSet.Clear(); stopwatch.Stop(); break; } } } waypoints = RetracePath(targetNode, order.ConvertAll(x => (Node)x)); unit.PathToPosition(startPosition, targetPosition, waypoints); }
public List <DFSNode> GetDFSNodes() { List <DFSNode> dfsNodes = new List <DFSNode>(); foreach (DfsNode dfsNodeInformation in DfsNode.GetInstances()) { DFSNode dfsNodeData = new DFSNode(dfsNodeInformation.Name, dfsNodeInformation.Root, dfsNodeInformation.Description, dfsNodeInformation.Timeout); dfsNodes.Add(dfsNodeData); } return(dfsNodes); }
/// <summary> /// Retrace the found path from the start to end node, including the order that the path was found in. /// </summary> protected override Vector2[] RetracePath(Node endNode, List <Node> order) { List <Node> path = new List <Node>(); DFSNode currentNode = (DFSNode)endNode; path = currentNode.History.ConvertAll(x => (Node)x); path[0].IsStartNode = true; endNode.IsEndNode = true; grid.Path = path; grid.Order = order.ConvertAll(x => (Node)x); grid.ShowFinalPath(); nodesVisitedText.text = "Nodes Visited: " + order.Count + " in " + stopwatch.ElapsedMilliseconds + "ms"; Vector2[] waypoints = ConvertToWaypoints(path); return(waypoints); }
public bool checkDFSNodeInStack(DFSNode node) { foreach (DFSNode item in this.DFSNodes) { if (item.Equals(node)) { Console.WriteLine("Node is in stack already u f*****g numb"); return true; } } return false; }
public void getDFSChildren(DFSNode node) { int x = node.X; int y = node.Y; if (!checkRightSide()) { DFSNode rightChild = new DFSNode(x + 1, y); rightChild.ParentNode = node; if (!checkDFSNodeInStack(rightChild)) { node.RightChild = rightChild; } } if (!checkTopSide()) { DFSNode topChild = new DFSNode(x, y + 1); topChild.ParentNode = node; if (!checkDFSNodeInStack(topChild)) node.TopChild = topChild; } if (!checkLeftSide()) { DFSNode leftChild = new DFSNode(x - 1, y); leftChild.ParentNode = node; if (!checkDFSNodeInStack(leftChild)) node.LeftChild = leftChild; } if (!checkBottomSide()) { DFSNode bottomChild = new DFSNode(x, y - 1); bottomChild.ParentNode = node; if (!checkDFSNodeInStack(bottomChild)) node.BottomChild = bottomChild; } }
/// <summary> /// Create a new instance of the grid, instantiating the corresponding active algorithms nodes. /// </summary> public void CreateGrid() { CheckExistingGrid(); grid = new Node[gridSizeX, gridSizeY]; Vector2 bottomLeft = (Vector2)transform.position - Vector2.right * gridWorldSize.x / 2 - Vector2.up * gridWorldSize.y / 2; // Calculate the bottom left position of the grid by starting from the centre (transform.position) and subtracting half the length and height of the grid. // Cycle through every position of the grid. for (int y = 0; y < gridSizeY; y++) { for (int x = 0; x < gridSizeX; x++) { Vector2 worldPoint = bottomLeft + Vector2.right * (x * nodeDiameter + nodeRadius) + Vector2.up * (y * nodeDiameter + nodeRadius); // Calculate position the node is in the world based on position in the grid and node size. bool walkable = true; // Flag as not being obstructed by default. // CircleCast at the current position of the grid to check if there are any obstacles, useful for adapting to level design changes. if (Physics2D.CircleCast(worldPoint, nodeRadius, Vector2.zero, 0.5f, unwalkableMask)) { walkable = false; // Flag as being obstructed if an obstacle was overalpping the circlecast. } // Instantiate node game object and scale to set size. GameObject _nodeGO = Instantiate(node, worldPoint, Quaternion.identity); _nodeGO.transform.localScale = Vector3.one * (nodeDiameter - distanceBetweenNodes); // Assign active algorithms node class to the node game object and store at the current grid position. switch (PathfinderFactory.ActiveAlgorithm) { case PathfinderFactory.Pathfinding.AStar: AStarNode _aStarNode = _nodeGO.AddComponent <AStarNode>(); _aStarNode.SetValues(walkable, worldPoint, x, y); grid[x, y] = _aStarNode; break; case PathfinderFactory.Pathfinding.Dijkstra: DijkstraNode _dijkstraNode = _nodeGO.AddComponent <DijkstraNode>(); _dijkstraNode.SetValues(walkable, worldPoint, x, y); grid[x, y] = _dijkstraNode; break; case PathfinderFactory.Pathfinding.BFS: BFSNode _BFSNode = _nodeGO.AddComponent <BFSNode>(); _BFSNode.SetValues(walkable, worldPoint, x, y); grid[x, y] = _BFSNode; break; case PathfinderFactory.Pathfinding.DFS: DFSNode _DFSNode = _nodeGO.AddComponent <DFSNode>(); _DFSNode.SetValues(walkable, worldPoint, x, y); grid[x, y] = _DFSNode; break; } } } if (previousObstaclePoints != null) // If any previous obstacles are recorded... { // Loop over each, calculate the node that has taken their position and flag them as not walkable. foreach (Vector2 point in previousObstaclePoints) { Node node = NodeFromWorldPoint(point); node.Walkable = false; } } if (previousStartPosition != Vector2.zero) // If a previous start position exists... { // Calculate the node that has taken its position and flag as start node. Node node = NodeFromWorldPoint(previousStartPosition); node.IsStartNode = true; PathfindingManager.instance.startNode = node.transform; } if (previousEndPosition != Vector2.zero) // If a previous end position exists... { // Calculate the node that has taken its position and flag as end node. Node node = NodeFromWorldPoint(previousEndPosition); node.IsEndNode = true; PathfindingManager.instance.endNode = node.transform; } UpdateNodeColours(); }
private void Update() { if (Input.GetMouseButtonDown(0) && !Input.GetKey(KeyCode.LeftControl)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { if (hit.transform.gameObject.GetComponent <DFSNode>() != null) { if (begin == null) { begin = hit.transform.gameObject.GetComponent <DFSNode>(); hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.green;; } else { begin.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white; begin = hit.transform.gameObject.GetComponent <DFSNode>(); hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.green;; } } } } if (Input.GetMouseButtonDown(1) && !Input.GetKey(KeyCode.LeftControl)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { if (hit.transform.gameObject.GetComponent <DFSNode>() != null) { if (end == null) { end = hit.transform.gameObject.GetComponent <DFSNode>(); hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.red;; } else { end.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white; end = hit.transform.gameObject.GetComponent <DFSNode>(); hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.red;; } } } } if (Input.GetKeyDown(KeyCode.C)) { foreach (DFSNode node in pathNodes) { node.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white; } alreadyBeenNodes.Clear(); nodeParent.Clear(); pathNodes.Clear(); toDoNodes.Clear(); result.text = "Result:"; loops = 0; } }
protected List <DFSNode> Generate(DFSNode start, DFSNode goal) { toDoNodes.Add(start); nodeParent.Add(start, null); while (toDoNodes.Count > 0) { DFSNode currentNode = toDoNodes[toDoNodes.Count - 1]; alreadyBeenNodes.Add(currentNode); toDoNodes.Remove(currentNode); if (currentNode == goal) { DFSNode backTrack = goal; do { pathNodes.Add(backTrack); backTrack = nodeParent[backTrack]; }while (backTrack != null); pathNodes.Reverse(); if (loops > 0) { loops--; alreadyBeenNodes.Clear(); nodeParent.Clear(); pathNodes.Clear(); toDoNodes.Clear(); Generate(begin, end); return(null); } else { for (int i = 1; i < pathNodes.Count - 1; i++) { pathNodes[i].transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.yellow; } sw.Stop(); result.text = "Result: " + sw.ElapsedMilliseconds + "ms & " + pathNodes.Count + " Nodes"; sw.Reset(); return(pathNodes); } } foreach (DFSNode nextNode in currentNode.connections) { if (toDoNodes.Contains(nextNode) | alreadyBeenNodes.Contains(nextNode)) { //Nothing } else { toDoNodes.Add(nextNode); nodeParent.Add(nextNode, currentNode); } } } return(null); }