diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2020-05-28 14:41:22 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2020-06-24 10:02:23 -0400 |
commit | 82df66b852fd2e16f3ab5cc0b4bbf32034ee49db (patch) | |
tree | 26faf2084d1a02246935795d3ca2cd05c6aeb624 /src/coords.rs | |
parent | 911ec5008fd78d726cd62768069fa5dbfb4212c0 (diff) | |
download | acap-82df66b852fd2e16f3ab5cc0b4bbf32034ee49db.tar.xz |
coords: Implement coordinate spaces
Diffstat (limited to 'src/coords.rs')
-rw-r--r-- | src/coords.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/coords.rs b/src/coords.rs new file mode 100644 index 0000000..c43b7e9 --- /dev/null +++ b/src/coords.rs @@ -0,0 +1,113 @@ +//! Coordinate spaces. + +use crate::distance::{Distance, Value}; + +/// A coordinate space. +pub trait Coordinates { + /// The type of individual coordinates. + type Value: Value; + + /// Get the number of dims this point has. + fn dims(&self) -> usize; + + /// Get the `i`th coordinate of this point. + fn coord(&self, i: usize) -> Self::Value; + + /// Create a vector with this point's coordinates as values. + fn as_vec(&self) -> Vec<Self::Value> { + let len = self.dims(); + let mut vec = Vec::with_capacity(len); + for i in 0..len { + vec.push(self.coord(i)); + } + vec + } +} + +/// [Coordinates] implementation for slices. +impl<T: Value> Coordinates for [T] { + type Value = T; + + fn dims(&self) -> usize { + self.len() + } + + fn coord(&self, i: usize) -> T { + self[i] + } +} + +/// [Coordinates] implementation for arrays. +macro_rules! array_coordinates { + ($n:expr) => ( + impl<T: Value> Coordinates for [T; $n] { + type Value = T; + + fn dims(&self) -> usize { + $n + } + + fn coord(&self, i: usize) -> T { + self[i] + } + } + ); +} + +array_coordinates!(1); +array_coordinates!(2); +array_coordinates!(3); +array_coordinates!(4); +array_coordinates!(5); +array_coordinates!(6); +array_coordinates!(7); +array_coordinates!(8); + +/// [Coordinates] implemention for vectors. +impl<T: Value> Coordinates for Vec<T> { + type Value = T; + + fn dims(&self) -> usize { + self.len() + } + + fn coord(&self, i: usize) -> T { + self[i] + } +} + +/// Blanket [Coordinates] implementation for references. +impl<T: ?Sized + Coordinates> Coordinates for &T { + type Value = T::Value; + + fn dims(&self) -> usize { + (*self).dims() + } + + fn coord(&self, i: usize) -> Self::Value { + (*self).coord(i) + } +} + +/// Types that support computing distances to raw slices of coordinates. +pub trait CoordinateProximity<T> { + type Distance: Distance; + + /// Compute the distance to a point specified by its coordinates. + fn distance_to_coords(&self, coords: &[T]) -> Self::Distance; +} + +/// Blanket [CoordinateProximity] implementation for references. +impl<T: CoordinateProximity<U>, U> CoordinateProximity<U> for &T { + type Distance = T::Distance; + + fn distance_to_coords(&self, coords: &[U]) -> Self::Distance { + (*self).distance_to_coords(coords) + } +} + +/// Marker trait for coordinate proximities that are [metrics][crate::distance::Metric]. +pub trait CoordinateMetric<T>: CoordinateProximity<T> {} + +/// Blanket [CoordinateMetric] implementation for references. +impl<T: CoordinateMetric<U>, U> CoordinateMetric<U> for &T {} |