geo_partition v0.1.1 GeoPartition.Geometry View Source

Extensions of Topo and Geo to perform calculations on map geometries

Link to this section Summary

Functions

Find the area of a polygon. To find geographic area based on lat/long coords, use geo: :globe, default is geo: :flat

Removes occluding holes from a given polygon, preserving properly contained holes

Check if three points are collinear

Converts a cycle (graph) into a polygon

Converts a graph into a polygon

Find the intersection point of two LineStrings. Returns a tuple indicating the type of intersection:

  • :disjoint, the LineStrings have no points in common
  • :degen, the LineStrings share points but are collinear, the endpoint of one incident with non-endpoint of other, or they share an endpoint
  • :intersects, the LineStrings have a non-trivial point of intersection

Converts a polygon (Geo.Polygon) to a graph. If the polygon has holes that overlap the outer ring, they will be circumvented

Link to this section Types

Link to this type graph() View Source
graph() :: {list(), [MapSet]}

Link to this section Functions

Link to this function area(shape, opts \\ [geo: :flat]) View Source

Find the area of a polygon. To find geographic area based on lat/long coords, use geo: :globe, default is geo: :flat

Examples

iex> shape = %Geo.Polygon{
...>   coordinates: [
...>     [
...>       {0.0, 0.0},
...>       {4.0, 0.0},
...>       {4.0, 3.0},
...>       {0.0, 3.0},
...>       {0.0, 0.0},
...>     ],
...>     [
...>       {1.0, 1.0},
...>       {3.0, 1.0},
...>       {3.0, 4.0},
...>       {1.0, 4.0},
...>       {1.0, 1.0},
...>     ]
...>   ]
...> }
iex> GeoPartition.Geometry.area(shape, [geo: :flat])
8.0

Removes occluding holes from a given polygon, preserving properly contained holes

Examples

iex> shape = %Geo.Polygon{
...>   coordinates: [
...>     [
...>       {0.0, 0.0},
...>       {4.0, 0.0},
...>       {4.0, 3.0},
...>       {0.0, 3.0},
...>       {0.0, 0.0},
...>     ],
...>     [
...>       {1.0, 1.0},
...>       {3.0, 1.0},
...>       {3.0, 4.0},
...>       {1.0, 4.0},
...>       {1.0, 1.0},
...>     ],
...>     [
...>       {1.0, 0.3},
...>       {3.0, 0.3},
...>       {3.0, 0.7},
...>       {1.0, 0.3}
...>     ]
...>   ]
...> }
iex> GeoPartition.Geometry.clean_holes(shape)
%Geo.Polygon{
  coordinates: [
     [
       {0.0, 0.0},
       {4.0, 0.0},
       {4.0, 3.0},
       {3.0, 3.0},
       {3.0, 1.0},
       {1.0, 1.0},
       {1.0, 3.0},
       {0.0, 3.0},
       {0.0, 0.0},
     ],
     [
       {1.0, 0.3},
       {3.0, 0.3},
       {3.0, 0.7},
       {1.0, 0.3}
     ]
  ],
  properties: %{},
  srid: nil
 }
Link to this function collinear?(a, b, c) View Source
collinear?({any(), any()}, {any(), any()}, {any(), any()}) :: boolean()

Check if three points are collinear

Examples

iex> GeoPartition.Geometry.collinear?({1, 1}, {2, 2}, {3, 3})
true

iex> GeoPartition.Geometry.collinear?({1, 1}, {2, 2}, {3, 4})
false

Converts a cycle (graph) into a polygon.

Examples

iex> cycle = {
...>  [
...>    %Geo.Point{ coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil },
...>    %Geo.Point{ coordinates: {3.0, 2.0}, properties: %{covered: false, ring: :outer}, srid: nil },
...>    %Geo.Point{ coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil }
...>  ], [
...>    MapSet.new([
...>      %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>      %Geo.Point{coordinates: {3.0, 2.0}, properties: %{covered: false, ring: :outer}, srid: nil}
...>    ]),
...>    MapSet.new([
...>      %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>      %Geo.Point{coordinates: {3.0, 2.0}, properties: %{covered: false, ring: :outer}, srid: nil}
...>    ]),
...>    MapSet.new([
...>      %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>      %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil}
...>    ])
...>  ]}
iex>  GeoPartition.Geometry.cycle_to_ring(cycle)
[
  {1.0, 3.0},
  {3.0, 2.0},
  {1.0, 1.0},
  {1.0, 3.0}
]

Converts a graph into a polygon

Examples

