コード例 #1
0
        private static Node<string> BFSGetGoalParent(MyGraph<string> graph, Node<string> rootNode, Node<string> goalNode)
        {
            // Create a queue to keep track of search
            Queue<Node<String>> q = new Queue<Node<string>>();
            q.Enqueue(rootNode);
            rootNode.Visited = true;

            //Visiting children each level at a time
            while (!(q.Count == 0))
            {
                Node<string> n = q.Dequeue();
                Node<string> child = null;

                //Check each child before moving on to the next level
                while ((child = getUnvisitedChildNode(n)) != null)
                {
                    q.Enqueue(child);
                    child.Visited = true;
                    if (child == goalNode)
                    {
                        clearNodes(graph);
                        return n;
                    }
                }
            }
            return null;
        }
コード例 #2
0
            private void rangeFunction(Node lookAt)
            {
                if (lookAt.isWalkable())
                {
                    // adds node to range pairs if not present already.
                    if (!nodesInRangeSet.Contains(lookAt))
                    {
                        nodesInRangeSet.Add(lookAt);
                        nodesInRange.Add(lookAt);
                    }

                    bool frendType = uRef.isEnemy();

                    // targets!
                    if (lookAt.Occupied && lookAt.Occupier.isEnemy() != frendType)
                    {
                        currentTargets.Add(new Node.NodePointer(shootingFrom, lookAt, Node.range(shootingFrom, lookAt)));
                    }

                    if (reverseNodesInRangeSetCost.ContainsKey(lookAt))
                    {
                        if (reverseNodesInRangeSetCost[lookAt] > shootingFrom.realCost)
                            reverseNodesInRangeSetCost[lookAt] = (int) shootingFrom.realCost;
                    }
                    else
                        reverseNodesInRangeSetCost.Add(lookAt, (int) (shootingFrom.realCost));
                }
            }
コード例 #3
0
 private void initialize(Node start, float endurance)
 {
     pathFinderRef.nodesThatSatisfyPred(start, pathfindPredicate, endurance);
     foreach (Node n in nodesCanWalkTo)
     {
         shootingFrom = n;
         pathFinderRef.runFuncOnAllNodesInRangeOfNode(shootingFrom, uRef.getMinAttackRange(), uRef.getMaxAttackRange(), rangeFunction);
     }
 }
コード例 #4
0
        public void CreateEdges(int num_edges)
        {
            Console.WriteLine("================================================================");

            Console.WriteLine("Creating " + num_edges + " edges");
            const int RANDOM_SEED = 55555;

            DateTime dt = DateTime.Now;
            Node from = new Node();
            Node to = new Node();
             for (int z = 0; z < (5 * num_edges); z++)
            {
                // Get two random nodes from node_list
                Random rand = new Random(RANDOM_SEED + z);
                int r = rand.Next(node_list.Count);
                //Console.WriteLine("First r = " + r);
                from = searchNode(r);
                // get one more random number
                r = rand.Next(node_list.Count);
                //Console.WriteLine("second r = " + r);
                to = searchNode(r);

                // dont allow self loops as of now
                if (from.node_id == to.node_id)
                {
                    r = rand.Next(node_list.Count);
                    to = searchNode(r);
                }
                // avoid creating duplpicate edges between nodes
                if(isEdge(from.node_id, to.node_id))
                {
                    Console.WriteLine("Avoiding duplicate edges");
                    r = rand.Next(node_list.Count);
                    to = searchNode(r);
                }

                //now we have 2 random nodes. see if we can hook up these two
                Waxman w = new Waxman();
                double value = 0.0;
                double compare = 0.0;
                compare = rand.NextDouble();
                value = w.ProbFunc(from, to);
                //Console.WriteLine("Compare = " + compare + " value = " + value);

                Random rndm = new Random();
                if (value < compare)
                {

                    int rndm_num = rand.Next(1, 100);

                    Console.WriteLine("Connecting edge from " + to.node_id + " to " + from.node_id + " with cost = " + rndm_num);
                    from.addAdjNode(to, rndm_num);
                    to.addAdjNode(from, rndm_num);
                }

            }
        }
コード例 #5
0
ファイル: Waxman.cs プロジェクト: BGCX261/zhimera-svn-to-git
        public double ProbFunc(Node src, Node dest)
        {
            double distance, L, alpha, beta;
            alpha = 0.15;
            beta = 0.2;
            int x1, x2, y1, y2, dx, dy;
            x1 = src.Xpos; x2 = dest.Xpos;
            y1 = src.Ypos; y2 = dest.Ypos;

            dx = x2 - x1;
            dy = y2 - y1;

            distance = Math.Sqrt(dx * dx + dy * dy);
            //Console.WriteLine("Distance between " + src.node_id + " and " + dest.node_id + " = " + distance);
            L = Math.Sqrt(2) * MAX_X;

            /*Console.WriteLine("distance = " + distance);
            Console.WriteLine("L = " + L);*/
            //Console.WriteLine("final value = " + (alpha * Math.Exp(-1.0 * (distance / (beta * L)))));

            return 10 * alpha * Math.Exp(-1.0 * (distance / (beta * L)));
        }
