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

Coordinate Reference System utilities.

Meridian defaults to WGS-84 (EPSG:4326). This module provides helpers
for distance calculations that respect the graph's declared CRS, and
stubs for reprojection.

# `bbox`

```elixir
@spec bbox(Meridian.Graph.t()) :: {float(), float(), float(), float()} | nil
```

Returns the bounding box of a graph as `{min_lon, min_lat, max_lon, max_lat}`.

Returns `nil` if the graph has no geometries.

# `compute_edge_weights`

```elixir
@spec compute_edge_weights(
  Meridian.Graph.t(),
  keyword()
) :: Meridian.Graph.t()
```

Computes edge weights for all edges as the geographic distance between
their endpoint nodes.

Returns a new `Meridian.Graph` where every edge weight has been replaced
by the computed distance in meters. Edges whose endpoints lack point
geometries are left unchanged.

## Options

  * `:round` — round to N decimal places (default: no rounding)

## 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: {0.0, 1.0}}})
    ...>   |> Meridian.Graph.add_edge_ensure(:a, :b, nil)
    iex> g = Meridian.CRS.compute_edge_weights(g)
    iex> [{:a, :b, weight}] = Meridian.Graph.edges(g)
    iex> weight > 110_000 and weight < 112_000
    true

# `distance`

```elixir
@spec distance(Meridian.Graph.t(), Yog.node_id(), Yog.node_id()) :: float() | nil
```

Returns the great-circle distance between two nodes in **meters**.

Requires that both nodes have `%Geo.Point{}` geometries in their data.
Currently assumes the graph is in WGS-84.

Returns `nil` if either node lacks a point geometry.

## Examples

    iex> g = Meridian.Graph.new()
    iex> g = g
    ...>   |> Meridian.Graph.add_node(:a, %{geometry: %Geo.Point{coordinates: {-73.9857, 40.7484}}})
    ...>   |> Meridian.Graph.add_node(:b, %{geometry: %Geo.Point{coordinates: {-73.9851, 40.7489}}})
    iex> dist = Meridian.CRS.distance(g, :a, :b)
    iex> is_float(dist) and dist > 0
    true

    iex> g = Meridian.Graph.new() |> Meridian.Graph.add_node(:a, %{foo: 1})
    iex> Meridian.CRS.distance(g, :a, :b)
    nil

# `reproject`

```elixir
@spec reproject(Meridian.Graph.t(), String.t()) :: Meridian.Graph.t()
```

Reprojects all node geometries to a new CRS.

> **Note:** Currently a stub. Real reprojection requires a PROJ binding.
> The CRS field is updated but coordinates are **not** transformed.

# `same_crs?`

```elixir
@spec same_crs?(Meridian.Graph.t(), Meridian.Graph.t()) :: boolean()
```

Returns `true` if both graphs declare the same CRS.

---

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