iex> graph = {[
...>  %Geo.Point{ coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil },
...>  %Geo.Point{ coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil },
...>  %Geo.Point{ coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil },
...>  %Geo.Point{ coordinates: {2.5, 1.75}, srid: nil, properties: %{covered: false, ring: :intersection} },
...>  %Geo.Point{ coordinates: {2.5, 2.25}, srid: nil, properties: %{covered: false, ring: :intersection} }
...>  ], [
...>  MapSet.new([
...>  %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>  %Geo.Point{coordinates: {2.5, 2.25}, properties: %{covered: false, ring: :intersection}, srid: nil}
...>  ]),
...>  MapSet.new([
...>  %Geo.Point{coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil},
...>  %Geo.Point{coordinates: {2.5, 2.25}, properties: %{covered: false, ring: :intersection}, srid: nil}
...>  ]),
...>  MapSet.new([
...>  %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>  %Geo.Point{coordinates: {2.5, 1.75}, properties: %{covered: false, ring: :intersection}, srid: nil}
...>  ]),
...>  MapSet.new([
...>  %Geo.Point{coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil},
...>  %Geo.Point{coordinates: {2.5, 1.75}, properties: %{covered: false, ring: :intersection}, srid: nil}
...>  ]),
...>  MapSet.new([
...>  %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil},
...>  %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil}
...>  ])
...>]}
iex> GeoPartition.Geometry.graph_to_polygon(graph)
%Geo.Polygon{
  coordinates: [
    [
      {1.0, 1.0},
      {2.5, 1.75},
      {2.0, 2.0},
      {2.5, 2.25},
      {1.0, 3.0},
      {1.0, 1.0}
    ]
  ]
}
Link to this function intersection(l1, l2) View Source
intersection(Geo.LineString, Geo.LineString) :: {atom(), any()}

Find the intersection point of two LineStrings. Returns a tuple indicating the type of intersection:

  • :disjoint, the LineStrings have no points in common
  • :degen, the LineStrings share points but are collinear, the endpoint of one incident with non-endpoint of other, or they share an endpoint
  • :intersects, the LineStrings have a non-trivial point of intersection

Examples

iex> reference = %Geo.LineString{coordinates: [{1.0, 1.0}, {2.0, 2.0}]}
iex> disjoint = %Geo.LineString{coordinates: [{2.0, 1.0}, {2.0, 2.0}]}
iex> GeoPartition.Geometry.intersection(reference, disjoint)
{:endpoint, "endpoint"}

iex> reference = %Geo.LineString{coordinates: [{1.0, 1.0}, {2.0, 2.0}]}
iex> disjoint = %Geo.LineString{coordinates: [{2.0, 1.0}, {3.0, 2.0}]}
iex> GeoPartition.Geometry.intersection(reference, disjoint)
{:disjoint, "disjoint"}

iex> reference = %Geo.LineString{coordinates: [{1.0, 1.0}, {2.0, 2.0}]}
iex> overlap = %Geo.LineString{coordinates: [{1.5, 1.5}, {3.0, 3.0}]}
iex> GeoPartition.Geometry.intersection(reference, overlap)
{:degen, "degen"}

iex> reference = %Geo.LineString{coordinates: [{1.0, 1.0}, {2.0, 2.0}]}
iex> intersect = %Geo.LineString{coordinates: [{2.0, 1.0}, {1.0, 2.0}]}
iex> GeoPartition.Geometry.intersection(reference, intersect)
{:intersects, %Geo.Point{coordinates: {1.5, 1.5}, properties: %{}, srid: nil}}

Converts a polygon (Geo.Polygon) to a graph. If the polygon has holes that overlap the outer ring, they will be circumvented

Examples

iex> shape = %Geo.Polygon{
...>   coordinates: [
...>     [
...>       {1.0, 1.0},
...>       {3.0, 2.0},
...>       {1.0, 3.0},
...>       {1.0, 1.0}
...>     ],
...>     [
...>       {2.0, 2.0},
...>       {4.0, 1.0},
...>       {4.0, 3.0},
...>       {2.0, 2.0}
...>     ],
...>     [
...>       {1.4, 2.4},
...>       {1.4, 1.6},
...>       {1.8, 1.6},
...>       {1.8, 2.4},
...>       {1.4, 2.4}
...>     ]
...>   ]
...> }
iex> GeoPartition.Geometry.polygon_to_graph(shape)
{[
  %Geo.Point{ coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil },
  %Geo.Point{ coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil },
  %Geo.Point{ coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil },
  %Geo.Point{ coordinates: {1.4, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil },
  %Geo.Point{ coordinates: {1.4, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil },
  %Geo.Point{ coordinates: {1.8, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil },
  %Geo.Point{ coordinates: {1.8, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil },
  %Geo.Point{ coordinates: {2.5, 1.75}, srid: nil, properties: %{covered: false, ring: :intersection} },
  %Geo.Point{ coordinates: {2.5, 2.25}, srid: nil, properties: %{covered: false, ring: :intersection} }
], [
  MapSet.new([
    %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil},
    %Geo.Point{coordinates: {2.5, 2.25}, properties: %{covered: false, ring: :intersection}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {2.5, 2.25}, properties: %{covered: false, ring: :intersection}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil},
    %Geo.Point{coordinates: {2.5, 1.75}, properties: %{covered: false, ring: :intersection}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {2.0, 2.0}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {2.5, 1.75}, properties: %{covered: false, ring: :intersection}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.0, 1.0}, properties: %{covered: false, ring: :outer}, srid: nil},
    %Geo.Point{coordinates: {1.0, 3.0}, properties: %{covered: false, ring: :outer}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.4, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {1.4, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.8, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {1.4, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.8, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {1.8, 1.6}, properties: %{covered: true, ring: :inner}, srid: nil}
  ]),
  MapSet.new([
    %Geo.Point{coordinates: {1.8, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil},
    %Geo.Point{coordinates: {1.4, 2.4}, properties: %{covered: true, ring: :inner}, srid: nil}
  ])
]}