# Envelope (envelope v1.4.0)

A library for calculating envelopes of geometries and tools to compare them. This is most useful as an approximation of spacial relationships between more complicated geometries.

``````iex> Envelope.from_geo( %Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]} )
%Envelope{ min_x: 2, min_y: -2, max_x: 20, max_y: 11 }

iex> Envelope.from_geo( %Geo.LineString{coordinates: [{1, 3}, {2, -1}, {0, -1}, {1, 3}]} )
%Envelope{ min_x: 0, min_y: -1, max_x: 2, max_y: 3 }``````

You can also expand an existing Envelope with a geometry or another Envelope

``````iex> a = Envelope.from_geo( %Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]} )
...> b = %Geo.LineString{coordinates: [{1, 3}, {2, -1}, {0, -1}, {1, 3}]}
...> Envelope.expand(a, b)
%Envelope{ min_x: 0, min_y: -2, max_x: 20, max_y: 11 }``````

# Link to this section Summary

## Functions

Calculates the simple area of an Envelope.

Estimates the area of an Envelope in square meters when the Envelope's coordinates are in degress of longitude and latitude.

Returns the center point of an envelope.

Returns whether one envelope fully contains another envelope or point.

Returns an `Envelope` that represents no extent at all. This is primarily a convenience function for starting an expanding Envelope. Internally, "empty" Envelopes are represented with `nil` values for all extents.

Returns `true` if the given envelope is empty (has non-existent extent), otherwise `false`

Returns a new Envelope that is expanded to include an additional geometry.

Returns a new Envelope that is expanded in positive and negative directions in each axis by `radius`.

Returns an `Envelope` that represents the extent of the geometry or coordinates.

Simple distance from the bottom bounadary to the top boundary of the Envelope.

When an Envelope's coordinates are in degress of longitude and latitude, calculates the great circle distance between the center of the north and south extent in meters.

Returns whether two envelopes touch or intersect.

Returns a `Geo.Polygon`, `Geo.LineString`, or `Geo.Point` that is equal to the area covered by the given `Envelope`.

Simple distance from the left bounadary to the right boundary of the Envelope.

When an Envelope's coordinates are in degress of longitude and latitude, calculates the great circle distance between the center of the east and west extent in meters.

The inverse of the relationship tested by Envelope#contains?

# point()

## Specs

`point() :: {number(), number()}`

# points()

## Specs

```points() ::
point()
| list()
| %{coordinates: list()}
| %Geo.Point{coordinates: term(), properties: term(), srid: term()}
| %Geo.MultiPoint{coordinates: term(), properties: term(), srid: term()}
| %Geo.LineString{coordinates: term(), properties: term(), srid: term()}
| %Geo.MultiLineString{coordinates: term(), properties: term(), srid: term()}
| %Geo.Polygon{coordinates: term(), properties: term(), srid: term()}
| %Geo.MultiPolygon{coordinates: term(), properties: term(), srid: term()}```

# t()

## Specs

```t() :: %Envelope{
max_x: number() | nil,
max_y: number() | nil,
min_x: number() | nil,
min_y: number() | nil
}```

# area(env)

## Specs

`area(t()) :: number()`

Calculates the simple area of an Envelope.

## Examples

``````iex> Envelope.area(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]}))
234``````

# area_gc(env)

## Specs

`area_gc(t()) :: number()`

Estimates the area of an Envelope in square meters when the Envelope's coordinates are in degress of longitude and latitude.

## Examples

``````iex> Envelope.area_gc(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]})) |> round
2865575088701``````

# center(env)

## Specs

`center(t()) :: {number(), number()}`

Returns the center point of an envelope.

## Examples

iex> %Envelope{ min_x: 0, min_y: -1, max_x: 2, max_y: 5 } |> Envelope.center() {1.0, 2.0}

iex> Envelope.empty() |> Envelope.center() nil

# contains?(env, env2)

## Specs

`contains?(t() | points(), t() | points()) :: boolean()`

Returns whether one envelope fully contains another envelope or point.

## Examples

