use geometry_adapt::{Adapt, register_linestring, register_polygon, register_ring};
use geometry_algorithm::{area, comparable_distance, distance, length, within};
use geometry_derive::Point as DerivePoint;
use geometry_model::{Polygon as ModelPolygon, Ring as ModelRing};
use geometry_trait::{Linestring, Polygon as PolygonTrait, Ring as RingTrait};
const QUICKSTART_EPS: f64 = 1e-4;
#[test]
fn adapted_array_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 adapted_array_to_tuple_distance_is_sqrt8_29() {
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 adapted_array_comparable_distance_matches_squared() {
let a = Adapt([0.0_f64, 0.0]);
let b = Adapt([3.0_f64, 0.0]);
let cd = comparable_distance(&a, &b);
assert_eq!(
cd.to_bits(),
9.0_f64.to_bits(),
"comparable_distance({a:?}, {b:?}) = {cd}, want 9.0",
);
}
#[derive(Default, DerivePoint)]
#[geometry(cs = "Cartesian", scalar = "f64")]
struct MyPoint {
x: f64,
y: f64,
}
#[test]
fn derived_distance_p1_p2_is_sqrt2() {
let p1 = MyPoint { x: 1.0, y: 1.0 };
let p2 = MyPoint { x: 2.0, y: 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 derived_distance_a_b_is_sqrt5() {
let a = MyPoint { x: 1.0, y: 1.0 };
let b = MyPoint { x: 2.0, y: 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 derived_distance_a_to_tuple_p() {
let a = MyPoint { x: 1.0, y: 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 derived_comparable_distance_matches_squared() {
let p1 = MyPoint { x: 0.0, y: 0.0 };
let p2 = MyPoint { x: 3.0, y: 0.0 };
let cd = comparable_distance(&p1, &p2);
assert_eq!(
cd.to_bits(),
9.0_f64.to_bits(),
"comparable_distance = {cd}, want 9.0",
);
}
struct MyLs {
v: Vec<MyPoint>,
}
register_linestring!(MyLs, MyPoint, |s| s.v.iter());
#[test]
fn registered_linestring_has_three_points() {
let ls = MyLs {
v: vec![
MyPoint { x: 0.0, y: 0.0 },
MyPoint { x: 1.0, y: 1.0 },
MyPoint { x: 2.0, y: 0.0 },
],
};
assert_eq!(ls.points().count(), 3);
}
#[test]
fn registered_linestring_length_3_4_is_5() {
let ls = MyLs {
v: vec![MyPoint { x: 0.0, y: 0.0 }, MyPoint { x: 3.0, y: 4.0 }],
};
let got = length(&ls);
assert!(
(got - 5.0).abs() < 1e-12,
"got {got}, expected 5.0 (length.cpp:24)",
);
}
struct MyRing {
v: Vec<MyPoint>,
}
register_ring!(MyRing, MyPoint, |s| s.v.iter());
struct MyPoly {
outer: MyRing,
inners: Vec<MyRing>,
}
register_polygon!(
MyPoly,
MyPoint,
ring = MyRing,
|s| outer = &s.outer,
inners = s.inners.iter()
);
#[test]
fn registered_polygon_area_diamond_is_2() {
let p = MyPoly {
outer: MyRing {
v: vec![
MyPoint { x: 1.0, y: 1.0 },
MyPoint { x: 2.0, y: 2.0 },
MyPoint { x: 3.0, y: 1.0 },
MyPoint { x: 2.0, y: 0.0 },
MyPoint { x: 1.0, y: 1.0 },
],
},
inners: vec![],
};
let got = area(&p);
assert!(
(got - 2.0).abs() < 1e-12,
"got {got}, expected 2.0 (area.cpp:45)",
);
}
#[test]
fn registered_polygon_quickstart_area_is_3_015() {
let p = MyPoly {
outer: MyRing {
v: vec![
MyPoint { x: 2.0, y: 1.3 },
MyPoint { x: 4.1, y: 3.0 },
MyPoint { x: 5.3, y: 2.6 },
MyPoint { x: 2.9, y: 0.7 },
MyPoint { x: 2.0, y: 1.3 },
],
},
inners: vec![],
};
let got = area(&p);
assert!(
(got - 3.015).abs() < 1e-3,
"got {got}, expected ~= 3.015 (quickstart prints Area: 3.015)",
);
}
#[test]
fn adapted_tuple_within_quickstart_polygon() {
let p = Adapt((3.7_f64, 2.0));
let outer = ModelRing::from_vec(vec![
Adapt((2.0_f64, 1.3)),
Adapt((4.1, 3.0)),
Adapt((5.3, 2.6)),
Adapt((2.9, 0.7)),
Adapt((2.0, 1.3)),
]);
let poly: ModelPolygon<Adapt<(f64, f64)>> = ModelPolygon::new(outer);
assert!(
within(&p, &poly),
"(3.7, 2.0) should be inside the quickstart polygon",
);
assert_eq!(poly.exterior().points().count(), 5);
assert_eq!(poly.interiors().count(), 0);
}