///|
/// A triangle mesh for tessellated decorative surfaces.
pub(all) struct TriangleMesh {
  vertices : Array[Vec2]
  indices : Array[(Int, Int, Int)]
} derive(Eq, Debug, ToJson)

///|
pub fn TriangleMesh::new() -> TriangleMesh {
  { vertices: [], indices: [] }
}

///|
pub fn TriangleMesh::add_vertex(self : TriangleMesh, vertex : Vec2) -> Int {
  self.vertices.push(vertex)
  self.vertices.length() - 1
}

///|
pub fn TriangleMesh::add_triangle(
  self : TriangleMesh,
  a : Int,
  b : Int,
  c : Int,
) -> Bool {
  if a < 0 ||
    b < 0 ||
    c < 0 ||
    a >= self.vertices.length() ||
    b >= self.vertices.length() ||
    c >= self.vertices.length() {
    false
  } else {
    self.indices.push((a, b, c))
    true
  }
}

///|
pub fn TriangleMesh::triangle_area(self : TriangleMesh, index : Int) -> Double {
  if index < 0 || index >= self.indices.length() {
    0.0
  } else {
    let triangle = self.indices[index]
    polygon_area([
      self.vertices[triangle.0],
      self.vertices[triangle.1],
      self.vertices[triangle.2],
    ]).abs()
  }
}

///|
pub fn TriangleMesh::area(self : TriangleMesh) -> Double {
  let mut total = 0.0
  for i in 0.. Rect {
  bounds_of_points(self.vertices)
}

///|
pub fn TriangleMesh::transform(
  self : TriangleMesh,
  matrix : Matrix2D,
) -> TriangleMesh {
  { vertices: transform_points(self.vertices, matrix), indices: self.indices }
}

///|
pub fn fan_mesh(center : Vec2, boundary : Array[Vec2]) -> TriangleMesh {
  let mesh = TriangleMesh::new()
  let center_index = mesh.add_vertex(center)
  for point in boundary {
    let _ = mesh.add_vertex(point)
  }
  if boundary.length() >= 2 {
    for i in 0.. TriangleMesh {
  let mesh = TriangleMesh::new()
  if columns > 0 && rows > 0 {
    for row in 0..<=rows {
      for col in 0..<=columns {
        let _ = mesh.add_vertex(
          Vec2::new(
            col.to_double() * width / columns.to_double(),
            row.to_double() * height / rows.to_double(),
          ),
        )
      }
    }
    let stride = columns + 1
    for row in 0.. Array[Path] {
  let result = []
  for triangle in mesh.indices {
    result.push(
      polyline(
        [
          mesh.vertices[triangle.0],
          mesh.vertices[triangle.1],
          mesh.vertices[triangle.2],
        ],
        closed=true,
      ),
    )
  }
  result
}