defmodule AshGeo do
@moduledoc """
Base module containing common utility functions
This module contains some things used internally that may also be useful
outside of `AshGeo` itself, but depending upon what you what to do, you should
probably be using one of:
- `AshGeo.Validation` for validations of `Geo` types and using `Topo`
functions
- `AshGeo.Postgis` for [PostGIS `st_*`
functions](https://postgis.net/docs/reference.html) for use with `Ash.Expr`
- `AshGeo.GeoAny`, `AshGeo.GeoJson`, `AshGeo.GeoWkt`, `AshGeo.GeoWkb` for
input types
- `AshGeo.Geometry` for base geometry type
"""
@moduledoc since: "0.1.0"
@doc "Transform the last element of a module path into a snake-cased atom."
@doc since: "0.1.0"
# sobelow_skip ["DOS.StringToAtom"]
def module_suffix_to_snake(module) do
module
|> Module.split()
|> List.last()
|> Macro.underscore()
|> String.to_atom()
end
@doc "Macro to check whether a module is a `Geo` type, suitable for use in guards"
@doc since: "0.1.0"
# credo:disable-for-lines:17 Credo.Check.Refactor.CyclomaticComplexity
defmacro is_geo(struct) do
quote location: :keep do
unquote(struct) == Geo.Point or
unquote(struct) == Geo.PointZ or
unquote(struct) == Geo.PointM or
unquote(struct) == Geo.PointZM or
unquote(struct) == Geo.LineString or
unquote(struct) == Geo.LineStringZ or
unquote(struct) == Geo.Polygon or
unquote(struct) == Geo.PolygonZ or
unquote(struct) == Geo.MultiPoint or
unquote(struct) == Geo.MultiPointZ or
unquote(struct) == Geo.MultiLineString or
unquote(struct) == Geo.MultiLineStringZ or
unquote(struct) == Geo.MultiPolygon or
unquote(struct) == Geo.MultiPolygonZ or
unquote(struct) == Geo.GeometryCollection
end
end
@doc "List of `Geo` types"
@doc since: "0.1.0"
def geo_types do
[
Geo.Point,
Geo.PointZ,
Geo.PointM,
Geo.PointZM,
Geo.LineString,
Geo.LineStringZ,
Geo.Polygon,
Geo.PolygonZ,
Geo.MultiPoint,
Geo.MultiPointZ,
Geo.MultiLineString,
Geo.MultiLineStringZ,
Geo.MultiPolygon,
Geo.MultiPolygonZ,
Geo.GeometryCollection
]
end
@doc """
Type aliases for `Geo` types, auto-generated from the module names
For example, the alias derived from `Geo.PointZM` is `:point_zm`.
"""
@doc since: "0.1.0"
def geo_type_aliases do
Enum.map(geo_types(), fn type ->
{module_suffix_to_snake(type), type}
end)
end
@doc "List of `Topo` functions"
@doc since: "0.1.0"
def topo_functions do
[
:contains?,
:disjoint?,
:equals?,
:intersects?,
:within?
]
end
end