///|
/// A two-dimensional point or vector.
pub(all) struct Point {
x : Double
y : Double
} derive(Debug)
///|
/// Construct a point.
pub fn Point::new(x~ : Double, y~ : Double) -> Point {
{ x, y }
}
///|
/// Add two points as vectors.
pub fn Point::add(self : Point, other : Point) -> Point {
{ x: self.x + other.x, y: self.y + other.y }
}
///|
/// Subtract two points as vectors.
pub fn Point::sub(self : Point, other : Point) -> Point {
{ x: self.x - other.x, y: self.y - other.y }
}
///|
/// Scale a vector.
pub fn Point::scale(self : Point, factor : Double) -> Point {
{ x: self.x * factor, y: self.y * factor }
}
///|
/// Dot product.
pub fn Point::dot(self : Point, other : Point) -> Double {
self.x * other.x + self.y * other.y
}
///|
/// Euclidean length.
pub fn Point::length(self : Point) -> Double {
(self.x * self.x + self.y * self.y).sqrt()
}
///|
/// Distance between two points.
pub fn Point::distance(self : Point, other : Point) -> Double {
self.sub(other).length()
}
///|
/// Axis-aligned rectangular bounds.
pub(all) struct Aabb {
min : Point
max : Point
} derive(Debug)
///|
/// Construct normalized bounds even when corners are supplied in reverse.
pub fn Aabb::new(min~ : Point, max~ : Point) -> Aabb {
{
min: { x: min.x.min(max.x), y: min.y.min(max.y) },
max: { x: min.x.max(max.x), y: min.y.max(max.y) },
}
}
///|
/// True when a point lies inside or on the bounds.
pub fn Aabb::contains(self : Aabb, point : Point) -> Bool {
point.x >= self.min.x &&
point.x <= self.max.x &&
point.y >= self.min.y &&
point.y <= self.max.y
}
///|
/// Circle geometry primitive.
pub(all) struct Circle {
center : Point
radius : Double
} derive(Debug)
///|
/// Construct a circle.
pub fn Circle::new(center~ : Point, radius~ : Double) -> Circle {
{ center, radius }
}
///|
/// Signed distance from a circle boundary; negative means inside.
pub fn Circle::signed_distance(self : Circle, point : Point) -> Double {
point.distance(self.center) - self.radius
}
///|
/// A shape that can be rasterized into a lattice mask.
pub(all) enum Shape {
CircleShape(Circle)
RectangleShape(Aabb)
} derive(Debug)
///|
/// Build a circle shape.
pub fn Shape::circle(center~ : Point, radius~ : Double) -> Shape {
CircleShape(Circle::new(center~, radius~))
}
///|
/// Build a rectangle shape.
pub fn Shape::rectangle(bounds~ : Aabb) -> Shape {
RectangleShape(bounds)
}
///|
/// Test a shape using lattice-cell-center coordinates.
pub fn Shape::contains(self : Shape, point : Point) -> Bool {
match self {
CircleShape(circle) =>
circle.signed_distance(point) <= 0.0 && circle.radius >= 0.0
RectangleShape(bounds) => bounds.contains(point)
}
}
///|
/// Integer coordinate used by connected-component reports.
pub(all) struct GridPoint {
x : Int
y : Int
} derive(Debug, Eq)
///|
/// A connected solid region in a domain mask.
pub(all) struct ConnectedComponent {
size : Int
cells : Array[GridPoint]
} derive(Debug)