-
Notifications
You must be signed in to change notification settings - Fork 95
Add pairwise intersection between segments with sweep-line algorithm #1251
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
Merged
Merged
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
da20a78
new PR for line segment intersections. Simpler, not quite as efficien…
souma4 8aa5cfc
add tests
souma4 7f19f82
update utils.jl to include intersect
souma4 35a062b
update names to intervalsweep since this is no longer 'true' bentley-…
souma4 746382a
add test for coverage when segments stop overlapping
souma4 174ff95
incorporated review feedback. sweep1D is a descriptive name and leave…
souma4 63a26f9
sweep1D doesn't update the initial queue.
souma4 03e407a
simplified implementation, no new structs, moved from sets of indices…
souma4 e8b8585
consolidated code, cleaned up names, removed maps, improved type stab…
souma4 744189e
disolve _checkintersection function and change P definition
souma4 a07ddbc
basic cleanup
juliohm 5a290df
minor cleanup
souma4 d381b5d
fixed addintersection. it gets I
souma4 efc65c4
split out the for loops because continue for inline double for loops …
souma4 a79e599
no need for continue
souma4 d401576
Basic cleanup
juliohm 28a7f8a
Basic cleanup
juliohm 1939484
Improve docstring
juliohm 9a746e2
Refactor tests
juliohm ad49ebc
improved docstring and edited @inferred test
souma4 4dab40a
Adjust type of key in dictionary of intersections
juliohm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # ------------------------------------------------------------------ | ||
| # Licensed under the MIT License. See LICENSE in the project root. | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| """ | ||
| pairwiseintersect(segments; [digits]) | ||
|
|
||
| Compute pairwise intersections between n `segments` | ||
| with `digits` precision in O(n⋅log(n+k)) time | ||
| where k is the number of intersections, using | ||
| a sweep line algorithm. Similar to an optimal | ||
| Bentley-Ottmann algorithm in sparse systems, | ||
| and closer to O(n²) in dense systems. | ||
|
|
||
| Return intersection points and corresponding indices | ||
| of segments involved in the intersection. | ||
|
|
||
| By default, set `digits` based on the absolute | ||
| tolerance of the length type of the segments. | ||
|
|
||
| ## Examples | ||
|
|
||
| ```julia | ||
| points, seginds = pairwiseintersect(segments) | ||
| points[i] # i-th intersection point | ||
| seginds[i] # corresponding segments | ||
| ``` | ||
|
|
||
| ## References | ||
|
|
||
| * Bentley & Ottmann 1979. [Algorithms for reporting and counting | ||
| geometric intersections](https://ieeexplore.ieee.org/document/1675432) | ||
| """ | ||
| function pairwiseintersect(segments; digits=_digits(segments)) | ||
| # orient segments and round coordinates | ||
| segs = map(segments) do s | ||
| a, b = coordround.(extrema(s), digits=digits) | ||
| a > b ? Segment(b, a) : Segment(a, b) | ||
| end | ||
|
|
||
| # extract first (or "x") coordinate from | ||
| # first and last vertices of segments | ||
| x(p) = flat(coords(p)).x | ||
| xₛ = [x(first(vertices(s))) for s in segs] | ||
| xₑ = [x(last(vertices(s))) for s in segs] | ||
|
|
||
| # sort segments based on first coordinates | ||
| inds = sortperm(xₛ) | ||
| segs = segs[inds] | ||
| xₛ = xₛ[inds] | ||
| xₑ = xₑ[inds] | ||
|
|
||
| # sweepline algorithm | ||
| n = length(segs) | ||
| P = eltype(first(segs)) | ||
| D = Dict{P,Vector{Int}}() | ||
| for i in 1:n | ||
| for j in (i + 1):n | ||
| # break if segments don't overlap w.r.t. first coordinate | ||
| xₛ[i] ≤ xₛ[j] ≤ xₑ[i] || break | ||
|
|
||
| # perform more expensive intersection algorithm | ||
| intersection(segs[i], segs[j]) do I | ||
| if type(I) == Crossing || type(I) == EdgeTouching | ||
| p = coordround(get(I); digits) | ||
| if haskey(D, p) | ||
| append!(D[p], (inds[i], inds[j])) | ||
| else | ||
| D[p] = [inds[i], inds[j]] | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| # remove duplicate indices | ||
| for p in keys(D) | ||
| unique!(D[p]) | ||
| end | ||
|
|
||
| collect(keys(D)), collect(values(D)) | ||
juliohm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| end | ||
|
|
||
| # compute the number of significant digits based on the segment type | ||
| # this is used to determine the precision of the points | ||
| function _digits(segments) | ||
| s = first(segments) | ||
| ℒ = lentype(s) | ||
| τ = ustrip(eps(ℒ)) | ||
| round(Int, 0.8 * (-log10(τ))) # 0.8 is a heuristic to avoid numerical issues | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.