Skip to content

Commit

Permalink
Always use GeometryVector as column (currently a noop).
Browse files Browse the repository at this point in the history
  • Loading branch information
evetion committed Jan 30, 2025
1 parent 28c8481 commit eb37a18
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 59 deletions.
1 change: 1 addition & 0 deletions docs/src/reference/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add new driver framework to read files using native drivers.
- Added native driver package extensions on GeoJSON, ShapeFile, GeoParquet, GeoArrow and FlatGeobuf.
- Geometry columns are now wrapped in a GeometryVector, allowing for future improvements.
- Now exports GeoInterface methods instead of ArchGDAL methods for geometry operation.

## v0.3.11
- Changed `reproject` to work on a DataFrame, correctly setting the (crs) metadata
Expand Down
1 change: 1 addition & 0 deletions src/GeoDataFrames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import GeoInterface as GI
using DataAPI
using Reexport

include("vector.jl")
include("exports.jl")
include("drivers.jl")
include("io.jl")
Expand Down
72 changes: 22 additions & 50 deletions src/exports.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
@reexport using ArchGDAL:
@reexport using GeoInterface:
intersects, equals, disjoint, touches, crosses, within, contains, overlaps
@reexport using ArchGDAL: boundary, convexhull, buffer
@reexport using ArchGDAL: intersection, union, difference, symdifference, distance
@reexport using ArchGDAL: geomlength, geomarea, centroid
@reexport using ArchGDAL: isvalid, issimple, isring, geomarea, centroid
@reexport using ArchGDAL:
createpoint,
createlinestring,
createlinearring,
createpolygon,
createmultilinestring,
createmultipolygon
@reexport using GeoInterface: boundary, convexhull, buffer
@reexport using GeoInterface: intersection, union, difference, symdifference, distance
@reexport using GeoInterface: area, centroid
@reexport using GeoInterface: isvalid, issimple, isring, geomarea, centroid
# @reexport using GeoInterface:
# createpoint,
# createlinestring,
# createlinearring,
# createpolygon,
# createmultilinestring,
# createmultipolygon

@reexport using Extents
@reexport using GeoInterface: crs
Expand Down Expand Up @@ -49,41 +49,13 @@ export AbstractWellKnownText,
WellKnownText,
WellKnownText2 #=GeoJSON,=#

