Skip to content

Commit

Permalink
Merge pull request #36 from caspervdw/missingvalues
Browse files Browse the repository at this point in the history
[Done] Separating Missing (NaG) and Empty
  • Loading branch information
caspervdw committed Sep 9, 2019
2 parents 5202ade + 1b43a9a commit 3d9e246
Show file tree
Hide file tree
Showing 16 changed files with 523 additions and 436 deletions.
10 changes: 5 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ Run the unittests::
References
----------

- GEOS: http://trac.osgeo.org/geos
- Shapely: https://shapely.readthedocs.io/en/latest/
- Numpy ufuncs: https://docs.scipy.org/doc/numpy/reference/ufuncs.html
- Joris van den Bossche's blogpost: https://jorisvandenbossche.github.io/blog/2017/09/19/geopandas-cython/
- Matthew Rocklin's blogpost: http://matthewrocklin.com/blog/work/2017/09/21/accelerating-geopandas-1
- GEOS: http://trac.osgeo.org/geos
- Shapely: https://shapely.readthedocs.io/en/latest/
- Numpy ufuncs: https://docs.scipy.org/doc/numpy/reference/ufuncs.html
- Joris van den Bossche's blogpost: https://jorisvandenbossche.github.io/blog/2017/09/19/geopandas-cython/
- Matthew Rocklin's blogpost: http://matthewrocklin.com/blog/work/2017/09/21/accelerating-geopandas-1


Copyright & License
Expand Down
3 changes: 1 addition & 2 deletions pygeos/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from .ufuncs import GEOSException # NOQA
from .ufuncs import Geometry # NOQA
from .ufuncs import Empty # NOQA
from .geometry import *
from .creation import *
from .constructive import *
from .predicates import *
from .measurements import *
from .measurement import *
from .set_operations import *
from .linear import *
54 changes: 23 additions & 31 deletions pygeos/constructive.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from enum import IntEnum
import numpy as np
from . import Empty, Geometry # NOQA
from . import Geometry # NOQA
from . import ufuncs


Expand Down Expand Up @@ -44,19 +44,15 @@ def boundary(geometry, **kwargs):
Examples
--------
>>> boundary(Geometry("POINT (0 0)"))
<pygeos.Empty>
<pygeos.Geometry GEOMETRYCOLLECTION EMPTY>
>>> boundary(Geometry("LINESTRING(0 0, 1 1, 1 2)"))
<pygeos.Geometry MULTIPOINT (0 0, 1 2)>
>>> boundary(Geometry("LINEARRING (0 0, 1 0, 1 1, 0 1, 0 0)"))
<pygeos.Empty>
<pygeos.Geometry MULTIPOINT EMPTY>
>>> boundary(Geometry("POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))"))
<pygeos.Geometry LINESTRING (0 0, 1 0, 1 1, 0 1, 0 0)>
>>> boundary(Geometry("MULTIPOINT (0 0, 1 2)"))
<pygeos.Empty>
>>> boundary(Geometry("MULTILINESTRING ((0 0, 1 1), (2 2, 3 3))"))
<pygeos.Geometry MULTIPOINT (0 0, 1 1, 2 2, 3 3)>
>>> boundary(Empty)
<pygeos.Empty>
>>> boundary(Geometry("MULTIPOINT (0 0, 1 2)")) is None
True
"""
return ufuncs.boundary(geometry, **kwargs)

Expand Down Expand Up @@ -112,7 +108,7 @@ def buffer(
>>> buffer(Geometry("POINT (10 10)"), 2, quadsegs=2)
<pygeos.Geometry POLYGON ((12 10, 11.4 8.59, 10 8, 8.59 8.59, 8 10, 8.59 11.4, 10 12, 11.4 11.4, 12 10))>
>>> buffer(Geometry("POINT (10 10)"), -2, quadsegs=1)
<pygeos.Empty>
<pygeos.Geometry POLYGON EMPTY>
>>> line = Geometry("LINESTRING (10 10, 20 10)")
>>> buffer(line, 2, cap_style="square")
<pygeos.Geometry POLYGON ((20 12, 22 12, 22 8, 10 8, 8 8, 8 12, 20 12))>
Expand All @@ -133,9 +129,9 @@ def buffer(
>>> buffer(square, -2, join_style="mitre")
<pygeos.Geometry POLYGON ((2 2, 2 8, 8 8, 8 2, 2 2))>
>>> buffer(square, -5, join_style="mitre")
<pygeos.Empty>
>>> buffer(Empty, 1)
<pygeos.Empty>
<pygeos.Geometry POLYGON EMPTY>
>>> buffer(line, float("nan")) is None
True
"""
if isinstance(cap_style, str):
cap_style = BufferCapStyles[cap_style.upper()].value
Expand Down Expand Up @@ -183,8 +179,6 @@ def centroid(geometry, **kwargs):
<pygeos.Geometry POINT (5 5)>
>>> centroid(Geometry("MULTIPOINT (0 0, 10 10)"))
<pygeos.Geometry POINT (5 5)>
>>> centroid(Empty)
<pygeos.Empty>
"""
return ufuncs.centroid(geometry, **kwargs)

Expand All @@ -200,8 +194,8 @@ def convex_hull(geometry, **kwargs):
--------
>>> convex_hull(Geometry("MULTIPOINT (0 0, 10 0, 10 10)"))
<pygeos.Geometry POLYGON ((0 0, 10 10, 10 0, 0 0))>
>>> convex_hull(Empty)
<pygeos.Empty>
>>> convex_hull(Geometry("POLYGON EMPTY"))
<pygeos.Geometry GEOMETRYCOLLECTION EMPTY>
"""
return ufuncs.convex_hull(geometry, **kwargs)

