extern crate geo_types;
use std::fmt;
use types::*;
use Geometry;
#[derive(Debug)]
pub enum Error {
PointConversionError,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::PointConversionError => {
f.write_str("impossible to convert empty point to geo_type point")
}
}
}
}
fn try_into_point(point: &Point) -> Result<geo_types::Geometry<f64>, Error> {
match point.0 {
Some(ref c) => {
let geo_point: geo_types::Point<f64> = (c.x, c.y).into();
Ok(geo_point.into())
}
None => Err(Error::PointConversionError),
}
}
pub fn try_into_geometry(geometry: &Geometry) -> Result<geo_types::Geometry<f64>, Error> {
match geometry {
Geometry::Point(point) => try_into_point(point),
Geometry::LineString(linestring) => Ok(linestring.into()),
Geometry::Polygon(polygon) => Ok(polygon.into()),
Geometry::MultiLineString(multilinestring) => Ok(multilinestring.into()),
Geometry::MultiPoint(multipoint) => Ok(multipoint.into()),
Geometry::MultiPolygon(multipolygon) => Ok(multipolygon.into()),
Geometry::GeometryCollection(geometrycollection) => {
try_into_geometry_collection(geometrycollection)
}
}
}
impl<'a> From<&'a LineString> for geo_types::Geometry<f64> {
fn from(linestring: &LineString) -> Self {
let geo_linestring: geo_types::LineString<f64> =
linestring.0.iter().map(|c| (c.x, c.y)).collect();
geo_linestring.into()
}
}
impl<'a> From<&'a MultiLineString> for geo_types::Geometry<f64> {
fn from(multilinestring: &MultiLineString) -> Self {
let geo_multilinestring: geo_types::MultiLineString<f64> = multilinestring
.0
.iter()
.map(|l| l.0.iter().map(|c| (c.x, c.y)).collect::<Vec<_>>())
.collect();
geo_multilinestring.into()
}
}
fn w_polygon_to_g_polygon(polygon: &Polygon) -> geo_types::Polygon<f64> {
let mut iter = polygon
.0
.iter()
.map(|l| l.0.iter().map(|c| (c.x, c.y)).collect::<Vec<_>>().into());
match iter.next() {
Some(interior) => geo_types::Polygon::new(interior, iter.collect()),
None => geo_types::Polygon::new(geo_types::LineString(vec![]), vec![]),
}
}
impl<'a> From<&'a Polygon> for geo_types::Geometry<f64> {
fn from(polygon: &Polygon) -> Self {
w_polygon_to_g_polygon(polygon).into()
}
}
impl<'a> From<&'a MultiPoint> for geo_types::Geometry<f64> {
fn from(multipoint: &MultiPoint) -> Self {
let geo_multipoint: geo_types::MultiPoint<f64> = multipoint
.0
.iter()
.filter_map(|p| p.0.as_ref())
.map(|c| (c.x, c.y))
.collect();
geo_multipoint.into()
}
}
impl<'a> From<&'a MultiPolygon> for geo_types::Geometry<f64> {
fn from(multipolygon: &MultiPolygon) -> Self {
let geo_multipolygon: geo_types::MultiPolygon<f64> = multipolygon
.0
.iter()
.map(|p| w_polygon_to_g_polygon(p))
.collect();
geo_multipolygon.into()
}
}
pub fn try_into_geometry_collection(
geometrycollection: &GeometryCollection,
) -> Result<geo_types::Geometry<f64>, Error> {
let geo_geometrycollection: geo_types::GeometryCollection<f64> = geometrycollection
.0
.iter()
.map(|g| try_into_geometry(g))
.collect::<Result<_, _>>()?;
Ok(geo_types::Geometry::GeometryCollection(
geo_geometrycollection,
))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn convert_empty_point() {
let point = Point(None).as_item();
assert!(try_into_geometry(&point).is_err());
}
#[test]
fn convert_point() {
let point = Point(Some(Coord {
x: 10.,
y: 20.,
z: None,
m: None,
})).as_item();
let g_point: geo_types::Point<f64> = (10., 20.).into();
assert_eq!(
geo_types::Geometry::Point(g_point),
try_into_geometry(&point).unwrap()
);
}
#[test]
fn convert_empty_linestring() {
let w_linestring = LineString(vec![]).as_item();
let g_linestring: geo_types::LineString<f64> = geo_types::LineString(vec![]);
assert_eq!(
geo_types::Geometry::LineString(g_linestring),
try_into_geometry(&w_linestring).unwrap()
);
}
#[test]
fn convert_linestring() {
let w_linestring = LineString(vec![
Coord {
x: 10.,
y: 20.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 40.,
z: None,
m: None,
},
]).as_item();
let g_linestring: geo_types::LineString<f64> = vec![(10., 20.), (30., 40.)].into();
assert_eq!(
geo_types::Geometry::LineString(g_linestring),
try_into_geometry(&w_linestring).unwrap()
);
}
#[test]
fn convert_empty_polygon() {
let w_polygon = Polygon(vec![]).as_item();
let g_polygon: geo_types::Polygon<f64> =
geo_types::Polygon::new(geo_types::LineString(vec![]), vec![]);
assert_eq!(
geo_types::Geometry::Polygon(g_polygon),
try_into_geometry(&w_polygon).unwrap()
);
}
#[test]
fn convert_polygon() {
let w_polygon = Polygon(vec![
LineString(vec![
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
]),
LineString(vec![
Coord {
x: 5.,
y: 5.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 30.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 5.,
z: None,
m: None,
},
Coord {
x: 5.,
y: 5.,
z: None,
m: None,
},
]),
]).as_item();
let g_polygon: geo_types::Polygon<f64> = geo_types::Polygon::new(
vec![(0., 0.), (20., 40.), (40., 0.), (0., 0.)].into(),
vec![vec![(5., 5.), (20., 30.), (30., 5.), (5., 5.)].into()],
);
assert_eq!(
geo_types::Geometry::Polygon(g_polygon),
try_into_geometry(&w_polygon).unwrap()
);
}
#[test]
fn convert_empty_multilinestring() {
let w_multilinestring = MultiLineString(vec![]).as_item();
let g_multilinestring: geo_types::MultiLineString<f64> = geo_types::MultiLineString(vec![]);
assert_eq!(
geo_types::Geometry::MultiLineString(g_multilinestring),
try_into_geometry(&w_multilinestring).unwrap()
);
}
#[test]
fn convert_multilinestring() {
let w_multilinestring = MultiLineString(vec![
LineString(vec![
Coord {
x: 10.,
y: 20.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 40.,
z: None,
m: None,
},
]),
LineString(vec![
Coord {
x: 50.,
y: 60.,
z: None,
m: None,
},
Coord {
x: 70.,
y: 80.,
z: None,
m: None,
},
]),
]).as_item();
let g_multilinestring: geo_types::MultiLineString<f64> = geo_types::MultiLineString(vec![
vec![(10., 20.), (30., 40.)].into(),
vec![(50., 60.), (70., 80.)].into(),
]);
assert_eq!(
geo_types::Geometry::MultiLineString(g_multilinestring),
try_into_geometry(&w_multilinestring).unwrap()
);
}
#[test]
fn convert_empty_multipoint() {
let w_multipoint = MultiPoint(vec![]).as_item();
let g_multipoint: geo_types::MultiPoint<f64> = geo_types::MultiPoint(vec![]);
assert_eq!(
geo_types::Geometry::MultiPoint(g_multipoint),
try_into_geometry(&w_multipoint).unwrap()
);
}
#[test]
fn convert_multipoint() {
let w_multipoint = MultiPoint(vec![
Point(Some(Coord {
x: 10.,
y: 20.,
z: None,
m: None,
})),
Point(Some(Coord {
x: 30.,
y: 40.,
z: None,
m: None,
})),
]).as_item();
let g_multipoint: geo_types::MultiPoint<f64> = vec![(10., 20.), (30., 40.)].into();
assert_eq!(
geo_types::Geometry::MultiPoint(g_multipoint),
try_into_geometry(&w_multipoint).unwrap()
);
}
#[test]
fn convert_empty_multipolygon() {
let w_multipolygon = MultiPolygon(vec![]).as_item();
let g_multipolygon: geo_types::MultiPolygon<f64> = geo_types::MultiPolygon(vec![]);
assert_eq!(
geo_types::Geometry::MultiPolygon(g_multipolygon),
try_into_geometry(&w_multipolygon).unwrap()
);
}
#[test]
fn convert_multipolygon() {
let w_multipolygon = MultiPolygon(vec![
Polygon(vec![
LineString(vec![
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
]),
LineString(vec![
Coord {
x: 5.,
y: 5.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 30.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 5.,
z: None,
m: None,
},
Coord {
x: 5.,
y: 5.,
z: None,
m: None,
},
]),
]),
Polygon(vec![LineString(vec![
Coord {
x: 40.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 45.,
z: None,
m: None,
},
Coord {
x: 45.,
y: 30.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 40.,
z: None,
m: None,
},
])]),
]).as_item();
let g_multipolygon: geo_types::MultiPolygon<f64> = geo_types::MultiPolygon(vec![
geo_types::Polygon::new(
vec![(0., 0.), (20., 40.), (40., 0.), (0., 0.)].into(),
vec![vec![(5., 5.), (20., 30.), (30., 5.), (5., 5.)].into()],
),
geo_types::Polygon::new(
vec![(40., 40.), (20., 45.), (45., 30.), (40., 40.)].into(),
vec![],
),
]);
assert_eq!(
geo_types::Geometry::MultiPolygon(g_multipolygon),
try_into_geometry(&w_multipolygon).unwrap()
);
}
#[test]
fn convert_empty_geometrycollection() {
let w_geometrycollection = GeometryCollection(vec![]).as_item();
let g_geometrycollection: geo_types::GeometryCollection<f64> =
geo_types::GeometryCollection(vec![]);
assert_eq!(
geo_types::Geometry::GeometryCollection(g_geometrycollection),
try_into_geometry(&w_geometrycollection).unwrap()
);
}
#[test]
fn convert_geometrycollection() {
let w_point = Point(Some(Coord {
x: 10.,
y: 20.,
z: None,
m: None,
})).as_item();
let w_linestring = LineString(vec![
Coord {
x: 10.,
y: 20.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 40.,
z: None,
m: None,
},
]).as_item();
let w_polygon = Polygon(vec![LineString(vec![
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
])]).as_item();
let w_multilinestring = MultiLineString(vec![
LineString(vec![
Coord {
x: 10.,
y: 20.,
z: None,
m: None,
},
Coord {
x: 30.,
y: 40.,
z: None,
m: None,
},
]),
LineString(vec![
Coord {
x: 50.,
y: 60.,
z: None,
m: None,
},
Coord {
x: 70.,
y: 80.,
z: None,
m: None,
},
]),
]).as_item();
let w_multipoint = MultiPoint(vec![
Point(Some(Coord {
x: 10.,
y: 20.,
z: None,
m: None,
})),
Point(Some(Coord {
x: 30.,
y: 40.,
z: None,
m: None,
})),
]).as_item();
let w_multipolygon = MultiPolygon(vec![
Polygon(vec![LineString(vec![
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 0.,
z: None,
m: None,
},
Coord {
x: 0.,
y: 0.,
z: None,
m: None,
},
])]),
Polygon(vec![LineString(vec![
Coord {
x: 40.,
y: 40.,
z: None,
m: None,
},
Coord {
x: 20.,
y: 45.,
z: None,
m: None,
},
Coord {
x: 45.,
y: 30.,
z: None,
m: None,
},
Coord {
x: 40.,
y: 40.,
z: None,
m: None,
},
])]),
]).as_item();
let w_geometrycollection = GeometryCollection(vec![
w_point,
w_multipoint,
w_linestring,
w_multilinestring,
w_polygon,
w_multipolygon,
]).as_item();
let g_point: geo_types::Point<f64> = (10., 20.).into();
let g_linestring: geo_types::LineString<f64> = vec![(10., 20.), (30., 40.)].into();
let g_polygon: geo_types::Polygon<f64> = geo_types::Polygon::new(
vec![(0., 0.), (20., 40.), (40., 0.), (0., 0.)].into(),
vec![],
);
let g_multilinestring: geo_types::MultiLineString<f64> = geo_types::MultiLineString(vec![
vec![(10., 20.), (30., 40.)].into(),
vec![(50., 60.), (70., 80.)].into(),
]);
let g_multipoint: geo_types::MultiPoint<f64> = vec![(10., 20.), (30., 40.)].into();
let g_multipolygon: geo_types::MultiPolygon<f64> = geo_types::MultiPolygon(vec![
geo_types::Polygon::new(
vec![(0., 0.), (20., 40.), (40., 0.), (0., 0.)].into(),
vec![],
),
geo_types::Polygon::new(
vec![(40., 40.), (20., 45.), (45., 30.), (40., 40.)].into(),
vec![],
),
]);
let g_geometrycollection: geo_types::GeometryCollection<f64> =
geo_types::GeometryCollection(vec![
geo_types::Geometry::Point(g_point),
geo_types::Geometry::MultiPoint(g_multipoint),
geo_types::Geometry::LineString(g_linestring),
geo_types::Geometry::MultiLineString(g_multilinestring),
geo_types::Geometry::Polygon(g_polygon),
geo_types::Geometry::MultiPolygon(g_multipolygon),
]);
assert_eq!(
geo_types::Geometry::GeometryCollection(g_geometrycollection),
try_into_geometry(&w_geometrycollection).unwrap()
);
}
}