/// <summary>
        /// Core Process of Theta* pathfinding algorithm.
        /// </summary>
        /// <param name="run"> A Boolean value that declare starting of the algorithm.</param>
        /// <param name="context"> A Brep representing the context of the navigation model.</param>
        /// <param name="startPoint"> A Point3d representing the start location.</param>
        /// <param name="goalPoint"> A Point3d representing the destination location.</param>
        /// <param name="wallData"> A DataTree representing the locations of the obstacle cells in the navigation model.</param>
        /// <param name="cellSize"> A double that indicates size of the navigation model's cells.</param>
        /// <returns> A Polyline that represents the result of the Theta* pathfinding algorithm.</returns>
        Polyline pathFinding(bool run, Brep context, Point3d startPoint, Point3d goalPoint, GH_Structure <GH_Integer> wallData, double cellSize)
        {
            int[] startID = new int[2];
            int[] goalID  = new int[2];

            SimplePriorityQueue <Spot> openSet = new SimplePriorityQueue <Spot>();

            List <Point3d> path = new List <Point3d>();

            Polyline finalPaths = new Polyline();

            int gridSize = wallData.Branches.Count;

            double[] modelLocation = { context.Vertices[0].Location.X, context.Vertices[0].Location.Y };

            Spot neighbor;
            Spot current;

            Spot[,] grid  = new Spot[gridSize + 1, gridSize + 1];
            Cell[,] cells = new Cell[gridSize, gridSize];

            for (int i = 0; i < gridSize + 1; i++)
            {
                for (int j = 0; j < gridSize + 1; j++)
                {
                    if (i < gridSize && j < gridSize)
                    {
                        cells[i, j] = new Cell(cellSize, wallData.Branches[i][j].Value);
                    }

                    grid[i, j]   = new Spot(modelLocation, new int[] { i, j }, cellSize);
                    grid[i, j].g = float.MaxValue;
                    grid[i, j].f = float.MaxValue;
                    grid[i, j].getNeighbors(gridSize);
                    if (i == 0 && j == 0)
                    {
                        grid[i, j].adjCells.Add(cells[i, j]);
                    }
                    if (i == 0 && j == gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[0, j - 1]);
                    }
                    if (i == gridSize && j == 0)
                    {
                        grid[i, j].adjCells.Add(cells[i - 1, j]);
                    }
                    if (i == gridSize && j == gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i - 1, j - 1]);
                    }
                    if (i == 0 && j > 0 && j < gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i, j]);
                        grid[i, j].adjCells.Add(cells[i, j - 1]);
                    }
                    if (j == 0 && i > 0 && i < gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i, j]);
                        grid[i, j].adjCells.Add(cells[i - 1, j]);
                    }
                    if (i == gridSize && j > 0 && j < gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i - 1, j - 1]);
                        grid[i, j].adjCells.Add(cells[i - 1, j]);
                    }
                    if (j == gridSize && i > 0 && i < gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i - 1, j - 1]);
                        grid[i, j].adjCells.Add(cells[i, j - 1]);
                    }
                    if (i > 0 && j > 0 && i < gridSize && j < gridSize)
                    {
                        grid[i, j].adjCells.Add(cells[i, j]);
                        grid[i, j].adjCells.Add(cells[i - 1, j]);
                        grid[i, j].adjCells.Add(cells[i - 1, j - 1]);
                        grid[i, j].adjCells.Add(cells[i, j - 1]);
                    }
                }
            }

            for (int i = 0; i < gridSize; i++)
            {
                for (int j = 0; j < gridSize; j++)
                {
                    cells[i, j].cornerSpots[0] = grid[i, j];
                    cells[i, j].cornerSpots[1] = grid[i + 1, j];
                    cells[i, j].cornerSpots[2] = grid[i + 1, j + 1];
                    cells[i, j].cornerSpots[3] = grid[i, j + 1];
                }
            }

            double tempValue = double.MaxValue;

            double tempDistance = new double();

            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    tempDistance = startPoint.DistanceTo(grid[i, j].pos);
                    if (tempDistance < tempValue)
                    {
                        tempValue  = tempDistance;
                        startID[0] = i;
                        startID[1] = j;
                    }
                }
            }

            tempValue = double.MaxValue;

            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    tempDistance = goalPoint.DistanceTo(grid[i, j].pos);
                    if (tempDistance < tempValue)
                    {
                        tempValue = tempDistance;
                        goalID[0] = i;
                        goalID[1] = j;
                    }
                }
            }

            Spot start = grid[startID[0], startID[1]];
            Spot goal  = grid[goalID[0], goalID[1]];

            start.g      = 0;
            start.parent = start;
            start.he     = Methods.calcHeuristic(start, goal);

            openSet.Enqueue(start, start.f);

            while (openSet.Count > 0)
            {
                current = openSet.Dequeue();
                if (current == goal)
                {
                    Methods.buildPath(path, current, start);
                    finalPaths = Methods.drawPath(path);
                    break;
                }
                current.closedSet = true;
                Methods.updateBounds(grid, current, start);
                for (int k = 0; k < current.neighbors.Count; k++)
                {
                    neighbor = grid[current.neighbors[k][0], current.neighbors[k][1]];
                    if (neighbor.closedSet == false)
                    {
                        if (!openSet.Contains(neighbor))
                        {
                            neighbor.g = float.MaxValue;
                        }
                        Methods.updateVertex(openSet, current, neighbor, start, goal);
                    }
                }
            }

            return(finalPaths);
        }
