From 0b20272507159fb72df69c3e94df92063bef8200 Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Thu, 21 Jan 2021 17:59:59 +0100 Subject: [PATCH 1/4] area: document signed result, fixes for custom indices --- Project.toml | 3 ++- src/triangulation.jl | 24 ++++++++++++++---------- test/geometrytypes.jl | 9 --------- test/runtests.jl | 20 +++++++++++++++++++- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Project.toml b/Project.toml index a2dc8a27..dc979684 100644 --- a/Project.toml +++ b/Project.toml @@ -19,8 +19,9 @@ Tables = "0.2, 1" julia = "1.3" [extras] +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Random"] +test = ["Test", "Random", "OffsetArrays"] diff --git a/src/triangulation.jl b/src/triangulation.jl index 6aced8f7..352860cc 100644 --- a/src/triangulation.jl +++ b/src/triangulation.jl @@ -33,23 +33,28 @@ function area(vertices::AbstractVector{<:AbstractPoint{3,VT}}, return sum(x -> area(vertices, x), faces) end -function area(contour::AbstractVector{<:AbstractPoint{N,T}}) where {N,T} - n = length(contour) - n < 3 && return zero(T) +""" + area(contour::AbstractVector{AbstractPoint}}) + +Calculate the area of a polygon. + +For 2D points, the oriented area is returned (negative when the points are +oriented clockwise). +""" +function area(contour::AbstractVector{<:AbstractPoint{2,T}}) where {T} + length(contour) < 3 && return zero(T) A = zero(T) p = lastindex(contour) - q = firstindex(contour) - while q <= n + for q in eachindex(contour) A += cross(contour[p], contour[q]) p = q - q += 1 end return A * T(0.5) end -function area(contour::AbstractVector{Point{3,T}}) where {T} +function area(contour::AbstractVector{<:AbstractPoint{3,T}}) where {T} A = zero(eltype(contour)) - o = contour[1] + o = first(contour) for i in (firstindex(contour) + 1):(lastindex(contour) - 1) A += cross(contour[i] - o, contour[i + 1] - o) end @@ -59,8 +64,7 @@ end """ in(point, triangle) - InsideTriangle decides if a point P is Inside of the triangle - defined by A, B, C. +Determine if a point is inside of a triangle. """ function Base.in(P::T, triangle::Triangle) where {T<:AbstractPoint} A, B, C = coordinates(triangle) diff --git a/test/geometrytypes.jl b/test/geometrytypes.jl index 569153a7..bd180cf9 100644 --- a/test/geometrytypes.jl +++ b/test/geometrytypes.jl @@ -1,14 +1,5 @@ using Test, GeometryBasics -@testset "algorithms.jl" begin - cube = Rect(Vec3f0(-0.5), Vec3f0(1)) - cube_faces = decompose(TriangleFace{Int}, faces(cube)) - cube_vertices = decompose(Point{3,Float32}, cube) - @test area(cube_vertices, cube_faces) == 6 - mesh = Mesh(cube_vertices, cube_faces) - @test GeometryBasics.volume(mesh) ≈ 1 -end - @testset "Cylinder" begin @testset "constructors" begin o, extr, r = Point2f0(1, 2), Point2f0(3, 4), 5.0f0 diff --git a/test/runtests.jl b/test/runtests.jl index dcb96f61..6f39d157 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,28 @@ -using Test, Random, StructArrays, Tables, StaticArrays +using Test, Random, StructArrays, Tables, StaticArrays, OffsetArrays using GeometryBasics using LinearAlgebra using GeometryBasics: attributes @testset "GeometryBasics" begin +@testset "algorithms" begin + cube = Rect(Vec3f0(-0.5), Vec3f0(1)) + cube_faces = decompose(TriangleFace{Int}, faces(cube)) + cube_vertices = decompose(Point{3,Float32}, cube) + @test area(cube_vertices, cube_faces) == 6 + mesh = Mesh(cube_vertices, cube_faces) + @test GeometryBasics.volume(mesh) ≈ 1 + + points_cwise = Point2f0[(0,0), (0,1), (1,1)] + points_ccwise = Point2f0[(0,0), (1,0), (1,1)] + @test area(points_cwise) ≈ -0.5 + @test area(points_ccwise) ≈ 0.5 + @test area(OffsetArray(points_cwise, -2)) ≈ -0.5 + + points3d = Point3f0[(0,0,0), (0,0,1), (0,1,1)] + @test area(OffsetArray(points3d, -2)) ≈ 0.5 +end + @testset "embedding metadata" begin @testset "Meshes" begin From af6f355b0519eae30eb9c8791cbcb4a25cdc26e4 Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Fri, 22 Jan 2021 14:58:27 +0100 Subject: [PATCH 2/4] Fix MetaFree for fully-specified types --- src/metadata.jl | 2 +- test/runtests.jl | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/metadata.jl b/src/metadata.jl index ea90bc46..f0eaa16b 100644 --- a/src/metadata.jl +++ b/src/metadata.jl @@ -102,7 +102,7 @@ macro meta_type(name, mainfield, supertype, params...) return $MetaName{$(params_sym...),ST,Names,Types} end - GeometryBasics.MetaFree(::Type{<:$MetaName{Typ}}) where {Typ} = Typ + GeometryBasics.MetaFree(::Type{<:$MetaName{$(params_sym...),Typ}}) where {$(params_sym...), Typ<:$supertype{$(params_sym...)} } = Typ GeometryBasics.MetaFree(::Type{<:$MetaName}) = $name GeometryBasics.metafree(x::$MetaName) = getfield(x, :main) GeometryBasics.metafree(x::AbstractVector{<:$MetaName}) = getproperty(x, $field) diff --git a/test/runtests.jl b/test/runtests.jl index 6f39d157..3cc89bc7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,6 +21,9 @@ using GeometryBasics: attributes points3d = Point3f0[(0,0,0), (0,0,1), (0,1,1)] @test area(OffsetArray(points3d, -2)) ≈ 0.5 + + pm2d = [PointMeta(0.0, 0.0, a=:d), PointMeta(0.0, 1.0, a=:e), PointMeta(1.0, 0.0, a=:f)] + @test area(pm2d) ≈ -0.5 end @testset "embedding metadata" begin @@ -102,13 +105,14 @@ end @testset "point with metadata" begin p = Point(1.1, 2.2) @test p isa AbstractVector{Float64} - pm = GeometryBasics.PointMeta(1.1, 2.2; a=1, b=2) + pm = PointMeta(1.1, 2.2; a=1, b=2) p1 = Point(2.2, 3.6) p2 = [p, p1] @test coordinates(p2) == p2 @test meta(pm) === (a=1, b=2) @test metafree(pm) === p @test propertynames(pm) == (:position, :a, :b) + @test GeometryBasics.MetaFree(typeof(pm)) == Point{2,Float64} end @testset "MultiPoint with metadata" begin From 422896b801919047bcaba9fd5f60ac33448fc88a Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Fri, 22 Jan 2021 15:09:59 +0100 Subject: [PATCH 3/4] Add broken tests for area and zero of PointMeta --- test/runtests.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 3cc89bc7..4c771ab0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -24,6 +24,9 @@ using GeometryBasics: attributes pm2d = [PointMeta(0.0, 0.0, a=:d), PointMeta(0.0, 1.0, a=:e), PointMeta(1.0, 0.0, a=:f)] @test area(pm2d) ≈ -0.5 + + pm3d = [PointMeta(0.0, 0.0, 0.0, a=:d), PointMeta(0.0, 1.0, 0.0, a=:e), PointMeta(1.0, 0.0, 0.0, a=:f)] + @test_broken area(pm3d) ≈ 0.5 # Currently broken as zero(PointMeta(0.0, 0.0, 0.0, a=:d)) fails end @testset "embedding metadata" begin @@ -113,6 +116,7 @@ end @test metafree(pm) === p @test propertynames(pm) == (:position, :a, :b) @test GeometryBasics.MetaFree(typeof(pm)) == Point{2,Float64} + @test_broken zero(pm) == [0, 0] end @testset "MultiPoint with metadata" begin From 302fdb08f2072826300a7426c4ac2e27c6e97d59 Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Fri, 22 Jan 2021 15:00:01 +0100 Subject: [PATCH 4/4] Add Julia 1.3 to CI matrix --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9627234a..33d975ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ jobs: fail-fast: false matrix: version: + - '1.3' - '1' - 'nightly' os: