// Ported from georust/geo
// https://github.com/georust/geo/blob/main/geo/src/algorithm/cross_track_distance.rs
//
// The cross-track distance (also known as cross-track error) is the shortest
// great-circle distance between a point `p` and a great circle that passes
// through `line_point_a` and `line_point_b`.
//
// Formula:
// δ_xt = asin( sin(d_13 / R) * sin(θ_12 - θ_13) )
// distance = R * |δ_xt|
// where
// d_13 = haversine distance from `line_point_a` to `p`
// θ_13 = haversine bearing from `line_point_a` to `p`
// θ_12 = haversine bearing from `line_point_a` to `line_point_b`
// R = mean Earth radius (GRS80 mean radius is used here, matching
// `geo`'s `MEAN_EARTH_RADIUS`).
///|
/// Cross-track distance from `p` to the great circle through `line_point_a`
/// and `line_point_b`. Uses the same mean-Earth radius as `Haversine()`
/// (GRS80 mean radius, 6_371_008.8 m). Result is in meters.
///
/// ```check
/// test "cross_track_distance - one degree off the equator" {
/// let p = @type.Point::from_tuple((1.0, 1.0))
/// let a = @type.Point::from_tuple((0.0, 0.0))
/// let b = @type.Point::from_tuple((2.0, 0.0))
/// let distance = cross_track_distance(p, a, b)
/// assert_true(distance > 100_000.0 && distance < 120_000.0)
/// }
/// ```
pub fn cross_track_distance(
p : @type.Point,
line_point_a : @type.Point,
line_point_b : @type.Point,
) -> Double {
let h = haversine()
let r = h.radius
let d_13 = h.distance(line_point_a, p) / r
let theta_13 = h.bearing(line_point_a, p) * @math.PI / 180.0
let theta_12 = h.bearing(line_point_a, line_point_b) * @math.PI / 180.0
let delta_xt = @math.asin(@math.sin(d_13) * @math.sin(theta_12 - theta_13))
r * delta_xt.abs()
}