コード例 #6
0
        /// <summary>
        /// Initializes the graph.
        /// Important: Since this uses physics, we cannot use a constructor.
        /// Instead, we have to call this on the already constructed object.
        /// </summary>
        /// <param name="lowLeftBound">The lower left bound of the map in world space.</param>
        /// <param name="upRightBound">The upper right bound of the map in world space.</param>
        /// <param name="pathWidth">How wide to make the path. Smaller values mean we can place nodes in tighter spaces.</param>
        /// <param name="nodeDensity">How dense the nodes should be. Smaller values mean less nodes are placed.</param>
        /// <param name="startPos">The starting seed position of the graph.</param>
        public void initializeGraph(Vector2 lowLeftBound, Vector2 upRightBound, float pathWidth, float nodeDensity = 1.0f, Vector2 startPos = new Vector2())
        {
            lowerLeftBound = lowLeftBound;
            upperRightBound = upRightBound;

            this.nodeDensity = nodeDensity;

            // Determine proper numbers of nodes in the x direction.
            float xDist = lowerLeftBound.x - upperRightBound.x;
            int xDensity = Mathf.CeilToInt(Mathf.Abs(xDist * nodeDensity));

            // Same, but for y direction.
            float yDist = upperRightBound.y - lowerLeftBound.y;
            int yDensity = Mathf.CeilToInt(Mathf.Abs(yDist * nodeDensity));

            numXNodes = xDensity;
            numYNodes = yDensity;

            // Initialize the node array. Note the inverted y, normal x setup.
            nodeArr = new Node[yDensity][];
            for (int i = 0; i < yDensity; i++)
                nodeArr[i] = new Node[xDensity];

            radii = pathWidth / 2.0f;

            numValidNodes = 0;

            //floodFill(startPos);
            fillAll();

            isInitialized = true;
        }
コード例 #7
0
        /// <summary>
        /// Returns a sorted list of nodes within a given endurance value.
        /// Performs a Dijkstra-like algorithm.
        /// </summary>
        /// <param name="satifies">The predicate each node must follow.</param>
        /// <param name="endurance">The maximum endurance to follow out.</param>
        /// <returns>A sorted list of nodes within a given endurance value.</returns>
        public List<Node> nodesThatSatisfyPred(Node startNode, System.Predicate<Node> satifies, float endurance = 16.0f, bool stopOnFirst = false, bool isPathfinding = true)
        {
            List<Node> foundNodes = new List<Node>();
            MinPriorityQueue<Node> nodeList = new MinPriorityQueue<Node>();

            initializePathfinding(isPathfinding);

            startNode.realCost = 0;
            nodeList.Enqueue(startNode, startNode.realCost);

#if DEBUG_PATHFINDER_LOGDEBUG
            StringBuilder encountered = new StringBuilder();
            StringBuilder nodes = new StringBuilder();
            nodes.Append("Start node ").Append(startNode.Number).AppendLine();
            encountered.Append("Start node ").Append(startNode.Number).AppendLine();
            encountered.Append("endurance = ").Append(endurance).AppendLine();
#endif

            while (nodeList.Count > 0)
            {
                //Pick the best looking node, by f-value.
                Node best = nodeList.Dequeue();
                double bestDist = best.realCost;
                
#if DEBUG_PATHFINDER_LOGDEBUG
                encountered.Append("Node ").Append(best.Number).Append(" ").Append(best).AppendLine();
                nodes.Append("Node ").Append(best.Number).AppendLine();
#endif

                best.Visited = true;

                if (satifies(best))
                {
                    foundNodes.Add(best);
                    if (stopOnFirst)
                        return foundNodes;
                }

                //string updateString = "updating: ";
                foreach (Edge e in best.getEdges())
                {
                    Node other = e.getNode();

                    //We already visited this node, move along,
                    if (other.Visited)
                        continue;

                    //Tentative distance.
                    double testDist = e.getWeight() + bestDist;

                    if (testDist > endurance)
                        continue;

                    //If the other node isn't in the priority queue, add it.
                    if (!nodeList.Contains(other))
                    {
                        other.CameFrom = best;
                        other.realCost = testDist;
                        nodeList.Enqueue(other, other.realCost);

#if DEBUG_PATHFINDER_LOGDEBUG
                        encountered.Append("   added ").Append(other.Number)
                                   .Append(", total estimated cost ")
                                   .Append(other.realCost).AppendLine();
#endif
                        continue;
                    }
                    //If the other node was a bad path, and this one's better, replace it.
                    else if (other.realCost > testDist)
                    {
                        other.CameFrom = best;
                        other.realCost = testDist;
                        nodeList.Update(other, other.realCost);

#if DEBUG_PATHFINDER_LOGDEBUG
                        encountered.Append("   updated ").Append(other.Number)
                                   .Append(", total new estimated cost ")
                                   .Append(other.realCost).AppendLine();
#endif
                    }
                }
            }
#if DEBUG_PATHFINDER_LOGDEBUG
            Debug.Log(encountered);
            Debug.Log(nodes);
#endif

            return foundNodes;
        }
