diff --git a/lib/geo_postgis.ex b/lib/geo_postgis.ex index f25b496..8a8832d 100644 --- a/lib/geo_postgis.ex +++ b/lib/geo_postgis.ex @@ -259,6 +259,45 @@ defmodule Geo.PostGIS do quote do: fragment("ST_Point(?, ?)", unquote(x), unquote(y)) end + defmacro st_point_z(x, y, z) do + quote do: fragment("ST_PointZ(?, ?, ?)::geometry", unquote(x), unquote(y), unquote(z)) + end + + defmacro st_point_z(x, y, z, srid) do + quote do: + fragment( + "ST_PointZ(?, ?, ?, ?)::geometry", + unquote(x), + unquote(y), + unquote(z), + unquote(srid) + ) + end + + defmacro st_point_m(x, y, m) do + quote do: fragment("ST_PointM(?, ?, ?)", unquote(x), unquote(y), unquote(m)) + end + + defmacro st_point_m(x, y, m, srid) do + quote do: fragment("ST_PointM(?, ?, ?, ?)", unquote(x), unquote(y), unquote(m), unquote(srid)) + end + + defmacro st_point_zm(x, y, z, m) do + quote do: fragment("ST_PointZM(?, ?, ?, ?)", unquote(x), unquote(y), unquote(z), unquote(m)) + end + + defmacro st_point_zm(x, y, z, m, srid) do + quote do: + fragment( + "ST_PointZM(?, ?, ?, ?, ?)", + unquote(x), + unquote(y), + unquote(z), + unquote(m), + unquote(srid) + ) + end + defmacro st_exterior_ring(geometry) do quote do: fragment("ST_ExteriorRing(?)", unquote(geometry)) end diff --git a/test/ecto_test.exs b/test/ecto_test.exs index 3c85d39..8a5bc5b 100644 --- a/test/ecto_test.exs +++ b/test/ecto_test.exs @@ -1005,4 +1005,83 @@ defmodule Geo.Ecto.Test do assert MapSet.new(polygon_coords) == MapSet.new(result.coordinates) end end + + describe "st_point_z/3 and st_point_z/4" do + test "creates a 3D point without SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = from(l in LocationMulti, select: st_point_z(-71.104, 42.315, 3.4), limit: 1) + + result = Repo.one(query) + assert %Geo.PointZ{} = result + assert result.coordinates == {-71.104, 42.315, 3.4} + assert result.srid == nil + end + + test "creates a 3D point with SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = from(l in LocationMulti, select: st_point_z(-71.104, 42.315, 3.4, 4326), limit: 1) + + result = Repo.one(query) + assert %Geo.PointZ{} = result + assert result.coordinates == {-71.104, 42.315, 3.4} + assert result.srid == 4326 + end + end + + describe "st_point_m/3 and st_point_m/4" do + test "creates a point with M coordinate without SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = from(l in LocationMulti, select: st_point_m(-71.104, 42.315, 3.4), limit: 1) + + result = Repo.one(query) + assert %Geo.PointM{} = result + assert result.coordinates == {-71.104, 42.315, 3.4} + assert result.srid == nil + end + + test "creates a point with M coordinate with SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = from(l in LocationMulti, select: st_point_m(-71.104, 42.315, 3.4, 4326), limit: 1) + + result = Repo.one(query) + assert %Geo.PointM{} = result + assert result.coordinates == {-71.104, 42.315, 3.4} + assert result.srid == 4326 + end + end + + describe "st_point_zm/4 and st_point_zm/5" do + test "creates a 4D point without SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = from(l in LocationMulti, select: st_point_zm(-71.104, 42.315, 3.4, 4.5), limit: 1) + + result = Repo.one(query) + assert %Geo.PointZM{} = result + assert result.coordinates == {-71.104, 42.315, 3.4, 4.5} + assert result.srid == nil + end + + test "creates a 4D point with SRID" do + point = %Geo.Point{coordinates: {0, 0}, srid: 4326} + Repo.insert(%LocationMulti{name: "empty", geom: point}) + + query = + from(l in LocationMulti, select: st_point_zm(-71.104, 42.315, 3.4, 4.5, 4326), limit: 1) + + result = Repo.one(query) + assert %Geo.PointZM{} = result + assert result.coordinates == {-71.104, 42.315, 3.4, 4.5} + assert result.srid == 4326 + end + end end