d3_geo_rs/clip/
compare_intersection.rs

1use core::cell::RefCell;
2use core::cmp::Ordering;
3use std::rc::Rc;
4
5use geo::CoordFloat;
6use num_traits::FloatConst;
7
8use crate::clip::rejoin::CompareIntersectionsFn;
9use crate::math::EPSILON;
10
11use super::intersection::Intersection;
12
13/// Intersections are sorted along the clip edge. For both antimeridian cutting
14/// and circle clipping, the same comparison is used.
15///
16/// # Panics
17/// `unwrap()` is used here but a panic will never happen as EPSILON will always be converted into T.
18#[must_use]
19pub(super) fn gen_compare<T>() -> CompareIntersectionsFn<T>
20where
21    T: 'static + CoordFloat + FloatConst,
22{
23    let epsilon = T::from(EPSILON).unwrap();
24    Box::new(
25        move |a: &Rc<RefCell<Intersection<T>>>,
26              b: &Rc<RefCell<Intersection<T>>>|
27              -> Ordering {
28            let ax = a.borrow().x;
29            let part1 = if ax.p.x < T::zero() {
30                ax.p.y - T::FRAC_PI_2() - epsilon
31            } else {
32                T::FRAC_PI_2() - ax.p.y
33            };
34            let bx = b.borrow().x;
35
36            let part2 = if bx.p.x < T::zero() {
37                bx.p.y - T::FRAC_PI_2() - epsilon
38            } else {
39                T::FRAC_PI_2() - bx.p.y
40            };
41
42            let diff = part1 - part2;
43            if diff > T::zero() {
44                Ordering::Greater
45            } else if diff < T::zero() {
46                Ordering::Less
47            } else {
48                Ordering::Equal
49            }
50        },
51    )
52}