Skip to content

Latest commit

 

History

History
108 lines (81 loc) · 3.5 KB

README.md

File metadata and controls

108 lines (81 loc) · 3.5 KB

Geometry Library for Elixir

Build Status Hex.pm

A Geometry library for Elixir that calculates spatial relationships between two geometries. Geometries can be of any of the following types:

  • Point
  • LineString
  • Polygon
  • MultiPoint
  • MultiLineString
  • MultiPolygon

Installation

defp deps do
  [{:topo, "~> 0.1.0"}]
end

Usage

Full Documentation

The Topo module provides functions for determining the relationship between two geometries. Each function returns a boolean and accepts any combination of Point, LineString, Polygon, MultiPoint, MultiLineString, or MultiPolygon.

  • intersects? - Geometries A and B share at least one point in common.
  • disjoint? - Disjoint geometries share no points in common. This is the direct opposite of the intersects? result.
  • contains? - All points of geometry B lie within A. See section below on [Contains].
  • within? - This is the direct inverse of contains?. All points of geometry A lie within geometry B.
  • equals? - Geometries A and B are equivalent and cover the exact same set of points. By definition, A and B are equal if A contains B and B contains A. Equality does not necessarily mean that the geometries are of the same type. A Point A is equal to a MultiPoint that contains only the same Point A.

Each of these functions can be passed any two Geometries in either a Map with a :type and :coordinates keys or as a struct generated via the Geo library (https://github.com/bryanjos/geo). Coordinates are represented as atoms {x, y} and multiple coordinates as Lists.

a = %{type: "Polygon", coordinates: [[{2, 2}, {20, 2}, {11, 11}, {2, 2}]]}
b = %Geo.Polygon{coordinates: [[{2, 2}, {20, 2}, {11, 11}, {2, 2}]]}

Topo.equals? a, b # => true

Instead of a Point geometry, just a single coordinate can be used.

a = %{type: "Polygon", coordinates: [[{2, 2}, {20, 2}, {11, 11}, {2, 2}]]}

Topo.intersects? a, {4, 6} # => true

The Topo library's functions will automatically attempt to "clean" geometries passed to them:

  • Linear Rings (including Polygons) will be reordered to a counter-clockwise direction.
  • Polygon's Linear Rings will automatically be closed if the first point is not repeated as the last point.
  • Points that are equal or collinear with surrounding points are removed from LineStrings or Polygons.

A note on contains?

There are a few non-obvious special cases that are worth mentioning:

  • A Polygon does not contain its own boundary. Specifically a LineString that is the exact same as a Polygon's exterior Linear ring is not contained within a that Polygon.
a = %Geo.Polygon{coordinates: [[{2, 2}, {20, 2}, {11, 11}, {2, 2}]]}
b = %Geo.LineString{coordinates: [{2, 2}, {20, 2}, {11, 11}, {2, 2}]}

Topo.contains? a, b # => false
Topo.intersects? a, b  # => true
  • A LineString does not contain it's own first and last point (unless those points are the same, as in a LinearRing)
a = %Geo.LineString{coordinates: [{1, 3}, {2, -1}, {0, -1}]}
b = %Geo.LineString{coordinates: [{1, 3}, {2, -1}, {0, -1}, {1, 3}]}

Topo.contains? a, {1, 3} # => false
Topo.intersects? a, {1, 3} # => true
Topo.contains? b, {1, 3} # => true

Tests

> mix test