diff --git a/src/Delaunator.jl b/src/Delaunator.jl index c96ed65..fa4c3c8 100644 --- a/src/Delaunator.jl +++ b/src/Delaunator.jl @@ -5,7 +5,7 @@ export triangulate, basictriangulation, update!, triangles, points, inhull include("quicksort.jl") include("geometry.jl") -export isinfinite, dualcell, firstpoint, lastpoint, segments +export isinfinite, dualcell, firstpoint, lastpoint, segments, cellarea include("clipping.jl") export clippedpoly, clippedpoly!, margin_bbox diff --git a/src/geometry.jl b/src/geometry.jl index dc6052e..74308e1 100644 --- a/src/geometry.jl +++ b/src/geometry.jl @@ -244,6 +244,35 @@ function dualcell(t::Triangulation, centers, i::Integer) raystart, rayend) end +""" + cellarea(p) + +Compute the area of a possibly infinite polygon. +""" +function cellarea(p::InfinitePolygon) + if isinfinite(p) + return typemax(eltype(eltype(p))) + # Area of a line is zero + elseif length(p.points) < 3 + return zero(eltype(eltype(p))) + else + # Compute the area of the polygon using the shoelace formula using iterators + area = zero(eltype(eltype(p))) + previous, ite = iterate(p.points) + while true + el = iterate(p.points, ite) + if isnothing(el) + break + end + current, ite = el + area += (previous[1] + current[1]) * (previous[2] - current[2]) + previous = current + end + current = first(p.points) + return 0.5 * abs(area + (previous[1] + current[1]) * (previous[2] - current[2])) + end +end + # monotonically increases with real angle, but doesn't need expensive trigonometry function pseudoAngle(dx, dy) p = dx / (abs(dx) + abs(dy)) diff --git a/test/runtests.jl b/test/runtests.jl index 691ea33..cc5801f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -52,6 +52,20 @@ end end end +@testset "cellarea" begin + # Test Infinite case + p = Delaunator.InfinitePolygon([(-5.0,0.0)], (0.0,-1.0), (0.0,1.0)) + @test cellarea(p) == Inf + # Test Degenerate (point, segment) case + p = Delaunator.InfinitePolygon([(-5.0,0.0)], (0.0, 0.0), (0.0, 0.0)) + @test cellarea(p) == 0.0 + p = Delaunator.InfinitePolygon([(-5.0,0.0), (5.0, 0.0)], (0.0, 0.0), (0.0, 0.0)) + @test cellarea(p) == 0.0 + # Test normal case + p = Delaunator.InfinitePolygon([(-1.0,-1.0),(1.0,-1.0),(1.0,1.0),(-1.0,1.0)], (0.0,0.0), (0.0,0.0)) + @test cellarea(p) == 4.0 +end + # test('triangulates plain array', (t) => { # const d = new Delaunator([].concat(...points)); # t.same(d.triangles, Delaunator.from(points).triangles);