``````iex> Envelope.contains?(
...> %Envelope{ min_x: -1, min_y: -5, max_x: 23, max_y: 14 },
...> %Envelope{ min_x: 0, min_y: 3, max_x: 7, max_y: 4 })
true

iex> Envelope.contains?(
...> %Envelope{ min_x: -1, min_y: 5, max_x: 23, max_y: 14 },
...> %Envelope{ min_x: -2, min_y: 5, max_x: 7, max_y: 4 })
false

iex> Envelope.contains?(
...> %Geo.Polygon{ coordinates: [{-1, 3}, {-3, -1}, { 5, -3}, {4, 12}, {-2, 11}, {-1, 3}] },
...> {0, 11})
true``````

# empty()

## Specs

`empty() :: t()`

Returns an `Envelope` that represents no extent at all. This is primarily a convenience function for starting an expanding Envelope. Internally, "empty" Envelopes are represented with `nil` values for all extents.

Note that there is a important distinction between an empty Envelope and an Envelope around a single Point (where the min and max for each axis are real numbers but may represent zero area).

## Examples

``````iex> Envelope.empty
%Envelope{max_x: nil, max_y: nil, min_x: nil, min_y: nil}

iex> Envelope.empty |> Envelope.empty?
true``````

# empty?(envelope)

## Specs

`empty?(t()) :: boolean()`

Returns `true` if the given envelope is empty (has non-existent extent), otherwise `false`

## Examples

``````iex> Envelope.empty |> Envelope.empty?
true

iex> %Envelope{ min_x: 0, min_y: -1, max_x: 2, max_y: 3 } |> Envelope.empty?
false``````

# expand(env1, env2)

## Specs

`expand(t(), point() | t() | points()) :: t()`

Returns a new Envelope that is expanded to include an additional geometry.

## Examples

``````iex> a = Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]})
...> b = %Geo.LineString{coordinates: [{1, 3}, {2, -1}, {0, -1}, {1, 3}]}
...> Envelope.expand(a, b)
%Envelope{ min_x: 0, min_y: -2, max_x: 20, max_y: 11 }

iex> a = %Envelope{ min_x: 0, min_y: -2, max_x: 20, max_y: 11 }
...> b = %Envelope{ min_x: 2, min_y: -3, max_x: 12, max_y: -2 }
...> Envelope.expand(a, b)
%Envelope{ min_x: 0, min_y: -3, max_x: 20, max_y: 11 }

iex> Envelope.empty
...> |> Envelope.expand(%Envelope{ min_x: 0, min_y: -2, max_x: 12, max_y: 11 })
...> |> Envelope.expand(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]})
...> |> Envelope.expand(%{type: "Point", coordinates: {-1, 3}})
%Envelope{ min_x: -1, min_y: -2, max_x: 20, max_y: 11 }

iex> Envelope.expand(Envelope.empty, Envelope.empty) |> Envelope.empty?
true``````

## Specs

`expand_by(t(), number()) :: t()`

Returns a new Envelope that is expanded in positive and negative directions in each axis by `radius`.

## Examples

``````iex> Envelope.expand_by(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]}), 3)
%Envelope{ min_x: -1, min_y: -5, max_x: 23, max_y: 14 }

iex> Envelope.expand_by(Envelope.empty, 4) |> Envelope.empty?
true``````

# from_geo(coordinates)

## Specs

`from_geo(points()) :: t()`

Returns an `Envelope` that represents the extent of the geometry or coordinates.

## Examples

``````iex> Envelope.from_geo %{coordinates: [{11, 10}, {4, 2.5}, {16, 2.5}, {11, 10}]}
%Envelope{ max_x: 16, max_y: 10, min_x: 4, min_y: 2.5 }

iex> Envelope.from_geo [{11, 10}, {4, 2.5}, {16, 2.5}, {11, 10}]
%Envelope{ max_x: 16, max_y: 10, min_x: 4, min_y: 2.5 }

