public void Render(Graphics objGraphics) { //render all the cells for (int nd = 0; nd < m_Graph.NumNodes(); ++nd) { int left = (int)(m_Graph.GetNode(nd).Pos.X - m_dCellWidth / 2.0); int top = (int)(m_Graph.GetNode(nd).Pos.Y - m_dCellHeight / 2.0); int right = (int)(1 + m_Graph.GetNode(nd).Pos.X + m_dCellWidth / 2.0); int bottom = (int)(1 + m_Graph.GetNode(nd).Pos.Y + m_dCellHeight / 2.0); Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom); SolidBrush fillBrush = new SolidBrush(Color.Gray); switch (m_TerrainType[nd]) { case (int)brush_type.normal: fillBrush.Color = Color.White; break; case (int)brush_type.obstacle: fillBrush.Color = Color.Black; break; case (int)brush_type.water: fillBrush.Color = Color.DodgerBlue; break; case (int)brush_type.mud: fillBrush.Color = Color.Brown; break; default: fillBrush.Color = Color.White; break; }//end switch objGraphics.FillRectangle(fillBrush, rect); if (m_bShowTiles) { objGraphics.DrawLine(Pens.Gray, rect.Location, new Point(rect.Right, rect.Top)); objGraphics.DrawLine(Pens.Gray, rect.Location, new Point(rect.Left, rect.Bottom)); } if (nd == m_iTargetCell) { rect.Inflate(-4, -4); objGraphics.FillRectangle(Brushes.Red, rect); objGraphics.DrawString("T", m_font, Brushes.Black, rect.Right - (int)(rect.Width * 0.75), rect.Y); } else if (nd == m_iSourceCell) { rect.Inflate(-4, -4); objGraphics.FillRectangle(Brushes.LightGreen, rect); objGraphics.DrawString("S", m_font, Brushes.Black, rect.Right - (int)(rect.Width * 0.75), rect.Y); } //render dots at the corners of the cells objGraphics.DrawLine(m_ThickBlack, left, top, left + 1, top + 1); } //draw the graph nodes and edges if rqd if (m_bShowGraph) { if (m_Graph.NumNodes() > 0) { SparseGraph.NodeIterator NodeItr = new SparseGraph.NodeIterator(m_Graph); while (NodeItr.MoveNext()) { objGraphics.DrawEllipse(Pens.LightGray, (int)(NodeItr.Current.Pos.X - 2), (int)(NodeItr.Current.Pos.Y - 2), (int)2 * 2, (int)2 * 2); SparseGraph.EdgeIterator EdgeItr = new SparseGraph.EdgeIterator(m_Graph, NodeItr.Current.Index); while (EdgeItr.MoveNext()) { objGraphics.DrawLine(Pens.LightGray, (int)NodeItr.Current.Pos.X, (int)NodeItr.Current.Pos.Y, (int)m_Graph.GetNode(EdgeItr.Current.To).Pos.X, (int)m_Graph.GetNode(EdgeItr.Current.To).Pos.Y); } } } } //draw any tree retrieved from the algorithms for (int e = 0; e < m_SubTree.Count; ++e) { if (!NavGraphEdge.IsNull(m_SubTree[e])) { Vector2D from = m_Graph.GetNode(m_SubTree[e].From).Pos; Vector2D to = m_Graph.GetNode(m_SubTree[e].To).Pos; objGraphics.DrawLine(Pens.Red, (int)from.X, (int)from.Y, (int)to.X, (int)to.Y); } } //draw the path (if any) if (m_Path.Count > 0) { for (int i = 0; i < m_Path.Count; ++i) { if (i > 0) { Point start = new Point((int)m_Graph.GetNode(m_Path[i - 1]).Pos.X, (int)m_Graph.GetNode(m_Path[i - 1]).Pos.Y); Point end = new Point((int)m_Graph.GetNode(m_Path[i]).Pos.X, (int)m_Graph.GetNode(m_Path[i]).Pos.Y); objGraphics.DrawLine(m_ThickBlue, start, end); } } } }
public override bool Search() { //create an indexed priority queue that sorts smallest to largest //(front to back).Note that the maximum number of elements the iPQ //may contain is N. This is because no node can be represented on the //queue more than once. IndexedPriorityQLow pq = new IndexedPriorityQLow(m_FCosts, m_Graph.NumNodes()); //put the source node on the queue pq.insert(m_iSource); //while the queue is not empty while (!pq.empty()) { //get lowest cost node from the queue. int NextClosestNode = pq.Pop(); //move this node from the frontier to the spanning tree m_ShortestPathTree[NextClosestNode] = m_SearchFrontier[NextClosestNode]; //if the target has been found exit if (NextClosestNode == m_iTarget) return true; //now to relax the edges. SparseGraph.EdgeIterator EdgeItr = new SparseGraph.EdgeIterator(m_Graph, NextClosestNode); while (EdgeItr.MoveNext()) { //calculate the heuristic cost from this node to the target (H) double HCost = funcPointer(m_Graph, m_iTarget, EdgeItr.Current.To); //calculate the 'real' cost to this node from the source (G) double GCost = m_GCosts[NextClosestNode] + EdgeItr.Current.Cost; //if the node has not been added to the frontier, add it and update //the G and F costs if (NavGraphEdge.IsNull(m_SearchFrontier[EdgeItr.Current.To])) { m_FCosts[EdgeItr.Current.To] = GCost + HCost; m_GCosts[EdgeItr.Current.To] = GCost; pq.insert(EdgeItr.Current.To); m_SearchFrontier[EdgeItr.Current.To] = EdgeItr.Current; } //if this node is already on the frontier but the cost to get here //is cheaper than has been found previously, update the node //costs and frontier accordingly. else if ((GCost < m_GCosts[EdgeItr.Current.To]) && NavGraphEdge.IsNull(m_ShortestPathTree[EdgeItr.Current.To])) { m_FCosts[EdgeItr.Current.To] = GCost + HCost; m_GCosts[EdgeItr.Current.To] = GCost; pq.ChangePriority(EdgeItr.Current.To); m_SearchFrontier[EdgeItr.Current.To] = EdgeItr.Current; } } } return false; }
public override bool Search() { //create a std stack of edges Stack<NavGraphEdge> stack = new Stack<NavGraphEdge>(); //create a dummy edge and put on the stack NavGraphEdge Dummy = new NavGraphEdge(m_iSource, m_iSource, 0); stack.Push(Dummy); //while there are edges in the stack keep searching while (stack.Count > 0) { //grab and remove the next edge NavGraphEdge NextEdge = stack.Pop(); //make a note of the parent of the node this edge points to m_Route[NextEdge.To] = NextEdge.From; //put it on the tree. (making sure the dummy edge is not placed on the tree) if (NextEdge != Dummy) { m_SpanningTree.Add(NextEdge); } //and mark it visited m_Visited[NextEdge.To] = (int)NodeState.visited; //if the target has been found the method can return success if (NextEdge.To == m_iTarget) { return true; } //push the edges leading from the node this edge points to onto //the stack (provided the edge does not point to a previously //visited node) SparseGraph.EdgeIterator EdgeItr = new SparseGraph.EdgeIterator(m_Graph, NextEdge.To); while (EdgeItr.MoveNext()) { if (m_Visited[EdgeItr.Current.To] == (int)NodeState.unvisited) { stack.Push(EdgeItr.Current); } } } //no path to target return false; }
public override bool Search() { //create an indexed priority queue that sorts smallest to largest //(front to back).Note that the maximum number of elements the iPQ //may contain is N. This is because no node can be represented on the //queue more than once. IndexedPriorityQLow pq = new IndexedPriorityQLow(m_CostToThisNode, m_Graph.NumNodes()); //put the source node on the queue pq.insert(m_iSource); //while the queue is not empty while (!pq.empty()) { //get lowest cost node from the queue. Don't forget, the return value //is a *node index*, not the node itself. This node is the node not already //on the SPT that is the closest to the source node int NextClosestNode = pq.Pop(); //move this edge from the frontier to the shortest path tree m_ShortestPathTree[NextClosestNode] = m_SearchFrontier[NextClosestNode]; //if the target has been found exit if (NextClosestNode == m_iTarget) return true; //now to relax the edges. SparseGraph.EdgeIterator EdgeItr = new SparseGraph.EdgeIterator(m_Graph, NextClosestNode); while (EdgeItr.MoveNext()) { //the total cost to the node this edge points to is the cost to the //current node plus the cost of the edge connecting them. double NewCost = m_CostToThisNode[NextClosestNode] + EdgeItr.Current.Cost; //if this edge has never been on the frontier make a note of the cost //to get to the node it points to, then add the edge to the frontier //and the destination node to the PQ. if (NavGraphEdge.IsNull(m_SearchFrontier[EdgeItr.Current.To])) { m_CostToThisNode[EdgeItr.Current.To] = NewCost; pq.insert(EdgeItr.Current.To); m_SearchFrontier[EdgeItr.Current.To] = EdgeItr.Current; } //else test to see if the cost to reach the destination node via the //current node is cheaper than the cheapest cost found so far. If //this path is cheaper, we assign the new cost to the destination //node, update its entry in the PQ to reflect the change and add the //edge to the frontier else if ((NewCost < m_CostToThisNode[EdgeItr.Current.To]) && NavGraphEdge.IsNull(m_ShortestPathTree[EdgeItr.Current.To])) { m_CostToThisNode[EdgeItr.Current.To] = NewCost; //because the cost is less than it was previously, the PQ must be //re-sorted to account for this. pq.ChangePriority(EdgeItr.Current.To); m_SearchFrontier[EdgeItr.Current.To] = EdgeItr.Current; } } } return false; }