Skip to content

Commit

Permalink
generalize macro
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelkirk committed Oct 30, 2024
1 parent ba1cf70 commit 348f622
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 25 deletions.
15 changes: 15 additions & 0 deletions geo/src/algorithm/line_measures/distance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,18 @@ pub trait Distance<F, Origin, Destination> {
/// - returns: depends on the trait implementation.
fn distance(origin: Origin, destination: Destination) -> F;
}

// Distance is a symmetric operation, so we can implement it once for both
macro_rules! symmetric_distance_impl {
($a:ty, $b:ty, for: $metric_space: ty, where: $($bound:tt)+) => {
impl<F> $crate::Distance<F, $a, $b> for $metric_space
where
F: $($bound)+,
{
fn distance(a: $a, b: $b) -> F {
Self::distance(b, a)
}
}
};
}
pub(crate) use symmetric_distance_impl;
35 changes: 11 additions & 24 deletions geo/src/algorithm/line_measures/metric_spaces/euclidean/distance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,12 @@ use super::{Distance, Euclidean};
use crate::algorithm::Intersects;
use crate::coordinate_position::{coord_pos_relative_to_ring, CoordPos};
use crate::geometry::*;
use crate::line_measures::distance::symmetric_distance_impl;
use crate::{CoordFloat, GeoFloat, GeoNum};
use num_traits::{Bounded, Float};
use rstar::primitives::CachedEnvelope;
use rstar::RTree;

// Distance is a symmetric operation, so we can implement it once for both
macro_rules! symmetric_distance_impl {
($t:ident, $a:ty, $b:ty) => {
impl<F> $crate::Distance<F, $a, $b> for Euclidean
where
F: $t,
{
fn distance(a: $a, b: $b) -> F {
Self::distance(b, a)
}
}
};
}

// ┌───────────────────────────┐
// │ Implementations for Coord │
// └───────────────────────────┘
Expand Down Expand Up @@ -124,8 +111,8 @@ impl<F: GeoFloat> Distance<F, &Point<F>, &Polygon<F>> for Euclidean {
// │ Implementations for Line │
// └──────────────────────────┘

symmetric_distance_impl!(CoordFloat, &Line<F>, Coord<F>);
symmetric_distance_impl!(CoordFloat, &Line<F>, &Point<F>);
symmetric_distance_impl!(&Line<F>, Coord<F>, for: Euclidean, where: CoordFloat);
symmetric_distance_impl!(&Line<F>, &Point<F>, for: Euclidean, where: CoordFloat);

impl<F: GeoFloat> Distance<F, &Line<F>, &Line<F>> for Euclidean {
fn distance(line_a: &Line<F>, line_b: &Line<F>) -> F {
Expand Down Expand Up @@ -169,8 +156,8 @@ impl<F: GeoFloat> Distance<F, &Line<F>, &Polygon<F>> for Euclidean {
// │ Implementations for LineString │
// └────────────────────────────────┘

symmetric_distance_impl!(CoordFloat, &LineString<F>, &Point<F>);
symmetric_distance_impl!(GeoFloat, &LineString<F>, &Line<F>);
symmetric_distance_impl!(&LineString<F>, &Point<F>, for: Euclidean, where: CoordFloat);
symmetric_distance_impl!(&LineString<F>, &Line<F>, for: Euclidean, where: GeoFloat);

impl<F: GeoFloat> Distance<F, &LineString<F>, &LineString<F>> for Euclidean {
fn distance(line_string_a: &LineString<F>, line_string_b: &LineString<F>) -> F {
Expand Down Expand Up @@ -206,9 +193,9 @@ impl<F: GeoFloat> Distance<F, &LineString<F>, &Polygon<F>> for Euclidean {
// │ Implementations for Polygon │
// └─────────────────────────────┘

symmetric_distance_impl!(GeoFloat, &Polygon<F>, &Point<F>);
symmetric_distance_impl!(GeoFloat, &Polygon<F>, &Line<F>);
symmetric_distance_impl!(GeoFloat, &Polygon<F>, &LineString<F>);
symmetric_distance_impl!(&Polygon<F>, &Point<F>, for: Euclidean, where: GeoFloat);
symmetric_distance_impl!(&Polygon<F>, &Line<F>, for: Euclidean, where: GeoFloat);
symmetric_distance_impl!(&Polygon<F>, &LineString<F>, for: Euclidean, where: GeoFloat);
impl<F: GeoFloat> Distance<F, &Polygon<F>, &Polygon<F>> for Euclidean {
fn distance(polygon_a: &Polygon<F>, polygon_b: &Polygon<F>) -> F {
if polygon_a.intersects(polygon_b) {
Expand Down Expand Up @@ -259,7 +246,7 @@ macro_rules! impl_euclidean_distance_for_polygonlike_geometry {
Self::distance(&polygonlike.to_polygon(), geometry_b)
}
}
symmetric_distance_impl!(GeoFloat, $geometry_b, $polygonlike);
symmetric_distance_impl!($geometry_b, $polygonlike, for: Euclidean, where: GeoFloat);
)*
};
}
Expand Down Expand Up @@ -293,7 +280,7 @@ macro_rules! impl_euclidean_distance_for_iter_geometry {
})
}
}
symmetric_distance_impl!(GeoFloat, $to_geometry, $iter_geometry);
symmetric_distance_impl!($to_geometry, $iter_geometry, for: Euclidean, where: GeoFloat);
)*
};
}
Expand Down Expand Up @@ -327,7 +314,7 @@ macro_rules! impl_euclidean_distance_for_geometry_and_variant {
}
}
}
symmetric_distance_impl!(GeoFloat, &Geometry<F>, $target);
symmetric_distance_impl!(&Geometry<F>, $target, for: Euclidean, where: GeoFloat);
)*
};
}
Expand Down
10 changes: 9 additions & 1 deletion geo/src/algorithm/line_measures/metric_spaces/haversine.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use num_traits::FromPrimitive;

use super::super::{Bearing, Destination, Distance, InterpolatePoint};
use crate::line_measures::distance::symmetric_distance_impl;
use crate::utils::normalize_longitude;
use crate::{CoordFloat, Point, MEAN_EARTH_RADIUS};
use crate::{CoordFloat, Line, Point, MEAN_EARTH_RADIUS};

/// A spherical model of the earth using the [haversine formula].
///
Expand Down Expand Up @@ -151,6 +152,13 @@ impl<F: CoordFloat + FromPrimitive> Distance<F, Point<F>, Point<F>> for Haversin
}
}

impl<F: CoordFloat + FromPrimitive> Distance<F, Line<F>, Point<F>> for Haversine {
fn distance(origin: Line<F>, destination: Point<F>) -> F {
todo!()
}
}
symmetric_distance_impl!(Point<F>, Line<F>, for: Haversine, where: CoordFloat + FromPrimitive);

/// Interpolate Point(s) along a [great circle].
///
/// [great circle]: https://en.wikipedia.org/wiki/Great_circle
Expand Down

0 comments on commit 348f622

Please sign in to comment.