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

Collection-based CAPI for coverage operations #867

Closed
wants to merge 9 commits into from

Conversation

pramsey
Copy link
Member

@pramsey pramsey commented Apr 12, 2023

Exposing three coverage functions (global is-valid, is-valid with result collection, and simplify with result collection) using geometry collection as the input and output type.

@dbaston
Copy link
Member

dbaston commented Apr 12, 2023

I'm thinking about the use use of "is this coverage valid? if not, give me the error locations." Currently that would require performing the validation twice, or requesting the errors and scanning it to see if any is non-empty.

Here is a signature that could accommodate the above scenario more directly, without creating a new object type. I'm not sure if I like it or not, curious what others think.

// return 1 if the coverage if the coverage is valid, 0 if it is invalid, 2 on error
// if coverage is invalid, and `errors` is not NULL, 
//`*errors` will point to a collection with the same number of elements as `cov`, providing the
// locations of errors associated with each element of `cov`
int GEOSCoverageIsValid(GEOSGeometry* cov, double gapWidth, GEOSGeometry** errors)

Another idea that I don't love is to have GEOSCoverageValid return an empty geometry if the coverage is valid (as opposed to a collection of invalid geometries).

@pramsey
Copy link
Member Author

pramsey commented Apr 12, 2023

I like the optional signature more than I like the two separate ones.

Copy link
Contributor

@brendan-ward brendan-ward left a comment

Choose a reason for hiding this comment

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

Thanks for pulling this together @pramsey to contrast with #866

Between the two, this API seems more reasonable for downstream users to implement (purely my own opinion though).

To implement against this, I'd need a bit more info in the docstrings, esp. for simplify. Are geometries below the tolerance simplified out and returned as empty polygons, do they collapse into triangles, etc.

It isn't immediately obvious what to do with the output of the validation step; if I get back MultiLineStrings for invalid edges, what can I do next to make edges valid? I'm assuming this is mostly just for flagging which polygons in the input are not valid and it's entirely up to the caller to figure out what to do next, but thought I'd ask in case the docstring could be expanded a bit to give suggested next steps...

capi/geos_c.h.in Outdated Show resolved Hide resolved
capi/geos_c.h.in Show resolved Hide resolved
capi/geos_c.h.in Outdated Show resolved Hide resolved
capi/geos_c.h.in Outdated
*
* \since 3.12
*/
extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplify(
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplify(
extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplifyVW(

(to allow for suffixes for other simplification methods later)

Ditto above question about what this returns on error.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto above question about what this returns on error.

Should return NULL on error.

capi/geos_c.h.in Outdated Show resolved Hide resolved
@dr-jts
Copy link
Contributor

dr-jts commented Apr 12, 2023

Another idea that I don't love is to have GEOSCoverageValid return an empty geometry if the coverage is valid (as opposed to a collection of invalid geometries).

Of course, I'm +1 for that idea :). Seems nice and simple, and keeps things a bit more functional.

It also works for empty coverage inputs (which have to be handled).

@dr-jts
Copy link
Contributor

dr-jts commented Apr 12, 2023

Thanks for pulling this together @pramsey to contrast with #866

Between the two, this API seems more reasonable for downstream users to implement (purely my own opinion though).

I agree, this API feels simpler and more familiar (even if less optimal - but beware premature optimization! And we have ideas for improving this in the future).

@dr-jts
Copy link
Contributor

dr-jts commented Apr 12, 2023

To implement against this, I'd need a bit more info in the docstrings, esp. for simplify. Are geometries below the tolerance simplified out and returned as empty polygons, do they collapse into triangles, etc.

More info can be provided. To answer: geometries never disappear, but they may be simplified down to just a triangle.
Also, some invalid geoms (such as Polygons which have too few non-repeated points) will be returned unchanged (garbage-in-garbage-out). Another thing that can be noted: if the input dataset is not a valid coverage due to overlaps, it will still be simplified, but invalid topology will still be invalid.

It isn't immediately obvious what to do with the output of the validation step; if I get back MultiLineStrings for invalid edges, what can I do next to make edges valid? I'm assuming this is mostly just for flagging which polygons in the input are not valid and it's entirely up to the caller to figure out what to do next, but thought I'd ask in case the docstring could be expanded a bit to give suggested next steps...

At the moment, you can do whatever you do now to fix the edges manually. :). The hope is to provide a CoverageClean function soon, which will try and fix all or most topology errors. But as no doubt you know, the scope for bad data is huge, so it's a challenge to try to handle all errors (and to avoid making things worse).

@pramsey
Copy link
Member Author

pramsey commented Apr 12, 2023

How do you feel about the current state?

@pramsey pramsey requested a review from dbaston April 12, 2023 21:39
capi/geos_c.h.in Show resolved Hide resolved
capi/geos_c.h.in Outdated Show resolved Hide resolved
capi/geos_c.h.in Outdated Show resolved Hide resolved
capi/geos_c.h.in Show resolved Hide resolved
@dbaston
Copy link
Member

dbaston commented Apr 12, 2023

How do you feel about the current state?

I like it. Thanks for the discussion and willingness to iterate.

capi/geos_ts_c.cpp Outdated Show resolved Hide resolved
{
using geos::coverage::CoverageValidator;

return execute(extHandle, 0, [&]() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return execute(extHandle, 0, [&]() {
return execute(extHandle, 2, [&]() {

@@ -2005,6 +2026,7 @@ extern void GEOS_DLL GEOSFree_r(
* This function does not have a reentrant variant and is
* available if `GEOS_USE_ONLY_R_API` is defined.
* \return version string
* \since 2.2
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason all these since annotations are in this PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

oops?

@brendan-ward
Copy link
Contributor

This looks good to me too, thanks for iterating on this. Excited to start using this!

pramsey added a commit that referenced this pull request Apr 13, 2023
Expose the CoverateSimplifier and CoverageValidator via the CAPI
@pramsey pramsey closed this Apr 13, 2023
@pramsey pramsey deleted the main-coverage-capi-gc branch April 24, 2023 18:54
pramsey added a commit to postgis/postgis that referenced this pull request May 3, 2023
Add three new functions,

    ST_CoverageIsValid(geom geometry winset, tolerance float8)
    ST_CoverageSimplify(geom geometry winset, tolerance float8, simplifyBoundary integer)
    ST_CoverageUnion(geom geometry set)

For the purpose of these functions a "coverage" is a set of polygons with perfectly shared edges (no overlaps or gaps and exact vertex matching). For associated GEOS discussion, see libgeos/geos#867
robe2 pushed a commit to postgis/postgis that referenced this pull request May 3, 2023
    ST_CoverageIsValid(geom geometry winset, tolerance float8)
    ST_CoverageSimplify(geom geometry winset, tolerance float8, simplifyBoundary integer)
    ST_CoverageUnion(geom geometry set)

For the purpose of these functions a "coverage" is a set of polygons with perfectly shared edges (no overlaps or gaps and exact vertex matching). For associated GEOS discussion, see libgeos/geos#867
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.

None yet

4 participants