diff --git a/.gitignore b/.gitignore index d32781d..a6a0e03 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ test/.cpenv .CondaPkg *.arrow +*.arrows # pixi environments .pixi diff --git a/src/arrow.jl b/src/arrow.jl index f756061..b405db2 100644 --- a/src/arrow.jl +++ b/src/arrow.jl @@ -10,26 +10,41 @@ WKB = Symbol("geoarrow.wkb") WKT = Symbol("geoarrow.wkt") BOX = Symbol("geoarrow.box") -function ArrowTypes.JuliaType(::Val{POINT}, x, metadata) - D = length(x.types) - T = x.types[1] - return Geometry{PointTrait,D,T} +# Helper to unwrap Union{Missing, T} to get T +_unwrap_type(::Type{Union{Missing,T}}) where {T} = T +_unwrap_type(::Type{T}) where {T} = T + +# Helper to get number of dimensions from a type +_ndims(::Type{<:NTuple{N,T}}) where {N,T} = N +_ndims(::Type{<:NamedTuple{names}}) where {names} = length(names) + +# Helper to get element type from a type +_eltype(::Type{<:NTuple{N,T}}) where {N,T} = T +_eltype(::Type{<:NamedTuple{names,<:Tuple{Vararg{T}}}}) where {names,T} = T + +function ArrowTypes.JuliaType(::Val{POINT}, x::Type, metadata) + T = _unwrap_type(x) + D = _ndims(T) + ET = _eltype(T) + return Geometry{PointTrait,D,ET} end -ArrowTypes.JuliaType(::Val{LINESTRING}, x, metadata) = Geometry{LineStringTrait} -ArrowTypes.JuliaType(::Val{POLYGON}, x, metadata) = Geometry{PolygonTrait} -ArrowTypes.JuliaType(::Val{MULTIPOINT}, x, metadata) = Geometry{MultiPointTrait} -ArrowTypes.JuliaType(::Val{MULTILINESTRING}, x, metadata) = Geometry{MultiLineStringTrait} -ArrowTypes.JuliaType(::Val{MULTIPOLYGON}, x, metadata) = Geometry{MultiPolygonTrait} -ArrowTypes.JuliaType(::Val{WKB}, x, metadata) = GeoFormatTypes.WellKnownBinary -ArrowTypes.JuliaType(::Val{WKT}, x, metadata) = GeoFormatTypes.WellKnownText -function ArrowTypes.JuliaType(::Val{BOX}, x, metadata) - D = length(x.types) +ArrowTypes.JuliaType(::Val{LINESTRING}, x::Type, metadata) = Geometry{LineStringTrait} +ArrowTypes.JuliaType(::Val{POLYGON}, x::Type, metadata) = Geometry{PolygonTrait} +ArrowTypes.JuliaType(::Val{MULTIPOINT}, x::Type, metadata) = Geometry{MultiPointTrait} +ArrowTypes.JuliaType(::Val{MULTILINESTRING}, x::Type, metadata) = Geometry{MultiLineStringTrait} +ArrowTypes.JuliaType(::Val{MULTIPOLYGON}, x::Type, metadata) = Geometry{MultiPolygonTrait} +ArrowTypes.JuliaType(::Val{WKB}, x::Type, metadata) = GeoFormatTypes.WellKnownBinary +ArrowTypes.JuliaType(::Val{WKT}, x::Type, metadata) = GeoFormatTypes.WellKnownText +function ArrowTypes.JuliaType(::Val{BOX}, x::Type, metadata) + T = _unwrap_type(x) + D = _ndims(T) + ET = _eltype(T) if D == 4 - Extents.Extent{(:X, :Y)} + Extents.Extent{(:X, :Y),NTuple{2,NTuple{2,ET}}} elseif D == 6 - Extents.Extent{(:X, :Y, :Z)} + Extents.Extent{(:X, :Y, :Z),NTuple{3,NTuple{2,ET}}} elseif D == 8 - Extents.Extent{(:X, :Y, :Z, :M)} + Extents.Extent{(:X, :Y, :Z, :M),NTuple{4,NTuple{2,ET}}} else throw(ArgumentError("Invalid number of dimensions for Extent")) end @@ -37,27 +52,30 @@ end ArrowTypes.ArrowKind(::Type{Geometry}) = ArrowTypes.ListKind() ArrowTypes.ArrowKind(::Type{<:Geometry{PointTrait,D,T}}) where {D,T} = ArrowTypes.FixedSizeListKind{D,T}() ArrowTypes.ArrowKind(::Type{Wrapper}) = ArrowTypes.ListKind() -ArrowTypes.ArrowKind(::Type{Wrapper{Seperated, T, G}}) where {T,G} = ArrowTypes.StructKind() -ArrowTypes.ArrowKind(::Type{Wrapper{Interleaved, T, N, G}}) where {T,N,G} = ArrowTypes.ListKind() -ArrowTypes.ArrowKind(::Type{Wrapper{Interleaved, PointTrait, N, G}}) where {N,G} = ArrowTypes.FixedSizeListKind{N,Float64}() -ArrowTypes.ArrowKind(::Type{Wrapper{WellKnownText, T, N, G}}) where {T,N,G} = ArrowTypes.ListKind() -ArrowTypes.ArrowKind(::Type{Wrapper{WellKnownBinary, T, N, G}}) where {T,N,G} = ArrowTypes.ListKind() +ArrowTypes.ArrowKind(::Type{Wrapper{Seperated,T,G}}) where {T,G} = ArrowTypes.StructKind() +ArrowTypes.ArrowKind(::Type{Wrapper{Interleaved,T,N,G}}) where {T,N,G} = ArrowTypes.ListKind() +ArrowTypes.ArrowKind(::Type{Wrapper{Interleaved,PointTrait,N,G}}) where {N,G} = ArrowTypes.FixedSizeListKind{N,Float64}() +ArrowTypes.ArrowKind(::Type{Wrapper{WellKnownText,T,N,G}}) where {T,N,G} = ArrowTypes.ListKind() +ArrowTypes.ArrowKind(::Type{Wrapper{WellKnownBinary,T,N,G}}) where {T,N,G} = ArrowTypes.ListKind() ArrowTypes.ArrowType(::Type{Geometry{X,D,T,G}}) where {X,D,T,G} = G ArrowTypes.ArrowType(::Type{Wrapper{WellKnownText,T,N,G}}) where {T,N,G} = String ArrowTypes.ArrowType(::Type{Wrapper{WellKnownBinary,T,N,G}}) where {T,N,G} = Vector{UInt8} ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,PointTrait,N,G}}) where {N,G} = NTuple{N,Float64} ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,LineStringTrait,N,G}}) where {N,G} = Vector{NTuple{N,Float64}} -ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,MultiLineStringTrait,N,G}}) where {N,G} = Vector{Vector{NTuple{N,Float64}}} +ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,MultiLineStringTrait,N,G}}) where {N,G} = Vector{Vector{NTuple{N,Float64}}} ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,MultiPointTrait,N,G}}) where {N,G} = Vector{NTuple{N,Float64}} ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,PolygonTrait,N,G}}) where {N,G} = Vector{Vector{NTuple{N,Float64}}} ArrowTypes.ArrowType(::Type{Wrapper{Interleaved,MultiPolygonTrait,N,G}}) where {N,G} = Vector{Vector{Vector{NTuple{N,Float64}}}} ArrowTypes.ArrowType(::Type{Wrapper{Seperated,PointTrait,N,G}}) where {N,G} = _named(NTuple{N,Float64}) ArrowTypes.ArrowType(::Type{Wrapper{Seperated,LineStringTrait,N,G}}) where {N,G} = Vector{_named(NTuple{N,Float64})} -ArrowTypes.ArrowType(::Type{Wrapper{Seperated,MultiLineStringTrait,N,G}}) where {N,G} = Vector{Vector{_named(NTuple{N,Float64})}} +ArrowTypes.ArrowType(::Type{Wrapper{Seperated,MultiLineStringTrait,N,G}}) where {N,G} = Vector{Vector{_named(NTuple{N,Float64})}} ArrowTypes.ArrowType(::Type{Wrapper{Seperated,MultiPointTrait,N,G}}) where {N,G} = Vector{_named(NTuple{N,Float64})} ArrowTypes.ArrowType(::Type{Wrapper{Seperated,PolygonTrait,N,G}}) where {N,G} = Vector{Vector{_named(NTuple{N,Float64})}} ArrowTypes.ArrowType(::Type{Wrapper{Seperated,MultiPolygonTrait,N,G}}) where {N,G} = Vector{Vector{Vector{_named(NTuple{N,Float64})}}} +ArrowTypes.ArrowType(::Type{<:Extents.Extent{(:X, :Y),NTuple{2,NTuple{2,T}}}}) where {T} = @NamedTuple{xmin::T, ymin::T, xmax::T, ymax::T} +ArrowTypes.ArrowType(::Type{<:Extents.Extent{(:X, :Y, :Z),NTuple{3,NTuple{2,T}}}}) where {T} = @NamedTuple{xmin::T, ymin::T, zmin::T, xmax::T, ymax::T, zmax::T} +ArrowTypes.ArrowType(::Type{<:Extents.Extent{(:X, :Y, :Z, :M),NTuple{4,NTuple{2,T}}}}) where {T} = @NamedTuple{xmin::T, ymin::T, zmin::T, mmin::T, xmax::T, ymax::T, zmax::T, mmax::T} ArrowTypes.arrowname(::Type{Geometry{PointTrait}}) = POINT ArrowTypes.arrowname(::Type{Geometry{LineStringTrait}}) = LINESTRING @@ -65,6 +83,8 @@ ArrowTypes.arrowname(::Type{Geometry{PolygonTrait}}) = POLYGON ArrowTypes.arrowname(::Type{Geometry{MultiPointTrait}}) = MULTIPOINT ArrowTypes.arrowname(::Type{Geometry{MultiLineStringTrait}}) = MULTILINESTRING ArrowTypes.arrowname(::Type{Geometry{MultiPolygonTrait}}) = MULTIPOLYGON +ArrowTypes.arrowname(::Type{<:GeoFormatTypes.WellKnownBinary}) = WKB +ArrowTypes.arrowname(::Type{<:GeoFormatTypes.WellKnownText}) = WKT ArrowTypes.arrowname(::Type{Wrapper{WellKnownBinary,T,N,G}}) where {T,N,G} = WKB ArrowTypes.arrowname(::Type{Wrapper{WellKnownText,T,N,G}}) where {T,N,G} = WKT ArrowTypes.arrowname(::Type{Wrapper{E,PointTrait,N,G}}) where {E<:AbstractNativeEncoding,N,G} = POINT @@ -73,7 +93,7 @@ ArrowTypes.arrowname(::Type{Wrapper{E,PolygonTrait,N,G}}) where {E<:AbstractNati ArrowTypes.arrowname(::Type{Wrapper{E,MultiPointTrait,N,G}}) where {E<:AbstractNativeEncoding,N,G} = MULTIPOINT ArrowTypes.arrowname(::Type{Wrapper{E,MultiLineStringTrait,N,G}}) where {E<:AbstractNativeEncoding,N,G} = MULTILINESTRING ArrowTypes.arrowname(::Type{Wrapper{E,MultiPolygonTrait,N,G}}) where {E<:AbstractNativeEncoding,N,G} = MULTIPOLYGON -ArrowTypes.arrowname(::Type{Extents.Extent}) = BOX +ArrowTypes.arrowname(::Type{<:Extents.Extent}) = BOX ArrowTypes.toarrow(x::Geometry) = x.geom ArrowTypes.toarrow(x::Wrapper{E,T,<:Geometry}) where {E,T} = x.geom @@ -81,24 +101,34 @@ ArrowTypes.toarrow(x::Wrapper) = data(x) ArrowTypes.toarrow(ex::Extents.Extent{(:X, :Y)}) = (; xmin=ex.X[1], ymin=ex.Y[1], xmax=ex.X[2], ymax=ex.Y[2]) ArrowTypes.toarrow(ex::Extents.Extent{(:X, :Y, :Z)}) = (; xmin=ex.X[1], ymin=ex.Y[1], zmin=ex.Z[1], xmax=ex.X[2], ymax=ex.Y[2], zmax=ex.Z[2]) ArrowTypes.toarrow(ex::Extents.Extent{(:X, :Y, :Z, :M)}) = (; xmin=ex.X[1], ymin=ex.Y[1], zmin=ex.Z[1], mmin=ex.M[1], xmax=ex.X[2], ymax=ex.Y[2], zmax=ex.Z[2], mmax=ex.M[2]) +ArrowTypes.toarrow(geom::GeoFormatTypes.WellKnownBinary{GeoFormatTypes.Geom}) = GeoFormatTypes.val(geom) +ArrowTypes.toarrow(geom::GeoFormatTypes.WellKnownText{GeoFormatTypes.Geom}) = GeoFormatTypes.val(geom) ArrowTypes.fromarrow(::Type{GeoFormatTypes.WellKnownBinary}, x) = GeoFormatTypes.WellKnownBinary(GeoFormatTypes.Geom(), x) ArrowTypes.fromarrow(::Type{GeoFormatTypes.WellKnownText}, x) = GeoFormatTypes.WellKnownText(GeoFormatTypes.Geom(), String(x)) # should be StringView + +# fromarrow for list-based encodings (interleaved) function ArrowTypes.fromarrow(::Type{Geometry{X}}, x) where {X} nt = nested_eltype(x) D = length(nt.types) return Geometry{X,D,Float64}(x) end -function fromarrow(::Type{GeoArrow.Geometry{X}}, nt::NamedTuple) where X - return Geometry{X,length(nt),Float64}(nt) -end -ArrowTypes.fromarrow(::Type{Extents.Extent}, x) = Extents.Extent(X=(x.xmin, x.xmax), Y=(x.ymin, x.ymax)) + +# fromarrow for separated Point encoding (Struct with x, y, [z, [m]] fields) +ArrowTypes.fromarrow(::Type{Geometry{PointTrait,2,T}}, x, y) where {T} = Geometry{PointTrait,2,T}((x, y)) +ArrowTypes.fromarrow(::Type{Geometry{PointTrait,3,T}}, x, y, z) where {T} = Geometry{PointTrait,3,T}((x, y, z)) +ArrowTypes.fromarrow(::Type{Geometry{PointTrait,4,T}}, x, y, z, m) where {T} = Geometry{PointTrait,4,T}((x, y, z, m)) + +# fromarrow for Box/Extent (Struct with xmin, ymin, xmax, ymax, [zmin, zmax, [mmin, mmax]] fields) +ArrowTypes.fromarrow(::Type{<:Extents.Extent{(:X, :Y)}}, xmin, ymin, xmax, ymax) = Extents.Extent(X=(xmin, xmax), Y=(ymin, ymax)) +ArrowTypes.fromarrow(::Type{<:Extents.Extent{(:X, :Y, :Z)}}, xmin, ymin, zmin, xmax, ymax, zmax) = Extents.Extent(X=(xmin, xmax), Y=(ymin, ymax), Z=(zmin, zmax)) +ArrowTypes.fromarrow(::Type{<:Extents.Extent{(:X, :Y, :Z, :M)}}, xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax) = Extents.Extent(X=(xmin, xmax), Y=(ymin, ymax), Z=(zmin, zmax), M=(mmin, mmax)) nested_eltype(x) = nested_eltype(typeof(x)) nested_eltype(::Type{Union{Missing,T}}) where {T} = nested_eltype(T) nested_eltype(::Type{T}) where {T<:AbstractArray} = nested_eltype(eltype(T)) nested_eltype(::Type{T}) where {T} = T -_named(::Type{NTuple{2, T}}) where {T} = @NamedTuple{x::Float64, y::Float64} -_named(::Type{NTuple{3, T}}) where {T} = @NamedTuple{x::Float64, y::Float64, z::Float64} -_named(::Type{NTuple{4, T}}) where {T} = @NamedTuple{x::Float64, y::Float64, z::Float64, m::Float64} +_named(::Type{NTuple{2,T}}) where {T} = @NamedTuple{x::Float64, y::Float64} +_named(::Type{NTuple{3,T}}) where {T} = @NamedTuple{x::Float64, y::Float64, z::Float64} +_named(::Type{NTuple{4,T}}) where {T} = @NamedTuple{x::Float64, y::Float64, z::Float64, m::Float64} diff --git a/src/io.jl b/src/io.jl index fed8ed2..806c220 100644 --- a/src/io.jl +++ b/src/io.jl @@ -29,9 +29,10 @@ function write(path, t; geocolumns=GeoInterface.geometrycolumns(t), crs=GeoInter column in Tables.columnnames(t) || error("Geometry column $column not found in table") data = Tables.getcolumn(t, column) T = nonmissingtype(Tables.columntype(t, column)) - GeoInterface.isgeometry(T) || error("Geometry in $column must support the GeoInterface") - ct = merge(ct, NamedTuple{(column,)}((Wrapper.(Ref(encoding), data),))) - + if ArrowTypes.arrowname(T) == Symbol("") + GeoInterface.isgeometry(T) || error("Geometry type $T in column $column must support the GeoInterface") + ct = merge(ct, NamedTuple{(column,)}((Wrapper.(Ref(encoding), data),))) + end geometa = Dict("ARROW:extension:metadata" => JSON3.write(dcrs)) if haskey(colmetadata, column) merge!(colmetadata[column], geometa) diff --git a/src/type.jl b/src/type.jl index f612ec1..0d313f8 100644 --- a/src/type.jl +++ b/src/type.jl @@ -6,6 +6,7 @@ Base.:(==)(x::Geometry{X,D,T,G}, y::Geometry{X,D,T,G}) where {X,D,T,G} = x.geom Base.show(io::IO, x::Geometry{X,D,T}) where {X,D,T} = print(io, "$X geometry in $(D)D with eltype $T") Geometry{X,D,T}(x) where {X,D,T} = Geometry{X,D,T,typeof(x)}(x) Geometry{PointTrait}(x::Vararg{T,D}) where {T,D} = Geometry{PointTrait,D,T}(reinterpret(NTuple{D,T}, x)) +Geometry{PointTrait,D,T}(x, y, z, m) where {T,D} = Geometry{PointTrait,D,T}((x, y, z, m)) Geometry{PointTrait,D,T}(x, y, z) where {T,D} = Geometry{PointTrait,D,T}((x, y, z)) Geometry{PointTrait,D,T}(x, y) where {T,D} = Geometry{PointTrait,D,T}((x, y)) @@ -53,6 +54,7 @@ end Base.:(==)(x::Wrapper{E,T,N,G}, y::Wrapper{E,T,N,G}) where {E,T,N,G} = x.geom == y.geom Base.show(io::IO, ::Wrapper{E,T,G}) where {E,T,G} = print(io, "$T geometry encoded as $E") Wrapper(e::AbstractEncoding, x) = Wrapper{typeof(e),typeof(GeoInterface.geomtrait(x)),GeoInterface.ncoord(x),typeof(x)}(x) +Wrapper(::AbstractEncoding, ::Missing) = missing Wrapper(x) = Wrapper(Interleaved(), x) data(x::Wrapper{E,T,N,G}) where {E,T,N,G} = _coordinates(E(), T(), Val{N}(), x.geom) diff --git a/test/links.txt b/test/links.txt index 83135cb..7c7f8fe 100644 --- a/test/links.txt +++ b/test/links.txt @@ -1,3 +1,4 @@ +# GeoPandas example files (basic geometry types) https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point-interleaved.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point-wkb.arrow @@ -16,6 +17,8 @@ https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/ https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon-interleaved.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon-wkb.arrow + +# GeoPandas example files (Z dimension) https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point_z.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point_z-interleaved.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-point_z-wkb.arrow @@ -34,3 +37,170 @@ https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/ https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon_z.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon_z-interleaved.arrow https://raw.githubusercontent.com/geopandas/geopandas/refs/heads/main/geopandas/io/tests/data/geoarrow/example-multipolygon_z-wkb.arrow + +# GeoArrow-data: Example files (2D) +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested_wkb.arrows + +# GeoArrow-data: Example files (Z dimension) +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-z.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-z_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-z_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-z_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-z_wkb.arrows + +# GeoArrow-data: Example files (M dimension) +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-m.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-m_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-m_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-m_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-m_wkb.arrows + +# GeoArrow-data: Example files (ZM dimension) +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_point-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_linestring-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_polygon-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipoint-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multilinestring-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-zm.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-zm_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_multipolygon-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-zm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-zm_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometrycollection-nested-zm_wkb.arrows + +# GeoArrow-data: Example files (mixed dimensions) +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-mixed-dimensions_wkt.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example/files/example_geometry-mixed-dimensions_wkb.arrows + +# GeoArrow-data: Nova Scotia Water (~1.7MB, point data only - other layers are >10MB) +https://github.com/geoarrow/geoarrow-data/releases/download/v0.2.0/ns-water_water-point.arrows +https://github.com/geoarrow/geoarrow-data/releases/download/v0.2.0/ns-water_water-point_interleaved.arrows +https://github.com/geoarrow/geoarrow-data/releases/download/v0.2.0/ns-water_water-point_wkb.arrows + +# GeoArrow-data: Natural Earth +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_cities.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_cities_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_cities_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-geography.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-geography_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-geography_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-bounds.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-bounds_box.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-bounds_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries-bounds_wkb.arrows + +# GeoArrow-data: USGS Quadrangles +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/quadrangles/files/quadrangles_100k.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/quadrangles/files/quadrangles_100k_box.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/quadrangles/files/quadrangles_100k_interleaved.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/quadrangles/files/quadrangles_100k_wkb.arrows + +# GeoArrow-data: CRS Examples +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-crs84_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-4326_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-utm_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-custom_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-crs84-wkt2_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-crs84-auth-code_wkb.arrows +https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/example-crs/files/example-crs_vermont-crs84-unknown_wkb.arrows diff --git a/test/runtests.jl b/test/runtests.jl index 1d3bb64..8ea45a1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,13 +8,15 @@ using DataFrames using Extents using DataAPI -mkpath(joinpath(@__DIR__, "data/write")) +const testdatadir = joinpath(@__DIR__, "data") +mkpath(joinpath(testdatadir, "write")) @testset "GeoArrow.jl" begin @testset "Test datasets" begin # Data taken from the geopandas tests, courtesy of Joris Van den Bossche for url in readlines("links.txt") - fn = joinpath("data", split(url, "/")[end]) + (isempty(strip(url)) || startswith(url, "#")) && continue + fn = joinpath(testdatadir, split(url, "/")[end]) isfile(fn) && continue try @info "Downloading $fn" @@ -24,13 +26,13 @@ mkpath(joinpath(@__DIR__, "data/write")) end end - for arrowfn in filter(endswith("arrow"), readdir("data", join=true)) + for arrowfn in filter(endswith(r".arrow|.arrows"), readdir(testdatadir, join=true)) @testset "$arrowfn" begin t = Arrow.Table(arrowfn) geom = t.geometry[1] @test GeoInterface.isgeometry(geom) @test GeoInterface.geomtrait(geom) isa GeoInterface.AbstractGeometryTrait - @test GeoInterface.ncoord(geom) in [2, 3] + @test GeoInterface.ncoord(geom) in [2, 3, 4] @test GeoInterface.testgeometry(geom) io = IOBuffer() @@ -92,6 +94,7 @@ mkpath(joinpath(@__DIR__, "data/write")) w = GeoArrow.Wrapper(GeoArrow.WellKnownBinary(), g) @test ArrowTypes.ArrowKind(typeof(w)) == ArrowTypes.ListKind() @test ArrowTypes.ArrowType(typeof(w)) == Vector{UInt8} + @test ArrowTypes.arrowname(typeof(w)) == Symbol("geoarrow.wkb") @test ArrowTypes.toarrow(w)[1:10] == UInt8[0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] w = GeoArrow.Wrapper(g) # Encoding defaults to Interleaved @@ -106,14 +109,26 @@ mkpath(joinpath(@__DIR__, "data/write")) @test ArrowTypes.arrowname(typeof(w)) == Symbol("geoarrow.point") @test ArrowTypes.toarrow(w) == (; x=1.0, y=2.0) end + @testset "Box" begin + box_type = @NamedTuple{xmin::Float64, ymin::Float64, xmax::Float64, ymax::Float64} + extent_type = Extents.Extent{(:X, :Y),Tuple{Tuple{Float64,Float64},Tuple{Float64,Float64}}} + @test ArrowTypes.JuliaType(Val(Symbol("geoarrow.box")), box_type, nothing) == extent_type + @test ArrowTypes.arrowname(extent_type) == Symbol("geoarrow.box") + @test ArrowTypes.ArrowType(extent_type) == + @NamedTuple{xmin::Float64,ymin::Float64,xmax::Float64,ymax::Float64} + @test ArrowTypes.toarrow(Extents.Extent(X=(1.0, 3.0), Y=(2.0, 4.0))) == + (; xmin=1.0, ymin=2.0, xmax=3.0, ymax=4.0) + @test ArrowTypes.fromarrow(extent_type, 1.0, 2.0, 3.0, 4.0) == + Extents.Extent(X=(1.0, 3.0), Y=(2.0, 4.0)) + end @testset "Simple" begin - df = DataFrame(a=1, geometry=[(1.,2.)]) + df = DataFrame(a=1, geometry=[(1., 2.)]) GeoArrow.write("simple.arrow", df) dfn = GeoArrow.read("simple.arrow") @test GeoInterface.isgeometry(dfn.geometry[1]) end @testset "Metadata" begin - df = DataFrame(a=1, geometry=[(1.,2.)]) + df = DataFrame(a=1, geometry=[(1., 2.)]) DataAPI.metadata!(df, "author", "test") DataAPI.colmetadata!(df, :a, "description", "A normal column") DataAPI.colmetadata!(df, :geometry, "description", "A point geometry")