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 SpadeBoolops trait #1089

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

Conversation

RobWalt
Copy link
Contributor

@RobWalt RobWalt commented Oct 11, 2023

Relevant commits start from 409b815
This PR depends on #1083 and #1087

Feel free to test the latest version of the algo with this app

... and report errors if you find some 🤞🏼

Description

This is a draft for a new algorithm for boolops.

It was created because the current implementation in the repo has some issues with panics. This spawns a lot of issues in the repository.

The new algorithm might not be the most performant candidate. Still, it poses a good alternative for scenarios in which not every nano second is counted. Overall, I couldn't notice any performance issues in my application yet. That being said, I'm still open for a discussion about performance if that's a critical thing for you.

Algorithm on a high level

The algorithm itself is dead simple:

  1. It triangulates the combined geometry of all it's arguments

image

  1. Based on the chosen boolop, it runs a predicate on each triangle (let's choose intersection here, so the predicate is that the triangles mid point (mid point for stability reasons) is contained in both original shapes). All triangles that don't pass the predicate are discarded

image

  1. We use the new Stitch trait to reassemble the triangles into MultiPolygons

  • add missing docs
  • add test cases from work
  • add test cases from current implementation
  • add test cases from open issues
  • 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.

@rmanoka
Copy link
Contributor

rmanoka commented Oct 12, 2023

@RobWalt this is a cool implementation! I don't fully understand the correctness yet, but are you getting this to pass all the JTS test fixtures that we run the current bool. ops. on? If so, I'm happy to merge this as the default boolean op.

@RobWalt RobWalt changed the title Draft: implement SpadeBoolops trait implement SpadeBoolops trait Oct 28, 2023
@RobWalt RobWalt marked this pull request as draft October 28, 2023 19:26
@RobWalt RobWalt changed the title implement SpadeBoolops trait Draft: implement SpadeBoolops trait Oct 28, 2023
@RobWalt
Copy link
Contributor Author

RobWalt commented Oct 31, 2023

@rmanoka How would you define "passing the current tests"? My algorithm won't find the outputs specified in these tests with the points in the linestrings in the exact same order. Is that allowed?

@RobWalt
Copy link
Contributor Author

RobWalt commented Oct 31, 2023

I ported the tests under the name "legacy_tests". They all run through. There is a small caveat though: The 894 test runs awfully long. (~18s for 3 intersections on my machine). This is probably due to the fact that the new algo isn't very efficient for bigger geometries.

@RobWalt RobWalt changed the title Draft: implement SpadeBoolops trait Implement SpadeBoolops trait Oct 31, 2023
@RobWalt RobWalt marked this pull request as ready for review October 31, 2023 20:36
@urschrei
Copy link
Member

urschrei commented Nov 1, 2023

I ported the tests under the name "legacy_tests". They all run through. There is a small caveat though: The 894 test runs awfully long. (~18s for 3 intersections on my machine). This is probably due to the fact that the new algo isn't very efficient for bigger geometries.

How long does the test take using the existing bool ops? How long in release mode? I don't think worse perf than the existing impl is a problem, but I'm interested in the performance characteristics more generally.

@RobWalt
Copy link
Contributor Author

RobWalt commented Nov 1, 2023

I ported the tests under the name "legacy_tests". They all run through. There is a small caveat though: The 894 test runs awfully long. (~18s for 3 intersections on my machine). This is probably due to the fact that the new algo isn't very efficient for bigger geometries.

How long does the test take using the existing bool ops? How long in release mode? I don't think worse perf than the existing impl is a problem, but I'm interested in the performance characteristics more generally.

It's

  • old : 0.011s
  • new: 13.050s

So you really should consider if you want to use that and if the input is ok for it. I might add a warning. I can also look into subtle optimizations (via bounding boxes) to squeeze out a bit of performance.

Please note that the Multipolygons in this example are absolutely giant (23 KB, 150 polygons per Multipolygon, 2600 vertices total per Multipolygon)

@michaelkirk
Copy link
Member

Feel free to test the latest version of the algo with this app

Lovely demo! The source is this right? https://github.com/RobWalt/is-geo-boolops-still-broken/blob/main/src/bin/is-geo-boolops-still-broken.rs

@RobWalt
Copy link
Contributor Author

RobWalt commented Nov 2, 2023

I implemented some minor bounding box optimizations and now the big test runs through in

4.5s instead of 13s

There were two test results I needed to change for it still to work:

  • one of them just returned the poly in a different coordinate order

  • the other actually had a difference in it's number of polygons. I took the time to inspect the change and here it is:

    SVG image of differences

    image

    • top is without new optimizations
    • bottom is with new optimizations

@RobWalt RobWalt force-pushed the feat/spade-boolops branch 2 times, most recently from 436110d to 5128160 Compare November 6, 2023 18:45
@RobWalt RobWalt self-assigned this Nov 28, 2023
@RobWalt RobWalt mentioned this pull request Dec 6, 2023
5 tasks
RobWalt and others added 28 commits January 15, 2024 13:54
As stated in one of the review comments, the main purpose of the algo is
to stitch together triangles that resulted from a triangulation.

Although it would also be nice to generalize the algo for polygons and
multi polygons, it makes the code harder to read. It is advised to just
triangulate in those cases and then run the stitching on the compound
triangulation.

On another note: special casing the algorithm to triangles also gave us
a real good performance boost again. We gained another ~50% boost from
all of the improvements in this commit.

Authored-by: RobWalt <[email protected]>
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

5 participants