예제 #1
0
        public static List <Position> FindPath(Grid grid, Position start, Position end, Offset[] movementPattern, int iterationLimit)
        {
            if (start == end)
            {
                return(new List <Position> {
                    start
                });
            }

            var head = new MinHeapNode(start, ManhattanDistance(start, end));
            var open = new MinHeap();

            open.Push(head);

            var costSoFar = new float[grid.DimX * grid.DimY];
            var cameFrom  = new Position[grid.DimX * grid.DimY];

            while (open.HasNext() && iterationLimit > 0)
            {
                // Get the best candidate
                var current = open.Pop().Position;

                if (current == end)
                {
                    return(ReconstructPath(grid, start, end, cameFrom));
                }

                Step(grid, open, cameFrom, costSoFar, movementPattern, current, end);
                --iterationLimit;
            }

            return(null);
        }
예제 #2
0
        /// <summary>
        /// Find path
        /// </summary>
        /// <param name="grid">Grid</param>
        /// <param name="start">Start point</param>
        /// <param name="end">End point</param>
        /// <param name="movementPattern">Movement pattern</param>
        /// <param name="shape">Shape of an agent</param>
        /// <param name="iterationLimit">Maximum count of iterations</param>
        /// <returns>List of movement steps</returns>
        public static List <Position> FindPath(Grid grid, Position start, Position end, Offset[] movementPattern, AgentShape shape, int iterationLimit = int.MaxValue)
        {
            ClearStepList();

            // If is where should be, then path is simple
            if (start == end)
            {
                return(new List <Position> {
                    start
                });
            }

            // To avoid lot of grid boundaries checking calculations during path finding, do the math here.
            // So get the possible boundaries considering the shape of the agent.
            var boundary = new Boundary()
            {
                X1 = -shape.TopLeft.X,
                Y1 = -shape.TopLeft.Y,
                X2 = grid.DimX - shape.BottomRight.X - 1,
                Y2 = grid.DimY - shape.BottomRight.Y - 1
            };

            // Make sure start and end are within boundary
            if (!boundary.IsInside(start) || !boundary.IsInside(end))
            {
                // Can't find such path
                return(null);
            }

            var head = new MinHeapNode(start, ManhattanDistance(start, end));
            var open = new MinHeap();

            open.Push(head);

            var costSoFar = new float[grid.DimX * grid.DimY];
            var cameFrom  = new Position[grid.DimX * grid.DimY];

            while (open.HasNext() && iterationLimit > 0)
            {
                // Get the best candidate
                var current = open.Pop().Position;
                MessageCurrent(current, PartiallyReconstructPath(grid, start, current, cameFrom));

                if (current == end)
                {
                    return(ReconstructPath(grid, start, end, cameFrom));
                }

                Step(grid, boundary, open, cameFrom, costSoFar, movementPattern, shape, current, end);

                MessageClose(current);

                --iterationLimit;
            }

            return(null);
        }
        public static SearchNode FindPath(Grid grid, Position start, Position end, Offset[] movementPattern)
        {
            ClearStepList();

            var head = new SearchNode(start);
            var open = new MinHeap();

            open.Push(head);

            var marked = new bool[grid.DimX * grid.DimY];

            while (open.HasNext())
            {
                var current = open.Pop();
                MessageCurrent(current);

                if (current.Position == end)
                {
                    return(current);
                }

                foreach (var p in GetNeighbours(current.Position, grid.DimX, grid.DimY, movementPattern))
                {
                    var index = grid.GetIndexUnchecked(p.X, p.Y);

                    // Use the unchecked variant here since GetNeighbours already filters out positions that are out of bounds
                    var cellCost = grid.GetCellCostUnchecked(p);
                    if (!marked[index] && !float.IsInfinity(cellCost))
                    {
                        marked[index] = true;
                        MessageOpen(p);

                        var costSoFar    = current.CostSoFar + cellCost;
                        var expectedCost = costSoFar + ChebyshevDistance(p, end);

                        open.Push(new SearchNode(p, expectedCost, costSoFar)
                        {
                            Next = current
                        });
                    }
                }

                MessageClose(current.Position);
            }

            return(null);
        }