AG.intersects(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.intersects.(a, b)
AG.equals(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.equals.(a, b)
AG.disjoint(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.disjoint.(a, b)
AG.touches(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.touches.(a, b)
AG.crosses(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.crosses.(a, b)
AG.within(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.within.(a, b)
AG.contains(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.contains.(a, b)
AG.overlaps(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.overlaps.(a, b)
AG.intersection(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.intersection.(a, b)
AG.union(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.union.(a, b)
AG.difference(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.difference.(a, b)
AG.symdifference(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.symdifference.(a, b)
AG.distance(a::Vector{AG.IGeometry{T}}, b::Vector{AG.IGeometry{X}}) where {X, T} =
AG.distance.(a, b)

AG.boundary(v::Vector{AG.IGeometry{T}}) where {T} = AG.boundary.(v)
AG.convexhull(v::Vector{AG.IGeometry{T}}) where {T} = AG.convexhull.(v)
AG.buffer(v::Vector{AG.IGeometry{T}}, d) where {T} = AG.buffer.(v, d)
AG.transform!(v::Vector{AG.IGeometry{T}}, d) where {T} = AG.buffer.(v, d)
AG.geomlength(v::Vector{AG.IGeometry{T}}) where {T} = AG.geomlength.(v)
AG.geomarea(v::Vector{AG.IGeometry{T}}) where {T} = AG.geomarea.(v)
AG.centroid(v::Vector{AG.IGeometry{T}}) where {T} = AG.centroid.(v)
AG.isempty(v::Vector{AG.IGeometry{T}}) where {T} = AG.isempty.(v)
AG.isvalid(v::Vector{AG.IGeometry{T}}) where {T} = AG.isvalid.(v)
AG.issimple(v::Vector{AG.IGeometry{T}}) where {T} = AG.issimple.(v)
AG.isring(v::Vector{AG.IGeometry{T}}) where {T} = AG.isring.(v)
GI.boundary(v::GeometryVector) = GI.boundary.(v)
GI.convexhull(v::GeometryVector) = GI.convexhull.(v)

Check warning on line 53 in src/exports.jl

View check run for this annotation

Codecov / codecov/patch

src/exports.jl#L52-L53

Added lines #L52 - L53 were not covered by tests
GI.buffer(v::GeometryVector, d) = GI.buffer.(v, d)
GI.length(v::GeometryVector) = GI.geomlength.(v)
GI.area(v::GeometryVector) = GI.area.(v)
GI.centroid(v::GeometryVector) = GI.centroid.(v)
GI.isempty(v::GeometryVector) = GI.isempty.(v)
GI.isvalid(v::GeometryVector) = GI.isvalid.(v)
GI.issimple(v::GeometryVector) = GI.issimple.(v)
GI.isring(v::GeometryVector) = GI.isring.(v)

Check warning on line 61 in src/exports.jl

View check run for this annotation

Codecov / codecov/patch

src/exports.jl#L55-L61

Added lines #L55 - L61 were not covered by tests
12 changes: 5 additions & 7 deletions src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ Read a file into a DataFrame. Any kwargs are passed to the driver, by default se
function read(fn; kwargs...)
ext = last(splitext(fn))
dr = driver(ext)
read(dr, fn; kwargs...)
df = read(dr, fn; kwargs...)
for geom in getgeometrycolumns(df)
df[!, geom] = GeometryVector(df[!, geom])
end
df
end

@deprecate read(fn::AbstractString, layer::Union{AbstractString, Integer}; kwargs...) read(
Expand Down Expand Up @@ -93,12 +97,6 @@ function read(driver::ArchGDALDriver, fn::AbstractString; layer=nothing, kwargs.
return t
end

@deprecate read(fn::AbstractString, layer::Union{AbstractString, Integer}; kwargs...) read(
fn;
layer,
kwargs...,
)

function read(::ArchGDALDriver, ds, layer)
df, gnames, sr = AG.getlayer(ds, layer) do table
if table.ptr == C_NULL
Expand Down
21 changes: 21 additions & 0 deletions src/vector.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
GeometryVector(A)
A vector of geometries, as used in GeoDataFrames.
"""
struct GeometryVector{T} <: AbstractArray{T, 1}
A::Vector{T}
# TODO Add spatial index
# TODO Add crs
end

Base.parent(G::GeometryVector) = G.A
Base.size(G::GeometryVector) = size(parent(G))
Base.length(G::GeometryVector) = length(parent(G))
Base.IndexStyle(::Type{<:GeometryVector}) = IndexLinear()
# TODO Invalidate spatial index
Base.getindex(G::GeometryVector, i::Int) = getindex(parent(G), i)
Base.setindex!(G::GeometryVector, v, i::Int) = setindex!(parent(G), v, i)

# https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array
Base.similar(G::GeometryVector, ::Type{T}, dims::Dims) where {T} = GeometryVector(similar(parent(G), T, dims))
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ unknown_crs = GFT.WellKnownText(
end

@testset "Spatial operations" begin
table = DataFrame(; geometry = AG.createpoint.(coords), name = "test")
table = DataFrame(; geometry = GDF.GeometryVector(AG.createpoint.(coords)), name = "test")

# Buffer to also write polygons
table.geometry = AG.buffer(table.geometry, 10)
table.geometry = GDF.buffer(table.geometry, 10)
GDF.write(joinpath(testdatadir, "test_polygons.shp"), table)
GDF.write(joinpath(testdatadir, "test_polygons.gpkg"), table)
GDF.write(joinpath(testdatadir, "test_polygons.geojson"), table)
Expand Down

0 comments on commit eb37a18

Please sign in to comment.