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

Adds Ewkt dialect #155

Merged
merged 15 commits into from
Aug 12, 2023
Merged

Adds Ewkt dialect #155

merged 15 commits into from
Aug 12, 2023

Conversation

Oreilles
Copy link
Contributor

@Oreilles Oreilles commented Aug 10, 2023

This PR adds:

  • enum WktDialect with options WktDialect::Wkt and WktDialect::Ewkt to wkt module
  • struct EwktString(pub String)
  • fn to_ewkt(&self, srid: Option<i32>) -> Result<String> to trait ToWkt
  • fn to_wkt_dialect(&self, dialect: WktDialect, dims: CoordDimensions, srid: Option<i32>) -> Result<String> to trait ToWkt

The trait FromWkb is implemented for EwktString so that the srid is inferred from the Wkb stream if available. The later is made possible by implementing GeomProcessor::srid for WktWriter and calling processor.srid(info.srid) in process_wkb_geom.

Side notes:

  • This PR only implements Ewkt write. Ewkt read should probably be implemented in the wkt crate.
  • Should we add ProcessToCsv::to_csv_ewkt and/or ProcessToCsv::to_csv_dialect?

@nyurik
Copy link
Member

nyurik commented Aug 10, 2023

TBH, I am not too happy about changing all of the APIs to force the user to always be WKT dialect aware. I would much rather keep the existing API, plus perhaps add a new constructor, e.g. keep the WktWriter::new(w: impl Write), and add another one like WktWriter::with_dialect(w: impl Write, dialect: WktDialect)?

@Oreilles
Copy link
Contributor Author

Sure, I changed the signature of the constructor for the sake of consistency with WkbWriter but I would definetly understand that an API change would not be acceptable.

@nyurik
Copy link
Member

nyurik commented Aug 10, 2023

oh, i didn't realize we already did it that way with WkbWriter... I'm a bit on a fence on this one then - ideally I would want Wkb to also be done the same way - WkbWriter::with_dialect(...), but I will let @pka to chime in on this one

@nyurik nyurik requested review from nyurik and pka August 10, 2023 06:11
Copy link
Member

@pka pka left a comment

Choose a reason for hiding this comment

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

I'm fine with changing the WktWriter-API. The ToWkt trait API should be kept compatible if possible, which is the case here.

Comments:

@Oreilles
Copy link
Contributor Author

Thanks for the review, I ran fmt and took example on the linked PR to remove the WktReader lifetime 👍

@nyurik
Copy link
Member

nyurik commented Aug 10, 2023

@Oreilles thx! Do you need help merging main branch into your PRs?

@Oreilles
Copy link
Contributor Author

I just rebased onto main and solved the few conflicts.

@nyurik nyurik requested a review from pka August 10, 2023 20:55
@pka
Copy link
Member

pka commented Aug 10, 2023

After discussing the PR with @nyurik, I'm also for keeping the WktWriter::new signature and adding a second method WktWriter::with_dialect. For WkbWriter the dialect is essential, but WKT users usually don't care and I don't want to force them to think about it. What's your use case of using EWKT? Can't remember anyone mentioning it for a long time.

Copy link
Member

@nyurik nyurik left a comment

Choose a reason for hiding this comment

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

I made a few suggestions in code. I think we shouldn't be removing the lifetime in the same PR - lets just figure out the dialects first, as it is not certain?