コード例 #8
0
ファイル: GraphRenderer.cs プロジェクト: fluffyfreak/Graph
        static void Render(Graphics graphics, Node node)
        {
            var size		= node.bounds.Size;
            var position	= node.bounds.Location;

            int cornerSize			= (int)GraphConstants.CornerSize * 2;
            int connectorSize		= (int)GraphConstants.ConnectorSize;
            int halfConnectorSize	= (int)Math.Ceiling(connectorSize / 2.0f);
            var connectorOffset		= (int)Math.Floor((GraphConstants.MinimumItemHeight - GraphConstants.ConnectorSize) / 2.0f);
            var left				= position.X + halfConnectorSize;
            var top					= position.Y;
            var right				= position.X + size.Width - halfConnectorSize;
            var bottom				= position.Y + size.Height;
            using (var path = new GraphicsPath(FillMode.Winding))
            {
                path.AddArc(left, top, cornerSize, cornerSize, 180, 90);
                path.AddArc(right - cornerSize, top, cornerSize, cornerSize, 270, 90);

                path.AddArc(right - cornerSize, bottom - cornerSize, cornerSize, cornerSize, 0, 90);
                path.AddArc(left, bottom - cornerSize, cornerSize, cornerSize, 90, 90);
                path.CloseFigure();

                if ((node.state & (RenderState.Dragging | RenderState.Focus)) != 0)
                {
                    graphics.FillPath(Brushes.DarkOrange, path);
                } else
                if ((node.state & RenderState.Hover) != 0)
                {
                    graphics.FillPath(Brushes.LightSteelBlue, path);
                } else
                {
                    graphics.FillPath(Brushes.LightGray, path);
                }
                graphics.DrawPath(Pens.DarkGray, path);
            }
            /*
            if (!node.Collapsed)
                graphics.DrawLine(Pens.Black,
                    left  + GraphConstants.ConnectorSize, node.titleItem.bounds.Bottom - GraphConstants.ItemSpacing,
                    right - GraphConstants.ConnectorSize, node.titleItem.bounds.Bottom - GraphConstants.ItemSpacing);
            */
            var itemPosition = position;
            itemPosition.X += connectorSize + (int)GraphConstants.HorizontalSpacing;
            if (node.Collapsed)
            {
                bool inputConnected = false;
                var inputState	= RenderState.None;
                var outputState = node.outputState;
                foreach (var connection in node.connections)
                {
                    if (connection.To.Node == node)
                    {
                        inputState |= connection.state;
                        inputConnected = true;
                    }
                    if (connection.From.Node == node)
                        outputState |= connection.state | RenderState.Connected;
                }

                RenderItem(graphics, new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0), node.titleItem, itemPosition);
                if (node.inputConnectors.Count > 0)
                    RenderConnector(graphics, node.inputBounds, node.inputState);
                if (node.outputConnectors.Count > 0)
                    RenderConnector(graphics, node.outputBounds, outputState);
                if (inputConnected)
                    RenderArrow(graphics, node.inputBounds, inputState);
            } else
            {
                node.inputBounds	= Rectangle.Empty;
                node.outputBounds	= Rectangle.Empty;

                var minimumItemSize = new SizeF(node.bounds.Width - GraphConstants.NodeExtraWidth, 0);
                foreach (var item in EnumerateNodeItems(node))
                {
                    RenderItem(graphics, minimumItemSize, item, itemPosition);
                    var inputConnector	= item.Input;
                    if (inputConnector != null && inputConnector.Enabled)
                    {
                        if (!inputConnector.bounds.IsEmpty)
                        {
                            var state		= RenderState.None;
                            var connected	= false;
                            foreach (var connection in node.connections)
                            {
                                if (connection.To == inputConnector)
                                {
                                    state |= connection.state;
                                    connected = true;
                                }
                            }

                            RenderConnector(graphics,
                                            inputConnector.bounds,
                                            inputConnector.state);

                            if (connected)
                                RenderArrow(graphics, inputConnector.bounds, state);
                        }
                    }
                    var outputConnector = item.Output;
                    if (outputConnector != null && outputConnector.Enabled)
                    {
                        if (!outputConnector.bounds.IsEmpty)
                        {
                            var state = outputConnector.state;
                            foreach (var connection in node.connections)
                            {
                                if (connection.From == outputConnector)
                                    state |= connection.state | RenderState.Connected;
                            }
                            RenderConnector(graphics, outputConnector.bounds, state);
                        }
                    }
                    itemPosition.Y += item.bounds.Height + GraphConstants.ItemSpacing;
                }
            }
        }
コード例 #9
0
 public NodeEventArgs(Node node)
 {
     Node = node;
 }
コード例 #10
0
		public void displayRangeOfUnit(Unit u, Vector2 mousePosition)
        {
            clearRangeDisplay();

            if (overlayNodes == null)
				overlayNodes = new List<Node>();
            
			List<Node> reach = nodesWithinEnduranceValue(closestMostValidNode(mousePosition), u.getCurrentWater());
            List<Node> range = NodesInRangeOfNodes(reach, u.getMinAttackRange(), u.getMaxAttackRange());
            
            HashSet<Node> inReach = new HashSet<Node>();
			inReach.UnionWith(reach);
			HashSet<Node> inRange = new HashSet<Node>();
			inRange.UnionWith(range);
			inRange.RemoveWhere(inReach.Contains);

			foreach (Node n in inReach)
			{
				//make slightly smaller to show square off
				Node q = new Node(transform.gameObject, nodeImg, n.getPos(), n.getGridPos(), Node.randWalkState(), radii * 1.75f);
				q.setColor(new Color(0, 0.5f, 0, 0.75f));

				overlayNodes.Add(q);
			}
            
			foreach (Node n in inRange)
			{
				//make slightly smaller to show square off
				Node q = new Node(transform.gameObject, nodeImg, n.getPos(), n.getGridPos(), Node.randWalkState(), radii * 1.75f);
				q.setColor(new Color(0, 0, 0.5f, 0.75f));

				overlayNodes.Add(q);
			}
		}
