///<summary> ///calculate the straight line distance from node nd1 to node nd2 ///</summary> ///<param name="graph"></param> ///<param name="nd1"></param> ///<param name="nd2"></param> ///<returns></returns> public static float Calculate(SparseGraph graph, int nd1, int nd2) { float result = TorqueUtil.GetFastRandomFloat(0.9f, 1.1f)* (graph.GetNode(nd1).Position - graph.GetNode(nd2).Position).Length(); return result; }
///<summary> ///use to add the eight neighboring edges of a graph node that ///is positioned in a grid layout ///</summary> ///<param name="graph"></param> ///<param name="row"></param> ///<param name="col"></param> ///<param name="numCellsX"></param> ///<param name="numCellsY"></param> public static void AddAllNeighborsToGridNode( SparseGraph graph, int row, int col, int numCellsX, int numCellsY) { for (int i = -1; i < 2; ++i) { for (int j = -1; j < 2; ++j) { int nodeX = col + j; int nodeY = row + i; //skip if equal to this node if ((i == 0) && (j == 0)) continue; //check to see if this is a valid neighbor if (!ValidNeighbor(nodeX, nodeY, numCellsX, numCellsY)) continue; //calculate the distance to this node Vector2 posNode = graph.GetNode(row*numCellsX + col).Position; Vector2 posNeighbour = graph.GetNode(nodeY*numCellsX + nodeX).Position; float dist = (posNode - posNeighbour).Length(); //this neighbor is okay so it can be added NavGraphEdge newEdge = new NavGraphEdge( row*numCellsX + col, nodeY*numCellsX + nodeX, dist); graph.AddEdge(newEdge); //if graph is not a digraph, an edge needs to be added going //in the other direction if (graph.IsDigraph) continue; NavGraphEdge newReverseEdge = new NavGraphEdge( nodeY*numCellsX + nodeX, row*numCellsX + col, dist); graph.AddEdge(newReverseEdge); } } }
///<summary> ///Tests if the current node is linked to an active trigger of the ///desired type. Used for search termination. ///</summary> ///<param name="graph"></param> ///<param name="target"></param> ///<param name="currentNodeIdx"></param> ///<param name="bot">bot to verify against</param> ///<returns></returns> public static bool IsSatisfied( SparseGraph graph, //TODO: should not use target as node index and entity type int target, int currentNodeIdx, BotEntity bot) { bool bSatisfied = false; EntityTypes targetEntityType = Entity.Entity.ItemTypeToEntityType((ItemTypes) target); //get a reference to the node at the given node index NavGraphNode node = graph.GetNode(currentNodeIdx); //if the extrainfo field is pointing to a giver-trigger, test to //make sure it is active and that it is of the correct type. Trigger.Trigger t = node.ExtraInfo as Trigger.Trigger; if (t != null && t.IsActive && t.EntityType == targetEntityType && bot.FoundTriggers.List.Contains(t)) { bSatisfied = true; } return bSatisfied; }
///<summary> ///Given a cost value and an index to a valid node this function ///examines all a node's edges, calculates their length, and ///multiplies the value with the weight. Useful for setting terrain ///costs. ///</summary> ///<param name="graph"></param> ///<param name="node"></param> ///<param name="weight"></param> public static void WeightNavGraphNodeEdges( SparseGraph graph, int node, float weight) { //make sure the node is present Assert.Fatal(node < graph.NumNodes, "GraphUtil.WeightNavGraphNodeEdges: node index out of range"); //set the cost for each edge foreach (NavGraphEdge curEdge in graph.Edges[node]) { //calculate the distance between nodes float dist = (graph.GetNode(curEdge.From).Position - graph.GetNode(curEdge.To).Position).Length(); //set the cost of this edge graph.SetEdgeCost(curEdge.From, curEdge.To, dist*weight); //if not a digraph, set the cost of the parallel edge to be //the same if (!graph.IsDigraph) { graph.SetEdgeCost(curEdge.To, curEdge.From, dist*weight); } } }
///<summary> ///draws the given graph ///</summary> ///<param name="graph"></param> ///<param name="color"></param> ///<param name="drawNodeIds"></param> public static void Draw( SparseGraph graph, Color color, bool drawNodeIds) { //just return if the graph has no nodes if (graph.NumNodes == 0) return; //draw the nodes foreach (NavGraphNode curNode in graph.Nodes) { if (GraphNode.IsInvalidIndex(curNode.Index)) continue; DrawUtil.Circle(curNode.Position, 2, color, 20); if (drawNodeIds) { TextUtil.DrawText( @"data\fonts\Arial6", //TODO: should be a parameter new Vector2( curNode.Position.X + 5, curNode.Position.Y - 5), new Color(200, 200, 200), curNode.Index.ToString()); } foreach (NavGraphEdge curEdge in graph.Edges[curNode.Index]) { DrawUtil.Line( curNode.Position, graph.GetNode(curEdge.To).Position, color); } } }
//---------------------- CalculateAverageGraphEdgeLength ---------------------- // // //------------------------------------------------------------------------------ ///<summary> ///determines the average length of the edges in a navgraph (using the ///distance between the source and target node positions (not the cost ///of the edge as represented in the graph, which may account for all ///sorts of other factors such as terrain type, gradients etc) ///</summary> ///<param name="graph"></param> ///<returns></returns> public static float CalculateAverageGraphEdgeLength(SparseGraph graph) { float totalLength = 0; int numEdgesCounted = 0; foreach (NavGraphNode curNode in graph.Nodes) { if (GraphNode.IsInvalidIndex(curNode.Index)) continue; foreach (NavGraphEdge curEdge in graph.Edges[curNode.Index]) { //increment edge counter ++numEdgesCounted; //add length of edge to total length totalLength += (graph.GetNode(curEdge.From).Position - graph.GetNode(curEdge.To).Position).Length(); } } return totalLength/numEdgesCounted; }