Skip to content

Commit

Permalink
Merge pull request #49 from JuliaGeo/check
Browse files Browse the repository at this point in the history
some editing of #33
  • Loading branch information
evetion committed May 15, 2022
2 parents ccd276a + cfadd5e commit 8468fa9
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 149 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
/docs/build/
.DS_Store
docs/src/reference/integrations.md

15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
[![Build Status](https://github.com/JuliaGeo/GeoInterface.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/JuliaGeo/GeoInterface.jl/actions/workflows/CI.yml?query=branch%3Amain)

# GeoInterface
An interface for geospatial vector data in Julia
An interface for geospatial vector data in [Julia](https://julialang.org/).

This Package describe a set of traits based on the [Simple Features standard (SF)](https://www.opengeospatial.org/standards/sfa)
for geospatial vector data, including the SQL/MM extension with support for circular geometry.
Using these traits, it should be easy to parse, serialize and use different geometries in the Julia ecosystem,
without knowing the specifics of each individual package. In that regard it is similar to Tables.jl, but for geometries instead of tables.
This Package describe a set of traits based on the [Simple Features standard
(SF)](https://www.opengeospatial.org/standards/sfa) for geospatial vector data, including
the SQL/MM extension with support for circular geometry. Using these traits, it should be
easy to parse, serialize and use different geometries in the Julia ecosystem, without
knowing the specifics of each individual package. In that regard it is similar to
[Tables.jl](https://github.com/JuliaData/Tables.jl), but for geometries instead of tables.

Packages which support the GeoInterface.jl interface can be found in [INTEGRATIONS.md](INTEGRATIONS.md).
Packages which support the GeoInterface.jl interface can be found in
[INTEGRATIONS.md](INTEGRATIONS.md).

We thank Julia Computing for supporting contributions to this package.
12 changes: 6 additions & 6 deletions docs/src/guides/defaults.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ endpoint(geom) = getpoint(geom, length(geom))
In some cases, we know the return value of a function for a specific geometry (sub)type beforehand and have implemented them.

```julia
npoint(::LineTrait, _) = 2
npoint(::TriangleTrait, _) = 3
npoint(::RectangleTrait, _) = 4
npoint(::QuadTrait, _) = 4
npoint(::PentagonTrait, _) = 5
npoint(::HexagonTrait, _) = 6
npoint(::LineTrait, geom) = 2
npoint(::TriangleTrait, geom) = 3
npoint(::RectangleTrait, geom) = 4
npoint(::QuadTrait, geom) = 4
npoint(::PentagonTrait, geom) = 5
npoint(::HexagonTrait, geom) = 6
```
74 changes: 37 additions & 37 deletions docs/src/guides/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Last but not least, we also provide an interface for features--geometries with p

```julia
GeoInterface.isgeometry(geom::customgeom)::Bool = true
GeoInterface.geomtype(geom::customgeom)::DataType = GeoInterface.XTrait() # <: AbstractGeometryTrait
GeoInterface.geomtype(geom::customgeom)::DataType = XTrait() # <: AbstractGeometryTrait
# for PointTraits
GeoInterface.ncoord(geomtype(geom), geom::customgeom)::Integer
GeoInterface.getcoord(geomtype(geom), geom::customgeom, i)::Real
Expand Down Expand Up @@ -93,79 +93,79 @@ GeoInterface.isgeometry(geom::customgeom)::Bool = true

A `geom::customgeom` with "Point"-like traits implements
```julia
GeoInterface.geomtype(geom::customgeom)::DataType = GeoInterface.PointTrait()
GeoInterface.ncoord(::GeoInterface.PointTrait, geom::customgeom)::Integer
GeoInterface.getcoord(::GeoInterface.PointTrait, geom::customgeom, i)::Real
GeoInterface.geomtype(geom::customgeom)::DataType = PointTrait()
GeoInterface.ncoord(::PointTrait, geom::customgeom)::Integer
GeoInterface.getcoord(::PointTrait, geom::customgeom, i)::Real

# Defaults
GeoInterface.ngeom(::GeoInterface.PointTrait, geom)::Integer = 0
GeoInterface.getgeom(::GeoInterface.PointTrait, geom::customgeom, i) = nothing
GeoInterface.ngeom(::PointTrait, geom)::Integer = 0
GeoInterface.getgeom(::PointTrait, geom::customgeom, i) = nothing
```

A `geom::customgeom` with "LineString"-like traits implements the following methods:
```julia
GeoInterface.geomtype(geom::customgeom)::DataType = GeoInterface.LineStringTrait()
GeoInterface.ncoord(::GeoInterface.LineStringTrait, geom::customgeom)::Integer
GeoInterface.geomtype(geom::customgeom)::DataType = LineStringTrait()
GeoInterface.ncoord(::LineStringTrait, geom::customgeom)::Integer

# These alias for npoint and getpoint
GeoInterface.ngeom(::GeoInterface.LineStringTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.LineStringTrait, geom::customgeom, i) # of geomtype Point
GeoInterface.ngeom(::LineStringTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::LineStringTrait, geom::customgeom, i) # of geomtype Point

# Optional
GeoInterface.isclosed(::GeoInterface.LineStringTrait, geom::customgeom)::Bool
GeoInterface.issimple(::GeoInterface.LineStringTrait, geom::customgeom)::Bool
GeoInterface.length(::GeoInterface.LineStringTrait, geom::customgeom)::Real
GeoInterface.isclosed(::LineStringTrait, geom::customgeom)::Bool
GeoInterface.issimple(::LineStringTrait, geom::customgeom)::Bool
GeoInterface.length(::LineStringTrait, geom::customgeom)::Real
```
A `geom::customgeom` with "Polygon"-like traits can implement the following methods:
```julia
GeoInterface.geomtype(geom::customgeom)::DataType = GeoInterface.PolygonTrait()
GeoInterface.ncoord(::GeoInterface.PolygonTrait, geom::customgeom)::Integer
GeoInterface.geomtype(geom::customgeom)::DataType = PolygonTrait()
GeoInterface.ncoord(::PolygonTrait, geom::customgeom)::Integer

# These alias for nring and getring
GeoInterface.ngeom(::GeoInterface.PolygonTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.PolygonTrait, geom::customgeom, i)::"LineStringTrait"
GeoInterface.ngeom(::PolygonTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::PolygonTrait, geom::customgeom, i)::"LineStringTrait"

# Optional
GeoInterface.area(::GeoInterface.PolygonTrait, geom::customgeom)::Real
GeoInterface.centroid(::GeoInterface.PolygonTrait, geom::customgeom)::"PointTrait"
GeoInterface.pointonsurface(::GeoInterface.PolygonTrait, geom::customgeom)::"PointTrait"
GeoInterface.boundary(::GeoInterface.PolygonTrait, geom::customgeom)::"LineStringTrait"
GeoInterface.area(::PolygonTrait, geom::customgeom)::Real
GeoInterface.centroid(::PolygonTrait, geom::customgeom)::"PointTrait"
GeoInterface.pointonsurface(::PolygonTrait, geom::customgeom)::"PointTrait"
GeoInterface.boundary(::PolygonTrait, geom::customgeom)::"LineStringTrait"
```

A `geom::customgeom` with "GeometryCollection"-like traits has to implement the following methods:
```julia
GeoInterface.geomtype(geom::customgeom) = GeoInterface.GeometryCollectionTrait()
GeoInterface.ncoord(::GeoInterface.GeometryCollectionTrait, geom::customgeom)::Integer
GeoInterface.ngeom(::GeoInterface.GeometryCollectionTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.GeometryCollectionTrait,geom::customgeomm, i)::"GeometryTrait"
GeoInterface.geomtype(geom::customgeom) = GeometryCollectionTrait()
GeoInterface.ncoord(::GeometryCollectionTrait, geom::customgeom)::Integer
GeoInterface.ngeom(::GeometryCollectionTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeometryCollectionTrait,geom::customgeomm, i)::"GeometryTrait"
```

A `geom::customgeom` with "MultiPoint"-like traits has to implement the following methods:
```julia
GeoInterface.geomtype(geom::customgeom) = GeoInterface.MultiPointTrait()
GeoInterface.ncoord(::GeoInterface.MultiPointTrait, geom::customgeom)::Integer
GeoInterface.geomtype(geom::customgeom) = MultiPointTrait()
GeoInterface.ncoord(::MultiPointTrait, geom::customgeom)::Integer

# These alias for npoint and getpoint
GeoInterface.ngeom(::GeoInterface.MultiPointTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.MultiPointTrait, geom::customgeom, i)::"PointTrait"
GeoInterface.ngeom(::MultiPointTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::MultiPointTrait, geom::customgeom, i)::"PointTrait"
```

A `geom::customgeom` with "MultiLineString"-like traits has to implement the following methods:
```julia
GeoInterface.geomtype(geom::customgeom) = GeoInterface.MultiLineStringTrait()
GeoInterface.ncoord(::GeoInterface.MultiLineStringTrait, geom::customgeom)::Integer
GeoInterface.geomtype(geom::customgeom) = MultiLineStringTrait()
GeoInterface.ncoord(::MultiLineStringTrait, geom::customgeom)::Integer

# These alias for nlinestring and getlinestring
GeoInterface.ngeom(::GeoInterface.MultiLineStringTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.MultiLineStringTrait,geom::customgeomm, i)::"LineStringTrait"
GeoInterface.ngeom(::MultiLineStringTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::MultiLineStringTrait,geom::customgeomm, i)::"LineStringTrait"
```

A `geom::customgeom` with "MultiPolygon"-like traits has to implement the following methods:
```julia
GeoInterface.geomtype(geom::customgeom) = GeoInterface.MultiPolygonTrait()
GeoInterface.ncoord(::GeoInterface.MultiPolygonTrait, geom::customgeom)::Integer
GeoInterface.geomtype(geom::customgeom) = MultiPolygonTrait()
GeoInterface.ncoord(::MultiPolygonTrait, geom::customgeom)::Integer

# These alias for npolygon and getpolygon
GeoInterface.ngeom(::GeoInterface.MultiPolygonTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::GeoInterface.MultiPolygonTrait, geom::customgeom, i)::"PolygonTrait"
GeoInterface.ngeom(::MultiPolygonTrait, geom::customgeom)::Integer
GeoInterface.getgeom(::MultiPolygonTrait, geom::customgeom, i)::"PolygonTrait"
```
4 changes: 2 additions & 2 deletions docs/src/tutorials/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ julia> geom = createpolygon(...)::ArchGDAL.IGeometry # no idea about the interf
julia> isgeometry(geom)
True
julia> geomtype(geom)
GeoInterface.PolygonTrait()
PolygonTrait()
julia> ext = exterior(geom);
julia> geomtype(ext)
GeoInterface.LineStringTrait()
LineStringTrait()
julia> getcoords.(getpoint.(Ref(ext), 1:npoint(ext)))
[[1.,2.],[2.,3.],[1.,2.]]
julia> coordinates(geom) # fallback based on ngeom & npoint above
Expand Down
4 changes: 2 additions & 2 deletions find_integrations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
###
### Usage
###
### 1. ensure a development version of Tables.jl (`pkg> add GeoInterface`)
### 1. ensure a development version of GeoInterface.jl (`pkg> add GeoInterface`)
### 2. make sure the General registry is up to date (`pkg> up`)
### 3. run this script, which uses the first depot from DEPOT_PATH

DEPOT = first(DEPOT_PATH)
REGISTRIES = joinpath(DEPOT, "registries")
@info DEPOT
# find each package w/ a direct dependency on Tables.jl
# find each package w/ a direct dependency on GeoInterface.jl
general = joinpath(DEPOT, "General")
mkpath(general)
# run(`tar -xzf General.tar.gz -C $general`)
Expand Down
52 changes: 41 additions & 11 deletions src/GeoInterface.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
module GeoInterface

using Base.Iterators
using Base.Iterators: flatten

export testgeometry, isgeometry, geomtype, ncoord, getcoord, ngeom, getgeom

# traits
export AbstractGeometryTrait,
AbstractGeometryCollectionTrait,
GeometryCollectionTrait,
AbstractPointTrait,
PointTrait,
AbstractCurveTrait,
AbstractLineStringTrait,
LineStringTrait,
LineTrait,
LinearRingTrait,
CircularStringTrait,
CompoundCurveTrait,
AbstractSurfaceTrait,
AbstractCurvePolygonTrait,
CurvePolygonTrait,
AbstractPolygonTrait,
PolygonTrait,
TriangleTrait,
RectangleTrait,
QuadTrait,
PentagonTrait,
HexagonTrait,
AbstractPolyHedralSurfaceTrait,
PolyHedralSurfaceTrait,
TINTrait,
AbstractMultiPointTrait,
MultiPointTrait,
AbstractMultiCurveTrait,
MultiCurveTrait,
AbstractMultiLineStringTrait,
MultiLineStringTrait,
AbstractMultiSurfaceTrait,
MultiSurfaceTrait,
AbstractMultiPolygonTrait,
MultiPolygonTrait

include("types.jl")
include("interface.jl")
include("defaults.jl")
include("fallbacks.jl")
include("utils.jl")

export testgeometry
export isgeometry

export geomtype
export ncoord
export getcoord
export ngeom
export getgeom

end # module
40 changes: 20 additions & 20 deletions src/defaults.jl → src/fallbacks.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Defaults for many of the interface functions are defined here as fallback.
# Methods here should take a type as first argument and should already be defined
# Methods here should take a trait instance as first argument and should already be defined
# in the `interface.jl` first as a generic f(geom) method.

## Coords
Expand Down Expand Up @@ -66,17 +66,17 @@ getgeom(t::AbstractGeometryTrait, geom) = (getgeom(t, geom, i) for i in 1:ngeom(
getcoord(t::AbstractPointTrait, geom) = (getcoord(t, geom, i) for i in 1:ncoord(t, geom))

## Npoints
npoint(::LineTrait, _) = 2
npoint(::TriangleTrait, _) = 3
nring(::TriangleTrait, _) = 1
npoint(::RectangleTrait, _) = 4
nring(::RectangleTrait, _) = 1
npoint(::QuadTrait, _) = 4
nring(::QuadTrait, _) = 1
npoint(::PentagonTrait, _) = 5
nring(::PentagonTrait, _) = 1
npoint(::HexagonTrait, _) = 6
nring(::HexagonTrait, _) = 1
npoint(::LineTrait, geom) = 2
npoint(::TriangleTrait, geom) = 3
nring(::TriangleTrait, geom) = 1
npoint(::RectangleTrait, geom) = 4
nring(::RectangleTrait, geom) = 1
npoint(::QuadTrait, geom) = 4
nring(::QuadTrait, geom) = 1
npoint(::PentagonTrait, geom) = 5
nring(::PentagonTrait, geom) = 1
npoint(::HexagonTrait, geom) = 6
nring(::HexagonTrait, geom) = 1

issimple(::AbstractCurveTrait, geom) =
allunique([getpoint(t, geom, i) for i in 1:npoint(geom)-1]) && allunique([getpoint(t, geom, i) for i in 2:npoint(t, geom)])
Expand Down Expand Up @@ -107,21 +107,21 @@ end
"""
subtrait(t::AbstractGeometryTrait)
Gets the expected, possible abstract, (sub)trait for subgeometries (retrieved with [`getgeom`](@ref)) of trait `t`.
This follows the [Type hierarchy](@ref) of Simple Features.
Gets the expected, possible abstract, (sub)trait for subgeometries (retrieved with
[`getgeom`](@ref)) of trait `t`. This follows the [Type hierarchy](@ref) of Simple Features.
# Examples
```jldoctest; setup = :(using GeoInterface)
julia> GeoInterface.subtrait(GeoInterface.LineStringTrait())
GeoInterface.AbstractPointTrait
julia> GeoInterface.subtrait(GeoInterface.PolygonTrait()) # Any of LineStringTrait, LineTrait, LinearRingTrait
GeoInterface.AbstractLineStringTrait
julia> GeoInterface.subtrait(LineStringTrait())
AbstractPointTrait
julia> GeoInterface.subtrait(PolygonTrait()) # Any of LineStringTrait, LineTrait, LinearRingTrait
AbstractLineStringTrait
```
```jldoctest; setup = :(using GeoInterface)
# `nothing` is returned when there's no subtrait or when it's not known beforehand
julia> isnothing(GeoInterface.subtrait(GeoInterface.PointTrait()))
julia> isnothing(GeoInterface.subtrait(PointTrait()))
true
julia> isnothing(GeoInterface.subtrait(GeoInterface.GeometryCollectionTrait()))
julia> isnothing(GeoInterface.subtrait(GeometryCollectionTrait()))
true
```
"""
Expand Down
17 changes: 9 additions & 8 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
GeoInterface.isgeometry(x) => Bool
Check if an object `x` is a geometry and thus implicitely supports GeoInterface methods.
Check if an object `x` is a geometry and thus implicitly supports GeoInterface methods.
It is recommended that for users implementing `MyType`, they define only
`isgeometry(::Type{MyType})`. `isgeometry(::MyType)` will then automatically delegate to this
method.
Expand All @@ -13,12 +13,13 @@ isgeometry(::Type{T}) where {T} = false
"""
GeoInterface.isfeature(x) => Bool
Check if an object `x` is a feature and thus implicitely supports some GeoInterface methods.
Check if an object `x` is a feature and thus implicitly supports some GeoInterface methods.
A feature is a combination of a geometry and properties, not unlike a row in a table.
It is recommended that for users implementing `MyType`, they define only
`isfeature(::Type{MyType})`. `isfeature(::MyType)` will then automatically delegate to this
method.
Ensures backwards compatibility with the older GeoInterface.
Ensures backwards compatibility with GeoInterface version 0.
"""
isfeature(x::T) where {T} = isfeature(T)
isfeature(::Type{T}) where {T} = false
Expand All @@ -27,22 +28,22 @@ isfeature(::Type{T}) where {T} = false
GeoInterface.geometry(feat) => geom
Retrieve the geometry of `feat`. It is expected that `isgeometry(geom) === true`.
Ensures backwards compatibility with the older GeoInterface.
Ensures backwards compatibility with GeoInterface version 0.
"""
geometry(feat) = nothing

"""
GeoInterface.properties(feat) => properties
Retrieve the properties of `feat`. This can be any Iterable that behaves like an AbstractRow.
Ensures backwards compatibility with the older GeoInterface.
Ensures backwards compatibility with GeoInterface version 0.
"""
properties(feat) = nothing

"""
GeoInterface.geomtype(geom) => T <: AbstractGeometry
Returns the geometry type, such as [`GeoInterface.PolygonTrait`](@ref) or [`GeoInterface.PointTrait`](@ref).
Returns the geometry type, such as [`PolygonTrait`](@ref) or [`PointTrait`](@ref).
"""
geomtype(geom) = nothing

Expand Down Expand Up @@ -375,7 +376,7 @@ extent(geom) = extent(geomtype(geom), geom)
Alias for [`extent`](@ref), for compatibility with
GeoJSON and the Python geointerface.
Ensures backwards compatibility with the older GeoInterface.
Ensures backwards compatibility with GeoInterface version 0.
"""
bbox(geom) = extent(geom)

Expand Down Expand Up @@ -550,7 +551,7 @@ ismeasured(geom) = ismeasured(geomtype(geom), geom)
coordinates(geom) -> Vector
Return (an iterator of) point coordinates.
Ensures backwards compatibility with the older GeoInterface.
Ensures backwards compatibility with GeoInterface version 0.
"""
coordinates(geom) = coordinates(geomtype(geom), geom)

Expand Down
Loading

0 comments on commit 8468fa9

Please sign in to comment.