///|
/// Types of grid layouts supported
pub(all) enum GridType {
  Rectangular
  Hexagonal
  Triangular
  Radial
} derive(Eq, Debug, ToJson)

///|
/// Represents a single cell inside the grid
pub(all) struct GridCell {
  x : Double
  y : Double
  row : Int
  col : Int
  transform : Matrix2D
} derive(Eq, Debug, ToJson)

///|
/// Configuration for the grid generator
pub(all) struct Grid {
  grid_type : GridType
  width : Double
  height : Double
  cols : Int
  rows : Int
  spacing_x : Double
  spacing_y : Double
  cell_size : Double
} derive(Eq, Debug, ToJson)

///|
/// Create a new grid configuration
pub fn Grid::new(
  grid_type : GridType,
  width : Double,
  height : Double,
  cols : Int,
  rows : Int,
  cell_size : Double,
) -> Grid {
  let (spacing_x, spacing_y) = match grid_type {
    Rectangular => (width / cols.to_double(), height / rows.to_double())
    Hexagonal => (cell_size * 1.73205080757, cell_size * 1.5)
    Triangular => (cell_size, cell_size * 0.86602540378)
    Radial => (2.0 * @math.PI / cols.to_double(), cell_size)
  }
  { grid_type, width, height, cols, rows, spacing_x, spacing_y, cell_size }
}

///|
/// Generates all cells of the grid with their centers and transform matrices
pub fn Grid::generate_cells(self : Grid) -> Array[GridCell] {
  let cells = []
  match self.grid_type {
    Rectangular =>
      for r in 0..
      for r in 0..
      for r in 0.. {
      let center_x = self.width / 2.0
      let center_y = self.height / 2.0
      for r in 0..