Skip to content
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

Converter functions for geo-traits to geo-types #1255

Merged
merged 4 commits into from
Nov 15, 2024
Merged

Conversation

kylebarron
Copy link
Member

  • I agree to follow the project's code of conduct.
  • I added an entry to CHANGES.md if knowledge of this change could be valuable to users.

Closes #1253

if let Some(coord) = point.coord() {
Point(coord_to_geo(&coord))
} else {
panic!("converting empty point to geo not implemented")
Copy link
Member

@michaelkirk michaelkirk Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can panic from user input, it should be documented under a # Panics heading.

In general I wish we'd think harder about how to avoid panics. Please read my rant if you haven't already: #1244

In this case, how about returning an Option<Point<T>>. Note it would cascade to the to_geometry function as well.

If you think it's not worth it, then an alternative I'd be willing to move forward with would be to document these panics, and add non-panic versions that return Option: try_point_to_geo.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this panic is unfortunate and not ideal.

In this case, how about returning an Option<Point<T>>. Note it would cascade to the to_geometry function as well.

I'm open to this for to_point but I think it seems rather bad for to_geometry.

Perhaps the best way is to have panicking and non-panicking variants? 🤷‍♂️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, panicking and try_* non-packing variants seems like a good middleground.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added panicking and non-panicking variants

/// Convert any coordinate to a [`Coord`].
///
/// Only the first two dimensions will be kept.
pub fn coord_to_geo<T: CoordNum>(coord: &impl CoordTrait<T = T>) -> Coord<T> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these functions are exported from the to_geo mod, should we name it to_coord instead of coord_to_geo?

use geo_traits::to_geo;

to_geo::to_coord(...);
to_geo::to_point(...);

etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or should that be: to_geo::from_coord(some_coord_trait) 🤯😱💥

Copy link
Member

@michaelkirk michaelkirk Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, I don't really know. I do think your shorter name is better than what's there current and unlikely to be confusing in context (assuming the caller keeps the to_geo in scope).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either way. I don't have a preference. Maybe from_coord is preferable in the hope that some day in the future the traits are stable enough that we could have geo_types::Coord::from_coord?

Copy link
Member

@michaelkirk michaelkirk Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do that today if you introduced a trait:

in geo-traits crate:

impl FromPointTrait {
    fn from_point(point: impl PointTrait) -> Self;
}

impl FromPointTrait on geo::Point {
...
 }

And then also in other crates:

impl FromPointTrait for wkt::Point {
  ...
}

Then you could do things like:

let geo_point = geo::Point::new(1.0, 2.0);
let wkt_point = wkt::Point::from_point(geo_point);
let back_to_geo_point = geo::Point::from_point(wkt_point);

Is that useful? I dunno. For some formats it'd be a nice conversion muxer between formats. Though I don't know that it would work for all formats where there isn't a "standalone" structure for one geometry (e.g. converting something to a single standalone GeoArrow point might be weird, right?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've #1157 (comment) that I don't think the traits should necessarily provide a way to construct new objects. I think that should be implementation defined.

In any case, I'm not advocating for adding a new method to CoordTrait, like you were arguing against in that comment, but rather to add a new trait designating "This thing can be constructed from a impl geo-traits"

I think that's basically the From foil of what you're proposing in To form with ToGeoCoord.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that's an important distinction. Especially because the From could be optionally implemented and isn't a requirement to implement the trait.

Rather I could imagine a trait being defined like

I like that. I'm happy with either merging something like ToGeoCoord or to_coord as you previously phrased.

Happy to do whatever. Any preferences?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dealers choice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched to traits. Do you like this impl?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@kylebarron
Copy link
Member Author

@michaelkirk any thoughts?

@michaelkirk
Copy link
Member

I'm on holiday for a couple weeks so can't really look closely. The approach looks good though! I'm happy to see it merged if someone else approves.

@frewsxcv frewsxcv enabled auto-merge November 11, 2024 21:27
@kylebarron
Copy link
Member Author

I don't think this will merge until Michael removes his request for changes.

@frewsxcv frewsxcv requested review from michaelkirk and removed request for michaelkirk November 12, 2024 02:06
@michaelkirk michaelkirk dismissed their stale review November 12, 2024 03:23

unavailable

@frewsxcv frewsxcv added this pull request to the merge queue Nov 12, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 12, 2024
@frewsxcv
Copy link
Member

Ugh is main broken again

@urschrei
Copy link
Member

It's failing on Clippy due to deprecations and a JTS overlay test, both related to i_overlay, which had a release (1.8) yesterday. We were on 1.7.2

@frewsxcv frewsxcv added this pull request to the merge queue Nov 14, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 14, 2024
@urschrei
Copy link
Member

@frewsxcv i_overlay 1.8 was breaking (I think intentionally), so we can't merge til we either pin to 1.72, or adapt the converter module to the new API.

@kylebarron
Copy link
Member Author

adapt the converter module to the new API.

I don't think anything in this PR touches i_overlay?

@urschrei
Copy link
Member

adapt the converter module to the new API.

I don't think anything in this PR touches i_overlay?

Sorry, I meant the boolops module that handles interaction with i_overlay!

@frewsxcv frewsxcv enabled auto-merge November 15, 2024 19:27
@frewsxcv frewsxcv added this pull request to the merge queue Nov 15, 2024
Merged via the queue into main with commit 896ea04 Nov 15, 2024
18 checks passed
@frewsxcv frewsxcv deleted the kyle/traits-to-geo branch November 15, 2024 19:33
@kylebarron
Copy link
Member Author

In this PR, we had the choice of whether to go with free functions or a trait-based approach and I chose the trait-based approach because it seemed like a cleaner API. Unfortunately, using the trait-based API with GeometryTrait and GeometryCollectionTrait hits this compiler regression: rust-lang/rust#128887, rust-lang/rust#131960

One way to get around that bug is to use the nightly compiler with RUSTFLAGS="-Zinline-mir=no". But that requires the nightly compiler, which is annoying to enforce. So in geoarrow/geoarrow-rs#956 I removed my use of ToGeoGeometry and ToGeoGeometryCollection, replacing them with free functions instead, which allows us to side step the upstream compiler bug and compile normally in release mode.

kylebarron added a commit to geoarrow/geoarrow-rs that referenced this pull request Dec 20, 2024
Closes #716. Ref
georust/geo#1255 (comment).

Note that this is the same underlying implementation as upstream geo in
<georust/geo#1255>. However, the trait-based
implementation hits this compiler regression
<rust-lang/rust#128887>,
<rust-lang/rust#131960>, which prevents from
compiling in release mode on a stable Rust version. For some reason, the
**function-based implementation** does not hit this regression, and thus
allows building geoarrow without using latest nightly and a custom
`RUSTFLAGS`.

Note that it's only `GeometryTrait` and `GeometryCollectionTrait` that
hit this compiler bug.
Other traits can use the upstream impls.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Convert geo-traits objects to geo objects
4 participants