Packages
geo
0.17.0
4.1.0
4.0.1
4.0.0
3.6.0
3.5.1
3.5.0
3.4.3
3.4.2
3.4.1
3.4.0
3.3.8
3.3.7
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.0
3.1.0
3.0.0
2.1.0
2.0.0
1.5.0
1.4.1
1.4.0
1.3.1
1.3.0
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.2
0.15.1
0.15.0
0.14.0
0.13.0
0.12.0
0.11.2
0.11.1
0.11.0
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.2
0.7.1
0.6.1
0.5.1
Encodes and decodes WKB, WKT, and GeoJSON formats.
Current section
Files
Jump to
Current section
Files
lib/geo/geo_json.ex
defmodule Geo.JSON do
alias Geo.Point
alias Geo.LineString
alias Geo.Polygon
alias Geo.MultiPoint
alias Geo.MultiLineString
alias Geo.MultiPolygon
alias Geo.GeometryCollection
@moduledoc """
Converts Geo structs to and from a map representing GeoJSON.
You are responsible to encoding and decoding of JSON. This is so
that you can use any JSON parser you want as well as making it
so that you can use the resulting GeoJSON structure as a property
in larger JSON structures.
```
#Using Poison as the JSON parser for these examples
json = "{ \\"type\\": \\"Point\\", \\"coordinates\\": [100.0, 0.0] }"
geom = Poison.decode!(json) |> Geo.JSON.decode(json)
Geo.Point[coordinates: {100.0, 0.0}, srid: nil]
Geo.JSON.encode(geom) |> Poison.encode!
"{ \\"type\\": \\"Point\\", \\"coordinates\\": [100.0, 0.0] }"
Geo.JSON.encode(geom)
%{ "type" => "Point", "coordinates" => [100.0, 0.0] }
```
"""
@doc """
Takes a map representing GeoJSON and returns a Geometry
"""
@spec decode(Map.t) :: Geo.geometry
def decode(geo_json) do
crs = Dict.get(geo_json, "crs")
case Dict.has_key?(geo_json, "geometries") do
true ->
geometries = Enum.map(Dict.get(geo_json, "geometries"),
fn(x) ->
do_decode(Dict.get(x, "type"), Dict.get(x, "coordinates"), crs)
end)
%GeometryCollection{ geometries: geometries }
false ->
do_decode(Dict.get(geo_json, "type"), Dict.get(geo_json, "coordinates"), crs)
end
end
defp do_decode("Point", [x, y], crs) do
%Point{ coordinates: {x, y}, srid: get_srid(crs)}
end
defp do_decode("LineString", coordinates, crs) do
coordinates = Enum.map(coordinates, &List.to_tuple(&1))
%LineString{ coordinates: coordinates, srid: get_srid(crs) }
end
defp do_decode("Polygon", coordinates, crs) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, &List.to_tuple(&1))
end)
%Polygon{ coordinates: coordinates, srid: get_srid(crs) }
end
defp do_decode("MultiPoint", coordinates, crs) do
coordinates = Enum.map(coordinates, &List.to_tuple(&1))
%MultiPoint{ coordinates: coordinates, srid: get_srid(crs)}
end
defp do_decode("MultiLineString", coordinates, crs) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, &List.to_tuple(&1))
end)
%MultiLineString{ coordinates: coordinates, srid: get_srid(crs) }
end
defp do_decode("MultiPolygon", coordinates, crs) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, fn(third_sub_coordinates) ->
Enum.map(third_sub_coordinates, &List.to_tuple(&1))
end)
end)
%MultiPolygon{ coordinates: coordinates, srid: get_srid(crs) }
end
defp get_srid(%{"type" => "name", "properties" => %{ "name" => "EPSG" <> srid } }) do
{srid, _} = Integer.parse(srid)
srid
end
defp get_srid(%{"type" => "name", "properties" => %{ "name" => srid } }) do
srid
end
defp get_srid(nil) do
nil
end
@doc """
Takes a Geometry and returns a map representing the GeoJSON
"""
@spec encode(Geo.geometry) :: Map.t
def encode(geom) do
case geom do
%GeometryCollection{ geometries: geometries, srid: srid } ->
%{ "type" => "GeometryCollection", "geometries" => Enum.map(geometries, &do_encode(&1))}
|> add_crs(srid)
_ ->
do_encode(geom)
|> add_crs(geom.srid)
end
end
defp do_encode(%Point{ coordinates: {x, y} }) do
%{ "type" => "Point", "coordinates" => [x, y] }
end
defp do_encode(%LineString{ coordinates: coordinates }) do
coordinates = Enum.map(coordinates, &Tuple.to_list(&1))
%{ "type" => "LineString", "coordinates" => coordinates }
end
defp do_encode(%Polygon{ coordinates: coordinates }) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, &Tuple.to_list(&1))
end)
%{ "type" => "Polygon", "coordinates" => coordinates }
end
defp do_encode(%MultiPoint{ coordinates: coordinates }) do
coordinates = Enum.map(coordinates, &Tuple.to_list(&1))
%{ "type" => "MultiPoint", "coordinates" => coordinates }
end
defp do_encode(%MultiLineString{ coordinates: coordinates }) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, &Tuple.to_list(&1))
end)
%{ "type" => "MultiLineString", "coordinates" => coordinates }
end
defp do_encode(%MultiPolygon{ coordinates: coordinates }) do
coordinates = Enum.map(coordinates, fn(sub_coordinates) ->
Enum.map(sub_coordinates, fn(third_sub_coordinates) ->
Enum.map(third_sub_coordinates, &Tuple.to_list(&1))
end)
end)
%{ "type" => "MultiPolygon", "coordinates" => coordinates }
end
defp add_crs(map, nil) do
map
end
defp add_crs(map, srid) do
Dict.put(map, "crs", %{"type" => "name", "properties" => %{"name" => "EPSG#{srid}"}})
end
end