use geometry_adapt::Adapt;
use geometry_algorithm::{area, comparable_distance, distance, length, within};
use geometry_cs::Cartesian;
use geometry_model::{Linestring, Point2D, Polygon, Ring, linestring, polygon};
const QUICKSTART_EPS: f64 = 1e-4;
fn quickstart_polygon() -> Polygon<Point2D<f64, Cartesian>> {
polygon![[(2.0, 1.3), (4.1, 3.0), (5.3, 2.6), (2.9, 0.7), (2.0, 1.3)]]
}
#[test]
fn distance_p1_p2_is_sqrt2() {
let p1 = Point2D::<f64, Cartesian>::new(1.0, 1.0);
let p2 = Point2D::<f64, Cartesian>::new(2.0, 2.0);
let d = distance(&p1, &p2);
let expected = 2.0_f64.sqrt();
assert!(
(d - expected).abs() < QUICKSTART_EPS,
"got {d}, expected ~= {expected} (quickstart prints 1.41421)",
);
}
#[test]
fn distance_a_b_is_sqrt5() {
let a = Adapt([1.0_f64, 1.0]);
let b = Adapt([2.0_f64, 3.0]);
let d = distance(&a, &b);
let expected = 5.0_f64.sqrt();
assert!(
(d - expected).abs() < QUICKSTART_EPS,
"got {d}, expected ~= {expected} (quickstart prints 2.23607)",
);
}
#[test]
fn distance_a_to_tuple_p() {
let a = Adapt([1.0_f64, 1.0]);
let p = Adapt((3.7_f64, 2.0));
let d = distance(&a, &p);
let expected = 2.879_236_009_777_435_f64; assert!(
(d - expected).abs() < QUICKSTART_EPS,
"got {d}, expected ~= {expected} (quickstart prints 2.87924)",
);
}
#[test]
fn comparable_distance_matches_squared() {
let p1 = Point2D::<f64, Cartesian>::new(0.0, 0.0);
let p2 = Point2D::<f64, Cartesian>::new(3.0, 0.0);
let cd = comparable_distance(&p1, &p2);
assert_eq!(
cd.to_bits(),
9.0_f64.to_bits(),
"comparable_distance({p1:?}, {p2:?}) = {cd}, want 9.0",
);
}
#[test]
fn within_quickstart_point_in_polygon() {
let p = Point2D::<f64, Cartesian>::new(3.7, 2.0);
assert!(
within(&p, &quickstart_polygon()),
"(3.7, 2.0) should be inside the quickstart polygon",
);
}
#[test]
fn area_quickstart_polygon_is_3_015() {
let a = area(&quickstart_polygon());
assert!(
(a - 3.015).abs() < 1e-3,
"got {a}, expected ~= 3.015 (quickstart prints Area: 3.015)",
);
}
#[test]
fn length_3_4_polyline_is_5() {
let ls: Linestring<Point2D<f64, Cartesian>> = linestring![(0.0, 0.0), (3.0, 4.0)];
let got = length(&ls);
assert!(
(got - 5.0).abs() < 1e-12,
"got {got}, expected 5.0 (length.cpp:24)",
);
}
#[test]
fn length_zigzag_with_diagonal_is_5_plus_sqrt2() {
let ls: Linestring<Point2D<f64, Cartesian>> = linestring![(0.0, 0.0), (3.0, 4.0), (4.0, 3.0)];
let got = length(&ls);
let expected = 5.0 + 2.0_f64.sqrt();
assert!(
(got - expected).abs() < 1e-12,
"got {got}, expected {expected} (length.cpp:27)",
);
}
#[test]
fn area_simple_diamond_is_2() {
let p: Polygon<Point2D<f64, Cartesian>> =
polygon![[(1.0, 1.0), (2.0, 2.0), (3.0, 1.0), (2.0, 0.0), (1.0, 1.0)]];
let got = area(&p);
assert!(
(got - 2.0).abs() < 1e-12,
"got {got}, expected 2.0 (area.cpp:45)",
);
}
#[test]
fn area_pentagon_with_hole_is_15() {
let outer: Ring<Point2D<f64, Cartesian>> = Ring::from_vec(vec![
Point2D::new(0.0, 0.0),
Point2D::new(0.0, 7.0),
Point2D::new(4.0, 2.0),
Point2D::new(2.0, 0.0),
Point2D::new(0.0, 0.0),
]);
let hole: Ring<Point2D<f64, Cartesian>> = Ring::from_vec(vec![
Point2D::new(1.0, 1.0),
Point2D::new(2.0, 1.0),
Point2D::new(2.0, 2.0),
Point2D::new(1.0, 2.0),
Point2D::new(1.0, 1.0),
]);
let mut p: Polygon<Point2D<f64, Cartesian>> = Polygon::new(outer);
p.inners.push(hole);
let got = area(&p);
assert!(
(got - 15.0).abs() < 1e-12,
"got {got}, expected 15.0 (area.cpp:49)",
);
}