diff --git a/src/CoveragePathPlanner/CoveragePathPlanner.cs b/src/CoveragePathPlanner/CoveragePathPlanner.cs index dbeff63..8bdf026 100644 --- a/src/CoveragePathPlanner/CoveragePathPlanner.cs +++ b/src/CoveragePathPlanner/CoveragePathPlanner.cs @@ -1,136 +1,135 @@ -using System; -using System.Collections.Generic; using System.Drawing; public class CoveragePathPlanner { - private int _width; - private int _height; - private List _cells; + private int _width; + private int _height; + private List _cells; - public CoveragePathPlanner(int width, int height) + public CoveragePathPlanner(int width, int height) + { + _width = width; + _height = height; + _cells = new List(); + + for (int x = 0; x < width; x++) { - _width = width; - _height = height; - _cells = new List(); + for (int y = 0; y < height; y++) + { + _cells.Add(new Cell { X = x, Y = y, IsObstacle = false, IsVisited = false, Cost = double.MaxValue }); + } + } + } - for (int x = 0; x < width; x++) + public List PlanPath(List obstacles) + { + // Add obstacles to the grid + foreach (Obstacle obstacle in obstacles) + { + foreach (Cell cell in _cells) + { + if (cell.IsWithinObstacle(obstacle)) { - for (int y = 0; y < height; y++) - { - _cells.Add(new Cell { X = x, Y = y, IsObstacle = false, IsVisited = false, Cost = double.MaxValue }); - } + cell.IsObstacle = true; } + } } - public List PlanPath(List obstacles) + // Initialize the start cell + Cell startCell = _cells[0]; + startCell.Cost = 0; + + // Create a priority queue to hold the cells to be processed + var queue = new PriorityQueue(); + queue.Enqueue(startCell, 0); + + while (queue.Count > 0) { - // Add obstacles to the grid - foreach (Obstacle obstacle in obstacles) + // Dequeue the cell with the lowest cost + Cell currentCell = queue.Dequeue(); + + // If the cell is the goal, construct the path + if (currentCell.X == _width - 1 && currentCell.Y == _height - 1) + { + List path = new List(); + while (currentCell != null) { - for (int x = obstacle.X; x < obstacle.X + obstacle.Width; x++) - { - for (int y = obstacle.Y; y < obstacle.Y + obstacle.Height; y++) - { - _cells[x + y * _width].IsObstacle = true; - } - } + path.Add(new Point(currentCell.X, currentCell.Y)); + currentCell = currentCell.Parent; } + return path; + } - // Initialize the start cell - Cell startCell = _cells[0]; - startCell.Cost = 0; + // Mark the cell as visited + currentCell.IsVisited = true; - // Create a priority queue to hold the cells to be processed - var queue = new PriorityQueue(); - queue.Enqueue(startCell, 0); - - while (queue.Count > 0) + // Explore the neighbors + foreach (Cell neighbor in currentCell.GetNeighbors(_cells)) + { + if (!neighbor.IsVisited && !neighbor.IsObstacle) { - // Dequeue the cell with the lowest cost - Cell currentCell = queue.Dequeue(); - - // If the cell is the goal, construct the path - if (currentCell.X == _width - 1 && currentCell.Y == _height - 1) - { - List path = new List(); - while (currentCell != null) - { - path.Add(new Point(currentCell.X, currentCell.Y)); - currentCell = currentCell.Parent; - } - return path; - } - - // Mark the cell as visited - currentCell.IsVisited = true; - - // Explore the neighbors - foreach (Cell neighbor in GetNeighbors(currentCell)) - { - if (!neighbor.IsVisited && !neighbor.IsObstacle) - { - // Calculate the cost of the neighbor - double cost = currentCell.Cost + 1; - if (cost < neighbor.Cost) - { - neighbor.Cost = cost; - neighbor.Parent = currentCell; - queue.Enqueue(neighbor, cost + Heuristic(neighbor)); - } - } - } + // Calculate the cost of the neighbor + double cost = currentCell.Cost + 1; + if (cost < neighbor.Cost) + { + neighbor.Cost = cost; + neighbor.Parent = currentCell; + queue.Enqueue(neighbor, cost + currentCell.Heuristic(_width, _height)); + } } - - // If no path is found, return an empty list - return new List(); - } - - private List GetNeighbors(Cell cell) - { - List neighbors = new List(); - - for (int x = -1; x <= 1; x++) - { - for (int y = -1; y <= 1; y++) - { - if (x == 0 && y == 0) continue; - - int neighborX = cell.X + x; - int neighborY = cell.Y + y; - - if (neighborX >= 0 && neighborX < _width && neighborY >= 0 && neighborY < _height) - { - neighbors.Add(_cells[neighborX + neighborY * _width]); - } - } - } - - return neighbors; - } - - private double Heuristic(Cell cell) - { - // Manhattan distance heuristic - return Math.Abs(cell.X - (_width - 1)) + Math.Abs(cell.Y - (_height - 1)); + } } + // If no path is found, return an empty list + return new List(); + } } public class Obstacle { - public int X { get; set; } - public int Y { get; set; } - public int Width { get; set; } - public int Height { get; set; } + public int X { get; set; } + public int Y { get; set; } + public int Width { get; set; } + public int Height { get; set; } } public class Cell { - public int X { get; set; } - public int Y { get; set; } - public bool IsObstacle { get; set; } - public bool IsVisited { get; set; } - public double Cost { get; set; } - public Cell Parent { get; set; } + public int X { get; set; } + public int Y { get; set; } + public bool IsObstacle { get; set; } + public bool IsVisited { get; set; } + public double Cost { get; set; } + public Cell Parent { get; set; } + + public bool IsWithinObstacle(Obstacle obstacle) + { + return X >= obstacle.X && X < obstacle.X + obstacle.Width && + Y >= obstacle.Y && Y < obstacle.Y + obstacle.Height; + } + + public IEnumerable GetNeighbors(List cells) + { + for (int x = -1; x <= 1; x++) + { + for (int y = -1; y <= 1; y++) + { + if (x == 0 && y == 0) continue; + + int neighborX = X + x; + int neighborY = Y + y; + + if (neighborX >= 0 && neighborX < cells.Count / cells[0].Y && neighborY >= 0 && neighborY < cells[0].Y) + { + yield return cells[neighborX + neighborY * cells.Count / cells[0].Y]; + } + } + } + } + + public double Heuristic(int width, int height) + { + // Manhattan distance heuristic + return Math.Abs(X - (width - 1)) + Math.Abs(Y - (height - 1)); + } }