예제 #4
0
        public static List <Position> FindPath(Grid grid, Position start, Position end, Offset[] movementPattern)
        {
            //ClearStepList();

            if (start == end)
            {
                return(new List <Position> {
                    start
                });
            }

            var head = new MinHeapNode(start, ManhattanDistance(start, end));
            var open = new MinHeap();

            open.Push(head);

            var costSoFar = new float[grid.DimX * grid.DimY];
            var cameFrom  = new Position[grid.DimX * grid.DimY];

            while (open.HasNext())
            {
                // Get the best candidate
                var current = open.Pop().Position;
                //MessageCurrent(current, PartiallyReconstructPath(grid, start, current, cameFrom));

                if (current == end)
                {
                    return(ReconstructPath(grid, start, end, cameFrom));
                }

                Step(grid, open, cameFrom, costSoFar, movementPattern, current, end);

                //MessageClose(current);
            }

            return(null);
        }
예제 #5
0
        /// <summary>
        /// Find path
        /// </summary>
        /// <param name="grid">Grid</param>
        /// <param name="start">Start point</param>
        /// <param name="end">End point</param>
        /// <param name="movementPattern">Movement pattern</param>
        /// <param name="shape">Shape of an agent</param>
        /// <param name="path">Returns shortest path from start to the end if found. Can also return partial path if end is not reachable. In case of error returns empty array.</param>
        /// <param name="iterationLimit">Maximum count of iterations</param>
        /// <returns>Result of the path finding.</returns>
        public static PathFindResult TryFindPath(Grid grid, Position start, Position end, Offset[] movementPattern, AgentShape shape, out List <Position> path, int iterationLimit = int.MaxValue)
        {
            ClearStepList();

            // If is where should be, then there's no path to take
            if (start == end)
            {
                path = new List <Position>();
                return(PathFindResult.AlreadyAtTheEnd);
            }

            // To avoid lot of grid boundaries checking calculations during path finding, do the math here.
            // So get the possible boundaries considering the shape of the agent.
            var boundary = Boundary.FromSizeAndShape(grid.DimX, grid.DimY, shape);

            // Make sure that agent is within grid. This means agent shape has to be considered.
            if (!boundary.IsInside(start))
            {
                path = new List <Position>();
                return(PathFindResult.StartOutsideBoundaries);
            }

            // Make sure that end position is within grid
            if (!grid.IsInside(end))
            {
                path = new List <Position>();
                return(PathFindResult.EndOutsideBoundaries);
            }

            var head = new MinHeapNode(start, ManhattanDistance(start, end));
            var open = new MinHeap();

            open.Push(head);

            var costSoFar = new float[grid.DimX * grid.DimY];
            var cameFrom  = new Position[grid.DimX * grid.DimY];

            // Keep record of closest point in case the end point is not reachable
            Position closestPosition = start;
            float    closestDistance = float.PositiveInfinity;

            // Try to find path until options run out or iterations limit is exceeded
            while (open.HasNext() && iterationLimit > 0)
            {
                // Get the best candidate
                var current = open.Pop().Position;
                MessageCurrent(current, PartiallyReconstructPath(grid, start, current, cameFrom));

                if (current == end)
                {
                    path = ReconstructPath(grid, start, end, cameFrom);
                    return(PathFindResult.PathFound);
                }

                Step(grid, boundary, open, cameFrom, costSoFar, movementPattern, shape, current, end, ref closestPosition, ref closestDistance);

                MessageClose(current);

                --iterationLimit;
            }

            // Construct path to the closest position
            if (start != closestPosition)
            {
                MessageCurrent(closestPosition, PartiallyReconstructPath(grid, start, closestPosition, cameFrom));
                path = ReconstructPath(grid, start, closestPosition, cameFrom);
                return(PathFindResult.PartialPathFound);
            }

            // Stuck
            path = new List <Position>();
            return(PathFindResult.Stuck);
        }