From decc73d5ff3541d3ec360941c22eef0cc869a1f9 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Mon, 16 May 2022 21:28:12 +0200 Subject: [PATCH 1/5] Add implementations for Base types. --- docs/src/guides/defaults.md | 14 ++++++++++++++ src/GeoInterface.jl | 1 + src/base.jl | 19 +++++++++++++++++++ src/utils.jl | 4 ++-- test/test_primitives.jl | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/base.jl diff --git a/docs/src/guides/defaults.md b/docs/src/guides/defaults.md index 7157b7fa..e22a58eb 100644 --- a/docs/src/guides/defaults.md +++ b/docs/src/guides/defaults.md @@ -45,3 +45,17 @@ npoint(::QuadTrait, geom) = 4 npoint(::PentagonTrait, geom) = 5 npoint(::HexagonTrait, geom) = 6 ``` + +# Implementations +GeoInterface is implemented automatically for `NTuple`s, `NamedTuple`s and `Vector`s to behave as Points. + +```julia +a = [1,2,3] +x(a) == 1 + +b = (1,2,3) +x(b) == 2 + +c = (;X=1, Y=2) +x(c) == 1 +``` diff --git a/src/GeoInterface.jl b/src/GeoInterface.jl index 1d4a4037..ed9925db 100644 --- a/src/GeoInterface.jl +++ b/src/GeoInterface.jl @@ -45,5 +45,6 @@ include("types.jl") include("interface.jl") include("fallbacks.jl") include("utils.jl") +include("base.jl") end # module diff --git a/src/base.jl b/src/base.jl new file mode 100644 index 00000000..4210573c --- /dev/null +++ b/src/base.jl @@ -0,0 +1,19 @@ +# Implementation of GeoInterface for Base Types + +GeoInterface.isgeometry(::Type{<:AbstractVector{<:Real}}) = true +GeoInterface.geomtrait(::AbstractVector{<:Real}) = PointTrait() +GeoInterface.ncoord(::PointTrait, geom::AbstractVector{<:Real}) = Base.length(geom) +GeoInterface.getcoord(::PointTrait, geom::AbstractVector{<:Real}, i) = getindex(geom, i) + +GeoInterface.isgeometry(::Type{<:NTuple{N,<:Real}}) where {N} = true +GeoInterface.geomtrait(::NTuple{N,<:Real}) where {N} = PointTrait() +GeoInterface.ncoord(::PointTrait, geom::NTuple{N,<:Real}) where {N} = N +GeoInterface.getcoord(::PointTrait, geom::NTuple{N,<:Real}, i) where {N} = getindex(geom, i) + +for i in 2:4 + sig = NamedTuple{default_coord_names[1:i],NTuple{i,T}} where {T<:Real} + GeoInterface.isgeometry(::Type{<:sig}) = true + GeoInterface.geomtrait(::sig) = PointTrait() + GeoInterface.ncoord(::PointTrait, geom::sig) = i + GeoInterface.getcoord(::PointTrait, geom::sig, i) = getindex(geom, i) +end diff --git a/src/utils.jl b/src/utils.jl index 1915724f..003299f3 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,7 +1,7 @@ """Test whether the required interface for your `geom` has been implemented correctly.""" function testgeometry(geom) try - @assert isgeometry(geom) + @assert isgeometry(geom) "Geom doesn't implement `isgeometry`." type = geomtrait(geom) if type == PointTrait() @@ -18,7 +18,7 @@ function testgeometry(geom) issub = geomtrait(g2) isa subtype !issub && error("Implemented hierarchy for this geometry type is incorrect. Subgeometry should be a $subtype") end - @assert testgeometry(g2) # recursive testing of subgeometries + @assert testgeometry(g2) "Subgeometry implementation is not valid." end end catch e diff --git a/test/test_primitives.jl b/test/test_primitives.jl index 1c2c7d96..6d53b781 100644 --- a/test/test_primitives.jl +++ b/test/test_primitives.jl @@ -290,3 +290,37 @@ end @test GeoInterface.astext(geom) isa String @test GeoInterface.asbinary(geom) isa Vector{UInt8} end + +@testset "Base Implementations" begin + + @testset "Vector" begin + geom = [1, 2] + @test testgeometry(geom) + @test GeoInterface.x(geom) == 1 + @test GeoInterface.ncoord(geom) == 2 + @test collect(GeoInterface.getcoord(geom)) == geom + end + + @testset "Tuple" begin + geom = (1, 2) + @test testgeometry(geom) + @test GeoInterface.x(geom) == 1 + @test GeoInterface.ncoord(geom) == 2 + @test collect(GeoInterface.getcoord(geom)) == [1, 2] + end + + @testset "NamedTuple" begin + geom = (; X=1, Y=2) + @test testgeometry(geom) + geom = (; X=1, Y=2, Z=3) + @test testgeometry(geom) + geom = (; X=1, Y=2, Z=3, M=4) + @test testgeometry(geom) + + @test GeoInterface.x(geom) == 1 + @test GeoInterface.m(geom) == 4 + @test GeoInterface.ncoord(geom) == 4 + @test collect(GeoInterface.getcoord(geom)) == [1, 2, 3, 4] + + end +end From d554c549c1d4d2045f50eb6654da0463bf8f8bff Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Mon, 16 May 2022 21:31:05 +0200 Subject: [PATCH 2/5] Document Base implementations. --- docs/src/guides/defaults.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/guides/defaults.md b/docs/src/guides/defaults.md index e22a58eb..614380ce 100644 --- a/docs/src/guides/defaults.md +++ b/docs/src/guides/defaults.md @@ -51,11 +51,11 @@ GeoInterface is implemented automatically for `NTuple`s, `NamedTuple`s and `Vect ```julia a = [1,2,3] -x(a) == 1 +GeoInterface.x(a) == 1 b = (1,2,3) -x(b) == 2 +GeoInterface.y(b) == 2 -c = (;X=1, Y=2) -x(c) == 1 +c = (;X=1, Y=2, Z=3) +GeoInterface.z(c) == 3 ``` From 1f97721bed8fec49021f18b3263c7d0175fde73d Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Mon, 16 May 2022 22:20:17 +0200 Subject: [PATCH 3/5] Implementations for custom order NamedTuple. --- src/base.jl | 7 +++++++ test/test_primitives.jl | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/base.jl b/src/base.jl index 4210573c..9a64a832 100644 --- a/src/base.jl +++ b/src/base.jl @@ -17,3 +17,10 @@ for i in 2:4 GeoInterface.ncoord(::PointTrait, geom::sig) = i GeoInterface.getcoord(::PointTrait, geom::sig, i) = getindex(geom, i) end + +# Custom coordinate order/names NamedTuple +GeoInterface.isgeometry(::Type{<:NamedTuple{Keys,NTuple{N,T}}}) where {Keys,N,T<:Real} = all(in(default_coord_names), Keys) +GeoInterface.geomtrait(::NamedTuple{Keys,NTuple{N,T}}) where {Keys,N,T<:Real} = PointTrait() +GeoInterface.ncoord(::PointTrait, geom::NamedTuple{Keys,NTuple{N,T}}) where {Keys,N,T<:Real} = Base.length(geom) +GeoInterface.getcoord(::PointTrait, geom::NamedTuple{Keys,NTuple{N,T}}, i) where {Keys,N,T<:Real} = getindex(geom, i) +GeoInterface.coordnames(::PointTrait, geom::NamedTuple{Keys,NTuple{N,T}}) where {Keys,N,T<:Real} = Keys diff --git a/test/test_primitives.jl b/test/test_primitives.jl index 6d53b781..d814dcc0 100644 --- a/test/test_primitives.jl +++ b/test/test_primitives.jl @@ -312,15 +312,20 @@ end @testset "NamedTuple" begin geom = (; X=1, Y=2) @test testgeometry(geom) + @test GeoInterface.x(geom) == 1 + @test collect(GeoInterface.getcoord(geom)) == [1, 2] + geom = (; X=1, Y=2, Z=3) @test testgeometry(geom) geom = (; X=1, Y=2, Z=3, M=4) @test testgeometry(geom) + geom = (; Z=3, X=1, Y=2, M=4) + @test testgeometry(geom) @test GeoInterface.x(geom) == 1 @test GeoInterface.m(geom) == 4 @test GeoInterface.ncoord(geom) == 4 - @test collect(GeoInterface.getcoord(geom)) == [1, 2, 3, 4] + @test collect(GeoInterface.getcoord(geom)) == [3, 1, 2, 4] end end From 2e4a2aa0be4e0cdaece7bfaaac9752683c458a25 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Tue, 17 May 2022 08:05:08 +0200 Subject: [PATCH 4/5] Clarified documentation. --- docs/src/guides/defaults.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/guides/defaults.md b/docs/src/guides/defaults.md index 614380ce..87e1d40b 100644 --- a/docs/src/guides/defaults.md +++ b/docs/src/guides/defaults.md @@ -47,7 +47,7 @@ npoint(::HexagonTrait, geom) = 6 ``` # Implementations -GeoInterface is implemented automatically for `NTuple`s, `NamedTuple`s and `Vector`s to behave as Points. +GeoInterface is implemented for `NTuple`s, `NamedTuple`s and `AbstractVector`s to behave as Points. Note the `eltype` in all cases should be a `Real`. Only the keys `X`, `Y`, `Z`, and `M` are supported for `NamedTuple`s. ```julia a = [1,2,3] From e1b3d9b04b009e23c6eb11e73d87344a10e6bb2a Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Tue, 17 May 2022 18:53:31 +0200 Subject: [PATCH 5/5] Update defaults.md --- docs/src/guides/defaults.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/guides/defaults.md b/docs/src/guides/defaults.md index 87e1d40b..f2d6811f 100644 --- a/docs/src/guides/defaults.md +++ b/docs/src/guides/defaults.md @@ -50,10 +50,10 @@ npoint(::HexagonTrait, geom) = 6 GeoInterface is implemented for `NTuple`s, `NamedTuple`s and `AbstractVector`s to behave as Points. Note the `eltype` in all cases should be a `Real`. Only the keys `X`, `Y`, `Z`, and `M` are supported for `NamedTuple`s. ```julia -a = [1,2,3] +a = [1, 2, 3] GeoInterface.x(a) == 1 -b = (1,2,3) +b = (1, 2, 3) GeoInterface.y(b) == 2 c = (;X=1, Y=2, Z=3)