Expand All @@ -211,7 +205,7 @@ def delaunay_triangles(geometry, tolerance=0.0, only_edges=False, **kwargs):
geometry.
The output is a geometrycollection containing polygons (default)
or linestrings (see only_edges). Returns an Empty if the input geometry
or linestrings (see only_edges). Returns an None if an input geometry
contains less than 3 vertices.
Parameters
Expand All @@ -236,8 +230,8 @@ def delaunay_triangles(geometry, tolerance=0.0, only_edges=False, **kwargs):
<pygeos.Geometry GEOMETRYCOLLECTION (POLYGON ((50 30, 60 30, 100 100, 50 30)))>
>>> delaunay_triangles(Geometry("LINESTRING (50 30, 60 30, 100 100)"))
<pygeos.Geometry GEOMETRYCOLLECTION (POLYGON ((50 30, 60 30, 100 100, 50 30)))>
>>> delaunay_triangles(Empty)
<pygeos.Empty>
>>> delaunay_triangles(Geometry("GEOMETRYCOLLECTION EMPTY"))
<pygeos.Geometry GEOMETRYCOLLECTION EMPTY>
"""
return ufuncs.delaunay_triangles(geometry, tolerance, only_edges, **kwargs)

Expand All @@ -257,8 +251,8 @@ def envelope(geometry, **kwargs):
<pygeos.Geometry POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))>
>>> envelope(Geometry("POINT (0 0)"))
<pygeos.Geometry POINT (0 0)>
>>> envelope(Empty)
<pygeos.Empty>
>>> envelope(Geometry("GEOMETRYCOLLECTION EMPTY"))
<pygeos.Geometry POINT EMPTY>
"""
return ufuncs.envelope(geometry, **kwargs)

Expand All @@ -283,8 +277,8 @@ def extract_unique_points(geometry, **kwargs):
<pygeos.Geometry MULTIPOINT (0 0, 1 0, 1 1)>
>>> extract_unique_points(Geometry("MULTIPOINT (0 0, 1 1, 0 0)"))
<pygeos.Geometry MULTIPOINT (0 0, 1 1)>
>>> extract_unique_points(Empty)
<pygeos.Empty>
>>> extract_unique_points(Geometry("LINESTRING EMPTY"))
<pygeos.Geometry MULTIPOINT EMPTY>
"""
return ufuncs.extract_unique_points(geometry, **kwargs)

Expand All @@ -304,8 +298,8 @@ def point_on_surface(geometry, **kwargs):
<pygeos.Geometry POINT (2 2)>
>>> point_on_surface(Geometry("MULTIPOINT (0 0, 10 10)"))
<pygeos.Geometry POINT (0 0)>
>>> point_on_surface(Empty)
<pygeos.Empty>
>>> point_on_surface(Geometry("POLYGON EMPTY"))
<pygeos.Geometry POINT EMPTY>
"""
return ufuncs.point_on_surface(geometry, **kwargs)

