From 3b7ea4778d82aad258ee524c68a0c843f50fe139 Mon Sep 17 00:00:00 2001 From: rafaqz Date: Mon, 20 Jun 2022 17:34:55 +0400 Subject: [PATCH 1/5] traits are all AbstractTrait --- src/types.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/types.jl b/src/types.jl index a1462afd..1a81cf87 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,5 +1,7 @@ +"An AbstractTrait type for all geometries, features and feature collections." +abstract type AbstractTrait end "An AbstractGeometryTrait type for all geometries." -abstract type AbstractGeometryTrait end +abstract type AbstractGeometryTrait <: AbstractTrait end "An AbstractGeometryCollectionTrait type for all geometrycollections." abstract type AbstractGeometryCollectionTrait <: AbstractGeometryTrait end @@ -82,11 +84,11 @@ struct MultiPolygonTrait <: AbstractMultiPolygonTrait end "An AbstractFeatureTrait for all features" -abstract type AbstractFeatureTrait end +abstract type AbstractFeatureTrait <: AbstractTrait end "A FeatureTrait holds `geometries`, `properties` and an `extent`" struct FeatureTrait <: AbstractFeatureTrait end "An AbstractFeatureCollectionTrait for all feature collections" -abstract type AbstractFeatureCollectionTrait end +abstract type AbstractFeatureCollectionTrait <: AbstractTrait end "A FeatureCollectionTrait holds objects of `FeatureTrait` and an `extent`" struct FeatureCollectionTrait <: AbstractFeatureCollectionTrait end From 23314e4adaf265a7f8aab7b6992506ed24a2438e Mon Sep 17 00:00:00 2001 From: rafaqz Date: Mon, 20 Jun 2022 19:30:31 +0400 Subject: [PATCH 2/5] drop :properties field from NamedTuple feature definition --- src/base.jl | 35 ++++++++++++++++++++++++----------- test/test_primitives.jl | 4 +++- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/base.jl b/src/base.jl index 60238078..69a6da4c 100644 --- a/src/base.jl +++ b/src/base.jl @@ -28,17 +28,30 @@ GeoInterface.coordnames(::PointTrait, geom::NamedTuple{Keys,NTuple{N,T}}) where # Default features using NamedTuple and AbstractArray -const NamedTupleFeature = NamedTuple{(:geometry, :properties)} +# Any named tuple with a `:geometry` field is a feature +_is_namedtuple_feature(::Type{<:NamedTuple{K}}) where K = :geometry in K +_is_namedtuple_feature(nt::NamedTuple) = _is_namedtuple_feature(typeof(nt)) + +GeoInterface.isfeature(T::Type{<:NamedTuple}) = _is_namedtuple_feature(T) +GeoInterface.trait(nt::NamedTuple) = _is_namedtuple_feature(nt) ? FeatureTrait() : nothing +GeoInterface.geometry(nt::NamedTuple) = _is_namedtuple_feature(nt) ? nt.geometry : nothing +GeoInterface.properties(nt::NamedTuple) = _is_namedtuple_feature(nt) ? _nt_properties(nt) : nothing + +# Use Val to force constant propagation through `reduce` +function _nt_properties(nt::NamedTuple{K}) where K + valkeys = reduce(K; init=()) do acc, k + k == :geometry ? acc : (acc..., k) + end + return nt[valkeys] +end -GeoInterface.isfeature(::Type{<:NamedTupleFeature}) = true -GeoInterface.trait(::NamedTupleFeature) = FeatureTrait() -GeoInterface.geometry(f::NamedTupleFeature) = f.geometry -GeoInterface.properties(f::NamedTupleFeature) = f.properties +const MaybeArrayFeatureCollection = AbstractArray{<:NamedTuple} -const ArrayFeatureCollection = AbstractArray{<:NamedTupleFeature} +_is_array_featurecollection(::Type{<:AbstractArray{T}}) where {T<:NamedTuple} = _is_namedtuple_feature(T) +_is_array_featurecollection(A::AbstractArray{<:NamedTuple}) = _is_array_featurecollection(typeof(A)) -GeoInterface.isfeaturecollection(::Type{<:ArrayFeatureCollection}) = true -GeoInterface.trait(::ArrayFeatureCollection) = FeatureCollectionTrait() -GeoInterface.nfeature(::FeatureCollectionTrait, fc::ArrayFeatureCollection) = Base.length(fc) -GeoInterface.getfeature(::FeatureCollectionTrait, fc::ArrayFeatureCollection, i::Integer) = fc[i] -GeoInterface.geometrycolumns(fc::ArrayFeatureCollection) = (:geometry,) +GeoInterface.isfeaturecollection(T::Type{<:MaybeArrayFeatureCollection}) = _is_array_featurecollection(T) +GeoInterface.trait(fc::MaybeArrayFeatureCollection) = _is_array_featurecollection(fc) ? FeatureCollectionTrait() : nothing +GeoInterface.nfeature(::FeatureCollectionTrait, fc::MaybeArrayFeatureCollection) = _is_array_featurecollection(fc) ? Base.length(fc) : nothing +GeoInterface.getfeature(::FeatureCollectionTrait, fc::MaybeArrayFeatureCollection, i::Integer) = _is_array_featurecollection(fc) ? fc[i] : nothing +GeoInterface.geometrycolumns(fc::MaybeArrayFeatureCollection) = _is_array_featurecollection(fc) ? (:geometry,) : nothing diff --git a/test/test_primitives.jl b/test/test_primitives.jl index 37c16949..410ee7e6 100644 --- a/test/test_primitives.jl +++ b/test/test_primitives.jl @@ -344,7 +344,9 @@ end end @testset "NamedTupleFeature" begin - feature = (; geometry=(1, 2), properties=(a="x", b="y")) + feature = (; geometry=(1, 2), a="x", b="y", c="z") + GeoInterface.geometry(feature) = (1, 2) + @test GeoInterface.properties(feature) == (a="x", b="y", c="z") @test GeoInterface.testfeature(feature) @test GeoInterface.testfeaturecollection([feature, feature]) end From 234d7047e6e7a615c9bd6dc9d26138905c5773e1 Mon Sep 17 00:00:00 2001 From: rafaqz Date: Mon, 20 Jun 2022 21:03:29 +0400 Subject: [PATCH 3/5] subset with NamedTuple constructor not getindex, for 1.6 --- src/base.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base.jl b/src/base.jl index 69a6da4c..5169f27a 100644 --- a/src/base.jl +++ b/src/base.jl @@ -42,7 +42,7 @@ function _nt_properties(nt::NamedTuple{K}) where K valkeys = reduce(K; init=()) do acc, k k == :geometry ? acc : (acc..., k) end - return nt[valkeys] + return NamedTuple{valkeys}(nt) end const MaybeArrayFeatureCollection = AbstractArray{<:NamedTuple} From 1193cde64a52a9f5e936d08468a53532cbd64436 Mon Sep 17 00:00:00 2001 From: rafaqz Date: Mon, 20 Jun 2022 21:04:00 +0400 Subject: [PATCH 4/5] fix naming --- src/base.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base.jl b/src/base.jl index 5169f27a..9a54583e 100644 --- a/src/base.jl +++ b/src/base.jl @@ -39,10 +39,10 @@ GeoInterface.properties(nt::NamedTuple) = _is_namedtuple_feature(nt) ? _nt_prope # Use Val to force constant propagation through `reduce` function _nt_properties(nt::NamedTuple{K}) where K - valkeys = reduce(K; init=()) do acc, k + keys = reduce(K; init=()) do acc, k k == :geometry ? acc : (acc..., k) end - return NamedTuple{valkeys}(nt) + return NamedTuple{keys}(nt) end const MaybeArrayFeatureCollection = AbstractArray{<:NamedTuple} From 94bb30a94471393e966f1945dee780127ae8abd1 Mon Sep 17 00:00:00 2001 From: rafaqz Date: Wed, 22 Jun 2022 20:11:46 +0400 Subject: [PATCH 5/5] remove commented linje --- src/interface.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/interface.jl b/src/interface.jl index 5800e9de..bfa678c0 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -92,7 +92,6 @@ Returns the object type, such as [`FeatureTrait`](@ref). For all `isgeometry` objects `trait` is the same as `geomtrait(obj)`, e.g. [`PointTrait`](@ref). """ -# trait(geom::T) where T = isgeometry(T) ? geomtrait(geom) : nothing trait(geom) = geomtrait(geom) # All types