Current section
Files
Jump to
Current section
Files
script/gen_from_zm.exs
# This script generates modules and tests for geometries. The ZM version of the
# geometries is used as a template.
#
# The file `lib/geometry/point_zm.ex`:
# - `lib/geometry/point_z.ex`
# - `lib/geometry/point_m.ex`
# - `lib/geometry/point.ex`
#
#
# A note for contributors, interested readers or a future me.
#
# There are several ways to create the modules generated by this script. It is
# possible to create all modules at compile-time. In some other modules, this
# approach is in use. Another method could be the use of EEx.
#
# I have chosen the present way to keep developing the "*ZM" modules easier and
# the code readable. As a disadvantage, we get this unelegant script.
# As mentioned above, in some modules, code is created at compile-time. So we
# have two approaches to create code. These approaches should not be mixed in
# one module.
defmodule GenFromZM do
@lib_path "lib/geometry"
@test_path "test/geometry"
@geometries [
"Point",
"LineString",
"Polygon",
"MultiPoint",
"MultiLineString",
"MultiPolygon",
"GeometryCollection"
]
@geometries_m Enum.map(@geometries, fn geometry -> "#{geometry}M" end)
@geometries_z Enum.map(@geometries, fn geometry -> "#{geometry}Z" end)
@geometries_zm Enum.map(@geometries, fn geometry -> "#{geometry}ZM" end)
@types [:xy, :xym, :xyz]
def main do
info("Generate geometry modules/tests")
Enum.each(@geometries, &generate/1)
end
defp generate(geometry) do
if !check_lib!(geometry) do
code = read_lib!(geometry)
Enum.each(@types, fn type ->
write_lib!(geometry, type, gen(code, type))
end)
end
if !check_test!(geometry) do
test_code = read_test!(geometry)
Enum.each(@types, fn type ->
write_test!(geometry, type, gen_test(test_code, type))
end)
end
end
# returns true if the template (zm) is older as all the generated files
defp check_lib!(geometry) do
src_time =
@lib_path
|> Path.join("#{Macro.underscore(geometry)}_zm.ex")
|> change_time()
Enum.all?(@types, fn type ->
filename = "#{filename(geometry)}#{filename_extension(type)}.ex"
dest_time = @lib_path |> Path.join(filename) |> change_time()
src_time < dest_time
end)
end
# returns true if the template (zm) is older as all the generated files
defp check_test!(geometry) do
src_time =
@test_path
|> Path.join("#{Macro.underscore(geometry)}_zm_test.exs")
|> change_time()
Enum.all?(@types, fn type ->
filename = "#{filename(geometry)}#{filename_extension(type)}_test.exs"
dest_time = @test_path |> Path.join(filename) |> change_time()
src_time < dest_time
end)
end
defp change_time(file) do
case File.stat(file, time: :posix) do
{:ok, %File.Stat{ctime: time}} -> time
_error -> 0
end
end
defp read_lib!(geometry) do
@lib_path
|> Path.join("#{Macro.underscore(geometry)}_zm.ex")
|> File.read!()
end
defp read_test!(geometry) do
@test_path
|> Path.join("#{Macro.underscore(geometry)}_zm_test.exs")
|> File.read!()
end
defp write_lib!(geometry, type, code) do
filename = "#{filename(geometry)}#{filename_extension(type)}.ex"
file = Path.join(@lib_path, filename)
info("Write #{file}")
File.write!(file, code)
end
defp write_test!(geometry, type, code) do
filename = "#{filename(geometry)}#{filename_extension(type)}_test.exs"
file = Path.join(@test_path, filename)
info("Write #{file}")
File.write!(file, code)
end
defp filename(geometry), do: Macro.underscore(geometry)
defp filename_extension(type) do
case type do
:xy -> ""
:xym -> "_m"
:xyz -> "_z"
end
end
defp gen(code, type) do
code
|> replace(geometries(type))
|> replace(comment(code, type))
|> replace(args(code, type))
|> replace(lists(code, type))
|> replace(props(code, type))
|> replace(tuples(code, type))
|> replace(wkt_coordinates(code, type))
|> replace(wkt_tag(type))
|> replace(point_test(type))
|> replace(point(type))
|> replace(geometry_collection(type))
|> replace(wkb_code(type))
|> replace(hint(:code))
end
defp gen_test(code, type) do
code
|> replace(geometries(type))
|> replace(args(code, type))
|> replace(lists(code, type))
|> replace(props(code, type))
|> replace(tuples(code, type))
|> replace(wkt_coordinates(code, type))
|> replace(wkt_tag(type))
|> replace(hint(:test))
|> replace(point_test(type))
|> replace(point(type))
|> replace(line_string_test(type))
|> replace(polygon_test(type))
|> replace(multi_point_test(type))
|> replace(multi_line_string_test(type))
|> replace(multi_polygon_test(type))
|> replace(geometry_collection_test(type))
end
defp geometries(type) do
new =
case type do
:xy -> @geometries
:xyz -> @geometries_z
:xym -> @geometries_m
end
{@geometries_zm, new}
end
defp wkt_tag(type) do
new =
case type do
:xy -> ""
:xyz -> " Z"
:xym -> " M"
end
{" ZM", new}
end
defp hint(:code) do
{"""
@behaviour Geometry
""",
"""
# This file is auto-generated by `mix geometry.gen`.
# The ZM version of this file is used as a template.
@behaviour Geometry
"""}
end
defp hint(:test) do
{"""
use ExUnit.Case\
""",
"""
# This file is auto-generated by `mix geometry.gen`.
# The ZM version of this file is used as a template.
use ExUnit.Case\
"""}
end
defp point(type) do
replacements(type)
|> replacements(
xyzm: "fn [x, _y, _z, _m] -> x end",
xyz: "fn [x, _y, _z] -> x end",
xym: "fn [x, _y, _m] -> x end",
xy: "fn [x, _y] -> x end"
)
|> replacements(
xyzm: "new(number(), number(), number(), number())",
xyz: "new(number(), number(), number())",
xym: "new(number(), number(), number())",
xy: "new(number(), number())"
)
|> replacements(
xyzm: "defstruct [:x, :y, :z, :m]",
xyz: "defstruct [:x, :y, :z]",
xym: "defstruct [:x, :y, :m]",
xy: "defstruct [:x, :y]"
)
|> replacements(
xyzm: "{x: Geometry.x(), y: Geometry.y(), z: Geometry.y(), z: Geometry.m()}",
xy: "{x: Geometry.x(), y: Geometry.y()}",
xyz: "{x: Geometry.x(), y: Geometry.y(), z: Geometry.z()}",
xym: "{x: Geometry.x(), y: Geometry.y(), m: Geometry.m()}"
)
|> replacements(
xyzm: "[nil, nil, nil, nil]",
xyz: "[nil, nil, nil]",
xym: "[nil, nil, nil]",
xy: "[nil, nil]"
)
|> replacements(
xyzm: "x, y, z, m",
xy: "x, y",
xyz: "x, y, z",
xym: "x, y, m"
)
|> replacements(
xyzm: "Geometry.x(), Geometry.y(), Geometry.z(), Geometry.m()",
xy: "Geometry.x(), Geometry.y()",
xyz: "Geometry.x(), Geometry.y(), Geometry.z()",
xym: "Geometry.x(), Geometry.y(), Geometry.m()"
)
|> replacements(
xyzm: "{x: x, y: y, z: z, m: m}",
xy: "{x: x, y: y}",
xyz: "{x: x, y: y, z: z}",
xym: "{x: x, y: y, m: m}"
)
|> replacements(
xyzm: "`x`, `y`, `z`, and `m`",
xy: "`x` and `y`",
xyz: "`x`, `y`, and `z`",
xym: "`x`, `y`, and `m`"
)
|> replacements(
xyzm: ~S"""
to_wkt_number(x)::binary(),
@blank,
to_wkt_number(y)::binary(),
@blank,
to_wkt_number(z)::binary(),
@blank,
to_wkt_number(m)::binary()
""",
xyz: ~S"""
to_wkt_number(x)::binary(),
@blank,
to_wkt_number(y)::binary(),
@blank,
to_wkt_number(z)::binary()
""",
xym: ~S"""
to_wkt_number(x)::binary(),
@blank,
to_wkt_number(y)::binary(),
@blank,
to_wkt_number(m)::binary()
""",
xy: ~S"""
to_wkt_number(x)::binary(),
@blank,
to_wkt_number(y)::binary()
"""
)
|> replacements(
xyzm: """
7FF8000000000000\
7FF8000000000000\
7FF8000000000000\
7FF8000000000000\
""",
xy: """
7FF8000000000000\
7FF8000000000000\
""",
xyz: """
7FF8000000000000\
7FF8000000000000\
7FF8000000000000\
""",
xym: """
7FF8000000000000\
7FF8000000000000\
7FF8000000000000\
"""
)
|> replacements(
xyzm: """
000000000000F87F\
000000000000F87F\
000000000000F87F\
000000000000F87F\
""",
xy: """
000000000000F87F\
000000000000F87F\
""",
xyz: """
000000000000F87F\
000000000000F87F\
000000000000F87F\
""",
xym: """
000000000000F87F\
000000000000F87F\
000000000000F87F\
"""
)
|> replacements(
xyzm: ~S"""
to_wkb_number(x, endian, mode)::binary(),
to_wkb_number(y, endian, mode)::binary(),
to_wkb_number(z, endian, mode)::binary(),
to_wkb_number(m, endian, mode)::binary()
""",
xy: ~S"""
to_wkb_number(x, endian, mode)::binary(),
to_wkb_number(y, endian, mode)::binary()
""",
xym: ~S"""
to_wkb_number(x, endian, mode)::binary(),
to_wkb_number(y, endian, mode)::binary(),
to_wkb_number(m, endian, mode)::binary()
""",
xyz: ~S"""
to_wkb_number(x, endian, mode)::binary(),
to_wkb_number(y, endian, mode)::binary(),
to_wkb_number(z, endian, mode)::binary()
"""
)
|> replacements()
end
defp comment(code, type) do
case Regex.run(~r/3D\s(.*)\swith a measurement/m, code) do
[old, name] ->
new =
case type do
:xy -> "2D #{name}"
:xym -> "2D #{name} with a measurement"
:xyz -> "3D #{name}"
end
{old, new}
_not_found ->
:skip
end
end
defp args(code) do
regex = ~r/\(
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+)
\)/mx
Regex.scan(regex, code)
end
defp lists(code) do
regex = ~r/\[
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+)
\]/mx
Regex.scan(regex, code)
end
defp props(code) do
regex = ~r/\{
x:\s([-.0-9]+),\s
y:\s([-.0-9]+),\s
z:\s([-.0-9]+),\s
m:\s([-.0-9]+)
\}/mx
Regex.scan(regex, code)
end
defp tuples(code) do
regex = ~r/\{
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+),\s
([-.0-9]+)
\}/mx
Regex.scan(regex, code)
end
defp wkt_coordinates(code) do
regex = ~r/([-.0-9]+)\s([-.0-9]+)\s([-.0-9]+)\s([-.0-9]+)/m
Regex.scan(regex, code)
end
defp args(code, :xy) do
code
|> args()
|> Enum.map(fn [pattern, x, y | _] -> [pattern, "(#{x}, #{y})"] end)
|> unzip()
end
defp args(code, :xyz) do
code
|> args()
|> Enum.map(fn [pattern, x, y, z, _] -> [pattern, "(#{x}, #{y}, #{z})"] end)
|> unzip()
end
defp args(code, :xym) do
code
|> args()
|> Enum.map(fn [pattern, x, y, _, m] -> [pattern, "(#{x}, #{y}, #{m})"] end)
|> unzip()
end
defp lists(code, :xy) do
code
|> lists()
|> Enum.map(fn [pattern, x, y | _] -> [pattern, "[#{x}, #{y}]"] end)
|> unzip()
end
defp lists(code, :xyz) do
code
|> lists()
|> Enum.map(fn [pattern, x, y, z, _] -> [pattern, "[#{x}, #{y}, #{z}]"] end)
|> unzip()
end
defp lists(code, :xym) do
code
|> lists()
|> Enum.map(fn [pattern, x, y, _, m] -> [pattern, "[#{x}, #{y}, #{m}]"] end)
|> unzip()
end
defp props(code, :xy) do
code
|> props()
|> Enum.map(fn [pattern, x, y | _] -> [pattern, "{x: #{x}, y: #{y}}"] end)
|> unzip()
end
defp props(code, :xyz) do
code
|> props()
|> Enum.map(fn [pattern, x, y, z, _] -> [pattern, "{x: #{x}, y: #{y}, z: #{z}}"] end)
|> unzip()
end
defp props(code, :xym) do
code
|> props()
|> Enum.map(fn [pattern, x, y, _, m] -> [pattern, "{x: #{x}, y: #{y}, m: #{m}}"] end)
|> unzip()
end
defp tuples(code, :xy) do
code
|> tuples()
|> Enum.map(fn [pattern, x, y | _] -> [pattern, "{#{x}, #{y}}"] end)
|> unzip()
end
defp tuples(code, :xyz) do
code
|> tuples()
|> Enum.map(fn [pattern, x, y, z, _] -> [pattern, "{#{x}, #{y}, #{z}}"] end)
|> unzip()
end
defp tuples(code, :xym) do
code
|> tuples()
|> Enum.map(fn [pattern, x, y, _, m] -> [pattern, "{#{x}, #{y}, #{m}}"] end)
|> unzip()
end
defp wkt_coordinates(code, :xy) do
code
|> wkt_coordinates()
|> Enum.map(fn [pattern, x, y | _] -> [pattern, "#{x} #{y}"] end)
|> unzip()
end
defp wkt_coordinates(code, :xyz) do
code
|> wkt_coordinates()
|> Enum.map(fn [pattern, x, y, z, _] -> [pattern, "#{x} #{y} #{z}"] end)
|> unzip()
end
defp wkt_coordinates(code, :xym) do
code
|> wkt_coordinates()
|> Enum.map(fn [pattern, x, y, _, m] -> [pattern, "#{x} #{y} #{m}"] end)
|> unzip()
end
defp point_test(type) do
replacements(type)
|> replacements(
xyzm: "01010000C0000000000000F87F000000000000F87F000000000000F87F000000000000F87F",
xyz: "0101000080000000000000F87F000000000000F87F000000000000F87F",
xym: "0101000040000000000000F87F000000000000F87F000000000000F87F",
xy: "0101000000000000000000F87F000000000000F87F"
)
|> replacements(
xyzm: "00C00000013FF199999999999A400199999999999A400A666666666666401199999999999A",
xyz: "00800000013FF199999999999A400199999999999A400A666666666666",
xym: "00400000013FF199999999999A400199999999999A401199999999999A",
xy: "00000000013FF199999999999A400199999999999A"
)
|> replacements(
xyzm: "01010000C09A9999999999F13F9A999999999901406666666666660A409A99999999991140",
xyz: "01010000809A9999999999F13F9A999999999901406666666666660A40",
xym: "01010000409A9999999999F13F9A999999999901409A99999999991140",
xy: "01010000009A9999999999F13F9A99999999990140"
)
|> replacements(
xyzm: "00C00000017FF80000000000007FF80000000000007FF80000000000007FF8000000000000",
xyz: "00800000017FF80000000000007FF80000000000007FF8000000000000",
xym: "00400000017FF80000000000007FF80000000000007FF8000000000000",
xy: "00000000017FF80000000000007FF8000000000000"
)
|> replacements(
xyzm: "00E0000001000012673FF199999999999A400199999999999A400A666666666666401199999999999A",
xyz: "00A0000001000012673FF199999999999A400199999999999A400A666666666666",
xym: "0060000001000012673FF199999999999A400199999999999A401199999999999A",
xy: "0020000001000012673FF199999999999A400199999999999A"
)
|> replacements(
xyzm: "00E00000010000014D3FF199999999999A400199999999999A400A666666666666401199999999999A",
xyz: "00A00000010000014D3FF199999999999A400199999999999A400A666666666666",
xym: "00600000010000014D3FF199999999999A400199999999999A401199999999999A",
xy: "00200000010000014D3FF199999999999A400199999999999A"
)
|> replacements(
xyzm: "01010000E04D0100009A9999999999F13F9A999999999901406666666666660A409A99999999991140",
xyz: "01010000A04D0100009A9999999999F13F9A999999999901406666666666660A40",
xym: "01010000604D0100009A9999999999F13F9A999999999901409A99999999991140",
xy: "01010000204D0100009A9999999999F13F9A99999999990140"
)
|> replacements()
end
defp line_string_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
00\
E0000002\
0000004D\
00000002\
BFF199999999999AC00199999999999AC00A666666666666C01199999999999A\
4016000000000000401A666666666666401ECCCCCCCCCCCD402199999999999A\
""",
xyz: ~S"""
00\
A0000002\
0000004D\
00000002\
BFF199999999999AC00199999999999AC00A666666666666\
4016000000000000401A666666666666401ECCCCCCCCCCCD\
""",
xym: ~S"""
00\
60000002\
0000004D\
00000002\
BFF199999999999AC00199999999999AC01199999999999A\
4016000000000000401A666666666666402199999999999A\
""",
xy: ~S"""
00\
20000002\
0000004D\
00000002\
BFF199999999999AC00199999999999A\
4016000000000000401A666666666666\
"""
)
|> replacements(
xyzm: ~S"""
01\
020000C0\
02000000\
9A9999999999F1BF9A999999999901C06666666666660AC09A999999999911C0\
00000000000016406666666666661A40CDCCCCCCCCCC1E409A99999999992140\
""",
xyz: ~S"""
01\
02000080\
02000000\
9A9999999999F1BF9A999999999901C06666666666660AC0\
00000000000016406666666666661A40CDCCCCCCCCCC1E40\
""",
xym: ~S"""
01\
02000040\
02000000\
9A9999999999F1BF9A999999999901C09A999999999911C0\
00000000000016406666666666661A409A99999999992140\
""",
xy: ~S"""
01\
02000000\
02000000\
9A9999999999F1BF9A999999999901C0\
00000000000016406666666666661A40\
"""
)
|> replacements(
xyzm: ~S"""
01\
020000E0\
67120000\
02000000\
CB49287D21C451C0F0BF95ECD824454066666666666614409A9999999999F13F\
E5D022DBF93E24C0CDCCCCCCCC0C2440CDCCCCCCCCCC21409A99999999990140\
""",
xyz: ~S"""
01\
020000A0\
67120000\
02000000\
CB49287D21C451C0F0BF95ECD82445406666666666661440\
E5D022DBF93E24C0CDCCCCCCCC0C2440CDCCCCCCCCCC2140\
""",
xym: ~S"""
01\
02000060\
67120000\
02000000\
CB49287D21C451C0F0BF95ECD82445409A9999999999F13F\
E5D022DBF93E24C0CDCCCCCCCC0C24409A99999999990140\
""",
xy: ~S"""
01\
02000020\
67120000\
02000000\
CB49287D21C451C0F0BF95ECD8244540\
E5D022DBF93E24C0CDCCCCCCCC0C2440\
"""
)
|> replacements()
end
defp polygon_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
01\
030000E0\
4D010000\
02000000\
05000000\
000000000080414000000000000024400000000000002E400000000000003940\
0000000000804640000000000080464000000000000024400000000000003440\
0000000000002E40000000000000444000000000000034400000000000002440\
000000000000244000000000000034400000000000002E400000000000003940\
000000000080414000000000000024400000000000002E400000000000003940\
04000000\
00000000000034400000000000003E400000000000002E400000000000002440\
0000000000804140000000000080414000000000000024400000000000004940\
0000000000003E40000000000000344000000000000039400000000000804140\
00000000000034400000000000003E400000000000002E400000000000002440\
""",
xyz: ~S"""
01\
030000A0\
4D010000\
02000000\
05000000\
000000000080414000000000000024400000000000002E40\
000000000080464000000000008046400000000000002440\
0000000000002E4000000000000044400000000000003440\
000000000000244000000000000034400000000000002E40\
000000000080414000000000000024400000000000002E40\
04000000\
00000000000034400000000000003E400000000000002E40\
000000000080414000000000008041400000000000002440\
0000000000003E4000000000000034400000000000003940\
00000000000034400000000000003E400000000000002E40\
""",
xym: ~S"""
01\
03000060\
4D010000\
02000000\
05000000\
000000000080414000000000000024400000000000003940\
000000000080464000000000008046400000000000003440\
0000000000002E4000000000000044400000000000002440\
000000000000244000000000000034400000000000003940\
000000000080414000000000000024400000000000003940\
04000000\
00000000000034400000000000003E400000000000002440\
000000000080414000000000008041400000000000004940\
0000000000003E4000000000000034400000000000804140\
00000000000034400000000000003E400000000000002440\
""",
xy: ~S"""
01\
03000020\
4D010000\
02000000\
05000000\
00000000008041400000000000002440\
00000000008046400000000000804640\
0000000000002E400000000000004440\
00000000000024400000000000003440\
00000000008041400000000000002440\
04000000\
00000000000034400000000000003E40\
00000000008041400000000000804140\
0000000000003E400000000000003440\
00000000000034400000000000003E40\
"""
)
|> replacements(
xyzm: ~S"""
00\
C0000003\
00000001\
00000005\
403E00000000000040240000000000004034000000000000402E000000000000\
4044000000000000404400000000000040240000000000004034000000000000\
403400000000000040440000000000004039000000000000402E000000000000\
40240000000000004034000000000000402E0000000000004039000000000000\
403E00000000000040240000000000004034000000000000402E000000000000\
""",
xyz: ~S"""
00\
80000003\
00000001\
00000005\
403E00000000000040240000000000004034000000000000\
404400000000000040440000000000004024000000000000\
403400000000000040440000000000004039000000000000\
40240000000000004034000000000000402E000000000000\
403E00000000000040240000000000004034000000000000\
""",
xym: ~S"""
00\
40000003\
00000001\
00000005\
403E0000000000004024000000000000402E000000000000\
404400000000000040440000000000004034000000000000\
40340000000000004044000000000000402E000000000000\
402400000000000040340000000000004039000000000000\
403E0000000000004024000000000000402E000000000000\
""",
xy: ~S"""
00\
00000003\
00000001\
00000005\
403E0000000000004024000000000000\
40440000000000004044000000000000\
40340000000000004044000000000000\
40240000000000004034000000000000\
403E0000000000004024000000000000\
"""
)
|> replacements(
xyzm: ~S"""
00\
E0000003\
00001267\
00000001\
00000004\
403E000000000000402400000000000040140000000000004000000000000000\
4044000000000000404400000000000040100000000000004020000000000000\
4034000000000000404400000000000040200000000000004020000000000000\
403E000000000000402400000000000040140000000000004000000000000000\
""",
xyz: ~S"""
00\
A0000003\
00001267\
00000001\
00000004\
403E00000000000040240000000000004014000000000000\
404400000000000040440000000000004010000000000000\
403400000000000040440000000000004020000000000000\
403E00000000000040240000000000004014000000000000\
""",
xym: ~S"""
00\
60000003\
00001267\
00000001\
00000004\
403E00000000000040240000000000004000000000000000\
404400000000000040440000000000004020000000000000\
403400000000000040440000000000004020000000000000\
403E00000000000040240000000000004000000000000000\
""",
xy: ~S"""
00\
20000003\
00001267\
00000001\
00000004\
403E0000000000004024000000000000\
40440000000000004044000000000000\
40340000000000004044000000000000\
403E0000000000004024000000000000\
"""
)
|> replacements()
end
defp multi_line_string_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
00\
C0000005\
00000002\
00\
C0000002\
00000003\
402400000000000040240000000000004034000000000000403E000000000000\
4034000000000000403400000000000040440000000000004049000000000000\
4024000000000000404400000000000040240000000000004034000000000000\
00\
C0000002\
00000002\
40440000000000004044000000000000403E0000000000004034000000000000\
403E000000000000403E00000000000040440000000000004049000000000000\
""",
xyz: ~S"""
00\
80000005\
00000002\
00\
80000002\
00000003\
402400000000000040240000000000004034000000000000\
403400000000000040340000000000004044000000000000\
402400000000000040440000000000004024000000000000\
00\
80000002\
00000002\
40440000000000004044000000000000403E000000000000\
403E000000000000403E0000000000004044000000000000\
""",
xym: ~S"""
00\
40000005\
00000002\
00\
40000002\
00000003\
40240000000000004024000000000000403E000000000000\
403400000000000040340000000000004049000000000000\
402400000000000040440000000000004034000000000000\
00\
40000002\
00000002\
404400000000000040440000000000004034000000000000\
403E000000000000403E0000000000004049000000000000\
""",
xy: ~S"""
00\
00000005\
00000002\
00\
00000002\
00000003\
40240000000000004024000000000000\
40340000000000004034000000000000\
40240000000000004044000000000000\
00\
00000002\
00000002\
40440000000000004044000000000000\
403E000000000000403E000000000000\
"""
)
|> replacements(
xyzm: ~S"""
01\
050000E0\
15030000\
01000000\
01\
020000C0\
02000000\
9A9999999999F13F333333333333F33FCDCCCCCCCCCCF43F666666666666F63F\
000000000000F83F9A9999999999F93F333333333333FB3FCDCCCCCCCCCCFC3F\
""",
xyz: ~S"""
01\
050000A0\
15030000\
01000000\
01\
02000080\
02000000\
9A9999999999F13F333333333333F33FCDCCCCCCCCCCF43F\
000000000000F83F9A9999999999F93F333333333333FB3F\
""",
xym: ~S"""
01\
05000060\
15030000\
01000000\
01\
02000040\
02000000\
9A9999999999F13F333333333333F33F666666666666F63F\
000000000000F83F9A9999999999F93FCDCCCCCCCCCCFC3F\
""",
xy: ~S"""
01\
05000020\
15030000\
01000000\
01\
02000000\
02000000\
9A9999999999F13F333333333333F33F\
000000000000F83F9A9999999999F93F\
"""
)
|> replacements(
xyzm: ~S"""
01\
050000C0\
01000000\
01\
020000C0\
02000000\
9A9999999999F13F333333333333F33FCDCCCCCCCCCCF43F666666666666F63F\
000000000000F83F9A9999999999F93F333333333333FB3FCDCCCCCCCCCCFC3F\
""",
xyz: ~S"""
01\
05000080\
01000000\
01\
02000080\
02000000\
9A9999999999F13F333333333333F33FCDCCCCCCCCCCF43F\
000000000000F83F9A9999999999F93F333333333333FB3F\
""",
xym: ~S"""
01\
05000040\
01000000\
01\
02000040\
02000000\
9A9999999999F13F333333333333F33F666666666666F63F\
000000000000F83F9A9999999999F93FCDCCCCCCCCCCFC3F\
""",
xy: ~S"""
01\
05000000\
01000000\
01\
02000000\
02000000\
9A9999999999F13F333333333333F33F\
000000000000F83F9A9999999999F93F\
"""
)
|> replacements(
xyzm: ~S"""
00\
E0000005\
0000028E\
00000001\
00\
C0000002\
00000002\
3FF199999999999A3FF33333333333333FF4CCCCCCCCCCCD3FF6666666666666\
3FF80000000000003FF999999999999A3FFB3333333333333FFCCCCCCCCCCCCD\
""",
xyz: ~S"""
00\
A0000005\
0000028E\
00000001\
00\
80000002\
00000002\
3FF199999999999A3FF33333333333333FF4CCCCCCCCCCCD\
3FF80000000000003FF999999999999A3FFB333333333333\
""",
xym: ~S"""
00\
60000005\
0000028E\
00000001\
00\
40000002\
00000002\
3FF199999999999A3FF33333333333333FF6666666666666\
3FF80000000000003FF999999999999A3FFCCCCCCCCCCCCD\
""",
xy: ~S"""
00\
20000005\
0000028E\
00000001\
00\
00000002\
00000002\
3FF199999999999A3FF3333333333333\
3FF80000000000003FF999999999999A\
"""
)
|> replacements(
xyzm: ~S(wkb_start = "00C00000050000000200C0000002"),
xyz: ~S(wkb_start = "0080000005000000020080000002"),
xym: ~S(wkb_start = "0040000005000000020040000002"),
xy: ~S(wkb_start = "0000000005000000020000000002")
)
|> replacements()
end
defp geometry_collection_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
01\
070000C0\
03000000\
""",
xyz: ~S"""
01\
07000080\
03000000\
""",
xym: ~S"""
01\
07000040\
03000000\
""",
xy: ~S"""
01\
07000000\
03000000\
"""
)
|> replacements(
xyzm: ~S"""
01\
070000C0\
01000000\
01\
010000C0\
000000000000F03F000000000000004000000000000008400000000000001040\
""",
xyz: ~S"""
01\
07000080\
01000000\
01\
01000080\
000000000000F03F00000000000000400000000000000840\
""",
xym: ~S"""
01\
07000040\
01000000\
01\
01000040\
000000000000F03F00000000000000400000000000001040\
""",
xy: ~S"""
01\
07000000\
01000000\
01\
01000000\
000000000000F03F0000000000000040\
"""
)
|> replacements(
xyzm: ~S"""
01\
070000E0\
37000000\
01000000\
01\
010000C0\
000000000000F03F000000000000004000000000000008400000000000001040\
""",
xyz: ~S"""
01\
070000A0\
37000000\
01000000\
01\
01000080\
000000000000F03F00000000000000400000000000000840\
""",
xym: ~S"""
01\
07000060\
37000000\
01000000\
01\
01000040\
000000000000F03F00000000000000400000000000001040\
""",
xy: ~S"""
01\
07000020\
37000000\
01000000\
01\
01000000\
000000000000F03F0000000000000040\
"""
)
|> replacements(
xyzm: """
01\
070000C0\
01000000\
01\
010000E0\
37000000\
000000000000F03F000000000000004000000000000008400000000000001040\
""",
xym: """
01\
07000080\
01000000\
01\
010000A0\
37000000\
000000000000F03F00000000000000400000000000001040\
""",
xyz: """
01\
07000040\
01000000\
01\
01000060\
37000000\
000000000000F03F00000000000000400000000000000840\
""",
xy: """
01\
07000000\
01000000\
01\
01000020\
37000000\
000000000000F03F0000000000000040\
"""
)
|> replacements(
xyzm: "01070000C000000000",
xyz: "010700008000000000",
xym: "010700004000000000",
xy: "010700000000000000"
)
|> replacements()
end
defp multi_polygon_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
01\
060000C0\
02000000\
01\
030000C0\
02000000\
04000000\
000000000000F03F000000000000F03F00000000000008400000000000001040\
0000000000002240000000000000F03F00000000000010400000000000001440\
0000000000002240000000000000204000000000000014400000000000001840\
000000000000F03F000000000000F03F00000000000008400000000000001040\
04000000\
0000000000001840000000000000004000000000000010400000000000000840\
0000000000001C40000000000000004000000000000018400000000000001C40\
0000000000001C40000000000000084000000000000008400000000000001040\
0000000000001840000000000000004000000000000010400000000000000840\
01\
030000C0\
01000000\
04000000\
0000000000001840000000000000004000000000000008400000000000001040\
0000000000002040000000000000004000000000000010400000000000001440\
0000000000002040000000000000104000000000000014400000000000001840\
0000000000001840000000000000004000000000000008400000000000001040\
""",
xyz: ~S"""
01\
06000080\
02000000\
01\
03000080\
02000000\
04000000\
000000000000F03F000000000000F03F0000000000000840\
0000000000002240000000000000F03F0000000000001040\
000000000000224000000000000020400000000000001440\
000000000000F03F000000000000F03F0000000000000840\
04000000\
000000000000184000000000000000400000000000001040\
0000000000001C4000000000000000400000000000001840\
0000000000001C4000000000000008400000000000000840\
000000000000184000000000000000400000000000001040\
01\
03000080\
01000000\
04000000\
000000000000184000000000000000400000000000000840\
000000000000204000000000000000400000000000001040\
000000000000204000000000000010400000000000001440\
000000000000184000000000000000400000000000000840\
""",
xym: ~S"""
01\
06000040\
02000000\
01\
03000040\
02000000\
04000000\
000000000000F03F000000000000F03F0000000000001040\
0000000000002240000000000000F03F0000000000001440\
000000000000224000000000000020400000000000001840\
000000000000F03F000000000000F03F0000000000001040\
04000000\
000000000000184000000000000000400000000000000840\
0000000000001C4000000000000000400000000000001C40\
0000000000001C4000000000000008400000000000001040\
000000000000184000000000000000400000000000000840\
01\
03000040\
01000000\
04000000\
000000000000184000000000000000400000000000001040\
000000000000204000000000000000400000000000001440\
000000000000204000000000000010400000000000001840\
000000000000184000000000000000400000000000001040\
""",
xy: ~S"""
01\
06000000\
02000000\
01\
03000000\
02000000\
04000000\
000000000000F03F000000000000F03F\
0000000000002240000000000000F03F\
00000000000022400000000000002040\
000000000000F03F000000000000F03F\
04000000\
00000000000018400000000000000040\
0000000000001C400000000000000040\
0000000000001C400000000000000840\
00000000000018400000000000000040\
01\
03000000\
01000000\
04000000\
00000000000018400000000000000040\
00000000000020400000000000000040\
00000000000020400000000000001040\
00000000000018400000000000000040\
"""
)
|> replacements(
xyzm: ~S(wkb = "00C000000700000000"),
xyz: ~S(wkb = "008000000700000000"),
xym: ~S(wkb = "004000000700000000"),
xy: ~S(wkb = "000000000700000000")
)
|> replacements(
xyzm: ~S(wkb = "01070000E07B00000000000000"),
xyz: ~S(wkb = "01070000A07B00000000000000"),
xym: ~S(wkb = "01070000607B00000000000000"),
xy: ~S(wkb = "01070000207B00000000000000")
)
|> replacements(
xyzm: ~S(wkb = "00E00000070000014100000000"),
xyz: ~S(wkb = "00A00000070000014100000000"),
xym: ~S(wkb = "00600000070000014100000000"),
xy: ~S(wkb = "00200000070000014100000000")
)
|> replacements(
xyzm: ~S(wkb = "01060000E00903000000000000"),
xyz: ~S(wkb = "01060000A00903000000000000"),
xym: ~S(wkb = "01060000600903000000000000"),
xy: ~S(wkb = "01060000200903000000000000")
)
|> replacements(
xyzm: ~S(wkb = "00E00000060000023400000000"),
xyz: ~S(wkb = "00A00000060000023400000000"),
xym: ~S(wkb = "00600000060000023400000000"),
xy: ~S(wkb = "00200000060000023400000000")
)
|> replacements(
xyzm: ~S(wkb = "00C000000600000000"),
xyz: ~S(wkb = "008000000600000000"),
xym: ~S(wkb = "004000000600000000"),
xy: ~S(wkb = "000000000600000000")
)
|> replacements(
xyzm: ~S(wkb_start = "01060000C00200000001030000C0"),
xyz: ~S(wkb_start = "0106000080020000000103000080"),
xym: ~S(wkb_start = "0106000040020000000103000040"),
xy: ~S(wkb_start = "0106000000020000000103000000")
)
|> replacements()
end
defp multi_point_test(type) do
replacements(type)
|> replacements(
xyzm: ~S"""
00\
C0000004\
00000003\
00\
C0000001\
403E0000000000004024000000000000402E0000000000004024000000000000\
00\
C0000001\
404400000000000040440000000000004034000000000000403E000000000000\
00\
C0000001\
40340000000000004044000000000000402E0000000000004034000000000000\
""",
xyz: ~S"""
00\
80000004\
00000003\
00\
80000001\
403E0000000000004024000000000000402E000000000000\
00\
80000001\
404400000000000040440000000000004034000000000000\
00\
80000001\
40340000000000004044000000000000402E000000000000\
""",
xym: ~S"""
00\
40000004\
00000003\
00\
40000001\
403E00000000000040240000000000004024000000000000\
00\
40000001\
40440000000000004044000000000000403E000000000000\
00\
40000001\
403400000000000040440000000000004034000000000000\
""",
xy: ~S"""
00\
00000004\
00000003\
00\
00000001\
403E0000000000004024000000000000\
00\
00000001\
40440000000000004044000000000000\
00\
00000001\
40340000000000004044000000000000\
"""
)
|> replacements(
xyzm: ~S"""
01\
040000E0\
0F270000\
01000000\
01\
010000C0\
0000000000003E4000000000000024400000000000002E400000000000002440\
""",
xyz: ~S"""
01\
040000A0\
0F270000\
01000000\
01\
01000080\
0000000000003E4000000000000024400000000000002E40\
""",
xym: ~S"""
01\
04000060\
0F270000\
01000000\
01\
01000040\
0000000000003E4000000000000024400000000000002440\
""",
xy: ~S"""
01\
04000020\
0F270000\
01000000\
01\
01000000\
0000000000003E400000000000002440\
"""
)
|> replacements(
xyzm: ~S"""
00\
C0000004\
00000000\
""",
xyz: ~S"""
00\
80000004\
00000000\
""",
xym: ~S"""
00\
40000004\
00000000\
""",
xy: ~S"""
00\
00000004\
00000000\
"""
)
|> replacements(
xyzm: ~S"""
01\
040000C0\
00000000\
""",
xyz: ~S"""
01\
04000080\
00000000\
""",
xym: ~S"""
01\
04000040\
00000000\
""",
xy: ~S"""
01\
04000000\
00000000\
"""
)
|> replacements(
xyzm: ~S"""
00\
E0000004\
0000270F\
00000001\
00\
C0000001\
C051C4217D2849CB404524D8EC95BFF040265FB15B573EAB40149DB22D0E5604\
""",
xyz: ~S"""
00\
A0000004\
0000270F\
00000001\
00\
80000001\
C051C4217D2849CB404524D8EC95BFF040265FB15B573EAB\
""",
xym: ~S"""
00\
60000004\
0000270F\
00000001\
00\
40000001\
C051C4217D2849CB404524D8EC95BFF040149DB22D0E5604\
""",
xy: ~S"""
00\
20000004\
0000270F\
00000001\
00\
00000001\
C051C4217D2849CB404524D8EC95BFF0\
"""
)
|> replacements(
xyzm: ~S(wkb_start = "00C00000040000000300C0000001"),
xyz: ~S(wkb_start = "0080000004000000030080000001"),
xym: ~S(wkb_start = "0040000004000000030040000001"),
xy: ~S(wkb_start = "0000000004000000030000000001")
)
|> replacements()
end
defp geometry_collection(type) do
replacements(type)
|> replacements(
xyzm: ", type: :zm",
xyz: ", type: :z",
xym: ", type: :m",
xy: ""
)
|> replacements()
end
defp wkb_code(type) do
replacements(type)
|> replacements(
# Geometries without SRID
xyzm: "0xC",
xyz: "0x8",
xym: "0x4",
xy: "0x0"
)
|> replacements(
# Geometries with SRID
xyzm: "0xE",
xyz: "0xA",
xym: "0x6",
xy: "0x2"
)
|> replacements(
# Point
xy: """
{:xdr, false} -> "00000001"
{:ndr, false} -> "01000000"
{:xdr, true} -> "20000001"
{:ndr, true} -> "01000020"
""",
xym: """
{:xdr, false} -> "40000001"
{:ndr, false} -> "01000040"
{:xdr, true} -> "60000001"
{:ndr, true} -> "01000060"
""",
xyz: """
{:xdr, false} -> "80000001"
{:ndr, false} -> "01000080"
{:xdr, true} -> "A0000001"
{:ndr, true} -> "010000A0"
""",
xyzm: """
{:xdr, false} -> "C0000001"
{:ndr, false} -> "010000C0"
{:xdr, true} -> "E0000001"
{:ndr, true} -> "010000E0"
"""
)
|> replacements(
# LineString
xy: """
{:xdr, false} -> "00000002"
{:ndr, false} -> "02000000"
{:xdr, true} -> "20000002"
{:ndr, true} -> "02000020"
""",
xym: """
{:xdr, false} -> "40000002"
{:ndr, false} -> "02000040"
{:xdr, true} -> "60000002"
{:ndr, true} -> "02000060"
""",
xyz: """
{:xdr, false} -> "80000002"
{:ndr, false} -> "02000080"
{:xdr, true} -> "A0000002"
{:ndr, true} -> "020000A0"
""",
xyzm: """
{:xdr, false} -> "C0000002"
{:ndr, false} -> "020000C0"
{:xdr, true} -> "E0000002"
{:ndr, true} -> "020000E0"
"""
)
|> replacements(
# Polygon
xy: """
{:xdr, false} -> "00000003"
{:ndr, false} -> "03000000"
{:xdr, true} -> "20000003"
{:ndr, true} -> "03000020"
""",
xym: """
{:xdr, false} -> "40000003"
{:ndr, false} -> "03000040"
{:xdr, true} -> "60000003"
{:ndr, true} -> "03000060"
""",
xyz: """
{:xdr, false} -> "80000003"
{:ndr, false} -> "03000080"
{:xdr, true} -> "A0000003"
{:ndr, true} -> "030000A0"
""",
xyzm: """
{:xdr, false} -> "C0000003"
{:ndr, false} -> "030000C0"
{:xdr, true} -> "E0000003"
{:ndr, true} -> "030000E0"
"""
)
|> replacements(
# MultiPoint
xy: """
{:xdr, false} -> "00000004"
{:ndr, false} -> "04000000"
{:xdr, true} -> "20000004"
{:ndr, true} -> "04000020"
""",
xym: """
{:xdr, false} -> "40000004"
{:ndr, false} -> "04000040"
{:xdr, true} -> "60000004"
{:ndr, true} -> "04000060"
""",
xyz: """
{:xdr, false} -> "80000004"
{:ndr, false} -> "04000080"
{:xdr, true} -> "A0000004"
{:ndr, true} -> "040000A0"
""",
xyzm: """
{:xdr, false} -> "C0000004"
{:ndr, false} -> "040000C0"
{:xdr, true} -> "E0000004"
{:ndr, true} -> "040000E0"
"""
)
|> replacements(
# MultiLineString
xy: """
{:xdr, false} -> "00000005"
{:ndr, false} -> "05000000"
{:xdr, true} -> "20000005"
{:ndr, true} -> "05000020"
""",
xym: """
{:xdr, false} -> "40000005"
{:ndr, false} -> "05000040"
{:xdr, true} -> "60000005"
{:ndr, true} -> "05000060"
""",
xyz: """
{:xdr, false} -> "80000005"
{:ndr, false} -> "05000080"
{:xdr, true} -> "A0000005"
{:ndr, true} -> "050000A0"
""",
xyzm: """
{:xdr, false} -> "C0000005"
{:ndr, false} -> "050000C0"
{:xdr, true} -> "E0000005"
{:ndr, true} -> "050000E0"
"""
)
|> replacements(
# MultiPolygon
xy: """
{:xdr, false} -> "00000006"
{:ndr, false} -> "06000000"
{:xdr, true} -> "20000006"
{:ndr, true} -> "06000020"
""",
xym: """
{:xdr, false} -> "40000006"
{:ndr, false} -> "06000040"
{:xdr, true} -> "60000006"
{:ndr, true} -> "06000060"
""",
xyz: """
{:xdr, false} -> "80000006"
{:ndr, false} -> "06000080"
{:xdr, true} -> "A0000006"
{:ndr, true} -> "060000A0"
""",
xyzm: """
{:xdr, false} -> "C0000006"
{:ndr, false} -> "060000C0"
{:xdr, true} -> "E0000006"
{:ndr, true} -> "060000E0"
"""
)
|> replacements(
# GeometryCollection
xy: """
{:xdr, false} -> "00000007"
{:ndr, false} -> "07000000"
{:xdr, true} -> "20000007"
{:ndr, true} -> "07000020"
""",
xym: """
{:xdr, false} -> "40000007"
{:ndr, false} -> "07000040"
{:xdr, true} -> "60000007"
{:ndr, true} -> "07000060"
""",
xyz: """
{:xdr, false} -> "80000007"
{:ndr, false} -> "07000080"
{:xdr, true} -> "A0000007"
{:ndr, true} -> "070000A0"
""",
xyzm: """
{:xdr, false} -> "C0000007"
{:ndr, false} -> "070000C0"
{:xdr, true} -> "E0000007"
{:ndr, true} -> "070000E0"
"""
)
|> replacements()
end
defp replacements({old, new, _type}), do: {List.flatten(old), List.flatten(new)}
defp replacements(type), do: {[], [], type}
defp replacements({old, new, type}, items) do
{[Keyword.get(items, :xyzm) | old], [Keyword.fetch!(items, type) | new], type}
end
defp replace(code, :skip), do: code
defp replace(code, {patterns, replacements})
when is_list(patterns) and is_list(replacements) do
patterns
|> Enum.zip(replacements)
|> Enum.reduce(code, fn {pattern, replacement}, acc ->
String.replace(acc, pattern, replacement, global: true)
end)
end
defp replace(code, {pattern, replacement}),
do: String.replace(code, pattern, replacement, global: true)
defp unzip(list) do
Enum.reduce(list, {[], []}, fn [a, b], {as, bs} ->
{[a | as], [b | bs]}
end)
end
defp info(str), do: IO.write("#{str}\n")
end
GenFromZM.main()