geozero/src/gdal/gdal_reader.rs Outdated Show resolved Hide resolved
/// Convert to WKT String with dimensions.
fn to_wkt_ndim(&self, dims: CoordDimensions) -> Result<String>;
/// Convert to WKT String with srid, dimensions and dialect.
fn to_wkt_dialect(
Copy link
Member

Choose a reason for hiding this comment

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

Technically this is more of a to_wkt_with_options or to_wkt_extended method, not just dialect... Naming is hard, we may want to bikeshed this one.... (note that I am still kinda uneasy about the new constructor now requiring an additional dialect param even though most of the users probably won't ever care about it, and plus it doesn't allow us to have a default

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually maybe we don't want a to_wkt_with_options ? Then to_ewkt would leave you no choice over the output dimensions, e.g. taking all those available. I hardly think of a use case where you'd want an EWKT output with less information. Maybe we can just remove to_wkt_dialect, and just leave to_wkt, to_wkt_ndim and to_ewkt.

Copy link
Member

Choose a reason for hiding this comment

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

I just hope the number of dialects don't explode :) to_ewkt and to_ewkt_ndim sounds fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, but since there is now three to_wkt flavour, that would imply a lot of code duplicate to remove to_wkt_dialect. So we might as well just find an appropriate name for it as you suggested. About the number of Wkt dialect... I discovered while working on this that Spatialite rejects POINT(1 2 3 4) as valid Wkt and will only accept POINTZM(1 2 3 4) so maybe a next PR to come ? 😅

Copy link
Member

Choose a reason for hiding this comment

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

sigh :) I think we may as well just use to_wkt_with_opts, and provide all those detalis. We may even want to get rid of the to_wkt_ndims to reduce the api surface (TBD)

I just really don't like the to_wkt_dialect because it actually has many more params than just the dialect one, making it confusing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, not sure what the best solution is here so I'll that one up to you..!

geozero/src/wkt/mod.rs Outdated Show resolved Hide resolved
@Oreilles
Copy link
Contributor Author

After discussing the PR with @nyurik, I'm also for keeping the WktWriter::new signature and adding a second method WktWriter::with_dialect. For WkbWriter the dialect is essential, but WKT users usually don't care and I don't want to force them to think about it.

That's understandable, I'll do the modification 👍

What's your use case of using EWKT ?

Even though it's not a standard, thanks to PostGIS success it's still quite common and (AFAIAA) is the only human-friendly geometry format that allows SRID declaration. It will be used as a user input format in a product I'm working on.

geozero/src/gdal/gdal_reader.rs Outdated Show resolved Hide resolved
/// Convert to WKT String with dimensions.
fn to_wkt_ndim(&self, dims: CoordDimensions) -> Result<String>;
/// Convert to WKT String with srid, dimensions and dialect.
fn to_wkt_dialect(
Copy link
Member

Choose a reason for hiding this comment

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

I just hope the number of dialects don't explode :) to_ewkt and to_ewkt_ndim sounds fine.

geozero/src/wkt/mod.rs Outdated Show resolved Hide resolved
let mut out: Vec<u8> = Vec::new();
let mut writer = WktWriter::with_dialect(&mut out, WktDialect::Ewkt);
writer.dims = CoordDimensions::xyzm();
crate::wkb::process_wkb_type_geom(rdr, &mut writer, dialect)?;
Copy link
Member

Choose a reason for hiding this comment

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

not sure if actionable, just checking if this is correct: both the writer and the processor need a dialect? And when reading, the processor cannot auto-detect the dialect, or can it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So an Ewkt string can be parsed from several Wkb dialects, which is why we need to pass it as a parameter. In the current implementation, no detection of the Wkb dialect is implemented; I guess it would be pretty tricky to do so, as they all have their own quirks.

Copy link
Member

@nyurik nyurik left a comment

Choose a reason for hiding this comment

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

seems like this one is ready to go once we settle on the to_wkt_X name... I think to_wkt_with_opts is the cleanest?

/// Convert to WKT String with dimensions.
fn to_wkt_ndim(&self, dims: CoordDimensions) -> Result<String>;
/// Convert to WKT String with srid, dimensions and dialect.
fn to_wkt_dialect(
Copy link
Member

Choose a reason for hiding this comment

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

sigh :) I think we may as well just use to_wkt_with_opts, and provide all those detalis. We may even want to get rid of the to_wkt_ndims to reduce the api surface (TBD)

I just really don't like the to_wkt_dialect because it actually has many more params than just the dialect one, making it confusing

@nyurik
Copy link
Member

nyurik commented Aug 11, 2023

I made a few more suggestions for this PR in Oreilles#2

  • rename to_wkt_dialect -> to_wkt_with_opts
  • make WktWriter content private! It's ridiculous to have write access to a writer from outside
  • introduce WktWriter::with_dims to allow creation of a writer with the needed params

nyurik and others added 3 commits August 12, 2023 00:38
* rename `to_wkt_dialect` -> to_wkt_with_opts`
* make `WktWriter` content private!  It's ridiculous to have write access to a writer from outside
* introduce `WktWriter::with_dims` to allow creation of a writer with the needed params
@pka pka merged commit 5e92027 into georust:main Aug 12, 2023
1 check passed
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.

3 participants