Metadata
Meta
The Meta
method provides metadata handling capabilities in GeometryBasics. Similarly to remove the metadata and keep only the geometry, use metafree
, and for vice versa i.e., remove the geometry and keep the metadata use meta
.
Syntax
meta(geometry, meta::NamedTuple)
meta(geometry; meta...)
metafree(meta-geometry)
meta(meta-geometry)
Examples
julia> using GeometryBasics
julia> p1 = Point(2.2, 3.6)
2-element Point{2, Float64} with indices SOneTo(2): 2.2 3.6
julia> poi = meta(p1, city="Abuja", rainfall=1221.2)
2-element PointMeta{2, Float64, Point{2, Float64}, (:city, :rainfall), Tuple{String, Float64}} with indices SOneTo(2): 2.2 3.6
Metadata is stored in a NamedTuple and can be retrieved as such:
julia> meta(poi)
(city = "Abuja", rainfall = 1221.2)
Specific metadata attributes can be directly retrieved:
julia> poi.rainfall
1221.2
julia> metafree(poi)
2-element Point{2, Float64} with indices SOneTo(2): 2.2 3.6
Metatypes are predefined for geometries:
julia> multipoi = MultiPointMeta([p1], city="Abuja", rainfall=1221.2)
1-element MultiPointMeta{Point{2, Float64}, MultiPoint{2, Float64, Point{2, Float64}, Vector{Point{2, Float64}}}, (:city, :rainfall), Tuple{String, Float64}}: [2.2, 3.6]
(In the above example we have also used a geometry-specific meta method.)
julia> GeometryBasics.MetaType(Polygon)
PolygonMeta
julia> GeometryBasics.MetaType(Mesh)
MeshMeta
The metageometry objects are infact composed of the original geometry types.
julia> GeometryBasics.MetaFree(PolygonMeta)
Polygon
julia> GeometryBasics.MetaFree(MeshMeta)
Mesh
MetaT
In GeometryBasics we can have tabular layout for a collection of meta-geometries by putting them into a StructArray that extends the Tables.jl API.
In practice it's not necessary for the geometry or metadata types to be consistent. For example, a geojson format can have heterogeneous geometries. Hence, such cases require automatic widening of the geometry data types to the most appropriate type. The MetaT method works around the fact that, a collection of geometries and metadata of different types can be represented tabularly whilst widening to the appropriate type.
Syntax
MetaT(geometry, meta::NamedTuple)
MetaT(geometry; meta...)
Returns a MetaT
that holds a geometry and its metadata MetaT
acts the same as Meta
method. The difference lies in the fact that it is designed to handle geometries and metadata of different/heterogeneous types.
For example, while a Point MetaGeometry is a PointMeta
, the MetaT representation is MetaT{Point}
.
Examples
julia> MetaT(Point(1, 2), city = "Mumbai")
MetaT{Point{2, Int64}, (:city,), Tuple{String}}([1, 2], (city = "Mumbai",))
For a tabular representation, an iterable of MetaT
types can be passed on to a meta_table
method.
Syntax
meta_table(iter)
Examples
Create an array of 2 linestrings:
julia> ls = [LineString([Point(i, i+1), Point(i-1,i+5)]) for i in 1:2];
julia> coordinates.(ls)
2-element Vector{Vector{Point{2, Int64}}}: [[1, 2], [0, 6]] [[2, 3], [1, 7]]
Create a multi-linestring:
julia> mls = MultiLineString(ls);
julia> coordinates.(mls)
2-element Vector{Vector{Point{2, Int64}}}: [[1, 2], [0, 6]] [[2, 3], [1, 7]]
Create a polygon:
julia> poly = Polygon(Point{2, Int}[(40, 40), (20, 45), (45, 30), (40, 40)]);
julia> coordinates(poly)
4-element Vector{Point{2, Int64}}: [40, 40] [20, 45] [45, 30] [40, 40]
Put all geometries into an array:
julia> geom = [ls..., mls, poly];
Generate some random metadata:
julia> prop = [(country_states = "India$(i)", rainfall = (i*9)/2) for i in 1:4]
4-element Vector{NamedTuple{(:country_states, :rainfall), Tuple{String, Float64}}}: (country_states = "India1", rainfall = 4.5) (country_states = "India2", rainfall = 9.0) (country_states = "India3", rainfall = 13.5) (country_states = "India4", rainfall = 18.0)
julia> feat = [MetaT(i, j) for (i,j) = zip(geom, prop)]; # create an array of MetaT
We can now generate a StructArray
/ Table
with meta_table
:
julia> sa = meta_table(feat);
The data can be accessed through sa.main
and the metadata through sa.country_states
and sa.rainfall
. Here we print only the type names of the data items for brevity:
julia> [nameof.(typeof.(sa.main)) sa.country_states sa.rainfall]
4×3 Matrix{Any}: :LineString "India1" 4.5 :LineString "India2" 9.0 :MultiLineString "India3" 13.5 :Polygon "India4" 18.0
Disadvantages
The MetaT is pretty generic in terms of geometry types, it's not subtype to geometries. eg : A
MetaT{Point, NamedTuple{Names, Types}}
is not subtyped toAbstractPoint
like aPointMeta
is.This might cause problems on using
MetaT
with other constructors/methods inside or even outside GeometryBasics methods designed to work with the mainMeta
types.