コード例 #11
0
ファイル: GraphRenderer.cs プロジェクト: fluffyfreak/Graph
        public static void RenderConnections(Graphics graphics, Node node, HashSet<NodeConnection> skipConnections, bool showLabels)
        {
            foreach (var connection in node.connections.Reverse<NodeConnection>())
            {
                if (connection == null ||
                    connection.From == null ||
                    connection.To == null)
                    continue;

                if (skipConnections.Add(connection))
                {
                    var to		= connection.To;
                    var from	= connection.From;
                    RectangleF toBounds;
                    RectangleF fromBounds;
                    if (to.Node.Collapsed)		toBounds = to.Node.inputBounds;
                    else						toBounds = to.bounds;
                    if (from.Node.Collapsed)	fromBounds = from.Node.outputBounds;
                    else						fromBounds = from.bounds;

                    var x1 = (fromBounds.Left + fromBounds.Right) / 2.0f;
                    var y1 = (fromBounds.Top + fromBounds.Bottom) / 2.0f;
                    var x2 = (toBounds.Left + toBounds.Right) / 2.0f;
                    var y2 = (toBounds.Top + toBounds.Bottom) / 2.0f;

                    float centerX;
                    float centerY;
                    using (var path = GetArrowLinePath(x1, y1, x2, y2, out centerX, out centerY, false))
                    {
                        using (var brush = new SolidBrush(GetArrowLineColor(connection.state | RenderState.Connected)))
                        {
                            graphics.FillPath(brush, path);
                        }
                        connection.bounds = path.GetBounds();
                    }

                    if (showLabels &&
                        !string.IsNullOrWhiteSpace(connection.Name))
                    {
                        var center = new PointF(centerX, centerY);
                        RenderLabel(graphics, connection, center, connection.state);
                    }
                }
            }
        }
コード例 #12
0
        /// <summary>
        /// Note: This calculates the manhatten distance heuristic.
        /// </summary>
        /// <param name="startNode">Start node</param>
        /// <param name="endNode">End node</param>
        /// <returns></returns>
        public float ManhattenHeuristic(Node startNode, Node endNode)
        {
            int distX = Mathf.Abs(startNode.getGridPos().x - endNode.getGridPos().x);
            int distY = Mathf.Abs(startNode.getGridPos().y - endNode.getGridPos().y);

            return distX + distY;
        }
コード例 #13
0
        /// <summary>
        /// Reconstructs a path from the end to the start.
        /// </summary>
        /// <param name="path">Queue to store path in.</param>
        /// <param name="end">Ending node in graph</param>
        private void ReconstructPath(Queue<Node> path, Node end)
        {
            path.Clear();
            if (end == null)
                return;

            Stack<Node> reversePath = new Stack<Node>();
            Node cur = end;

            while (cur != null)
            {
                reversePath.Push(cur);
                cur = cur.CameFrom;
            }

            while (reversePath.Count > 0)
                path.Enqueue(reversePath.Pop());
        }
コード例 #14
0
 /// <summary>
 /// Returns a sorted list of nodes within a given endurance value.
 /// Performs a Dijkstra-like algorithm.
 /// </summary>
 /// <param name="endurance">The maximum endurance to follow out.</param>
 /// <returns>A sorted list of nodes within a given endurance value.</returns>
 public List<Node> nodesWithinEnduranceValue(Node startNode, float endurance = 16.0f)
 {
     //for future reference, less code copy-paste worth negligible performance reduction.
     return nodesThatSatisfyPred(startNode, (_) => true, endurance);
 }
コード例 #15
0
        /// <summary>
        /// Performs AStar on the graph.
        /// </summary>
        /// <param name="pathStoreLoc">The path will be stored in this queue.</param>
        /// <param name="startNode">The starting node.</param>
        /// <param name="targetPos">The target position.</param>
        public double AStar(Queue<Node> pathStoreLoc, Node startNode, Vector2 targetPos)
        {
            if (!isInitialized)
                throw new UnassignedReferenceException("Pathfinder not initialized yet!");
            Node end = closestMostValidNode(targetPos);

            return AStar(pathStoreLoc, startNode, end);
        }
コード例 #16
0
        public void addNode(int id, int num_nodes)
        {
            Node n = new Node(id, num_nodes);

            node_list.Add(n);
        }
コード例 #17
0
        public void addAdjNode(Node adj, int cost)
        {
            Edge edge = new Edge(this, adj, cost);

            this.edge_list.Add(edge);
        }
コード例 #18
0
 public Edge(Node src, Node dest, int cost)
 {
     _src = src;
     _dest = dest;
     _cost = cost;
 }
コード例 #19
0
 public AcceptNodeEventArgs(Node node)
 {
     Node = node;
 }
コード例 #20
0
 public AcceptNodeEventArgs(Node node, bool cancel) : base(cancel)
 {
     Node = node;
 }
