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

Add Bentley-Ottman Algorithm #1168

Open
wants to merge 55 commits into
base: master
Choose a base branch
from

Conversation

souma4
Copy link
Contributor

@souma4 souma4 commented Feb 11, 2025

see issue #1126 and PR #1125

I needed to refactor and I messed up with the last draft #1143.

This produces a dictionary of vertices with a vector of segment values. Future needs: A test that the outputs are correct, and general method for rebuilding polygons with this structure.

@juliohm sorry about messing up the prior draft. Live and learn. I'll let you look this over. I think a polygon build method for this output is a new PR. This outputs vertices with segment info. If someone just wants the vertices they can grab the keys. If someone wants a polygon they can use a build method.

@juliohm
Copy link
Member

juliohm commented Feb 17, 2025

@souma4 please let me know when the PR is ready for review. I have some review comments already, just waiting for your green light.

@souma4 souma4 marked this pull request as ready for review February 17, 2025 15:35
@souma4
Copy link
Contributor Author

souma4 commented Feb 17, 2025

@juliohm Thanks for reminding me!

Copy link
Member

@juliohm juliohm left a comment

Choose a reason for hiding this comment

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

Thank you @souma4 for working on this. It is really nice to see the amazing progress you've made already ❤️

Attached is my first round of review with a couple of suggestions to improve the PR. Let's work on it together slowly, possibly improving the BinaryTrees.jl dependency before coming back here.

Looking forward to the next round. It looks very promising!

…tests. Edited test to be more intensive. updated entire script to meet style and Julia best practices. Removed unneded functions. Shifted BinaryTrees relevant materials to PR JuliaGeometry#12 in BinaryTrees and adjusted code as needed. Reordered point processing to reduce the likelihood of a bug when processing start and intersection segments.
…d function. removed println calls used for debugging
Copy link
Member

@juliohm juliohm left a comment

Choose a reason for hiding this comment

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

Attaching a few minor comments. Tomorrow I will try to find some time to run tests locally.

The good news is that the output of @code_warntype is all green.

@juliohm
Copy link
Member

juliohm commented Mar 3, 2025

Tests are failing because the utility function is not exported. We can either export it or qualify the calls in the test suite with the Meshes prefix.

Copy link
Member

@juliohm juliohm left a comment

Choose a reason for hiding this comment

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

More basic fixes before the actual review of the algorithm.

Copy link
Member

@juliohm juliohm left a comment

Choose a reason for hiding this comment

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

Tests are failing due to the latest review changes.

@juliohm
Copy link
Member

juliohm commented Mar 14, 2025

@souma4 could you please rebase this PR onto the latest remote master branch?

I tried to push my rebased changes following the standard git-rebase methodology, but it didn't work. Perhaps you need to enable edits in your fork? It can also be just me not knowing gitology well.

@juliohm
Copy link
Member

juliohm commented Mar 15, 2025

@souma4 I've added a test with an infinite loop. Appreciate it if you could take a look.

@souma4
Copy link
Contributor Author

souma4 commented Mar 17, 2025

So this works, which is awesome. Problem, doing some performance testing shows its n^2. Most of the time spent (according to profview) is occurring in the intersection checks from the \ solving for intersect parameters. I do wonder, though, if dictionary checking is really adding up. When looking at allocations, the inds = [lookup[s] for s in ....] does appear to be a significant driver.

@juliohm
Copy link
Member

juliohm commented Mar 17, 2025

Really nice progress. How are you checking the n^2 performance?

Some tests are failing with Float32.

@souma4
Copy link
Contributor Author

souma4 commented Mar 17, 2025

I checked time complexity with the REPL off hand. created numbers = 1:10:10_000, generated n of numbers random segments over numbers, then iterated through each random generation, sending the output of @belapsed to a time variable. Then plotted it. I did fit a line by doing n .* n .* S where S is a scaling factor I just messed around with until it fit good enough for me.

Yeah, some tests are failing with Float32, I'm not sure why, and I'll deal with it tomorrow haha.

function _newevent!(𝒬, ℳ, s₁, s₂; kwargs...)
intersection(Segment(s₁), Segment(s₂)) do I
if type(I) == Crossing || type(I) == EdgeTouching
p = get(I)
Copy link
Member

Choose a reason for hiding this comment

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

Here we can simply call p the result of roundcoords

# sweep line algorithm
points = Vector{P}()
seginds = Vector{Vector{Int}}()
visited = Dict{P,Int}()
Copy link
Member

Choose a reason for hiding this comment

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

I believe we can eliminate this visited auxiliary variable if we start the function with all points rounded. The first block of code in the function could round the coords of points and then orient the segments. Everything is done in terms of rounded coordinates.

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 when the visited variable is removed, in the second test we get a duplicate of Point((10,4)). This is because the adjacency tree can't process segment 4 crossing 10,4 until many of the other segments are dropped. And the inds variable simply pushes to the points variable.

souma4 added 3 commits March 19, 2025 16:44
…ght it would so I'm just hard coding the Float32 tolerance.
…e removal of ending segments from the status structure. My local tests suggest roughly logarithmic time, although caching from garbage collection makes it sort of stepwise
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