-
Notifications
You must be signed in to change notification settings - Fork 27
/
tables.jl
73 lines (63 loc) · 2.57 KB
/
tables.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
"""
Constructs `Table` out of `FeatureLayer`, where every row is a `Feature` consisting of Geometry and attributes.
```
ArchGDAL.Table(T::Union{IFeatureLayer, FeatureLayer})
```
"""
struct Table{T<:Union{IFeatureLayer, FeatureLayer}}
layer::T
end
getlayer(t::Table) = Base.getfield(t, :layer)
function Tables.schema(layer::AbstractFeatureLayer)
field_names, geom_names, featuredefn, fielddefns = schema_names(layer)
ngeom = ArchGDAL.ngeom(featuredefn)
geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1)
field_types = (_FIELDTYPE[gettype(fielddefn)] for fielddefn in fielddefns)
geom_types = (IGeometry for i in 1:ngeom)
Tables.Schema((field_names..., geom_names...), (field_types..., geom_types...))
end
Tables.istable(::Type{<:Table}) = true
Tables.rowaccess(::Type{<:Table}) = true
Tables.rows(t::Table) = t
function Base.iterate(t::Table, st = 0)
layer = getlayer(t)
st >= nfeature(layer) && return nothing
if iszero(st)
resetreading!(layer)
end
return nextnamedtuple(layer), st + 1
end
function Base.getindex(t::Table, idx::Integer)
layer = getlayer(t)
setnextbyindex!(layer, idx-1)
return nextnamedtuple(layer)
end
Base.IteratorSize(::Type{<:Table}) = Base.HasLength()
Base.size(t::Table) = nfeature(getlayer(t))
Base.length(t::Table) = size(t)
Base.IteratorEltype(::Type{<:Table}) = Base.HasEltype()
Base.propertynames(t::Table) = Tables.schema(getlayer(t)).names
Base.getproperty(t::Table, s::Symbol) = [getproperty(row, s) for row in t]
"""
Returns the feature row of a layer as a `NamedTuple`
Calling it iteratively will work similar to `nextfeature` i.e. give the consecutive feature as `NamedTuple`
"""
function nextnamedtuple(layer::IFeatureLayer)
field_names, geom_names = schema_names(layer)
return nextfeature(layer) do feature
prop = (getfield(feature, name) for name in field_names)
geom = (getgeom(feature, idx-1) for idx in 1:length(geom_names))
NamedTuple{(field_names..., geom_names...)}((prop..., geom...))
end
end
function schema_names(layer::AbstractFeatureLayer)
featuredefn = layerdefn(layer)
fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(layer)-1)
field_names = (Symbol(getname(fielddefn)) for fielddefn in fielddefns)
geom_names = (Symbol(getname(getgeomdefn(featuredefn, i-1))) for i in 1:ngeom(layer))
return (field_names, geom_names, featuredefn, fielddefns)
end
function Base.show(io::IO, t::Table)
println(io, "Table with $(nfeature(getlayer(t))) features")
end
Base.show(io::IO, ::MIME"text/plain", t::Table) = show(io, t)