コード例 #21
0
        /// <summary>
        /// Unlike closestMostValidNode; BFS does up to a full BFS
        /// to find the closest unocupied & walkable node to a given location.
        /// Only use when not wanting to take into account edge costs.
        /// If no nodes found that are valid, returns the start node.
        /// Uses Nodes directly instead of converting from Vector2.
        /// </summary>
        /// <param name="startLoc">The location to start looking from.</param>
        /// <returns>The first unocupied/valid walkable tile found. If no nodes found that are valid, returns the start node.</returns>
        private Node BFSUnoccupiedAndValid(Node startNode)
        {
            if (!startNode.Occupied && startNode.isWalkable())
                return startNode;

            initializePathfinding(true);
            
            Queue<Node> listOfNodes = new Queue<Node>();
            listOfNodes.Enqueue(startNode);

            // Can't use visited, as we're already using that hack in initializePathfinding...
            startNode.realCost = -1;

            while (listOfNodes.Count > 0)
            {
                Node found = listOfNodes.Dequeue();
                if (!found.Occupied && found.isWalkable())
                    return found;

                foreach (Edge e in found.getEdges())
                {
                    Node candidate = e.getNode();
                    if (candidate.realCost > 0)
                        listOfNodes.Enqueue(candidate);

                    // Can't use visited, as we're already using that hack in initializePathfinding...
                    candidate.realCost = -1;
                }
            }

            return startNode;
        }
コード例 #22
0
ファイル: Edge.cs プロジェクト: punster94/AI-for-Game-Design
 /// <param name="pointTo">Edge to point to.</param>
 /// <param name="weight">Weight of edge, def = 1.</param>
 public Edge(Node pointTo, float weight = 1)
 {
     this.weight = weight;
     to = pointTo;
 }
コード例 #23
0
        /// <summary>
        /// Note: This calculates the diagonal distance heuristic.
        /// Taken from http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html.
        /// </summary>
        /// <param name="startNode">Start node</param>
        /// <param name="endNode">End node</param>
        /// <returns></returns>
        public float DiagonalHeuristic(Node startNode, Node endNode)
        {
            float distX = Mathf.Abs(startNode.getGridPos().x - endNode.getGridPos().x);
            float distY = Mathf.Abs(startNode.getGridPos().y - endNode.getGridPos().y);

            return distX + distY - (2 - sqrt2) * Mathf.Min(distX, distY);
        }
コード例 #24
0
        public static void RenderConnections(Graphics graphics, Node node, HashSet<NodeConnection> skipConnections, bool showLabels)
        {
            if (!node.shown)
                return;

            foreach (var connection in node.connections.Reverse<NodeConnection>())
            {
                if (connection == null ||
                    connection.From == null ||
                    connection.To == null ||
                    !connection.From.Node.shown ||
                    !connection.To.Node.shown)
                    continue;

                if (skipConnections.Add(connection))
                {
                    var to		= connection.To;
                    var from	= connection.From;
                    RectangleF toBounds;
                    RectangleF fromBounds;
                    if (to.Node.Collapsed)		toBounds = to.Node.inputBounds;
                    else						toBounds = to.bounds;
                    if (from.Node.Collapsed)	fromBounds = from.Node.outputBounds;
                    else						fromBounds = from.bounds;

                    var x1 = (fromBounds.Left + fromBounds.Right) / 2.0f;
                    var y1 = (fromBounds.Top + fromBounds.Bottom) / 2.0f;
                    var x2 = (toBounds.Left + toBounds.Right) / 2.0f;
                    var y2 = (toBounds.Top + toBounds.Bottom) / 2.0f;

                    float centerX;
                    float centerY;
                    int xOffset = GraphConstants.HiddenConnectionLabelOffset;

                    bool isFromNodeHover = (connection.From.Node.state & RenderState.Hover) != 0;
                    bool isConnectionHidden = (connection.state & RenderState.Hidden) != 0;
                    bool isConnectionHover = (connection.state & RenderState.Hover) != 0;

                    using (var path = GetArrowLinePath(x1, y1, x2, y2, out centerX, out centerY, false))
                    {
                        Color arrowLineColor = GetArrowLineColor(connection.state | RenderState.Connected);

                        if ((connection.state & RenderState.Marked) != 0)
                        {
                            Color glowColorBase = Color.Ivory;
                            Color glowColor = Color.FromArgb(
                                (int)(glowColorBase.A * 0.5),
                                glowColorBase.R,
                                glowColorBase.G,
                                glowColorBase.B);
                            // Draw a glow.
                            var pen = new Pen(new SolidBrush(glowColor), 4.0f);
                            graphics.DrawPath(pen, path);
                        }

                        Brush brush = new SolidBrush(arrowLineColor);

                        if (isConnectionHidden && !isConnectionHover)
                        {
                            if (isFromNodeHover)
                            {
                                graphics.FillPath(new SolidBrush(GetArrowLineColor(RenderState.Hover)), path);
                            }
                            else
                            {
                                graphics.FillRectangle(brush, x1, y1 - 0.75f, xOffset, 1.5f);
                                graphics.FillRectangle(brush, x2 - xOffset, y2 - 2, xOffset, 4);
                            }
                        }
                        else
                        {
                            graphics.FillPath(brush, path);
                        }

                        connection.bounds = RectangleF.Union(path.GetBounds(), connection.textBounds);
                    }

                    if (showLabels && !string.IsNullOrWhiteSpace(connection.Name))
                    {
                        if (isConnectionHidden)
                        {
                            RenderState rState = isFromNodeHover ? connection.state | RenderState.Hover : connection.state;

                            var center = new PointF(x1, y1);
                            RenderLabel(graphics, connection, center, rState, true);

                            center = new PointF(x2, y2);
                            RenderLabel(graphics, connection, center, rState);
                        }
                        else
                        {
                            var center = new PointF(centerX, centerY);
                            RenderLabel(graphics, connection, center, connection.state);
                        }
                    }
                }
            }
        }
