1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use crate::algorithm::broadcasting::BroadcastablePrimitive;
use crate::array::*;
use arrow_array::types::Float64Type;
use arrow_array::OffsetSizeTrait;
use geo::Translate as _Translate;
pub trait Translate {
/// Translate a Geometry along its axes by the given offsets
///
/// ## Performance
///
/// If you will be performing multiple transformations, like
/// [`Scale`](crate::algorithm::geo::Scale), [`Skew`](crate::algorithm::geo::Skew),
/// [`Translate`](crate::algorithm::geo::Translate), or
/// [`Rotate`](crate::algorithm::geo::Rotate), it is more efficient to compose the
/// transformations and apply them as a single operation using the
/// [`AffineOps`](crate::algorithm::geo::AffineOps) trait.
///
/// # Examples
///
/// ```
/// use geo::Translate;
/// use geo::line_string;
///
/// let ls = line_string![
/// (x: 0.0, y: 0.0),
/// (x: 5.0, y: 5.0),
/// (x: 10.0, y: 10.0),
/// ];
///
/// let translated = ls.translate(1.5, 3.5);
///
/// assert_eq!(translated, line_string![
/// (x: 1.5, y: 3.5),
/// (x: 6.5, y: 8.5),
/// (x: 11.5, y: 13.5),
/// ]);
/// ```
#[must_use]
fn translate(
&self,
x_offset: BroadcastablePrimitive<Float64Type>,
y_offset: BroadcastablePrimitive<Float64Type>,
) -> Self;
// /// Translate a Geometry along its axes, but in place.
// fn translate_mut(&mut self, x_offset: T, y_offset: T);
}
// Note: this can't (easily) be parameterized in the macro because PointArray is not generic over O
impl Translate for PointArray {
fn translate(
&self,
x_offset: BroadcastablePrimitive<Float64Type>,
y_offset: BroadcastablePrimitive<Float64Type>,
) -> Self {
let output_geoms: Vec<Option<geo::Point>> = self
.iter_geo()
.zip(&x_offset)
.zip(&y_offset)
.map(|((maybe_g, x_offset), y_offset)| {
maybe_g.map(|geom| geom.translate(x_offset.unwrap(), y_offset.unwrap()))
})
.collect();
output_geoms.into()
}
}
/// Implementation that iterates over geo objects
macro_rules! iter_geo_impl {
($type:ty, $geo_type:ty) => {
impl<O: OffsetSizeTrait> Translate for $type {
fn translate(
&self,
x_offset: BroadcastablePrimitive<Float64Type>,
y_offset: BroadcastablePrimitive<Float64Type>,
) -> Self {
let output_geoms: Vec<Option<$geo_type>> = self
.iter_geo()
.zip(x_offset.into_iter())
.zip(y_offset.into_iter())
.map(|((maybe_g, x_offset), y_offset)| {
maybe_g.map(|geom| geom.translate(x_offset.unwrap(), y_offset.unwrap()))
})
.collect();
output_geoms.into()
}
}
};
}
iter_geo_impl!(LineStringArray<O>, geo::LineString);
iter_geo_impl!(PolygonArray<O>, geo::Polygon);
iter_geo_impl!(MultiPointArray<O>, geo::MultiPoint);
iter_geo_impl!(MultiLineStringArray<O>, geo::MultiLineString);
iter_geo_impl!(MultiPolygonArray<O>, geo::MultiPolygon);
iter_geo_impl!(WKBArray<O>, geo::Geometry);
impl<O: OffsetSizeTrait> Translate for GeometryArray<O> {
crate::geometry_array_delegate_impl! {
fn translate(
&self,
x_offset: BroadcastablePrimitive<Float64Type>,
y_offset: BroadcastablePrimitive<Float64Type>
) -> Self;
}
}