Packages
geo
3.5.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/wkb/encoder.ex
defmodule Geo.WKB.Encoder do
@moduledoc false
@point 0x00_00_00_01
@point_m 0x40_00_00_01
@point_z 0x80_00_00_01
@point_zm 0xC0_00_00_01
@line_string 0x00_00_00_02
@line_string_z 0x80_00_00_02
@polygon 0x00_00_00_03
@polygon_z 0x80_00_00_03
@multi_point 0x00_00_00_04
@multi_point_z 0x80_00_00_04
@multi_line_string 0x00_00_00_05
@multi_line_string_z 0x80_00_00_05
@multi_polygon 0x00_00_00_06
@multi_polygon_z 0x80_00_00_06
@geometry_collection 0x00_00_00_07
@wkbsridflag 0x20000000
use Bitwise
alias Geo.{
Point,
PointZ,
PointM,
PointZM,
LineString,
LineStringZ,
Polygon,
PolygonZ,
MultiPoint,
MultiPointZ,
MultiLineString,
MultiLineStringZ,
MultiPolygon,
MultiPolygonZ,
GeometryCollection
}
defp add_srid(type), do: type + @wkbsridflag
def encode!(geom, endian \\ :ndr)
for {endian, endian_atom, modifier} <- [{1, :ndr, quote(do: little)}, {0, :xdr, quote(do: big)}] do
def encode!(geom, unquote(endian_atom)) do
{type, rest} = do_encode(geom, unquote(endian_atom))
binary =
if geom.srid do
<<add_srid(type)::unquote(modifier)-32, geom.srid::unquote(modifier)-32>>
else
<<type::unquote(modifier)-32>>
end
[unquote(endian), binary, rest]
end
def do_encode(%Point{coordinates: {x, y}}, unquote(endian_atom)) do
{@point, [<<x::unquote(modifier)-float-64>>, <<y::unquote(modifier)-float-64>>]}
end
def do_encode(%PointZ{coordinates: {x, y, z}}, unquote(endian_atom)) do
{@point_z,
[
<<x::unquote(modifier)-float-64>>,
<<y::unquote(modifier)-float-64>>,
<<z::unquote(modifier)-float-64>>
]}
end
def do_encode(%PointM{coordinates: {x, y, m}}, unquote(endian_atom)) do
{@point_m,
[
<<x::unquote(modifier)-float-64>>,
<<y::unquote(modifier)-float-64>>,
<<m::unquote(modifier)-float-64>>
]}
end
def do_encode(%PointZM{coordinates: {x, y, z, m}}, unquote(endian_atom)) do
{@point_zm,
[
<<x::unquote(modifier)-float-64>>,
<<y::unquote(modifier)-float-64>>,
<<z::unquote(modifier)-float-64>>,
<<m::unquote(modifier)-float-64>>
]}
end
def do_encode(%LineString{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn {x, y}, acc ->
{[<<x::unquote(modifier)-float-64>>, <<y::unquote(modifier)-float-64>>], acc + 1}
end)
{@line_string, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%LineStringZ{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn {x, y, z}, acc ->
{[
<<x::unquote(modifier)-float-64>>,
<<y::unquote(modifier)-float-64>>,
<<z::unquote(modifier)-float-64>>
], acc + 1}
end)
{@line_string_z, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%Polygon{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn ring, acc ->
{_, data} = do_encode(%LineString{coordinates: ring}, unquote(endian_atom))
{data, acc + 1}
end)
{@polygon, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%PolygonZ{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn ring, acc ->
{_, data} = do_encode(%LineStringZ{coordinates: ring}, unquote(endian_atom))
{data, acc + 1}
end)
{@polygon_z, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiPoint{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
point = encode!(%Point{coordinates: coordinate}, unquote(endian_atom))
{point, acc + 1}
end)
{@multi_point, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiPointZ{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
point = encode!(%PointZ{coordinates: coordinate}, unquote(endian_atom))
{point, acc + 1}
end)
{@multi_point_z, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiLineString{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
geom = encode!(%LineString{coordinates: coordinate}, unquote(endian_atom))
{geom, acc + 1}
end)
{@multi_line_string, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiLineStringZ{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
geom = encode!(%LineStringZ{coordinates: coordinate}, unquote(endian_atom))
{geom, acc + 1}
end)
{@multi_line_string_z, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiPolygon{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
geom = encode!(%Polygon{coordinates: coordinate}, unquote(endian_atom))
{geom, acc + 1}
end)
{@multi_polygon, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%MultiPolygonZ{coordinates: coordinates}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(coordinates, 0, fn coordinate, acc ->
geom = encode!(%PolygonZ{coordinates: coordinate}, unquote(endian_atom))
{geom, acc + 1}
end)
{@multi_polygon_z, [<<count::unquote(modifier)-32>> | coordinates]}
end
def do_encode(%GeometryCollection{geometries: geometries}, unquote(endian_atom)) do
{coordinates, count} =
Enum.map_reduce(geometries, 0, fn geom, acc ->
geom = encode!(%{geom | srid: nil}, unquote(endian_atom))
{geom, acc + 1}
end)
{@geometry_collection, [<<count::unquote(modifier)-32>> | coordinates]}
end
end
end