コード例 #25
0
        /// <summary>
        /// A* on the graph.
        /// </summary>
        /// <param name="pathStoreLoc">The Queue to store the path in.</param>
        /// <param name="start">The starting node.</param>
        /// <param name="end">The ending node.</param>
        public double AStar(Queue<Node> pathStoreLoc, Node start, Node end, Node toIgnore = null)
        {
            MinPriorityQueue<Node> nodeList = new MinPriorityQueue<Node>();

            initializePathfinding(true);
            if (toIgnore != null)
                toIgnore.Visited = false;

            System.Func<Node, Node, float> Heuristic;
            if (allowedPaths == Paths.quadDir)
                Heuristic = ManhattenHeuristic;
            else if (allowedPaths == Paths.octDir)
                Heuristic = DiagonalHeuristic;
            else
                Heuristic = DiagonalHeuristic;

            start.CameFrom = null;
            start.heuristicCost = Heuristic(start, end);
            start.realCost = 0;
            nodeList.Enqueue(start, start.heuristicCost);

#if DEBUG_PATHFINDER_LOGDEBUG
            StringBuilder encountered = new StringBuilder();
            StringBuilder nodes = new StringBuilder();
            nodes.Append("Start node ").Append(start.Number).AppendLine();
            encountered.Append("Start node ").Append(start.Number).AppendLine();
            nodes.Append("End node ").Append(end.Number).AppendLine();
            encountered.Append("End node ").Append(end.Number).AppendLine();
#endif

            while (nodeList.Count > 0)
            {
                //Pick the best looking node, by f-value.
                Node best = nodeList.Dequeue();
                double bestDist = best.realCost;

#if DEBUG_PATHFINDER_LOGDEBUG
                encountered.Append("Node ").Append(best.Number).Append(" ").Append(best).AppendLine();
                nodes.Append("Node ").Append(best.Number).AppendLine();
#endif

                //If this is the end, stop, show the path, and return it.
                if (best.Equals(end))
                {
                    ReconstructPath(pathStoreLoc, end);
                    ShowPath(pathStoreLoc);

#if DEBUG_PATHFINDER_LOGDEBUG
                    encountered.Append("Finished!\n\nFinal dist: ")
                               .Append(best.realCost).AppendLine();
                    Debug.Log(encountered);
                    Debug.Log(nodes);
#endif
                    return best.realCost;
                }
                best.Visited = true;

                //string updateString = "updating: ";
                foreach (Edge e in best.getEdges())
                {
                    Node other = e.getNode();

                    //We already visited this node, move along,
                    if (other.Visited)
                        continue;

                    //Tentative distance.
                    double testDist = e.getWeight() + bestDist;

                    //If the other node isn't in the priority queue, add it.
                    if (!nodeList.Contains(other))
                    {
                        other.CameFrom = best;
                        other.realCost = testDist;
                        other.heuristicCost = Heuristic(other, end);
                        nodeList.Enqueue(other, other.realCost + other.heuristicCost);

#if DEBUG_PATHFINDER_LOGDEBUG
                        encountered.Append("   added ").Append(other.Number)
                                   .Append(", total estimated cost ")
                                   .Append(other.realCost + other.heuristicCost)
                                   .AppendLine();
#endif
                        continue;
                    }
                    //If the other node was a bad path, and this one's better, replace it.
                    else if (other.realCost > testDist)
                    {
                        other.CameFrom = best;
                        other.realCost = testDist;
                        nodeList.Update(other, other.realCost + other.heuristicCost);

#if DEBUG_PATHFINDER_LOGDEBUG
                        encountered.Append("   updated ").Append(other.Number)
                                   .Append(", total new estimated cost ")
                                   .Append(other.realCost + other.heuristicCost)
                                   .AppendLine();
#endif
                    }
                }
            }

#if DEBUG_PATHFINDER_LOGDEBUG
            encountered.Append("Failed!\n");
            Debug.Log(encountered);
            Debug.Log(nodes);
#endif
            return double.PositiveInfinity;
        }
コード例 #26
0
 static Brush ResolveNodeBrush(Node node, Brush baseBrush)
 {
     if ((node.state & (RenderState.Dragging | RenderState.Focus)) != 0)
     {
         return Brushes.DarkOrange;
     }
     else if ((node.state & RenderState.Hover) != 0)
     {
         return Brushes.LightSteelBlue;
     }
     else
     {
         return baseBrush;
     }
 }
コード例 #27
0
 /// <summary>
 /// Idea of this function: You give it a function that has captured local variables so you can
 /// run whatever you want on all nodes that are in range of a given node.
 /// </summary>
 /// <param name="listNodes">Look at all nodes in range of this node.</param>
 /// <param name="minDist">Minimum firing distance.</param>
 /// <param name="maxDist">Maximum firing distance.</param>
 /// <param name="funcToRun">What function we should run on the nodes in range.</param>
 public void runFuncOnAllNodesInRangeOfNode(Node n, int minDist, int maxDist, System.Action<Node> funcToRun)
 {
     runFuncOnAllNodesInRangeOfNode(funcToRun, n.getGridPos().x, n.getGridPos().y, minDist, maxDist);
 }
