-
Notifications
You must be signed in to change notification settings - Fork 88
Add Bentley-Ottman Algorithm #1168
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
Open
souma4
wants to merge
73
commits into
JuliaGeometry:master
Choose a base branch
from
souma4:JRC_add_BentleyOttman
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 9 commits
Commits
Show all changes
73 commits
Select commit
Hold shift + click to select a range
c5a3b90
add test segment. proper test later
souma4 e004810
Clean single commit for BentleyOttman algorithm. Essentially, it outp…
souma4 491a130
test for valid answer
souma4 840c1a5
moved sweepline algorithm to Intersections since it is dependent on i…
souma4 6f018a3
Update Doc for bentley ottman implementation to specify output
souma4 eb0d56b
update project.toml to include BinaryTrees dependency
souma4 b869b6e
major commit. Moved sweepline from intersections to utils along with …
souma4 6be63f1
new_type and new_geom didn't meet style, so fixed. Removed an unneede…
souma4 ed09d87
forgot to rename _intersection to _pushintersection
souma4 2b83b1a
small commits to improve compatibility and fix mixed up old names
souma4 7484dc1
small updates to License text, cases, variable and function names, cl…
souma4 16791eb
Merge branch 'JRC_add_BentleyOttman' of https://github.com/souma4/Mes…
souma4 ec4c593
Updated algorithm to be simpler, output is points and segment indices…
souma4 e18eb99
updated tests to reflect changed output type
souma4 e27d9f1
add compat for BinaryTrees
souma4 56018d3
fixed names of variables and helper functions. removed output type f…
souma4 442861b
updated utils include path and refactored if else to new function for…
souma4 0cc5d91
Minor adjustments before review
juliohm 1c03947
More fixes
juliohm 00e2151
changed S = Tuple{P, P} to V and changed the empty vectors of S to ca…
souma4 83093e4
the s iter variable was modified to segment using the same name, so …
souma4 76d8be3
Rename V -> S
juliohm 1e36abe
More refactoring
juliohm d590d36
Rename \scrT to \scrR to match paper notation, and avoid confusion wi…
juliohm 93ce4a6
Refactor _newevent to improve readability
juliohm 9fdaf93
More refactoring to improve readability
juliohm 353cf70
More refactoring to improve readability and performance
juliohm d136b6e
More refactoring to improve readability
juliohm 602a579
More refactoring
juliohm 36e2497
More refactoring
juliohm f5ff53e
More refactoring
juliohm 0004c36
realigned more with original algorithm and reduced recomputation
souma4 dd88813
More refactoring
juliohm 2fb7e10
More refactoring
juliohm 8e618e0
More refactoring
juliohm 2850538
More refactoring
juliohm 7762044
Add more tests
juliohm 3f42e7d
Merge branch 'JuliaGeometry:master' into JRC_add_BentleyOttman
souma4 e288e23
edited the processing of intersections to better reflect the original…
souma4 5a21d3a
More refactoring
juliohm 165ddae
Refactor tests
juliohm 3ed853d
Add more tests
juliohm 859c846
Improve tests
juliohm 9732322
Fix formatting
juliohm 98f0786
More refactoring
juliohm 042e690
Add test with infinite loop
juliohm c9d933f
Fix formatting
juliohm 219add3
update to stop infinite loops, but has major TODOs to handle floating…
souma4 89a8d98
reverting prior to dictionary implementation
souma4 3078412
Merge branch 'JuliaGeometry:master' into JRC_add_BentleyOttman
souma4 fdb936b
fully functioning not infinitely looping bentleyottman algorithm all …
souma4 5ef6505
cleaned up test outputs and fixed tests to be T agnostic
souma4 33f2fba
hopefully fixed failing test on Float32 values
souma4 e933e9c
I think it's a precision issue, but T wasn't being handled how I thou…
souma4 5e972fc
shuffled to reduce redundant computations, particularly specifying th…
souma4 0ed8c5f
Minor adjustments
juliohm 0a18865
removed commented out useless code
souma4 e38d203
Minor adjustments
juliohm 893fafd
Int is default type for integer literals
souma4 a10680b
Set digits by default using exponent of absolute tolerance
juliohm 20178a3
Decrease number of digits by one
juliohm 01604f1
updated script to be simpler. updated tests. THIS FAILS THE GRID TEST…
souma4 8345d1e
WIP, With what little time I've had and will have for a bit, here's a…
souma4 562c778
complete functional Bentley Ottman Algorithm and passing all local te…
souma4 5557fbb
fix roundcoords to be coordround
souma4 5023a34
Merge remote-tracking branch 'origin/master' into JRC_add_BentleyOttman
souma4 701e8a9
fixed maxsearch and minsearch to not be exhaustive. findintersections…
souma4 5baeff2
fixed incorrect removal of end and midpoints
souma4 ee4d2b8
fixed type insecurity
souma4 fcdaa81
_findintersection appears to no longer exhaustively search the tree. …
souma4 f2bc9a2
Minor adjustments
juliohm 27a0b17
removed unneeded search
souma4 d87d91e
updated to use intersect function
souma4 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
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,180 @@ | ||
# Implementation of Bentley-Ottmann algorith | ||
# https://en.wikipedia.org/wiki/Bentley%E2%80%93Ottmann_algorithm | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
BentleyOttmann(segments) | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Compute pairwise intersections between n `segments` | ||
in O(n⋅log(n)) time using Bentley-Ottmann sweep line | ||
algorithm. | ||
|
||
Outputs a Dictionary of {Point, Vector{Tuple{Point, Point}}} | ||
where the key is each intersection point and the values are all | ||
pairs of segments that intersect at that point. | ||
""" | ||
function BentleyOttmann(segments) | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# adjust vertices of segments | ||
segs = map(segments) do s | ||
a, b = extrema(s) | ||
a > b ? reverse(s) : s | ||
end | ||
|
||
# retrieve relevant info | ||
s = first(segs) | ||
p = minimum(s) | ||
P = typeof(p) | ||
S = Tuple{P,P} | ||
|
||
# initialization | ||
𝒬 = BinaryTrees.AVLTree{P}() | ||
𝒯 = BinaryTrees.AVLTree{S}() | ||
ℒ = Dict{P,Vector{S}}() | ||
𝒰 = Dict{P,Vector{S}}() | ||
𝒞 = Dict{P,Vector{S}}() | ||
lookup = Dict{S,Int}() | ||
for (i, s) in enumerate(segs) | ||
a, b = extrema(s) | ||
BinaryTrees.insert!(𝒬, a) | ||
BinaryTrees.insert!(𝒬, b) | ||
haskey(ℒ, a) ? push!(ℒ[a], (a, b)) : (ℒ[a] = [(a, b)]) | ||
haskey(𝒰, b) ? push!(𝒰[b], (a, b)) : (𝒰[b] = [(a, b)]) | ||
haskey(ℒ, b) || (ℒ[b] = S[]) | ||
haskey(𝒰, a) || (𝒰[a] = S[]) | ||
haskey(𝒞, a) || (𝒞[a] = S[]) | ||
haskey(𝒞, b) || (𝒞[b] = S[]) | ||
lookup[(a, b)] = i | ||
end | ||
|
||
# sweep line | ||
I = Dict{P,Vector{Tuple{IntersectionType,Vector{Int}}}}() | ||
juliohm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
while !isnothing(BinaryTrees.root(𝒬)) | ||
p = BinaryTrees.key(BinaryTrees.minnode(𝒬)) | ||
BinaryTrees.delete!(𝒬, p) | ||
Meshes.handle!(I, lookup, p, S, 𝒬, 𝒯, ℒ, 𝒰, 𝒞) | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
I | ||
end | ||
|
||
function handle!(I, lookup, p, S, 𝒬, 𝒯, ℒ, 𝒰, 𝒞) | ||
𝒮ₛ = get(ℒ, p, S[]) | ||
𝒮ₑ = get(𝒰, p, S[]) | ||
𝒮ᵢ = get(𝒞, p, S[]) | ||
_processends!(𝒮ₑ, 𝒬, 𝒯, 𝒞) | ||
_processstarts!(𝒮ₛ, 𝒬, 𝒯, 𝒞) | ||
juliohm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
__processintersects!(𝒮ᵢ, 𝒬, 𝒯, 𝒞) | ||
if !isempty(𝒮ₛ ∪ 𝒮ₑ ∪ 𝒮ᵢ) | ||
corners = 𝒮ₛ ∪ 𝒮ₑ | ||
crossings = 𝒮ᵢ | ||
I[p] = _pushintersection(lookup, corners, crossings) | ||
end | ||
end | ||
|
||
function _processstarts!(𝒮ₛ, 𝒬, 𝒯, 𝒞) | ||
[BinaryTrees.insert!(𝒯, s) for s in 𝒮ₛ] | ||
for s in 𝒮ₛ | ||
prev, next = BinaryTrees.prevnext(𝒯, s) | ||
s = Segment(s) | ||
if !isnothing(prev) && !isnothing(next) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(next)), Segment(BinaryTrees.key(prev))) | ||
if _checkintersection(newtype) | ||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], BinaryTrees.key(next), BinaryTrees.key(prev)) : | ||
(𝒞[newgeom] = [BinaryTrees.key(next), BinaryTrees.key(prev)]) | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
end | ||
if !isnothing(prev) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(prev)), s) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], BinaryTrees.key(prev), vertices(s)) : | ||
(𝒞[newgeom] = [BinaryTrees.key(prev), vertices(s)]) | ||
end | ||
end | ||
if !isnothing(next) | ||
newgeom, newtype = _newevent(s, Segment(BinaryTrees.key(next))) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], vertices(s), BinaryTrees.key(next)) : | ||
(𝒞[newgeom] = [vertices(s), BinaryTrees.key(next)]) | ||
end | ||
end | ||
end | ||
end | ||
|
||
function _processends!(𝒮ₑ, 𝒬, 𝒯, 𝒞) | ||
for s in 𝒮ₑ | ||
prev, next = BinaryTrees.prevnext(𝒯, s) | ||
BinaryTrees.delete!(𝒯, s) | ||
s = Segment(s) | ||
if !isnothing(prev) && !isnothing(next) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(next)), Segment(BinaryTrees.key(prev))) | ||
if newtype == IntersectionType(0) | ||
souma4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], BinaryTrees.key(next), BinaryTrees.key(prev)) : | ||
(𝒞[newgeom] = [BinaryTrees.key(next), BinaryTrees.key(prev)]) | ||
end | ||
end | ||
end | ||
end | ||
|
||
function __processintersects!(𝒮ᵢ, 𝒬, 𝒯, 𝒞) | ||
for s in 𝒮ᵢ | ||
prev, _ = BinaryTrees.prevnext(𝒯, s) | ||
if !isnothing(prev) | ||
|
||
# Find segments r and u | ||
r, _ = BinaryTrees.prevnext(𝒯, s) | ||
_, u = BinaryTrees.prevnext(𝒯, BinaryTrees.key(prev)) | ||
|
||
# Remove crossing points rs and tu from event queue | ||
if !isnothing(r) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(r)), Segment(s)) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.delete!(𝒬, newgeom) | ||
end | ||
end | ||
if !isnothing(u) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(u)), Segment(BinaryTrees.key(prev))) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.delete!(𝒬, newgeom) | ||
end | ||
end | ||
|
||
# Add crossing points rt and su to event queue | ||
if !isnothing(r) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(r)), Segment(BinaryTrees.key(prev))) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], BinaryTrees.key(r), BinaryTrees.key(prev)) : | ||
(𝒞[newgeom] = [BinaryTrees.key(r), BinaryTrees.key(prev)]) | ||
end | ||
end | ||
if !isnothing(u) | ||
newgeom, newtype = _newevent(Segment(BinaryTrees.key(u)), Segment(s)) | ||
if newtype == IntersectionType(0) | ||
BinaryTrees.insert!(𝒬, newgeom) | ||
haskey(𝒞, newgeom) ? push!(𝒞[newgeom], BinaryTrees.key(u), s) : (𝒞[newgeom] = [BinaryTrees.key(u), s]) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
function _pushintersection(lookup, corners, crossings) | ||
return [ | ||
(IntersectionType(4), [lookup[segment] for segment in corners]), | ||
(IntersectionType(0), [lookup[segment] for segment in crossings]) | ||
] | ||
end | ||
function _newevent(s₁::Segment, s₂::Segment) | ||
newevent = intersection(s₁, s₂) | ||
if !isnothing(newevent) | ||
get(newevent), type(newevent) | ||
else | ||
nothing, nothing | ||
end | ||
end | ||
|
||
function _checkintersection(type) | ||
type == IntersectionType(0) || type == IntersectionType(1) || type == IntersectionType(2) | ||
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.