protected override void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int edgeIndex) { //TODO: Implement this method for the GoalBoundingPathfinding to Work. If you implemented the NodeArrayAStar properly, you wont need to change the search method. //Fetching index of GoalBoundingTable NodeRecord childNodeRecord = NodeRecordArray.GetNodeRecord(connectionEdge.ToNode); int index = childNodeRecord.node.NodeIndex; NodeGoalBounds nodeBounds = GoalBoundingTable.table[index]; if (nodeBounds == null) //Special check for some nodes that have null nodeBounds??? is NodeIndex correct or is the table malformed? { base.ProcessChildNode(parentNode, connectionEdge, edgeIndex); } //TODO: needs fix /* Check if the box of parent node in the direction of the childnode has goal within. Not working due to arrayIndexExceptions: * * DataStructures.GoalBounding.Bounds b = nodeBounds.connectionBounds[edgeIndex]; * if (!b.PositionInsideBounds(GoalPosition)) * { * this.DiscardedEdges++; * return; * } */ base.ProcessChildNode(parentNode, connectionEdge, edgeIndex); }
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 void ProcessChildNode(NodeRecord parent, NavigationGraphEdge connectionEdge, int connectionIndex) { float g; var childNode = connectionEdge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); //custo da sol ate agora (valor do no anterior mais a aresta do bestNode ate ao childnode) g = parent.gValue + connectionEdge.Cost; if (childNodeRecord.status == NodeStatus.Unvisited) { childNodeRecord.gValue = g; childNodeRecord.parent = parent; NodeRecordArray.AddToOpen(childNodeRecord); childNodeRecord.StartNodeOutConnectionIndex = connectionIndex; //das cor } else if (childNodeRecord.status == NodeStatus.Open && (childNodeRecord.gValue > g)) { childNodeRecord.gValue = g; childNodeRecord.parent = parent; NodeRecordArray.Replace(childNodeRecord, childNodeRecord); childNodeRecord.StartNodeOutConnectionIndex = connectionIndex; //trocas cor } }
public NodeArrayAStarPathFinding(NavMeshPathGraph graph, IHeuristic heuristic) : base(graph, null, null, heuristic) { //do not change this var nodes = this.GetNodesHack(graph); this.NodeRecordArray = new NodeRecordArray(nodes); this.Open = this.NodeRecordArray; this.Closed = this.NodeRecordArray; }
protected void ProcessChildNode(NodeRecord bestNode, NavigationGraphEdge connectionEdge, int connectionIndex, NodeGoalBounds nodeGoalBounds) { //TODO: Implement this method that processes a child node. Then you can use it in the Search method above. var childNode = connectionEdge.ToNode; NodeRecord childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); if (childNodeRecord.startNodeIndex != startNodeIndex) { childNodeRecord.status = NodeStatus.Unvisited; } 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); } if (childNodeRecord.status == NodeStatus.Closed) { return; } float g = bestNode.gValue + connectionEdge.Cost; float f = g; if (childNodeRecord.status == NodeStatus.Unvisited) { ChangeNodeValues(childNodeRecord, 0, g, f, bestNode, connectionIndex); NodeRecordArray.AddToOpen(childNodeRecord); return; } if (childNodeRecord.status == NodeStatus.Open && childNodeRecord.fValue > f) { ChangeNodeValues(childNodeRecord, 0, g, f, bestNode, connectionIndex); this.NodeRecordArray.Replace(childNodeRecord, childNodeRecord); return; } }
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); } } }
//cria rectangulos 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 // mete os vizinhos do no inicial. Inicializacao da lista var outConnections = startNode.OutEdgeCount; for (int i = 0; i < outConnections; i++) { NavigationGraphEdge edge = startNode.EdgeOut(i); var childNode = edge.ToNode; var childNodeRecord = this.NodeRecordArray.GetNodeRecord(childNode); //adicionar ao open NodeRecordArray.AddToOpen(childNodeRecord); //transformar em vector3 para inicializar cada rectangulo childNodeRecord.StartNodeOutConnectionIndex = i; } //giro: var startTime = Time.realtimeSinceStartup; //enquanto houver nos no conj open while (this.Open.CountOpen() > 0) { NodeRecord bestNode = this.Open.GetBestAndRemove(); //aumentar o rectangulo nodeGoalBounds.connectionBounds[bestNode.StartNodeOutConnectionIndex].UpdateBounds(bestNode.node.LocalPosition); //isto e a cor do rectangulo. falta updateBounds this.Closed.AddToClosed(bestNode); //para ver as ligacoes do no que acabamos de ver var outConnections2 = bestNode.node.OutEdgeCount; for (int j = 0; j < outConnections2; j++) { this.ProcessChildNode(bestNode, bestNode.node.EdgeOut(j), bestNode.StartNodeOutConnectionIndex); } // giro: this.MaxOpenNodes = Mathf.Max(this.Open.CountOpen(), this.MaxOpenNodes); } }
private void ApplayDijkstraAll() { if (navMesh != null) { nodes = GetNodesHack(navMesh); if (useNodeRecordArray) { Debug.Log("UsingNodeRecordArray"); recordArray = new NodeRecordArray<NavigationGraphNode, GoalBoundingRecord>(nodes); Open = recordArray; Closed = recordArray; } else { Debug.Log("NotUsingNodeRecordArray"); Open = new LeftPriorityList<GoalBoundingRecord>(); Closed = new ClosedDictionary<NavigationGraphNode, GoalBoundingRecord>(); } DummyRecord = new GoalBoundingRecord(); float runningTime = Time.realtimeSinceStartup; boundingBoxes = new List<List<BoundingBox>>(new List<BoundingBox>[nodes.Count]); for (int i = 0; i < nodes.Count; i++) { nodes[i].NodeIndex = i; } for (int k = 0; k < nodes.Count; k++) { if (useNodeRecordArray) { ApplyDijkstraNodeArray(nodes[k]); } else { ApplyDijkstra(nodes[k]); } ICollection<GoalBoundingRecord> closed = Closed.All(); foreach (GoalBoundingRecord record in closed) { if (record.OriginBoundingBox != null) { record.OriginBoundingBox.Update(record.Location.Position); } } if (boundingBoxes[k] != null) { foreach (BoundingBox boundingBox in boundingBoxes[k]) { boundingBox.Update(nodes[k].Position); } } PrintTimeFunc(k, Time.realtimeSinceStartup - runningTime); } //last print Debug.Log("Nodes: " + nodes.Count + " Processing time: " + (Time.realtimeSinceStartup - runningTime) + " s"); } }
//protected override void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge, int edgeIndex) protected override void ProcessChildNode(NodeRecord parentNode, NavigationGraphEdge connectionEdge) { //TODO: Implement this method for the GoalBoundingPathfinding to Work. If you implemented the NodeArrayAStar properly, you wont need to change the search method. 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 = parentNode, status = NodeStatus.Unvisited }; this.NodeRecordArray.AddSpecialCaseNode(childNodeRecord); } //TODO: implement the rest of your code here //custo da sol ate agora (valor do no anterior mais a aresta do bestNode ate ao childnode) g = parentNode.gValue + connectionEdge.Cost; //funcao heuristica: melhor custo estimado de n ate a solucao (como AStarPathFinding) h = this.Heuristic.H(childNode, this.GoalNode); f = F(g, h); //indice da cor do rectangulo var color = childNodeRecord.StartNodeOutConnectionIndex; //indice startNode var startNode = childNodeRecord.node.NodeIndex; //entrada da tabela dos rectangulos //var bbox = this.goalBoundingTable.table[color].connectionBounds[startNode]; bool inBounds; if (this.goalBoundingTable.table[startNode] != null) { var bbox = this.goalBoundingTable.table[startNode].connectionBounds[color]; inBounds = bbox.PositionInsideBounds(childNodeRecord.node.Position); } else { inBounds = true; } if (childNodeRecord.status == NodeStatus.Unvisited && inBounds) { childNodeRecord.fValue = f; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.parent = parentNode; NodeRecordArray.AddToOpen(childNodeRecord); } else if (childNodeRecord.status == NodeStatus.Open && (childNodeRecord.fValue > f || (f == childNodeRecord.fValue && childNodeRecord.hValue > h))) { childNodeRecord.fValue = f; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.parent = parentNode; NodeRecordArray.Replace(childNodeRecord, childNodeRecord); } else if (childNodeRecord.status == NodeStatus.Closed && f < childNodeRecord.fValue) { childNodeRecord.fValue = f; childNodeRecord.gValue = g; childNodeRecord.hValue = h; childNodeRecord.parent = parentNode; NodeRecordArray.RemoveFromClosed(childNodeRecord); NodeRecordArray.AddToOpen(childNodeRecord); } }