use extendr_api::prelude::*;
pub mod constructors;
pub mod esri;
pub mod fromsf;
pub mod sfg;
pub mod tosf;
pub mod vctrs;
use geo_types::{
Geometry, Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect,
};
use geo::BoundingRect;
use rstar::primitives::CachedEnvelope;
extendr_module! {
mod sfconversions;
impl Geom;
}
impl rstar::RTreeObject for Geom {
type Envelope = rstar::AABB<[f64; 2]>;
fn envelope(&self) -> Self::Envelope {
let bbox = self.geom.bounding_rect().unwrap();
let ll = bbox.min(); let ur = bbox.max(); rstar::AABB::from_corners(ll.into(), ur.into())
}
}
#[derive(Debug, Clone)]
#[extendr]
pub struct Geom {
pub geom: Geometry,
}
pub trait IntoGeom {
fn into_geom(self) -> Geom;
fn cached_envelope(self) -> CachedEnvelope<Geom>;
}
impl<T> IntoGeom for T
where
Geom: From<T>,
{
fn into_geom(self) -> Geom {
Geom::from(self)
}
fn cached_envelope(self) -> CachedEnvelope<Geom> {
CachedEnvelope::new(self.into())
}
}
#[extendr]
impl Geom {
pub fn print(&self) -> String {
let fstr = format!("{:?}", self.geom);
fstr.splitn(2, '(').nth(1).unwrap_or("").to_string()
}
}
impl From<Geometry> for Geom {
fn from(geo: Geometry) -> Self {
Geom { geom: geo }
}
}
impl From<Point> for Geom {
fn from(pnt: Point) -> Self {
let x: Geometry = pnt.into();
Geom { geom: x }
}
}
impl From<MultiPoint> for Geom {
fn from(pnt: MultiPoint) -> Self {
let x: Geometry = pnt.into();
Geom { geom: x }
}
}
impl From<Polygon> for Geom {
fn from(poly: Polygon) -> Self {
let x: Geometry = poly.into();
Geom { geom: x }
}
}
impl From<MultiPolygon> for Geom {
fn from(poly: MultiPolygon) -> Self {
let x: Geometry = poly.into();
Geom { geom: x }
}
}
impl From<LineString> for Geom {
fn from(lns: LineString) -> Self {
let x: Geometry = lns.into();
Geom { geom: x }
}
}
impl From<MultiLineString> for Geom {
fn from(lns: MultiLineString) -> Self {
let x: Geometry = lns.into();
Geom { geom: x }
}
}
impl From<Rect> for Geom {
fn from(r: Rect) -> Self {
let x: Geometry = r.into();
Geom { geom: x }
}
}
impl From<Line> for Geom {
fn from(l: Line) -> Self {
let x: Geometry = l.into();
Geom { geom: x }
}
}
impl From<Geom> for Polygon {
fn from(geom: Geom) -> Self {
let x = geom.geom;
let x: Polygon = x.try_into().unwrap();
x
}
}
impl From<Geom> for LineString {
fn from(geom: Geom) -> Self {
let x = geom.geom;
let x: LineString = x.try_into().unwrap();
x
}
}
impl From<Geom> for Point {
fn from(geom: Geom) -> Self {
let x = geom.geom;
let x: Point = x.try_into().unwrap();
x
}
}
impl From<Robj> for Geom {
fn from(robj: Robj) -> Self {
<&Geom>::try_from(&robj).unwrap().clone()
}
}
pub fn geoms_from_list(x: List) -> Vec<Option<Geom>> {
x.into_iter()
.map(|(_, robj)| {
if robj.is_null() {
None
} else {
Some(Geom::from(robj))
}
})
.collect::<Vec<Option<Geom>>>()
}
pub fn geoms_ref_from_list(x: List) -> Vec<Option<&'static Geom>> {
x.into_iter()
.map(|(_, robj)| {
if robj.is_null() {
None
} else {
Some(<&Geom>::try_from(&robj).unwrap())
}
})
.collect::<Vec<Option<&Geom>>>()
}
pub fn geometry_from_list(x: List) -> Vec<Option<Geometry>> {
x.into_iter()
.map(|(_, xi)| match <&Geom>::try_from(&xi) {
Ok(g) => Some(g.geom.clone()),
Err(_) => None,
})
.collect::<Vec<Option<Geometry>>>()
}