# `Meridian.Geometry`
[🔗](https://github.com/code-shoily/meridian/blob/v0.1.0/lib/meridian/geometry.ex#L1)

Pure-geometric helpers operating on `Geo` structs and `Yog.Graph` nodes.

These functions are CRS-agnostic: they work with whatever coordinates you
give them. When you need earth-aware distances, use `Meridian.CRS`.

# `centroid`

```elixir
@spec centroid(Geo.Polygon.t()) :: Geo.Point.t()
```

Computes the centroid of a `Geo.Polygon` as a `Geo.Point`.

Uses the arithmetic mean of vertices (not area-weighted).

## Examples

    iex> poly = %Geo.Polygon{coordinates: [[{0,0},{10,0},{10,10},{0,10},{0,0}]]}
    iex> centroid = Meridian.Geometry.centroid(poly)
    iex> centroid.coordinates
    {5.0, 5.0}

# `contains?`

```elixir
@spec contains?(Geo.Polygon.t(), Geo.Point.t()) :: boolean()
```

Returns true if `point` lies inside `polygon`.

Uses a simple ray-casting algorithm. Works for simple polygons.

## Examples

    iex> poly = %Geo.Polygon{coordinates: [[{0,0},{10,0},{10,10},{0,10},{0,0}]]}
    iex> Meridian.Geometry.contains?(poly, %Geo.Point{coordinates: {5, 5}})
    true
    iex> Meridian.Geometry.contains?(poly, %Geo.Point{coordinates: {15, 5}})
    false

# `envelope`

```elixir
@spec envelope(Yog.Graph.t()) :: Geo.Polygon.t() | nil
```

Computes the bounding envelope of all node geometries in a graph.

Returns a `%Geo.Polygon{}` representing the bounding box, or `nil` if
no geometries are present.

## Examples

    iex> g = Meridian.Graph.new()
    iex> g = g
    ...>   |> Meridian.Graph.add_node(:a, %{geometry: %Geo.Point{coordinates: {0.0, 0.0}}})
    ...>   |> Meridian.Graph.add_node(:b, %{geometry: %Geo.Point{coordinates: {2.0, 3.0}}})
    iex> %Geo.Polygon{} = Meridian.Geometry.envelope(Meridian.Graph.to_yog(g))

# `euclidean`

```elixir
@spec euclidean(Geo.Point.t(), Geo.Point.t()) :: float()
```

Euclidean distance between two points.

## Examples

    iex> a = %Geo.Point{coordinates: {0.0, 0.0}}
    iex> b = %Geo.Point{coordinates: {3.0, 4.0}}
    iex> Meridian.Geometry.euclidean(a, b)
    5.0

# `geo_length`

```elixir
@spec geo_length(Geo.LineString.t()) :: float()
```

Approximate length of a `Geo.LineString` in meters using the haversine formula.

Sums the great-circle distance of each segment.

## Examples

    iex> line = %Geo.LineString{coordinates: [{0.0, 0.0}, {0.0, 1.0}]}
    iex> len = Meridian.Geometry.geo_length(line)
    iex> len > 110_000 and len < 112_000
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
