Expand description
Exchange vector geometries between Rust and Python using pyo3 and Pythons __geo_interface__
protocol.
The __geo_interface__
protocol is implemented by most popular geospatial python modules like shapely
, geojson
, geopandas
, ….
While this protocol also defines Features
and FeatureCollections
, this library so far only focuses on the Geometry
type, as
this one can be directly mapped to the types of the geo-types
crate.
The main struct of this crate is Geometry
. This the docs there for usage examples.
§Features
As rust types exposed to python may not have generic type parameters, there are multiple implementations of the Geometry
type based
on different types for the coordinate values. The default is f64
, other types can be enabled using the f32
, u8
, u16
, u32
, u64
,
i8
, i16
, i32
and i64
feature gates. The implementation are then available as py_geo_interface::wrappers::[datatype]::Geometry
.
The default and probably most common used f64
-variant is also available as py_geo_interface::Geometry
.
The wkb
feature adds support for exchanging geometries using the Well-Known-Binary format. The wkb
-property of shapely
geometries will be used when found. Additionally, the Geometry
-type exposed to python will have a wkb
-property
itself. WKB is only supported for the f64
-variant of the Geometry
, the feature is disabled per default.
§Examples
§Read python types implementing __geo_interface__
into geo-types
:
use geo_types::{Geometry as GtGeometry, Point};
use pyo3::{prepare_freethreaded_python, Python};
use py_geo_interface::Geometry;
prepare_freethreaded_python();
let geom = Python::with_gil(|py| {
// Define a python class implementing the geo_interface. This could also be a shapely or geojson
// object instead. These provide the same interface.
py.run(r#"
class Something:
@property
def __geo_interface__(self):
return {"type": "Point", "coordinates": [5., 3.]}
"#, None, None).unwrap();
// create an instance of the class and extract the geometry
py.eval(r#"Something()"#, None, None)?.extract::<Geometry>()
}).unwrap();
assert_eq!(geom.0, GtGeometry::Point(Point::new(5.0_f64, 3.0_f64)));
§Pass geometries from Rust to Python:
use geo_types::{Geometry as GtGeometry, Point};
use pyo3::{prepare_freethreaded_python, Python};
use pyo3::types::{PyDict, PyTuple};
use pyo3::IntoPy;
use py_geo_interface::Geometry;
prepare_freethreaded_python();
Python::with_gil(|py| {
let geom: Geometry = Point::new(10.6_f64, 23.3_f64).into();
let mut locals = PyDict::new(py);
locals.set_item("geom", geom.into_py(py)).unwrap();
py.run(r#"
assert geom.__geo_interface__["type"] == "Point"
assert geom.__geo_interface__["coordinates"] == (10.6, 23.3)
"#, None, Some(locals)).unwrap();
});
Re-exports§
pub use crate::wrappers::f64::Geometry;
pub use crate::wrappers::f64::GeometryVec;
pub use crate::wrappers::f64::GeometryVecFc;