コード例 #28
0
        public void ShowPath(Queue<Node> Path)
        {
            Node[] PathCopy = Path.ToArray();
            if (PathCopy.Length == 0)
                return;

            //If we were displaying a path, reset the colors.
            if (manualStartNode != null)
                manualStartNode.resetColor();
            if (manualEndNode != null)
                manualEndNode.resetColor();

            //Set the colors for the start and end nodes.
            manualStartNode = PathCopy[0];
            manualEndNode = PathCopy[PathCopy.Length - 1];
            manualEndNode.setColor(Node.endColor);
            manualStartNode.setColor(Node.startColor);

            //Recycle garbage path renderers if necessary.
            if (pathDrawer != null)
            {
                UnityEngine.Object.Destroy(pathDrawer);
            }

            pathDrawer = new GameObject("Path");

            //Set up the line renderer for the path.
            // We loop back once, so have double nodes + 1.
            LineRenderer drawer = pathDrawer.AddComponent<LineRenderer>();
            drawer.SetWidth(0.3f, 0.3f);
            drawer.SetColors(Color.green, Color.green);
            drawer.SetVertexCount(PathCopy.Length * 2 + 1);
            // Need this otherwise the width is wrong on first edge.
            drawer.SetPosition(0, PathCopy[0].getPos());

            for (int i = 0; i < PathCopy.Length; i++)
                drawer.SetPosition(i + 1, PathCopy[i].getPos());
            for (int i = PathCopy.Length - 1, j = PathCopy.Length + 1; i >= 0; i--, j++)
                drawer.SetPosition(j, PathCopy[i].getPos());
        }
コード例 #29
0
ファイル: GraphRenderer.cs プロジェクト: fluffyfreak/Graph
        public static void PerformLayout(Graphics graphics, Node node)
        {
            if (node == null)
                return;
            var size		= Measure(graphics, node);
            var position	= node.Location;
            node.bounds		= new RectangleF(position, size);

            var path				= new GraphicsPath(FillMode.Winding);
            int connectorSize		= (int)GraphConstants.ConnectorSize;
            int halfConnectorSize	= (int)Math.Ceiling(connectorSize / 2.0f);
            var connectorOffset		= (int)Math.Floor((GraphConstants.MinimumItemHeight - GraphConstants.ConnectorSize) / 2.0f);
            var left				= position.X + halfConnectorSize;
            var top					= position.Y;
            var right				= position.X + size.Width - halfConnectorSize;
            var bottom				= position.Y + size.Height;

            node.inputConnectors.Clear();
            node.outputConnectors.Clear();
            //node.connections.Clear();

            var itemPosition = position;
            itemPosition.X += connectorSize + (int)GraphConstants.HorizontalSpacing;
            if (node.Collapsed)
            {
                foreach (var item in node.Items)
                {
                    var inputConnector	= item.Input;
                    if (inputConnector != null && inputConnector.Enabled)
                    {
                        inputConnector.bounds = Rectangle.Empty;
                        node.inputConnectors.Add(inputConnector);
                    }
                    var outputConnector = item.Output;
                    if (outputConnector != null && outputConnector.Enabled)
                    {
                        outputConnector.bounds = Rectangle.Empty;
                        node.outputConnectors.Add(outputConnector);
                    }
                }
                var itemSize		= PreRenderItem(graphics, node.titleItem, itemPosition);
                var realHeight		= itemSize.Height - GraphConstants.TopHeight;
                var connectorY		= itemPosition.Y  + (int)Math.Ceiling(realHeight / 2.0f);

                node.inputBounds	= new RectangleF(left  - (GraphConstants.ConnectorSize / 2),
                                                     connectorY,
                                                     GraphConstants.ConnectorSize,
                                                     GraphConstants.ConnectorSize);
                node.outputBounds	= new RectangleF(right - (GraphConstants.ConnectorSize / 2),
                                                     connectorY,
                                                     GraphConstants.ConnectorSize,
                                                     GraphConstants.ConnectorSize);
            } else
            {
                node.inputBounds	= Rectangle.Empty;
                node.outputBounds	= Rectangle.Empty;

                foreach (var item in EnumerateNodeItems(node))
                {
                    var itemSize		= PreRenderItem(graphics, item, itemPosition);
                    var realHeight		= itemSize.Height;
                    var inputConnector	= item.Input;
                    if (inputConnector != null && inputConnector.Enabled)
                    {
                        if (itemSize.IsEmpty)
                        {
                            inputConnector.bounds = Rectangle.Empty;
                        } else
                        {
                            inputConnector.bounds = new RectangleF(	left - (GraphConstants.ConnectorSize / 2),
                                                                    itemPosition.Y + connectorOffset,
                                                                    GraphConstants.ConnectorSize,
                                                                    GraphConstants.ConnectorSize);
                        }
                        node.inputConnectors.Add(inputConnector);
                    }
                    var outputConnector = item.Output;
                    if (outputConnector != null && outputConnector.Enabled)
                    {
                        if (itemSize.IsEmpty)
                        {
                            outputConnector.bounds = Rectangle.Empty;
                        } else
                        {
                            outputConnector.bounds = new RectangleF(right - (GraphConstants.ConnectorSize / 2),
                                                                    itemPosition.Y + realHeight - (connectorOffset + GraphConstants.ConnectorSize),
                                                                    GraphConstants.ConnectorSize,
                                                                    GraphConstants.ConnectorSize);
                        }
                        node.outputConnectors.Add(outputConnector);
                    }
                    itemPosition.Y += itemSize.Height + GraphConstants.ItemSpacing;
                }
            }
            node.itemsBounds = new RectangleF(left, top, right - left, bottom - top);
        }
