-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rudimentary support for geopandas geoseries #5
Conversation
This is not at all qualified for public use, but it was a quick (and ugly) hack to support either pub(crate) trait GeoCollect {
fn collect_geom(&self) -> Result<Vec<Geometry<f64>>>;
}
#[derive(FromPyObject, Debug)]
struct Feat {
#[pyo3(item)]
geometry: GeoInterface,
}
#[derive(FromPyObject, Debug)]
struct FeatColl {
#[pyo3(item)]
features: Vec<Feat>,
}
impl GeoCollect for FeatColl {
fn collect_geom(&self) -> Result<Vec<Geometry<f64>>> {
Ok(self.features.iter().map(|f| f.geometry.0.to_owned()).collect())
}
}
#[derive(FromPyObject, Debug)]
struct GeoProto {
__geo_interface__: FeatColl,
}
impl GeoCollect for GeoProto {
fn collect_geom(&self) -> Result<Vec<Geometry<f64>>> {
self.__geo_interface__.collect_geom()
}
}
#[derive(FromPyObject, Debug)]
enum DynamicGeom {
Proto(GeoProto),
FC(FeatColl),
}
impl GeoCollect for DynamicGeom {
fn collect_geom(&self) -> Result<Vec<Geometry<f64>>> {
match self {
DynamicGeom::Proto(coll) => coll.collect_geom(),
DynamicGeom::FC(coll) => coll.collect_geom()
}
}
}
#[derive(Debug)]
struct PyGeoms(pub Vec<Geometry<f64>>);
impl FromPyObject<'_> for PyGeoms {
fn extract(obj: &'_ PyAny) -> PyResult<Self> {
let geo: DynamicGeom = obj.extract()?;
let geo = geo.collect_geom();
geo.map(PyGeoms).map_err(Into::into)
}
}
#[derive(FromPyObject, Debug)]
/// NewType for Python object assumed to be a GeoPandas DataFrame or Series.
pub(crate) struct GeoDataFrame(PyObject);
impl GeoCollect for GeoDataFrame {
fn collect_geom(&self) -> Result<Vec<Geometry<f64>>> {
let g = Python::with_gil(|py| {
self.0.extract::<PyGeoms>(py)
});
g.map(|p| p.0).map_err(Into::into)
}
} |
src/lib.rs
Outdated
@@ -72,6 +72,9 @@ pub mod from_py; | |||
pub mod to_py; | |||
pub mod wrappers; | |||
|
|||
#[cfg(feature = "f64")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider this being a different feature flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the f64 feature as usescase of geopandas use the f64 coordinates anyways. The second thought was that this implementation would not cause much compilation overhead anyways, so I omitted creating an own feature for it.
Nice - looks good 👍 I also removed the wrapping into GeoInterface for the individual geometries later, but have not yet pushed/commited that. Would you thing it would be helpful for users to have the Feature and FeatureCollection wrappers available in this library? I would think it would help to get started. Especially as the wording in the Readme is not really clear that in reality only geometries are supported currently and not the complete geo-interface spec. |
I think something like them might be helpful, but if it were me I'd want to be careful in indicating it's not true However, the |
PS: Have you considered getting your crate listed here: https://georust.org/ ? I think it deserves to be 😄 |
I forked the project and was going to poke at it myself, but it doesn't look like you use |
Thats a good point. When I created this I had only passing single geometries between the two languages in the scope as I only needed that. I should make that clear in the readme. Supporting the whole spec is quite a bit more - did not remember that CRS is also part of this. Using Regarding submitting this project to georust: My thought was waiting a bit if the project gets any usage in the community to see if it is something of general interest. Glad you like it. Doesn`t maturin only help when building python extensions? I do not have any special setup in my environment, maybe what you are encountering is Mac-specific, CI and myself are using Linux. Something similar - but without solution - is here. Maybe there is a better way to use pyo3 from inside the unittests than what I am doing. At least on Mac the test binaries do not seem to be linked as expected. |
With #6 the tests hopefully work now when running using |
Yep... pretty sure that's it. Some combination of that, and trying to use a sandboxed python environment (conda in my case). Looks suspiciously similar to what you referenced as well as this open issue :/. In my other code I am writing an extension, so |
I'm not sure that is the case here, as the |
I probably overstated the complexity implied by that part of the support. it's basically just a (oddly formatted) string in GeoJson with weak support in most tooling anyway. |
FWIW, I have tests running after adding |
Glad you got the tests to work. Such linking issues are always annoying. I think I want to avoid more dependencies for now if possible - All other parts of the spec can be added when the need arises. |
@@ -2,6 +2,11 @@ | |||
|
|||
## Unreleased | |||
|
|||
* Rename `GeometryInterface` struct to `Geometry` - that is the last rename of this struct - promised. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, its is impossible to pack everything into a name ;)
Fixes #4