Skip to content

Commit

Permalink
Fix edge case for planar hull
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Feb 14, 2024
1 parent f582320 commit 3b2b462
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/planar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ function _semi_hull(ps::Vector{PT}, sign_sense, counterclockwise, sweep_norm, yr
end
prev = sign_sense == 1 ? first(ps) : last(ps)
cur = prev
flat_start = true
# Invariant:
# We either have:
# * `hull` is empty and `cur == prev` or
# * `hull` is nonempty and `prev = last(hull)`.
# In any case, the semihull of `ps[1:(j-1)]` is given by `[hull; cur]`.
for j in (sign_sense == 1 ? (2:length(ps)) : ((length(ps)-1):-1:1))
skip = false
flat = false
while prev != cur
cur_vec = cur - prev
psj_vec = ps[j] - prev
Expand All @@ -26,9 +28,18 @@ function _semi_hull(ps::Vector{PT}, sign_sense, counterclockwise, sweep_norm, yr
# The one that is closer to `prev` is redundant.
dcur = dot(cur_vec, sweep_norm)
dpsj = dot(psj_vec, sweep_norm)
if isapproxzero(dcur) && isapproxzero(dpsj)
flat = isapproxzero(dcur) && isapproxzero(dpsj)
if flat
# Case 1
if sign_sense * counterclockwise(cur_vec, sweep_norm) < sign_sense * counterclockwise(psj_vec, sweep_norm)
sense = flat_start ? sign_sense : -sign_sense
sense = sign_sense
ccjsweep = sense * counterclockwise(psj_vec, sweep_norm)
# if ccjsweep > 0
# hull[end] = ps[j]
# prev = last(hull)
# break
# end
if sense * counterclockwise(cur_vec, sweep_norm) < ccjsweep
skip = true
break
end
Expand All @@ -46,6 +57,9 @@ function _semi_hull(ps::Vector{PT}, sign_sense, counterclockwise, sweep_norm, yr
prev = last(hull)
end
end
if prev != cur && !flat
flat_start = false
end
if !skip
push!(hull, cur)
prev = cur
Expand Down
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Polyhedra = "67491407-f73d-577b-9b50-8179a7c68029"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Expand Down
33 changes: 33 additions & 0 deletions test/planar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,38 @@ function test_issue_271()
@test collect(points(p)) == expected
end

function test_issue_333()
vs = [
0.5 -0.4
-0.5 1
0 1
0.8 1
]

h = Polyhedra.planar_hull(vrep(vs))
@test all(points(h) .== [vs[i, :] for i in [1, 2, 4]])

vs = [-0.96 -0.4;
-0.5 -0.4;
0.0 -0.4;
0.5 -0.4;
1.0 -0.36065655;
-0.995 -0.05;
1.0 -0.05;
-1.0 0.3;
0.97 0.3;
-1.0 0.65;
0.930928 0.65;
-1.0 1.0;
-0.5 1.0;
0.0 1.0;
0.5 1.0;
0.865979 1.0;]

h = Polyhedra.planar_hull(vrep(vs))
@test all(points(h) .== [vs[i, :] for i in [1, 6, 8, 12, 16, 11, 9, 7, 5, 4]])
end

@testset "Planar" begin
for T in [Float64, Int]
for (VT, d) in [(Vector{T}, 2), (SVector{2, T}, StaticArrays.Size(2))]
Expand All @@ -116,4 +148,5 @@ end
end
test_planar_square_with_more()
test_issue_271()
test_issue_333()
end

0 comments on commit 3b2b462

Please sign in to comment.