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

Implement Stitch trait #1087

Open
wants to merge 75 commits into
base: main
Choose a base branch
from

Conversation

RobWalt
Copy link
Contributor

@RobWalt RobWalt commented Oct 10, 2023

This is an implementation of a trait which offers functionality to stitch up geometry parts that were split at some point of time. It's an alternative to boolean operations which doesn't panic and returns user friendly errors instead.

This is mostly used within the new SpadeBoolops trait which needs to stitch together some parts of a triangulation. Hence, this trait is mostly used on triangles but isn't constraint on those and was implemented here for a more general scenario. Here are some rough visuals of what the operation does

image


  • 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.

TODOs

  • add docs for main trait
  • Add simple benchmarks
  • try to optimize performance

@RobWalt RobWalt mentioned this pull request Oct 11, 2023
6 tasks
@RobWalt RobWalt marked this pull request as draft October 12, 2023 12:41
@RobWalt RobWalt changed the title Implement Stitch trait Draft: Implement Stitch trait Oct 28, 2023
@RobWalt RobWalt marked this pull request as ready for review October 31, 2023 20:35
@RobWalt RobWalt changed the title Draft: Implement Stitch trait Implement Stitch trait Oct 31, 2023
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
@RobWalt
Copy link
Contributor Author

RobWalt commented Nov 14, 2023

This PR is in a reviewable state now. Please feel free to take a look. It's important for the SpadeBoolops PR.

@RobWalt RobWalt self-assigned this Nov 28, 2023
Copy link
Member

@frewsxcv frewsxcv left a comment

Choose a reason for hiding this comment

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

still reviewing, but looking good so far!

geo/src/algorithm/stitch.rs Show resolved Hide resolved
@frewsxcv
Copy link
Member

frewsxcv commented Dec 4, 2023

how does this compare to the boolean operation "union"?

@RobWalt
Copy link
Contributor Author

RobWalt commented Dec 6, 2023

how does this compare to the boolean operation "union"?

Compared to the BooleanOps trait this is probably not as performant. One of the checks which reassociates holes needs to construct Polygons from LineString-rings just for containment checks. This and some other allocations probably make it less performant.

On the other hand, this is just another safe (non-panic) alternative to BooleanOps which provides robustness in all cases if the invariants of the algo are fulfilled at it's start. While writing this I wonder though if BooleanOps would be safe operation under exactly the same invariants though. I probably need to do some more testing on it and we might be able to scratch this algo. Nevertheless, even if that were the case, I couldn't prove that it wouldn't hit one of the BooleanOps panics.

Thanks for asking those kinds of questions!

Copy link
Member

@michaelkirk michaelkirk left a comment

Choose a reason for hiding this comment

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

Sorry this sat here so long @RobWalt!

All of the performance related commentary is "take it or leave it". I'd be happy to follow up on that later. I'm primarily interested in the correctness aspect, and have asked a few questions that I'd like to understand better.

geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Show resolved Hide resolved
geo/src/algorithm/stitch.rs Show resolved Hide resolved
geo/src/algorithm/stitch.rs Show resolved Hide resolved
@RobWalt
Copy link
Contributor Author

RobWalt commented Jan 11, 2024

Sorry this sat here so long @RobWalt!

All of the performance related commentary is "take it or leave it". I'd be happy to follow up on that later. I'm primarily interested in the correctness aspect, and have asked a few questions that I'd like to understand better.

Thanks for your efforts in reviewing this. I'd also like to improve performance here since it's a bottleneck in the SpadeBoolops so I'll take another shot in optimizing here. I'll try to add some benchmarks first so we can meassure improvements.

@RobWalt
Copy link
Contributor Author

RobWalt commented Jan 11, 2024

Thanks for the thorough review @michaelkirk. In the end we got a

27% + 88% + 8% which roughly equates 92% total

performance improvement.

geo/CHANGES.md Outdated Show resolved Hide resolved
geo/src/algorithm/mod.rs Outdated Show resolved Hide resolved
Copy link
Member

@frewsxcv frewsxcv left a comment

Choose a reason for hiding this comment

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

lgtm! thank you for your patience!

@frewsxcv
Copy link
Member

@michaelkirk Do you have any outstanding reservations before merging this?

@michaelkirk
Copy link
Member

Yes, I'd like to take another look now that it's been reformulated in terms of triangles. I'll try to do that in the next couple days.

geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Show resolved Hide resolved
Copy link
Member

@michaelkirk michaelkirk left a comment

Choose a reason for hiding this comment

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

Hi @RobWalt - I've left some little comments that should be easy to address, and conceptually I've made a lot of progress, but am still a struggling a bit understanding the inner workings of find_and_fix_holes_in_exterior - maybe you can elaborate?

geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
/// This is important for scenarios like the banana polygon. Which is considered invalid
/// https://www.postgis.net/workshops/postgis-intro/validity.html#repairing-invalidity
fn find_and_fix_holes_in_exterior<F: GeoFloat>(mut poly: Polygon<F>) -> Polygon<F> {
fn detect_if_rings_closed_with_point<F: GeoFloat>(
Copy link
Member

Choose a reason for hiding this comment

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

I'm having a hard time reconciling the name of this method with what it seems to do.

What I think it does: if p is in points, we return a new ring from the subsequence of points starting with wherever p is found.

So e.g. given as args:

let mut points = [a, b, c, d, e, f, g];
let point = d;
let ring = detect_if_rings_closed_with_point(&mut points, point);

Would result in:

ring = [d, e, f, g, d]
points: [a, b, c] // left over

Is that right?

TBH I'm not really sure what it's for... I'd of assumed the way that we constructed the rings precludes unclosed rings from occurring. Do any of the test cases exemplify what this method is for?

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 think the main problem here is that we don't really know which vertex we start at. We could get a list of points

[a3, a1, b1, b2, b3, b4, b1, a1, a2]

where the last (or first, whatever floats your boat) ring is looping around the Vec. For this ring we don't really want to get the points between the duplicates (a1, b1, b2, b3, b4, b1, a1) but the opposite or left over. I just gave it a try to find a better and more obvious way of doing that but for now I can't find a more concise way actually. Handling this special case for the last ring always results in a mess.

Copy link
Member

Choose a reason for hiding this comment

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

I'm pretty far from understanding what this method is for, so I'll continue to ask dumb questions.

Is this method given points that are not necessarily in the ring? Where did they come from? What happens to those points, do we just drop them?

Copy link
Contributor Author

@RobWalt RobWalt Feb 2, 2024

Choose a reason for hiding this comment

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

Given these triangles here

image

We could potentially end up with a exterior ring of the form

[F, C, E, D, C, B, A, H, G]

and we want to convert that into a nice polygon with a hole instead. As the order of the coords above is not deterministic we need to do the "one step at a time and remove finished rings" procedure to not miss the ring that will be added last. Here's how the algo works in steps for this example:

[F]
[F, C]
[F, C, E]
[F, C, E, D]  <-- adding another C closes a ring

remove and remember [C, E, D, C] and continue

[F, B] 
[F, B, A]
[F, B, A, H]
[F, B, A, H, G] <-- nothing left so this is also a ring

geo/src/algorithm/stitch.rs Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
geo/src/algorithm/stitch.rs Outdated Show resolved Hide resolved
urschrei and others added 25 commits February 1, 2024 10:47
Co-authored-by: Michael Kirk <michael.code@endoftheworl.de>
In particular the latest `home` crate used by bindgen, required by proj, needs rust-1.70+

Also updates CI containers to latest
This fixes a new lint introduced in rust 1.75

Fixes georust#1088
The previous approach worked, but then there was feedback that the trait
should maybe be "more complete" and implemented on additional types.

Really, I introduced the trait to solve a problem: we have some
undesirable unwraps in the codebase with some of our floating type
geometries. I didn't care to actually introduce a general-purpose TotalOrd
trait that was useful outside of that context.
There's so little you could do with HasKernel that isn't also a GeoNum.
I'm not sure there's value in having two traits.
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
We decided to do this since we're not sure yet about how users might use
this functionality. In the worst case the API is still confusing and
leads to a lot of error reports due to the implicit assumptions which
are only documented in doc strings and not enforced by code or won't be
caught by errors

Authored-by: RobWalt <robwalter96@gmail.com>
Add some notes that triangles shouldn't even overlap instead of just
stating that duplicates are not allowed.

Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
This benchmark needs a public export of the stitch trait which isn't
given anymore. I added some comments for the after world.

Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
Authored-by: RobWalt <robwalter96@gmail.com>
@piaoger
Copy link

piaoger commented Apr 19, 2024

@RobWalt
I tried your is-geo-boolops-still-broken tool, stitch/spade-boolops PRs. I am using them in my in-house tool and polygon boolean works really good. What make these great PRs suspended, need more tests or codeview?

@RobWalt
Copy link
Contributor Author

RobWalt commented Apr 19, 2024

Currently, this PR here boils down to this comment here #1087 (comment) . Once that is resolved, we should be able to merge this PR and continue with the Boolops PR. Given that someone (you) actually uses the new feature I might be motivated enough to tackle it! Thanks for the feedback by the way!

@piaoger
Copy link

piaoger commented May 1, 2024

Currently, this PR here boils down to this comment here #1087 (comment) . Once that is resolved, we should be able to merge this PR and continue with the Boolops PR. Given that someone (you) actually uses the new feature I might be motivated enough to tackle it! Thanks for the feedback by the way!

A robust geometry boolean library is always welcome and I find SpadeBoolops is quit good :)

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

9 participants