protected virtual void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int edgeIndex) { //this is where you process a child node var childNode = GenerateChildNodeRecord(parentNode, connectionEdge); NodeRecord childOpen = Open.SearchInOpen(childNode); NodeRecord childClose = Closed.SearchInClosed(childNode); if (childOpen == null && childClose == null) { Open.AddToOpen(childNode); if (this.MaxOpenNodes < Open.CountOpen()) { this.MaxOpenNodes = Open.CountOpen(); } // childOpen.status = NodeStatus.Open; } else if (childOpen != null && childOpen.fValue > childNode.fValue) { Open.Replace(childOpen, childNode); } else if (childClose != null && childClose.fValue > childNode.fValue) { Closed.RemoveFromClosed(childClose); Open.AddToOpen(childNode); //childOpen.status = NodeStatus.Open; } }
public void Initialize(List <IInfluenceUnit> units) { this.Open.Initialize(); this.Closed.Initialize(); this.Units = units; foreach (var unit in units) { //I need to do this because in Recast NavMesh graph, the edges of polygons are considered to be nodes and not the connections. //Theoretically the Quantize method should then return the appropriate edge, but instead it returns a polygon //Therefore, we need to create one explicit connection between the polygon and each edge of the corresponding polygon for the search algorithm to work ((NavMeshPoly)unit.Location).AddConnectedPoly(unit.Location.Position); var locationRecord = new LocationRecord { Influence = unit.DirectInfluence, StrongestInfluenceUnit = unit, Location = unit.Location }; Open.AddToOpen(locationRecord); } this.InProgress = true; }
protected void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge, int connectionIndex) { //TODO: Implement this method that processes a child node. Then you can use it in the Search method above. var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); //Distribute initial colors throughout startNode children: int startIndex = parent.StartNodeOutConnectionIndex; if (startIndex == -1) { startIndex = connectionIndex; } float g = parent.gValue + (childNode.LocalPosition - parent.node.LocalPosition).magnitude; NodeRecord nodeInOpen = Open.SearchInOpen(childNodeRecord); NodeRecord nodeInClosed = Closed.SearchInClosed(childNodeRecord); if (nodeInOpen == null && nodeInClosed == null) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.fValue = g; childNodeRecord.StartNodeOutConnectionIndex = startIndex; Open.AddToOpen(childNodeRecord); } else if (nodeInOpen != null && nodeInOpen.gValue > g) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.fValue = g; childNodeRecord.StartNodeOutConnectionIndex = startIndex; Open.Replace(nodeInOpen, childNodeRecord); } }
protected virtual void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int connectionIndex) { //this is where you process a child node var childNode = GenerateChildNodeRecord(parentNode, connectionEdge); NodeRecord openNode = Open.SearchInOpen(childNode); NodeRecord closeNode = Closed.SearchInClosed(childNode); if (openNode == null && closeNode == null) { this.Open.AddToOpen(childNode); } else if (openNode != null && childNode.fValue < openNode.fValue) { Open.Replace(openNode, childNode); } else if (openNode != null && childNode.fValue == openNode.fValue) { if (childNode.hValue < openNode.hValue) { Open.Replace(openNode, childNode); } } else if (closeNode != null && childNode.fValue < closeNode.fValue) { Closed.RemoveFromClosed(closeNode); Open.AddToOpen(childNode); } }
public void Search(NavigationGraphNode startNode, NodeGoalBounds nodeGoalBounds) { //TODO: Implement the algorithm that calculates the goal bounds using a dijkstra //Given that the nodes in the graph correspond to the edges of a polygon, we won't be able to use the vertices of the polygon to update the bounding boxes this.Open.Initialize(); this.Closed.Initialize(); NodeRecord StartNode = NodeRecordArray.GetNodeRecord(startNode); StartNode.StartNodeOutConnectionIndex = -1; Open.AddToOpen(StartNode); int OpenSize = Open.All().Count; while (OpenSize > 0) { NodeRecord currentNode = Open.GetBestAndRemove(); Open.RemoveFromOpen(currentNode); Closed.AddToClosed(currentNode); if (currentNode.StartNodeOutConnectionIndex != -1) { nodeGoalBounds.connectionBounds[currentNode.StartNodeOutConnectionIndex].UpdateBounds(currentNode.node.Position); } //Initialize start node edge colors: var outConnections = currentNode.node.OutEdgeCount; for (int i = 0; i < outConnections; i++) { this.ProcessChildNode(currentNode, currentNode.node.EdgeOut(i), i); } OpenSize = Open.All().Count; } }
protected virtual void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int edgeIndex) { //this is where you process a child node var childNode = GenerateChildNodeRecord(parentNode, connectionEdge); //TODO: implement the rest of the code here var nodeOpen = Open.SearchInOpen(childNode); var nodeClose = Closed.SearchInClosed(childNode); if (nodeOpen != null) { if (nodeOpen.fValue >= childNode.fValue) { Open.RemoveFromOpen(nodeOpen); Open.AddToOpen(childNode); } return; } else if (nodeClose != null) { if (nodeClose.fValue > childNode.fValue) { Closed.RemoveFromClosed(nodeClose); Open.AddToOpen(childNode); } return; } Open.AddToOpen(childNode); }
protected virtual void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge) { var childNode = connectionEdge.ToNode; var childNodeRecord = new NodeRecord { node = childNode, parent = parent, gValue = parent.gValue + connectionEdge.Cost, hValue = this.Heuristic.H(childNode, this.GoalNode) }; childNodeRecord.fValue = F(childNodeRecord); NodeRecord openNode = Open.SearchInOpen(childNodeRecord); NodeRecord closedNode = Closed.SearchInClosed(childNodeRecord); if (openNode == null && closedNode == null) { Open.AddToOpen(childNodeRecord); } else if (openNode != null && openNode.fValue > childNodeRecord.fValue) { Open.Replace(openNode, childNodeRecord); } else if (closedNode != null && closedNode.fValue > childNodeRecord.fValue) { Closed.RemoveFromClosed(closedNode); Open.AddToOpen(childNodeRecord); } }
protected void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge, int connectionIndex) { NavigationGraphNode childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); var open = Open.SearchInOpen(childNodeRecord); var close = Closed.SearchInClosed(childNodeRecord); if (open == null && close == null) { float g = parent.gValue + (childNodeRecord.node.LocalPosition - parent.node.LocalPosition).magnitude; UpdateNode(parent, childNodeRecord, g, 0, g, connectionIndex); Open.AddToOpen(childNodeRecord); } else if (open != null) { var g = parent.gValue + (childNodeRecord.node.LocalPosition - parent.node.LocalPosition).magnitude; if (g < childNodeRecord.gValue) { UpdateNode(parent, childNodeRecord, g, 0, g, connectionIndex); Open.Replace(childNodeRecord, childNodeRecord); } } }
public void Search(NavigationGraphNode startNode, NodeGoalBounds nodeGoalBounds) { this.Open.Initialize(); this.Closed.Initialize(); NodeRecord startNodeRecord = this.NodeRecordArray.GetNodeRecord(startNode); startNodeRecord.gValue = 0; startNodeRecord.fValue = 0; startNodeRecord.parent = null; startNodeRecord.StartNodeOutConnectionIndex = 0; Open.AddToOpen(startNodeRecord); while (true) { if (this.Open.CountOpen() == 0) { return; } NodeRecord currNode = this.Open.GetBestAndRemove(); this.Closed.AddToClosed(currNode); nodeGoalBounds.connectionBounds[currNode.StartNodeOutConnectionIndex].UpdateBounds(currNode.node.Position); int nOutConnections = currNode.node.OutEdgeCount; for (int i = 0; i < nOutConnections; i++) { this.ProcessChildNode(currNode, currNode.node.EdgeOut(i), i); } } //TODO: Implement the algorithm that calculates the goal bounds using a dijkstra //Given that the nodes in the graph correspond to the edges of a polygon, we won't be able to use the vertices of the polygon to update the bounding boxes }
protected override void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge, int edgeIndex) { float f; float g; float h; var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or your algorithm will not work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); return; } g = bestNode.gValue + (childNodeRecord.node.LocalPosition - bestNode.node.LocalPosition).magnitude; h = this.Heuristic.H(childNodeRecord.node, this.GoalNode); f = F(g, h); //childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); var childOpen = this.Open.SearchInOpen(childNodeRecord); var childClosed = this.Closed.SearchInClosed(childNodeRecord); if (childNodeRecord.status == NodeStatus.Unvisited) { childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); Open.AddToOpen(childNodeRecord); int count = Open.CountOpen(); if (this.MaxOpenNodes < count) { this.MaxOpenNodes = count; } } else if (childNodeRecord.status == NodeStatus.Open && childOpen != null && childOpen.fValue > childNodeRecord.fValue) { childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); this.Open.Replace(childOpen, childNodeRecord); } else if (childNodeRecord.status == NodeStatus.Closed && childClosed != null && childClosed.fValue > childNodeRecord.fValue) { childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); this.Closed.RemoveFromClosed(childClosed); this.Open.AddToOpen(childNodeRecord); } }
protected override void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge) { float f; float g; float h; var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or you algorithm wont work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } g = bestNode.gValue + connectionEdge.Cost; h = this.Heuristic.H(childNode, this.GoalNode); f = g + h; var ChildNodeOpen = Open.SearchInOpen(childNodeRecord); var ChildNodeClosed = Closed.SearchInClosed(childNodeRecord); if ((ChildNodeClosed == null) && (ChildNodeOpen == null)) { childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); } else if ((ChildNodeOpen != null) && f < childNodeRecord.fValue) { childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.Replace(ChildNodeOpen, childNodeRecord); } else if ((ChildNodeClosed != null) && f < childNodeRecord.fValue) { childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); } }
protected void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge, int connectionIndex) { //TODO: Implement this method that processes a child node. Then you can use it in the Search method above. var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or your algorithm will not work childNodeRecord = new NodeRecord { node = childNode, parent = parent, StartNodeOutConnectionIndex = parent.StartNodeOutConnectionIndex, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } //Distribute initial colors throughout startNode children: int color = parent.StartNodeOutConnectionIndex; if (color == -1) { color = connectionIndex; } NodeRecord parentNode = parent; float g = parentNode.gValue + (childNode.LocalPosition - parentNode.node.LocalPosition).magnitude; NodeRecord nodeInOpen = Open.SearchInOpen(childNodeRecord); NodeRecord nodeInClosed = Closed.SearchInClosed(childNodeRecord); if (nodeInOpen == null && nodeInClosed == null) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.StartNodeOutConnectionIndex = color; Open.AddToOpen(childNodeRecord); } else if (nodeInOpen != null && childNodeRecord.gValue > g) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.StartNodeOutConnectionIndex = color; Open.Replace(nodeInOpen, childNodeRecord); } }
protected override void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge, int edgeIndex) { var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or your algorithm will not work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } //this is where you process a child node var parent = bestNode; var g = bestNode.gValue + (childNode.LocalPosition - bestNode.node.LocalPosition).magnitude; var h = this.Heuristic.H(childNode, this.GoalNode); //var h = this.Heuristic.Fast_H(childNode.Position, this.GoalNode.Position); var f = F(g, h); NodeRecord nodeInOpen = Open.SearchInOpen(childNodeRecord); NodeRecord nodeInClosed = Closed.SearchInClosed(childNodeRecord); if (nodeInOpen == null && nodeInClosed == null) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); } else if (nodeInOpen != null && nodeInOpen.fValue > f) { childNodeRecord.parent = parent; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.Replace(nodeInOpen, childNodeRecord); } }
protected virtual void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int edgeIndex) { //this is where you process a child node var childNode = GenerateChildNodeRecord(parentNode, connectionEdge); NodeRecord nodeInOpen = Open.SearchInOpen(childNode); NodeRecord nodeInClosed = Closed.SearchInClosed(childNode); if (nodeInOpen == null && nodeInClosed == null) { Open.AddToOpen(childNode); } else if (nodeInOpen != null && childNode.fValue < nodeInOpen.fValue) { Open.Replace(nodeInOpen, childNode); } }
protected override void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge, int edgeIndex) { float f; float g; float h; var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or your algorithm will not work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } //TODO: implement the rest of your code here //this is where you process a child node childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); var openChildNode = Open.SearchInOpen(childNodeRecord); var closedChildNode = Closed.SearchInClosed(childNodeRecord); if (openChildNode == null && closedChildNode == null) { Open.AddToOpen(childNodeRecord); } else if (openChildNode != null && openChildNode.fValue > childNodeRecord.fValue) { Open.Replace(openChildNode, childNodeRecord); } else if (closedChildNode != null && closedChildNode.fValue > childNodeRecord.fValue) { //Closed.RemoveFromClosed(closedChildNode); Open.AddToOpen(childNodeRecord); } }
public void Search(NavigationGraphNode startNode, NodeGoalBounds nodeGoalBounds) { //TODO: Implement the algorithm that calculates the goal bounds using a dijkstra //Given that the nodes in the graph correspond to the edges of a polygon, we won't be able to use the vertices of the polygon to update the bounding boxes this.Open.Initialize(); this.Closed.Initialize(); //Initialize starting node for Dijkstra NodeRecord StartNode = NodeRecordArray.GetNodeRecord(startNode); StartNode.gValue = 0; StartNode.StartNodeOutConnectionIndex = -1; // -1 corresponds to not having a "color". Valid indices will start at 0 Open.AddToOpen(StartNode); //Dijkstra while (Open.CountOpen() > 0) { NodeRecord currentNode = Open.GetBestAndRemove(); Open.RemoveFromOpen(currentNode); Closed.AddToClosed(currentNode); //We don't fill out the starting position as it is colorless if (currentNode.StartNodeOutConnectionIndex != -1) { var outFillConnections = currentNode.node.OutEdgeCount; Vector3 edgePosition; //Update the bounding box with all positions of EdgeOuts of the current Node for (int i = 0; i < outFillConnections; i++) { edgePosition = currentNode.node.EdgeOut(i).ToNode.Position; nodeGoalBounds.connectionBounds[currentNode.StartNodeOutConnectionIndex].UpdateBounds(edgePosition); //update only the bound corresponding to the ConnectionIndex } } //Process Child Nodes var outConnections = currentNode.node.OutEdgeCount; for (int i = 0; i < outConnections; i++) { this.ProcessChildNode(currentNode, currentNode.node.EdgeOut(i), i); } } }
protected virtual void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge) { var childNodeRecord = GenerateChildNodeRecord(bestNode, connectionEdge); var oldChildNodeOpen = Open.SearchInOpen(childNodeRecord); var oldChildNodeClosed = Closed.SearchInClosed(childNodeRecord); if ((oldChildNodeClosed == null) && (oldChildNodeOpen == null)) { Open.AddToOpen(childNodeRecord); } else if ((oldChildNodeOpen != null) && oldChildNodeOpen.fValue > childNodeRecord.fValue) { Open.Replace(oldChildNodeOpen, childNodeRecord); } else if ((oldChildNodeClosed != null) && oldChildNodeClosed.fValue > childNodeRecord.fValue) { Closed.RemoveFromClosed(oldChildNodeClosed); Open.AddToOpen(childNodeRecord); } }
//don't forget to add the override keyword here if you define a ProcessChildNode method in the base class protected void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge) { var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or you algorithm wont work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } childNodeRecord.gValue = bestNode.gValue + connectionEdge.Cost; childNodeRecord.hValue = this.Heuristic.H(childNode, this.GoalNode); childNodeRecord.fValue = F(childNodeRecord); NodeRecord openNode = Open.SearchInOpen(childNodeRecord); NodeRecord closedNode = Closed.SearchInClosed(childNodeRecord); if (openNode == null && closedNode == null) { Open.AddToOpen(childNodeRecord); } else if (openNode != null && openNode.fValue > childNodeRecord.fValue) { Open.Replace(openNode, childNodeRecord); } else if (closedNode != null && closedNode.fValue > childNodeRecord.fValue) { Closed.RemoveFromClosed(closedNode); Open.AddToOpen(childNodeRecord); } }
protected virtual void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge) { //this is where you process a child node var ChildNode = GenerateChildNodeRecord(bestNode, connectionEdge); var ChildNodeOpen = Open.SearchInOpen(ChildNode); var ChildNodeClosed = Closed.SearchInClosed(ChildNode); if ((ChildNodeClosed == null) && (ChildNodeOpen == null)) { Open.AddToOpen(ChildNode); } else if ((ChildNodeOpen != null) && ChildNodeOpen.fValue >= ChildNode.fValue) { Open.Replace(ChildNodeOpen, ChildNode); } else if ((ChildNodeClosed != null) && ChildNodeClosed.fValue > ChildNode.fValue) { Closed.RemoveFromClosed(ChildNodeClosed); Open.AddToOpen(ChildNode); } }
protected void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge, int connectionIndex) { var childNode = connectionEdge.ToNode; //TODO: implement the rest of your code here //this is where you process a child node var gValue = parent.gValue + (childNode.LocalPosition - parent.node.LocalPosition).magnitude; var childNodeRecord = new NodeRecord { node = childNode, parent = parent, gValue = gValue, fValue = gValue }; if (parent.parent == null) { childNodeRecord.StartNodeOutConnectionIndex = connectionIndex; } else { childNodeRecord.StartNodeOutConnectionIndex = parent.StartNodeOutConnectionIndex; } var openChildNode = Open.SearchInOpen(childNodeRecord); var closedChildNode = Closed.SearchInClosed(childNodeRecord); if (openChildNode == null && closedChildNode == null) { Open.AddToOpen(childNodeRecord); } else if (openChildNode != null && openChildNode.fValue > childNodeRecord.fValue) { Open.Replace(openChildNode, childNodeRecord); } //TODO: Implement this method that processes a child node. Then you can use it in the Search method above. }
public void Search(NavigationGraphNode startNode, NodeGoalBounds nodeGoalBounds) { //TODO: Implement the algorithm that calculates the goal bounds using a dijkstra //Given that the nodes in the graph correspond to the edges of a polygon, we won't be able to use the vertices of the polygon to update the bounding boxes startNodeRecord = this.NodeRecordArray.GetNodeRecord(startNode); startNodeIndex = startNodeRecord.node.NodeIndex; startNodeRecord.startNodeIndex = startNodeIndex; bool first = true; Open.AddToOpen(startNodeRecord); while (this.Open.CountOpen() > 0) { bestNode = this.Open.GetBestAndRemove(); if (!first) { nodeGoalBounds.connectionBounds[bestNode.StartNodeOutConnectionIndex].UpdateBounds(bestNode.node.Position); } this.Closed.AddToClosed(bestNode); for (int i = 0; i < bestNode.node.OutEdgeCount; i++) { if (first) { this.ProcessChildNode(bestNode, bestNode.node.EdgeOut(i), i, nodeGoalBounds); } else { this.ProcessChildNode(bestNode, bestNode.node.EdgeOut(i), bestNode.StartNodeOutConnectionIndex, nodeGoalBounds); } } first = false; } }
protected virtual void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge) { //this is where you process a child node NodeRecord childNode = GenerateChildNodeRecord(bestNode, connectionEdge); NodeRecord openNode = Open.SearchInOpen(childNode); NodeRecord closedNode = Closed.SearchInClosed(childNode); bool inOpen = openNode != null ? true : false; bool inClosed = closedNode != null ? true : false; if (!inOpen && !inClosed) { Open.AddToOpen(childNode); } else if (inOpen && childNode.fValue < openNode.fValue) { Open.RemoveFromOpen(openNode); Open.AddToOpen(childNode); } else if (inClosed && childNode.fValue < closedNode.fValue) { Closed.RemoveFromClosed(closedNode); Open.AddToOpen(childNode); } }
public void AddToOpen(NodeRecord nodeRecord) { Open.AddToOpen(nodeRecord); NodeRecords[nodeRecord.node.NodeIndex].status = NodeStatus.Open; }
protected override void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge, int edgeIndex) { float f; float g; float h; var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); #region do not look into this if (childNodeRecord == null) { //this piece of code is used just because of the special start nodes and goal nodes added to the RAIN Navigation graph when a new search is performed. //Since these special goals were not in the original navigation graph, they will not be stored in the NodeRecordArray and we will have to add them //to a special structure //it's ok if you don't understand this, this is a hack and not part of the NodeArrayA* algorithm, just do NOT CHANGE THIS, or your algorithm will not work childNodeRecord = new NodeRecord { node = childNode, parent = bestNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } #endregion h = this.Heuristic.H(childNode, this.GoalNode); g = bestNode.gValue + connectionEdge.Cost; f = g + h; NodeRecord nodeOpen = this.Open.SearchInOpen(childNodeRecord); NodeRecord closedNode = this.Closed.SearchInClosed(childNodeRecord); if (nodeOpen != null) { if (nodeOpen.fValue >= f) { Open.RemoveFromOpen(nodeOpen); childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); } return; } else if (closedNode != null) { if (closedNode.fValue > f) { Closed.RemoveFromClosed(closedNode); childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); } return; } childNodeRecord.parent = bestNode; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.fValue = f; Open.AddToOpen(childNodeRecord); }
//this method should return true if it finished processing, and false if it still needs to continue public bool MapFloodDijkstra() { var processedNodes = 0; while (Open.CountOpen() > 0) { processedNodes++; if (processedNodes > NodesPerFlood) { return(false); } LocationRecord currentRecord = Open.GetBestAndRemove(); Closed.AddToClosed(currentRecord); int outConnections = currentRecord.Location.OutEdgeCount; for (int i = 0; i < outConnections; i++) { var location = GenerateChildNodeRecord(currentRecord, currentRecord.Location.EdgeOut(i)); float influence = InfluenceFunction.DetermineInfluence(currentRecord.StrongestInfluenceUnit, location.Location.Position); if (InfluenceThreshold.CompareTo(influence) > 0) { continue; } LocationRecord neighborRecord = Closed.SearchInClosed(location); if (neighborRecord != null) { if (neighborRecord.Influence >= influence) { continue; } else { Closed.RemoveFromClosed(neighborRecord); } } else { neighborRecord = Open.SearchInOpen(location); if (neighborRecord != null) { if (neighborRecord.Influence < influence) { neighborRecord.StrongestInfluenceUnit = currentRecord.StrongestInfluenceUnit; neighborRecord.Influence = influence; } continue; } else //we found a new record not in open or closed { neighborRecord = new LocationRecord(); neighborRecord.Location = location.Location; } } neighborRecord.StrongestInfluenceUnit = currentRecord.StrongestInfluenceUnit; neighborRecord.Influence = influence; Open.AddToOpen(neighborRecord); } } this.InProgress = false; //this.CleanUp(); return(true); }