コード例 #30
0
        /// <summary>
        /// Fills all nodes in area and connects edges as necessesary.
        /// Does not have stack overflow problems, but may create a graph
        /// that isn't connected all the way through.
        /// </summary>
        private void fillAll()
        {
            for (int y = 0; y < numYNodes; y++)
            {
                for (int x = 0; x < numXNodes; x++)
                {
                    IntVec2 arrPos = new IntVec2(x, y);
                    Vector2 newPosV2 = ArrPosToWorldSpace(arrPos);

#if DEBUG_PATHFINDER_UPDATELOOP
                    if (!Physics2D.OverlapCircle(newPosV2, radii, LAYER_FILTER_MASK))
#endif
                    {
                        nodeArr[y][x] = new Node(transform.gameObject, nodeImg, newPosV2, arrPos, Node.randWalkState(), radii * 2, numValidNodes++);

                        //add up-left edge (inverse y)
                        if (allowedPaths > Paths.quadDir)
                        {
                            if (x - 1 >= 0 && y - 1 >= 0
                                && nodeArr[y - 1][x - 1] != null
                                && isOkayToFloodDiag(arrPos, IntVec2.down, IntVec2.left))
                                nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x - 1], sqrt2);
                            //add up-right edge (inverse y)
                            if (x + 1 < numXNodes && y - 1 >= 0
                                && nodeArr[y - 1][x + 1] != null
                                && isOkayToFloodDiag(arrPos, IntVec2.down, IntVec2.right))
                                nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x + 1], sqrt2);
                        }
                        //add up edge
                        if (y - 1 >= 0
                            && nodeArr[y - 1][x] != null
                            && isOkayToFloodUDLR(arrPos, IntVec2.down, (Vector2)IntVec2.left))
                            nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x], 1);
                        //add left edge
                        if (x - 1 >= 0
                            && nodeArr[y][x - 1] != null
                            && isOkayToFloodUDLR(arrPos, IntVec2.left, (Vector2)IntVec2.up))
                            nodeArr[y][x].addBidirEdge(nodeArr[y][x - 1], 1);
                    }
                }
            }
        }
コード例 #31
0
ファイル: GraphRenderer.cs プロジェクト: fluffyfreak/Graph
        static IEnumerable<NodeItem> EnumerateNodeItems(Node node)
        {
            if (node == null)
                yield break;

            yield return node.titleItem;
            if (node.Collapsed)
                yield break;

            foreach (var item in node.Items)
                yield return item;
        }
コード例 #32
0
        public void initializeWithArray(Vector2 lowLeftBound, Vector2 upRightBound, Node.SquareType[][] terrainArr)
        {
            lowerLeftBound = lowLeftBound;
            upperRightBound = upRightBound;
            
            numXNodes = terrainArr[0].Length;
            numYNodes = terrainArr.Length;

            // Determine correct node density
            float xDist = lowerLeftBound.x - upperRightBound.x;
            nodeDensity = numXNodes / xDist;

            // Magic number allows for proper drawing of nodes.
            radii = 0.75f / nodeDensity;
            
            numValidNodes = 0;

            // Initialize the node array. Note the inverted y, normal x setup.
            nodeArr = new Node[numYNodes][];
            for (int y = 0; y < numYNodes; y++)
            {
                nodeArr[y] = new Node[numXNodes];

                for (int x = 0; x < numXNodes; x++)
                {
                    IntVec2 arrPos = new IntVec2(x, y);
                    Vector2 newPosV2 = ArrPosToWorldSpace(arrPos);

                    nodeArr[y][x] = new Node(transform.gameObject, nodeImg, newPosV2, arrPos, terrainArr[y][x], radii * 2, numValidNodes++);

                    //add up-left edge (inverse y)
                    if (allowedPaths > Paths.quadDir)
                    {
                        if (x - 1 >= 0 && y - 1 >= 0
                            && isOkayToFloodDiag(arrPos, IntVec2.down, IntVec2.left))
                            nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x - 1], sqrt2);
                        //add up-right edge (inverse y)
                        if (x + 1 < numXNodes && y - 1 >= 0
                            && isOkayToFloodDiag(arrPos, IntVec2.down, IntVec2.right))
                            nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x + 1], sqrt2);
                    }
                    //add up edge
                    if (y - 1 >= 0
                        && isOkayToFloodUDLR(arrPos, IntVec2.down, (Vector2)IntVec2.left))
                        nodeArr[y][x].addBidirEdge(nodeArr[y - 1][x], 1);
                    //add left edge
                    if (x - 1 >= 0
                        && isOkayToFloodUDLR(arrPos, IntVec2.left, (Vector2)IntVec2.up))
                        nodeArr[y][x].addBidirEdge(nodeArr[y][x - 1], 1);
                }
            }

            isInitialized = true;
        }
コード例 #33
0
ファイル: GraphRenderer.cs プロジェクト: fluffyfreak/Graph
        public static SizeF Measure(Graphics context, Node node)
        {
            if (node == null)
                return SizeF.Empty;

            SizeF size = Size.Empty;
            size.Height = //(int)NodeConstants.TopHeight +
                (int)GraphConstants.BottomHeight;
            foreach (var item in EnumerateNodeItems(node))
            {
                var itemSize = item.Measure(context);
                size.Width = Math.Max(size.Width, itemSize.Width);
                size.Height += GraphConstants.ItemSpacing + itemSize.Height;
            }

            if (node.Collapsed)
                size.Height -= GraphConstants.ItemSpacing;

            size.Width += GraphConstants.NodeExtraWidth;
            return size;
        }
コード例 #34
0
 public void AddNeighbor(Node<TNode> node)
 {
     if (node != null) mNeighbors.Add(node);
 }