Example #1
0
        /// <summary>Get array of nodes that are adjacent to specified position</summary>
        /// <param name="pos">Position to get adjacent nodes for</param>
        /// <param name="fnFilter">Optional function to test each node with</param>
        /// <returns>Array of adjacent, non-null nodes that pass filtering</returns>
        public PFState <TNode>[] GetAdjacent(MapPosition pos, Func <PFState <TNode>, bool> fnFilter = null)
        {
            List <PFState <TNode> > res = new List <PFState <TNode> >();

            // Orthogonal nodes
            res.Add(this[pos + MapDirection.Up]);
            res.Add(this[pos + MapDirection.Right]);
            res.Add(this[pos + MapDirection.Down]);
            res.Add(this[pos + MapDirection.Left]);

            // Diagonal nodes
            res.Add(this[pos + MapDirection.UpRight]);
            res.Add(this[pos + MapDirection.DownRight]);
            res.Add(this[pos + MapDirection.DownLeft]);
            res.Add(this[pos + MapDirection.UpLeft]);

            // Filer list
            for (int i = res.Count - 1; i >= 0; --i)
            {
                if (null == res[i])
                {
                    res.RemoveAt(i);
                }
                else if (null != fnFilter && !fnFilter(res[i]))
                {
                    res.RemoveAt(i);
                }
            }

            return(res.ToArray());
        }
Example #2
0
        /// <summary>Create a new value at the specified map position</summary>
        /// <param name="idx">Position to create value at</param>
        /// <returns>Created value</returns>
        protected override PFState <TNode> CreateAt(MapPosition idx)
        {
            PFState <TNode> res = new PFState <TNode>(idx);

            this[idx] = res;
            return(res);
        }
Example #3
0
        /// <summary>Get a list of map positions to reach target position from origin</summary>
        /// <param name="to">Target position of path</param>
        /// <param name="PathCost">Output, total cost of movement</param>
        /// <returns>List of positions in path, or null if no path found</returns>
        public MapPosition[] GetPath(MapPosition to, out double PathCost)
        {
            PathCost = double.PositiveInfinity;

            if (!data.ContainsKey(to))
            {
                //if (!this.ContainsKey(to))
                return(null);
            }

            LinkedList <MapPosition> res = new LinkedList <MapPosition>();

            PFState <TNode> curr = this[to];

            PathCost = curr.TotalCost;

            while (curr != null)
            {
                res.AddFirst(new MapPosition(curr));
                curr = (curr.IsOrigin ? null : this[curr.prevPosition]);
            }

            return(res.ToArray());
        }
Example #4
0
        /// <summary>Generate a map of possible moves for the given map nodes, origin and maximum movement cost</summary>
        /// <param name="nodes">Collection of map nodes describing surrounding movement obstacles and movement costs</param>
        /// <param name="origin">Starting point of path map</param>
        /// <param name="MaxCost">Maximum cost to calculate for</param>
        /// <returns>PathMap instance containing all possible moves</returns>
        public static PathMap <TNode> Generate(IEnumerable <KeyValuePair <MapPosition, TNode> > nodes, MapPosition origin, double MaxCost)
        {
            // setup work-space from supplied nodes
            PathMap <TNode> work = new PathMap <TNode>(nodes);

            work._createonread = true;

            work[origin].IsOrigin = true;

            // init processing queue
            Queue <PFState <TNode> > process = new Queue <PFState <TNode> >();

            foreach (var nxt in work.GetAdjacent(origin, s => s.Passable))
            {
                process.Enqueue(nxt);
            }

            // process nodes
            int iterations = 0;

            while (process.Count > 0)
            {
                PFState <TNode> current = process.Dequeue();
                if (current.IsOrigin)
                {
                    continue;
                }

                // get passable adjacent nodes
                PFState <TNode>[] adj = work.GetAdjacent(current, s => s.Passable);

                // find lowest cost movement to this node from adjacent nodes
                double          minCost = double.PositiveInfinity;
                PFState <TNode> minNode = null;

                foreach (var nxt in adj)
                {
                    double cost = current.CalcMoveCost(nxt);
                    if (cost < minCost)
                    {
                        minCost = cost;
                        minNode = nxt;
                    }
                }

                // if movement found with less cost, update and re-process adjacent nodes
                if (minCost <= MaxCost && (!current.Visited || minCost < current.TotalCost))
                {
                    // set low-cost node as prior node
                    current.TotalCost    = minCost;
                    current.prevPosition = minNode;

                    // reprocess all other adjacent nodes
                    foreach (var nxt in adj)
                    {
                        if (nxt != minNode && !process.Contains(nxt))
                        {
                            process.Enqueue(nxt);
                        }
                    }
                }
                iterations++;
            }

            // generate results and return
            PathMap <TNode> res = new PathMap <TNode>(work.Filter(s => s.Value.Passable && (s.Value.prevPosition != null || s.Value.IsOrigin) && s.Value.TotalCost <= MaxCost));

            res.Iterations = iterations;
            return(res);
        }