Packages

Elixir implementation of the Geobuf format. Geobuf is a compact binary encoding for geographic data. It is based on protobuf, but optimized for encoding geographic data. It is has 1to1 compatibility with GeoJSON.

Current section

Files

Jump to
geobuf lib decode_feature.ex
Raw

lib/decode_feature.ex

defmodule DecodeFeature do
# TODO: This is not working yet, to be fixed in a future release
def decode(%Geobuf.Data{data_type: {:feature_collection, feature_collection}}) do
%{
"type" => "FeatureCollection",
"features" => Enum.map(feature_collection.features, &decode/1)
}
end
def decode(%Geobuf.Data{data_type: {:feature, feature}} = data) do
%{
"properties" => decode_properties(feature.properties, feature.values, data.keys),
"type" => "Feature",
"geometry" => decode_geometry(feature.geometry, data.precision, data.dimensions)
}
|> maybe_add_id(feature.id_type)
end
def decode(%Geobuf.Data{data_type: {:geometry, geometry}} = data) do
decode_geometry(geometry, data.precision, data.dimensions)
end
defp maybe_add_id(feature, id) do
if id != nil do
Map.put(feature, "id", decode_id(id))
else
feature
end
end
defp decode_id(nil), do: nil
defp decode_id({:id, id}), do: id
defp decode_properties(properties, values, keys) do
Enum.chunk_every(properties, 2)
|> Enum.map(fn [key_idx, val_idx] ->
{keys |> Enum.at(key_idx), values |> Enum.at(val_idx) |> decode_value()}
end)
|> Enum.into(%{})
end
defp decode_geometry(geo, precision, dimensions) do
DecodeGeometry.decode(geo, precision, dimensions)
end
defp decode_value(%Geobuf.Data.Value{value_type: {type, value}}) do
case type do
:bool_value -> value
:double_value -> value
:string_value -> value
:pos_int_value -> value
:neg_int_value -> -value
:json_value -> decode_json(value)
_ -> nil
end
end
defp decode_json(json_value) do
case Jason.decode(json_value) do
{:ok, m} -> m
{:error, _} -> raise "Failed to decode JSON"
end
end
end