Expand Down Expand Up @@ -335,8 +329,6 @@ def simplify(geometry, tolerance, preserve_topology=False, **kwargs):
<pygeos.Geometry POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))>
>>> simplify(polygon_with_hole, tolerance=4, preserve_topology=False)
<pygeos.Geometry POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))>
>>> simplify(Empty, tolerance=1)
<pygeos.Empty>
"""
if preserve_topology:
return ufuncs.simplify_preserve_topology(geometry, tolerance, **kwargs)
Expand Down Expand Up @@ -379,7 +371,7 @@ def voronoi_polygons(
"""Computes a Voronoi diagram from the vertices of an input geometry.
The output is a geometrycollection containing polygons (default)
or linestrings (see only_edges). Returns Empty if an input geometry
or linestrings (see only_edges). Returns empty if an input geometry
contains less than 2 vertices or if the provided extent has zero area.
Parameters
Expand Down Expand Up @@ -407,7 +399,7 @@ def voronoi_polygons(
<pygeos.Geometry LINESTRING (3 10, 3 0)>
>>> voronoi_polygons(Geometry("LINESTRING (2 2, 4 2)"), only_edges=True)
<pygeos.Geometry LINESTRING (3 4, 3 0)>
>>> voronoi_polygons(Empty)
<pygeos.Empty>
>>> voronoi_polygons(Geometry("POINT (2 2)"))
<pygeos.Geometry GEOMETRYCOLLECTION EMPTY>
"""
return ufuncs.voronoi_polygons(geometry, tolerance, extend_to, only_edges, **kwargs)
52 changes: 31 additions & 21 deletions pygeos/geometry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import IntEnum
import numpy as np
from . import ufuncs
from . import Empty, Geometry # NOQA
from . import Geometry # NOQA

__all__ = [
"GeometryType",
Expand All @@ -26,6 +26,7 @@
class GeometryType(IntEnum):
"""The enumeration of GEOS geometry types"""

NAG = -1
POINT = 0
LINESTRING = 1
LINEARRING = 2
Expand All @@ -42,6 +43,7 @@ class GeometryType(IntEnum):
def get_type_id(geometry):
"""Returns the type ID of a geometry.
- None is -1
- POINT is 0
- LINESTRING is 1
- LINEARRING is 2
Expand Down Expand Up @@ -74,7 +76,7 @@ def get_dimensions(geometry):
The inherent dimension is 0 for points, 1 for linestrings and linearrings,
and 2 for polygons. For geometrycollections it is the max of the containing
elements.
elements. Empty and None geometries return -1.
Parameters
----------
Expand All @@ -88,15 +90,19 @@ def get_dimensions(geometry):
2
>>> get_dimensions(Geometry("GEOMETRYCOLLECTION (POINT(0 0), LINESTRING(0 0, 1 1))"))
1
>>> get_dimensions(Empty)
0
>>> get_dimensions(Geometry("GEOMETRYCOLLECTION EMPTY"))
-1
>>> get_dimensions(None)
-1
"""
return ufuncs.get_dimensions(geometry)


def get_coordinate_dimensions(geometry):
"""Returns the dimensionality of the coordinates in a geometry (2 or 3).
Returns -1 for not-a-geometry values.
Parameters
----------
geometry : Geometry or array_like
Expand All @@ -107,15 +113,17 @@ def get_coordinate_dimensions(geometry):
2
>>> get_coordinate_dimensions(Geometry("POINT Z (0 0 0)"))
3
>>> get_coordinate_dimensions(Empty).tolist()
2
>>> get_coordinate_dimensions(None)
-1
"""
return ufuncs.get_coordinate_dimensions(geometry)


def get_num_coordinates(geometry):
"""Returns the total number of coordinates in a geometry.
Returns -1 for not-a-geometry values.
Parameters
----------
geometry : Geometry or array_like
Expand All @@ -128,15 +136,17 @@ def get_num_coordinates(geometry):
1
>>> get_num_coordinates(Geometry("GEOMETRYCOLLECTION (POINT(0 0), LINESTRING(0 0, 1 1))"))
3
>>> get_num_coordinates(Empty)
0
>>> get_num_coordinates(None)
-1
"""
return ufuncs.get_num_coordinates(geometry)


def get_srid(geometry):
"""Returns the SRID of a geometry.
Returns -1 for not-a-geometry values.
Parameters
----------
geometry : Geometry or array_like
Expand Down Expand Up @@ -255,10 +265,10 @@ def get_point(geometry, index):
[<pygeos.Geometry POINT (0 0)>, <pygeos.Geometry POINT (3 3)>]
>>> get_point(Geometry("LINEARRING (0 0, 1 1, 2 2, 0 0)"), 1)
<pygeos.Geometry POINT (1 1)>
>>> get_point(Geometry("MULTIPOINT (0 0, 1 1, 2 2, 3 3)"), 1)
<pygeos.Empty>
>>> get_point(Geometry("POINT (1 1)"), 0)
<pygeos.Empty>
>>> get_point(Geometry("MULTIPOINT (0 0, 1 1, 2 2, 3 3)"), 1) is None
True
>>> get_point(Geometry("POINT (1 1)"), 0) is None
True
"""
return ufuncs.get_point(geometry, np.intc(index))

Expand Down Expand Up @@ -306,8 +316,8 @@ def get_exterior_ring(geometry):
--------
>>> get_exterior_ring(Geometry("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))"))
<pygeos.Geometry LINEARRING (0 0, 0 10, 10 10, 10 0, 0 0)>
>>> get_exterior_ring(Geometry("POINT (1 1)"))
<pygeos.Empty>
>>> get_exterior_ring(Geometry("POINT (1 1)")) is None
True
"""
return ufuncs.get_exterior_ring(geometry)

Expand All @@ -331,8 +341,8 @@ def get_interior_ring(geometry, index):
>>> polygon_with_hole = Geometry("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))")
>>> get_interior_ring(polygon_with_hole, 0)
<pygeos.Geometry LINEARRING (2 2, 2 4, 4 4, 4 2, 2 2)>
>>> get_interior_ring(Geometry("POINT (1 1)"), 0)
<pygeos.Empty>
>>> get_interior_ring(Geometry("POINT (1 1)"), 0) is None
True
"""
return ufuncs.get_interior_ring(geometry, np.intc(index))

Expand Down Expand Up @@ -379,7 +389,7 @@ def get_geometry(geometry, index):
Notes
-----
- simple geometries act as length-1 collections
- out-of-range values return Empty
- out-of-range values return None
See also
--------
Expand All @@ -392,12 +402,12 @@ def get_geometry(geometry, index):
<pygeos.Geometry POINT (1 1)>
>>> get_geometry(multipoint, -1)
<pygeos.Geometry POINT (3 3)>
>>> get_geometry(multipoint, 5)
<pygeos.Empty>
>>> get_geometry(multipoint, 5) is None
True
>>> get_geometry(Geometry("POINT (1 1)"), 0)
<pygeos.Geometry POINT (1 1)>
>>> get_geometry(Geometry("POINT (1 1)"), 1)
<pygeos.Empty>
>>> get_geometry(Geometry("POINT (1 1)"), 1) is None
True
"""
return ufuncs.get_geometry(geometry, np.intc(index))

Expand Down
18 changes: 13 additions & 5 deletions pygeos/measurements.py → pygeos/measurement.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from . import ufuncs
from . import Geometry, Empty # NOQA
from . import Geometry # NOQA

__all__ = ["area", "distance", "length", "hausdorff_distance"]

Expand All @@ -17,7 +17,9 @@ def area(geometry):
100.0
>>> area(Geometry("MULTIPOLYGON (((0 0, 0 10, 10 10, 0 0)), ((0 0, 0 10, 10 10, 0 0)))"))
100.0
>>> area(Empty)
>>> area(Geometry("POLYGON EMPTY"))
0.0
>>> area(None)
nan
"""
return ufuncs.area(geometry)
Expand All @@ -39,7 +41,9 @@ def distance(a, b):
1.0
>>> distance(Geometry("POLYGON ((3 0, 5 0, 5 5, 3 5, 3 0))"), point)
3.0
>>> distance(Empty, point)
>>> distance(Geometry("POINT EMPTY"), point)
nan
>>> distance(None, point)
nan
"""
return ufuncs.distance(a, b)
Expand All @@ -60,7 +64,9 @@ def length(geometry):
2.0
>>> length(Geometry("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))"))
40.0
>>> length(Empty)
>>> length(Geometry("LINESTRING EMPTY"))
0.0
>>> length(None)
nan
"""
return ufuncs.length(geometry)
Expand Down Expand Up @@ -89,7 +95,9 @@ def hausdorff_distance(a, b, densify=None):
14.14...
>>> hausdorff_distance(line_1, line_2, densify=0.5)
70.0
>>> hausdorff_distance(line_1, Empty)
>>> hausdorff_distance(line_1, Geometry("LINESTRING EMPTY"))
nan
>>> hausdorff_distance(line_1, None)
nan
"""
if densify is None:
Expand Down

0 comments on commit 3d9e246

Please sign in to comment.