// Ported from georust/geo
// https://github.com/georust/geo/blob/main/geo/src/algorithm/vector_ops.rs
///|
/// Euclidean distance from this coordinate to the origin: `sqrt(x² + y²)`.
pub fn magnitude(c : @type.Coord) -> Double {
(c.x() * c.x() + c.y() * c.y()).sqrt()
}
///|
/// Squared distance from this coordinate to the origin (avoids the
/// `sqrt` when it is not needed): `x² + y²`.
pub fn magnitude_squared(c : @type.Coord) -> Double {
c.x() * c.x() + c.y() * c.y()
}
///|
/// Rotate this coordinate around the origin by 90 degrees clockwise:
/// `(x, y) -> (-y, x)`.
pub fn left(c : @type.Coord) -> @type.Coord {
@type.Coord(-c.y(), c.x())
}
///|
/// Rotate this coordinate around the origin by 90 degrees anti-clockwise:
/// `(x, y) -> (y, -x)`.
pub fn right(c : @type.Coord) -> @type.Coord {
@type.Coord(c.y(), -c.x())
}
///|
/// Inner / dot product: `a · b = a.x * b.x + a.y * b.y`.
pub fn dot_product(a : @type.Coord, b : @type.Coord) -> Double {
a.dot(b)
}
///|
/// 2D wedge / cross product: `a ∧ b = a.x * b.y - a.y * b.x`.
pub fn wedge_product(a : @type.Coord, b : @type.Coord) -> Double {
a.cross(b)
}
///|
/// Returns whether both `x` and `y` are finite (not NaN, not infinity).
pub fn is_finite(c : @type.Coord) -> Bool {
// MoonBit Double provides `is_inf` and `is_nan`.
!c.x().is_inf() && !c.x().is_nan() && !c.y().is_inf() && !c.y().is_nan()
}
///|
/// Try to normalise this vector. Returns `None` if the result is not
/// finite (e.g. the input has zero magnitude that rounds to 0, or NaN /
/// infinite components).
pub fn try_normalize(c : @type.Coord) -> @type.Coord? {
let mag = magnitude(c)
let result = c.div(mag)
if is_finite(result) {
Some(result)
} else {
None
}
}