Skip to content

Commit

Permalink
Merge pull request #64 from JuliaGeo/features_fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
evetion authored Jun 23, 2022
2 parents 608717d + 94bb30a commit abcac34
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 16 deletions.
35 changes: 24 additions & 11 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
keys = reduce(K; init=()) do acc, k
k == :geometry ? acc : (acc..., k)
end
return NamedTuple{keys}(nt)
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
1 change: 0 additions & 1 deletion src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions src/types.jl
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
4 changes: 3 additions & 1 deletion test/test_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

2 comments on commit abcac34

@evetion
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/62927

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.1 -m "<description of version>" abcac342dbab4f6afdf390863affcf078b713215
git push origin v1.0.1

Please sign in to comment.