Пример #2
0
 public static float calcHeuristic(Spot s1, Spot s2)
 {
     return((float)s1.pos.DistanceTo(s2.pos));
 }
Пример #3
0
        public static void updateBounds(Spot[,] grid, Spot s, Spot start)
        {
            s.lb = -float.MaxValue;
            s.ub = float.MaxValue;

            float angle = new float();

            Cell adjCell;
            Spot neighbor;

            if (s != start)
            {
                // Condition - 1
                for (int i = 0; i < s.adjCells.Count; i++)
                {
                    adjCell = s.adjCells[i];
                    if (adjCell.wall == 1)
                    {
                        for (int j = 0; j < adjCell.cornerSpots.Length; j++)
                        {
                            adjCell.cornerSpots[j].los = false;
                            angle = theta(s.pos, s.parent.pos, adjCell.cornerSpots[j].pos);

                            if (s.parent == adjCell.cornerSpots[j] || angle < 0 || (angle == 0 && s.parent.pos.DistanceTo(adjCell.cornerSpots[j].pos) <= s.parent.pos.DistanceTo(s.pos)))
                            {
                                s.lb = 0;
                            }
                            if (s.parent == adjCell.cornerSpots[j] || angle > 0 || (angle == 0 && s.parent.pos.DistanceTo(adjCell.cornerSpots[j].pos) <= s.parent.pos.DistanceTo(s.pos)))
                            {
                                s.ub = 0;
                            }
                        }
                    }
                }
                for (int i = 0; i < s.neighbors.Count; i++)
                {
                    neighbor = grid[s.neighbors[i][0], s.neighbors[i][1]];
                    angle    = theta(s.pos, s.parent.pos, neighbor.pos);
                    // Condition - 2
                    if (neighbor.closedSet == true && s.parent == neighbor.parent && neighbor != start)
                    {
                        if (neighbor.lb + angle <= 0)
                        {
                            s.lb = Math.Max(s.lb, neighbor.lb + angle);
                        }
                        if (neighbor.ub + angle >= 0)
                        {
                            s.ub = Math.Min(s.ub, neighbor.ub + angle);
                        }
                    }
                    // Condition - 3
                    if ((neighbor.closedSet == false || s.parent != neighbor.parent) && (s.parent.pos.DistanceTo(neighbor.pos) < s.parent.pos.DistanceTo(s.pos)) && s.parent != neighbor)
                    {
                        if (angle < 0)
                        {
                            s.lb = Math.Max(s.lb, angle);
                        }
                        if (angle > 0)
                        {
                            s.ub = Math.Min(s.ub, angle);
                        }
                    }
                }
            }
        }
Пример #4
0
        public static void updateVertex(SimplePriorityQueue <Spot> openSet, Spot s, Spot succ, Spot start, Spot goal)
        {
            double angle = theta(s.pos, s.parent.pos, succ.pos);

            if (s != start && s.lb <= angle && s.ub >= angle)
            {
                // Path - 2
                if (s.parent.g + s.parent.pos.DistanceTo(succ.pos) < succ.g && s.los)
                {
                    succ.g      = s.parent.g + (float)s.parent.pos.DistanceTo(succ.pos);
                    succ.parent = s.parent;
                    if (openSet.Contains(succ))
                    {
                        openSet.Remove(succ);
                    }
                    succ.f = succ.g + calcHeuristic(succ, goal);
                    openSet.Enqueue(succ, succ.f);
                }
            }
            else
            {
                // Path - 1
                if (s.g + s.pos.DistanceTo(succ.pos) < succ.g && s.los)
                {
                    succ.g      = s.g + (float)s.pos.DistanceTo(succ.pos);
                    succ.parent = s;
                    if (openSet.Contains(succ))
                    {
                        openSet.Remove(succ);
                    }
                    succ.f = succ.g + calcHeuristic(succ, goal);
                    openSet.Enqueue(succ, succ.f);
                }
            }
        }