iex> Envelope.from_geo %Geo.Polygon{coordinates: [[{1, 3}, {2, -1}, {0, -1}, {1, 3}]]}
%Envelope{ min_x: 0, min_y: -1, max_x: 2, max_y: 3 }

iex> Envelope.from_geo {1, 3}
%Envelope{ min_x: 1, min_y: 3, max_x: 1, max_y: 3 }``````

# height(env)

## Specs

`height(t()) :: number()`

Simple distance from the bottom bounadary to the top boundary of the Envelope.

## Examples

``````iex> Envelope.height(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]}))
13``````

# height_gc(env)

## Specs

`height_gc(t()) :: number()`

When an Envelope's coordinates are in degress of longitude and latitude, calculates the great circle distance between the center of the north and south extent in meters.

## Examples

``````iex> Envelope.height_gc(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]})) |> round
1445536``````

# intersects?(env1, env2)

## Specs

`intersects?(t() | points(), t() | points()) :: boolean()`

Returns whether two envelopes touch or intersect.

## Examples

``````iex> Envelope.intersects?(
...> %Envelope{ min_x: -1, min_y: -5, max_x: 23, max_y: 14 },
...> %Envelope{ min_x: 0, min_y: 3, max_x: 7, max_y: 4 })
true

iex> Envelope.intersects?(
...> %Envelope{ min_x: -1, min_y: 5, max_x: 23, max_y: 14 },
...> %Envelope{ min_x: 0, min_y: -3, max_x: 7, max_y: 4 })
false``````

# to_geo(env)

## Specs

```to_geo(t()) ::
%Geo.Polygon{coordinates: term(), properties: term(), srid: term()}
| %Geo.Point{coordinates: term(), properties: term(), srid: term()}
| %Geo.LineString{coordinates: term(), properties: term(), srid: term()}```

Returns a `Geo.Polygon`, `Geo.LineString`, or `Geo.Point` that is equal to the area covered by the given `Envelope`.

Note that they exact type of the Geometry returned will depend on the nature of the Envelope:

## Examples

``````iex> Envelope.to_geo %Envelope{ max_x: 16, max_y: 10, min_x: 4, min_y: 2.5 }
%Geo.Polygon{coordinates: [[{4, 2.5}, {16, 2.5}, {16, 10}, {4, 10}, {4, 2.5}]]}

iex> Envelope.to_geo %Envelope{ min_x: 1, min_y: 3, max_x: 1, max_y: 5 }
%Geo.LineString{coordinates: [{1, 3}, {1, 5}]}

iex> Envelope.to_geo %Envelope{ min_x: 1, min_y: 3, max_x: 4, max_y: 3 }
%Geo.LineString{coordinates: [{1, 3}, {4, 3}]}

iex> Envelope.to_geo %Envelope{ min_x: 1, min_y: 3, max_x: 1, max_y: 3 }
%Geo.Point{coordinates: {1, 3}}``````

# width(env)

## Specs

`width(t()) :: number()`

Simple distance from the left bounadary to the right boundary of the Envelope.

## Examples

``````iex> Envelope.width(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]}))
18``````

# width_gc(env)

## Specs

`width_gc(t()) :: number()`

When an Envelope's coordinates are in degress of longitude and latitude, calculates the great circle distance between the center of the east and west extent in meters.

## Examples

``````iex> Envelope.width_gc(Envelope.from_geo(%Geo.Polygon{coordinates: [[{2, -2}, {20, -2}, {11, 11}, {2, -2}]]})) |> round
1982362``````

# within?(a, b)

## Specs

`within?(t() | points(), t() | points()) :: boolean()`

The inverse of the relationship tested by Envelope#contains?

## Examples

``````iex> Envelope.within?(
...> %Envelope{ min_x: 0, min_y: 3, max_x: 7, max_y: 4 },
...> %Envelope{ min_x: -1, min_y: -5, max_x: 23, max_y: 14 })
true

iex> Envelope.within?(
...> %Geo.Polygon{ coordinates: [{-1, 3}, {-3, -1}, { 5, -3}, {4, 12}, {-2, 11}, {-1, 3}] },
...> {0, 11})
false``````