pygeoif - Man Page
pygeoif 1.6.0
Overview
PyGeoIf provides a GeoJSON-like protocol <https://gist.github.com/2217756> for geo-spatial (GIS) vector data.
Other Python programs and packages that you may have heard of that implement this protocol:
- ArcPy <https://www.esri.com/about/newsroom/arcuser/geojson/>
- descartes <https://docs.descarteslabs.com/>
- PySAL <http://pysal.geodacenter.org/>
- Shapely <https://github.com/Toblerity/Shapely>
- pyshp <https://pypi.python.org/pypi/pyshp>
- GeoPandas <https://geopandas.org/>
- Karta <https://github.com/fortyninemaps/karta>
- mapnik <https://github.com/mapnik/mapnik>
When you want to write your own geospatial library with support for this protocol you may use pygeoif as a starting point and build your functionality on top of it. It has no requirements outside the Python standard library and is therefore easy to integrate into your project. It is tested on CPython <https://python.org>, PyPy <https://www.pypy.org/> and GraalPy <https://www.graalvm.org/python/>, but it should work on alternative Python implementations (that implement the language specification >=3.9) as well.
You may think of pygeoif as a 'shapely ultralight' which lets you construct geometries and perform very basic operations like reading and writing geometries from/to WKT, constructing line strings out of points, polygons from linear rings, multi polygons from polygons, etc. It was inspired by shapely and implements the geometries in a way that when you are familiar with pygeoif, you will feel right at home with shapely or the other way round. It provides Hypothesis strategies for all geometries for property based testing with Hypothesis <https://hypothesis.works>.
It was written to provide clean and python only geometries for fastkml <http://pypi.python.org/pypi/fastkml/>
[image: Documentation] [image]
<https://pygeoif.readthedocs.io/en/latest/?badge=latest> [image: GitHub Actions] [image]
<https://github.com/cleder/pygeoif/actions/workflows/run-all-tests.yml> [image: Codecov] [image]
<https://codecov.io/gh/cleder/pygeoif> [image: Tested with Hypothesis] [image]
<https://hypothesis.readthedocs.io> [image: Black] [image]
<https://github.com/psf/> [image: Mypy] [image]
<http://mypy-lang.org/> [image: Openhub] [image]
<https://www.openhub.net/p/pygeoif/> [image: CodeFactor] [image]
<https://www.codefactor.io/repository/github/cleder/pygeoif/overview/main> [image: pre-commit] [image]
<https://github.com/pre-commit/pre-commit> [image: Supported Python versions] [image]
<https://pypi.python.org/pypi/pygeoif/> [image: Supported Python implementations] [image]
<https://pypi.python.org/pypi/pygeoif/> [image: Latest Version] [image]
<https://pypi.python.org/pypi/pygeoif/> [image: Conda Version] [image]
<https://anaconda.org/conda-forge/pygeoif> [image: License] [image]
<https://pypi.python.org/pypi/pygeoif/> [image: Downloads] [image]
<https://www.pepy.tech/projects/pygeoif>
Installation
You can install PyGeoIf from pypi using pip:
pip install pygeoif
Example
>>> from pygeoif import geometry
>>> p = geometry.Point(1,1)
>>> p.__geo_interface__
{'type': 'Point', 'bbox': (1, 1, 1, 1), 'coordinates': (1, 1)}
>>> print(p)
POINT (1 1)
>>> p
Point(1, 1)
>>> l = geometry.LineString([(0.0, 0.0), (1.0, 1.0)])
>>> l.bounds
(0.0, 0.0, 1.0, 1.0)
>>> print(l)
LINESTRING (0.0 0.0, 1.0 1.0)You find more examples in the tests <https://github.com/cleder/pygeoif/tree/main/tests> directory which cover every aspect of pygeoif or in fastkml <http://pypi.python.org/pypi/fastkml/>.
Classes
All classes implement the attribute:
- __geo_interface__: as discussed above, an interface to GeoJSON <https://geojson.org/>.
All geometry classes implement the attributes:
- geom_type: Returns a string specifying the Geometry Type of the object
- bounds: Returns a (minx, miny, maxx, maxy) tuple that bounds the object.
- wkt: Returns the 'Well Known Text' representation of the object
For two-dimensional geometries the following methods are implemented:
- convex_hull: Returns a representation of the smallest convex Polygon containing all the points in the object unless the number of points in the object is less than three. For two points, the convex hull collapses to a LineString; for 1, a Point. For three dimensional objects only their projection in the xy plane is taken into consideration. Empty objects without coordinates return None for the convex_hull.
Point
A zero dimensional geometry
A point has zero length and zero area. A point cannot be empty.
Attributes
- x, y, z (float)
Coordinate values
Example
LineString
A one-dimensional figure comprising one or more line segments
A LineString has non-zero length and zero area. It may approximate a curve and need not be straight. Unlike a LinearRing, a LineString is not closed.
Attributes
- geoms (sequence)
A sequence of Points
LinearRing
A closed one-dimensional geometry comprising one or more line segments
A LinearRing that crosses itself or touches itself at a single point is invalid and operations on it may fail.
A LinearRing is self closing.
Polygon
A two-dimensional figure bounded by a linear ring
A polygon has a non-zero area. It may have one or more negative-space "holes" which are also bounded by linear rings. If any rings cross each other, the geometry is invalid and operations on it may fail.
Attributes
- exterior (LinearRing)
The ring which bounds the positive space of the polygon.
- interiors (sequence)
A sequence of rings which bound all existing holes.
MultiPoint
A collection of one or more points.
Attributes
- geoms (sequence)
A sequence of Points.
MultiLineString
A collection of one or more line strings.
A MultiLineString has non-zero length and zero area.
Attributes
- geoms (sequence)
A sequence of LineStrings
MultiPolygon
A collection of one or more polygons.
Attributes
- geoms (sequence)
A sequence of Polygon instances
GeometryCollection
A heterogenous collection of geometries (Points, LineStrings, LinearRings and Polygons).
Attributes
- geoms (sequence)
A sequence of geometry instances
Please note: GEOMETRYCOLLECTION isn't supported by the Shapefile or GeoJSON <https://geojson.org/> format. And this sub-class isn't generally supported by ordinary GIS sw (viewers and so on). So it's very rarely used in the real GIS professional world.
Example
>>> from pygeoif import geometry >>> p = geometry.Point(1.0, -1.0) >>> p2 = geometry.Point(1.0, -1.0) >>> geoms = [p, p2] >>> c = geometry.GeometryCollection(geoms) >>> [geom for geom in geoms] [Point(1.0, -1.0), Point(1.0, -1.0)]
Feature
Aggregates a geometry instance with associated user-defined properties.
Attributes
- geometry (object)
A geometry instance
- properties (dict)
A dictionary linking field keys with values associated with with geometry instance
Example
>>> from pygeoif import Point, Feature
>>> p = Point(1.0, -1.0)
>>> props = {'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a = Feature(p, props)
>>> a.properties
{'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a.properties['Name']
'Sample Point'FeatureCollection
A heterogenous collection of Features
Attributes
- features: sequence
A sequence of feature instances
Example
>>> from pygeoif import Point, Feature, FeatureCollection
>>> p = Point(1.0, -1.0)
>>> props = {'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a = Feature(p, props)
>>> p2 = Point(1.0, -1.0)
>>> props2 = {'Name': 'Sample Point2', 'Other': 'Other Data2'}
>>> b = Feature(p2, props2)
>>> features = [a, b]
>>> c = FeatureCollection(features)
>>> [feature for feature in c]
[Feature(Point(1.0, -1.0), {'Name': 'Sample Point', 'Other': 'Other Data'},...]Functions
shape
Create a pygeoif feature from an object that provides the __geo_interface__ or any GeoJSON <https://geojson.org/> compatible dictionary.
>>> from shapely.geometry import Point >>> from pygeoif import geometry, shape >>> shape(Point(0,0)) Point(0.0, 0.0)
from_wkt
Create a geometry from its WKT representation
>>> from pygeoif import from_wkt
>>> p = from_wkt('POINT (0 1)')
>>> print(p)
POINT (0.0 1.0)signed_area
Return the signed area enclosed by a ring. A value >= 0 indicates a counter-clockwise oriented ring.
orient
Returns a copy of a polygon with exteriors and interiors in the right orientation.
if ccw is True than the exterior will be in counterclockwise orientation and the interiors will be in clockwise orientation, or the other way round when ccw is False.
box
Return a rectangular polygon with configurable normal vector.
mapping
Return the __geo_interface__ dictionary.
Development
Clone this repository, create a virtualenv with Python 3.8 or later with python3 -m venv .venv and activate it with source .venv/bin/activate.
Then install the requirements with pip install -e ".[dev]".
pre-commit
Install the pre-commit hook with:
pip install pre-commit pre-commit install
and check the code with:
pre-commit run --all-files
Testing
Run the unit and static tests with:
pytest tests pytest --doctest-glob="README.rst" ruff check pygeoif ruff fmt pygeoif mypy pygeoif
Acknowledgments
The tests were improved with mutmut <https://github.com/boxed/mutmut> which discovered some nasty edge cases.
API Reference
pygeoif
Module contents
Submodules
pygeoif.geometry module
Geometries in pure Python.
- class pygeoif.geometry.GeometryCollection(geometries: Iterable[Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon> | GeometryCollection <#pygeoif.geometry.GeometryCollection>])
Bases: _MultiGeometry
A heterogenous collection of geometries.
Attributes
- geoms (sequence)
A sequence of geometry instances
Please note: GEOMETRYCOLLECTION isn't supported by the Shapefile format. And this sub- class isn't generally supported by ordinary GIS sw (viewers and so on). So it's very rarely used in the real GIS professional world.
Example
Initialize Geometries and construct a GeometryCollection
>>> from pygeoif import geometry
>>> p = geometry.Point(1.0, -1.0)
>>> p2 = geometry.Point(1.0, -1.0)
>>> geoms = [p, p2]
>>> c = geometry.GeometryCollection(geoms)
>>> c.__geo_interface__
{'type': 'GeometryCollection',
'geometries': [{'type': 'Point', 'coordinates': (1.0, -1.0)},
{'type': 'Point', 'coordinates': (1.0, -1.0)}]}- class pygeoif.geometry.LineString(coordinates: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]])
Bases: _Geometry
A one-dimensional figure comprising one or more line segments.
A LineString has non-zero length and zero area. It may approximate a curve and need not be straight. Unlike a LinearRing, a LineString is not closed.
Attributes
- geoms (sequence)
A sequence of Points
- property geoms: tuple[Point <#pygeoif.geometry.Point>, ...]
Return the underlying geometries.
- property coords: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]
Return the geometry coordinates.
- property is_empty: bool
Return if this geometry is empty.
A Linestring is considered empty when it has no points.
- property has_z: bool | None
Return True if the geometry's coordinate sequence(s) have z values.
- classmethod from_coordinates(coordinates: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]) -> LineString <#pygeoif.geometry.LineString>
Construct a linestring from coordinates.
- classmethod from_points(*args: Point <#pygeoif.geometry.Point>) -> LineString <#pygeoif.geometry.LineString>
Create a linestring from points.
- class pygeoif.geometry.LinearRing(coordinates: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]])
Bases: LineString
A closed one-dimensional geometry comprising one or more line segments.
A LinearRing that crosses itself or touches itself at a single point is invalid and operations on it may fail.
A Linear Ring is self closing
- property centroid: Point <#pygeoif.geometry.Point> | None
Return the centroid of the ring.
- property is_ccw: bool
Return True if the ring is oriented counter clock-wise.
- class pygeoif.geometry.MultiLineString(lines: Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]], unique: bool = False)
Bases: _MultiGeometry
A collection of one or more line strings.
A MultiLineString has non-zero length and zero area.
Attributes
- geoms (sequence)
A sequence of LineStrings
- property geoms: Iterator[LineString <#pygeoif.geometry.LineString>]
Iterate over the points.
- classmethod from_linestrings(*args: LineString <#pygeoif.geometry.LineString>, unique: bool = False) -> MultiLineString <#pygeoif.geometry.MultiLineString>
Create a MultiLineString from LineStrings.
- class pygeoif.geometry.MultiPoint(points: Sequence[tuple[float, float] | tuple[float, float, float]], unique: bool = False)
Bases: _MultiGeometry
A collection of one or more points.
Attributes
- geoms (sequence)
A sequence of Points
- property geoms: Iterator[Point <#pygeoif.geometry.Point>]
Iterate over the points.
- classmethod from_points(*args: Point <#pygeoif.geometry.Point>, unique: bool = False) -> MultiPoint <#pygeoif.geometry.MultiPoint>
Create a MultiPoint from Points.
- class pygeoif.geometry.MultiPolygon(polygons: Sequence[tuple[Sequence[tuple[float, float]], Sequence[Sequence[tuple[float, float]]]] | tuple[Sequence[tuple[float, float]]] | tuple[Sequence[tuple[float, float, float]], Sequence[Sequence[tuple[float, float, float]]]] | tuple[Sequence[tuple[float, float, float]]]], unique: bool = False)
Bases: _MultiGeometry
A collection of one or more polygons.
If component polygons overlap the collection is invalid and some operations on it may fail.
Attributes
- geoms (sequence)
A sequence of Polygon instances
- property geoms: Iterator[Polygon <#pygeoif.geometry.Polygon>]
Iterate over the points.
- classmethod from_polygons(*args: Polygon <#pygeoif.geometry.Polygon>, unique: bool = False) -> MultiPolygon <#pygeoif.geometry.MultiPolygon>
Create a MultiPolygon from Polygons.
- class pygeoif.geometry.Point(x: float, y: float, z: float | None = None)
Bases: _Geometry
A zero dimensional geometry.
A point has zero length and zero area.
Attributes
- x, y, z (float)
Coordinate values
Example
>>> p = Point(1.0, -1.0) >>> print p POINT (1.0 -1.0) >>> p.y -1.0 >>> p.x 1.0
- property is_empty: bool
Return if this geometry is empty.
A Point is considered empty when it has no valid coordinates.
- property x: float
Return x coordinate.
- property y: float
Return y coordinate.
- property z: float | None
Return z coordinate.
- property coords: tuple[tuple[float, float] | tuple[float, float, float]] | tuple[()]
Return the geometry coordinates.
- property has_z: bool
Return True if the geometry's coordinate sequence(s) have z values.
- classmethod from_coordinates(coordinates: Sequence[tuple[float, float] | tuple[float, float, float]]) -> Point <#pygeoif.geometry.Point>
Construct a point from coordinates.
- class pygeoif.geometry.Polygon(shell: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]], holes: Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]] | None = None)
Bases: _Geometry
A two-dimensional figure bounded by a linear ring.
A polygon has a non-zero area. It may have one or more negative-space "holes" which are also bounded by linear rings. If any rings cross each other, the geometry is invalid and operations on it may fail.
Attributes
- exterior (LinearRing)
The ring which bounds the positive space of the polygon.
- interiors (sequence)
A sequence of rings which bound all existing holes.
- property exterior: LinearRing <#pygeoif.geometry.LinearRing>
Return the exterior Linear Ring of the polygon.
- property interiors: Iterator[LinearRing <#pygeoif.geometry.LinearRing>]
Interiors (Holes) of the polygon.
- property is_empty: bool
Return if this geometry is empty.
A polygon is empty when it does not have an exterior.
- property coords: tuple[Sequence[tuple[float, float]], Sequence[Sequence[tuple[float, float]]]] | tuple[Sequence[tuple[float, float]]] | tuple[Sequence[tuple[float, float, float]], Sequence[Sequence[tuple[float, float, float]]]] | tuple[Sequence[tuple[float, float, float]]]
Return Coordinates of the Polygon.
Note that this is not implemented in Shapely.
- property has_z: bool | None
Return True if the geometry's coordinate sequence(s) have z values.
- classmethod from_coordinates(coordinates: tuple[Sequence[tuple[float, float]], Sequence[Sequence[tuple[float, float]]]] | tuple[Sequence[tuple[float, float]]] | tuple[Sequence[tuple[float, float, float]], Sequence[Sequence[tuple[float, float, float]]]] | tuple[Sequence[tuple[float, float, float]]]) -> Polygon <#pygeoif.geometry.Polygon>
Construct a linestring from coordinates.
- classmethod from_linear_rings(shell: LinearRing <#pygeoif.geometry.LinearRing>, *args: LinearRing <#pygeoif.geometry.LinearRing>) -> Polygon <#pygeoif.geometry.Polygon>
Construct a Polygon from linear rings.
pygeoif.feature module
Features.
- class pygeoif.feature.Feature(geometry: Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon>, properties: dict[str, Any] | None = None, feature_id: str | int | None = None)
Bases: object
Aggregates a geometry instance with associated user-defined properties.
Attributes
- geometry (object)
A geometry instance
- properties (dict)
A dictionary linking field keys with values associated with geometry instance
Example
>>> p = Point(1.0, -1.0)
>>> props = {'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a = Feature(p, props)
>>> a.properties
{'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a.properties['Name']
'Sample Point'- property id: str | int | None
Return the id of the feature.
- property geometry: Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon>
Return the geometry of the feature.
- property properties: dict[str, Any]
Return a dictionary of properties.
- class pygeoif.feature.FeatureCollection(features: Sequence[Feature <#pygeoif.feature.Feature>])
Bases: object
A heterogenous collection of Features.
Attributes
- features (sequence)
A sequence of feature instances
Example
>>> from pygeoif import geometry
>>> p = geometry.Point(1.0, -1.0)
>>> props = {'Name': 'Sample Point', 'Other': 'Other Data'}
>>> a = geometry.Feature(p, props)
>>> p2 = geometry.Point(1.0, -1.0)
>>> props2 = {'Name': 'Sample Point2', 'Other': 'Other Data2'}
>>> b = geometry.Feature(p2, props2)
>>> features = [a, b]
>>> c = geometry.FeatureCollection(features)
>>> c.__geo_interface__
{'type': 'FeatureCollection',
'features': [{'geometry': {'type': 'Point', 'coordinates': (1.0, -1.0)},
'type': 'Feature',
'properties': {'Other': 'Other Data', 'Name': 'Sample Point'}},
{'geometry': {'type': 'Point', 'coordinates': (1.0, -1.0)},
'type': 'Feature',
'properties': {'Other': 'Other Data2', 'Name': 'Sample Point2'}}]}- property features: Generator[Feature <#pygeoif.feature.Feature>, None, None]
Iterate over the features of the collection.
- property bounds: tuple[float, float, float, float]
Return the X-Y bounding box.
pygeoif.factories module
Geometry Factories.
- pygeoif.factories.box(minx: float, miny: float, maxx: float, maxy: float, ccw: bool = True) -> Polygon <#pygeoif.geometry.Polygon>
Return a rectangular polygon with configurable normal vector.
- pygeoif.factories.force_2d(context: GeoType <#pygeoif.types.GeoType> | GeoCollectionType <#pygeoif.types.GeoCollectionType>) -> Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon> | GeometryCollection <#pygeoif.geometry.GeometryCollection>
Force the dimensionality of a geometry to 2D.
>>> force_2d(Point(0, 0, 1)) Point(0, 0) >>> force_2d(Point(0, 0)) Point(0, 0) >>> force_2d(LineString([(0, 0, 0), (0, 1, 1), (1, 1, 2)])) LineString(((0, 0), (0, 1), (1, 1)))
- pygeoif.factories.force_3d(context: GeoType <#pygeoif.types.GeoType> | GeoCollectionType <#pygeoif.types.GeoCollectionType>, z: float = 0) -> Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon> | GeometryCollection <#pygeoif.geometry.GeometryCollection>
Force the dimensionality of a geometry to 3D.
>>> force_3d(Point(0, 0)) Point(0, 0, 0) >>> force_3d(Point(0, 0), 1) Point(0, 0, 1) >>> force_3d(Point(0, 0, 0)) Point(0, 0, 0) >>> force_3d(LineString([(0, 0), (0, 1), (1, 1)])) LineString(((0, 0, 0), (0, 1, 0), (1, 1, 0)))
- pygeoif.factories.from_wkt(geo_str: str) -> Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon> | GeometryCollection <#pygeoif.geometry.GeometryCollection> | None
Create a geometry from its WKT representation.
- pygeoif.factories.mapping(ob: GeoType <#pygeoif.types.GeoType> | GeoCollectionType <#pygeoif.types.GeoCollectionType>) -> GeoCollectionInterface <#pygeoif.types.GeoCollectionInterface> | GeoInterface <#pygeoif.types.GeoInterface>
Return a GeoJSON-like mapping.
Parameters
- ob :
An object which implements __geo_interface__.
Returns
dict Example ------- >>> pt = Point(0, 0) >>> mapping(pt) {'type': 'Point', 'bbox': (0, 0, 0, 0), 'coordinates': (0, 0)}
- pygeoif.factories.orient(polygon: Polygon <#pygeoif.geometry.Polygon>, ccw: bool = True) -> Polygon <#pygeoif.geometry.Polygon>
Return a polygon with exteriors and interiors in the right orientation.
if ccw is True than the exterior will be in counterclockwise orientation and the interiors will be in clockwise orientation, or the other way round when ccw is False.
- pygeoif.factories.shape(context: GeoType <#pygeoif.types.GeoType> | GeoCollectionType <#pygeoif.types.GeoCollectionType> | GeoInterface <#pygeoif.types.GeoInterface> | GeoCollectionInterface <#pygeoif.types.GeoCollectionInterface>) -> Point <#pygeoif.geometry.Point> | LineString <#pygeoif.geometry.LineString> | LinearRing <#pygeoif.geometry.LinearRing> | Polygon <#pygeoif.geometry.Polygon> | MultiPoint <#pygeoif.geometry.MultiPoint> | MultiLineString <#pygeoif.geometry.MultiLineString> | MultiPolygon <#pygeoif.geometry.MultiPolygon> | GeometryCollection <#pygeoif.geometry.GeometryCollection>
Return a new geometry with coordinates copied from the context.
Changes to the original context will not be reflected in the geometry object.
Parameters
- context :
a GeoJSON-like dict, which provides a "type" member describing the type of the geometry and "coordinates" member providing a list of coordinates, or an object which implements __geo_interface__.
Returns
Geometry object Example ------- Create a Point from GeoJSON, and then create a copy using __geo_interface__. >>> context = {'type': 'Point', 'coordinates': [0, 1]} >>> geom = shape(context) >>> geom.geom_type == 'Point' True >>> geom.wkt 'Point (0 1)' >>> geom2 = shape(geom) >>> geom == geom2 True
pygeoif.functions module
Functions for geometries.
- pygeoif.functions.centroid(coords: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]) -> tuple[tuple[float, float], float]
Calculate the coordinates of the centroid and the area of a LineString.
- pygeoif.functions.compare_coordinates(coords: float | tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]] | Sequence[tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]]], other: float | tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]] | Sequence[tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]]]) -> bool
Compare two coordinate sequences.
- pygeoif.functions.compare_geo_interface(first: GeoInterface <#pygeoif.types.GeoInterface> | GeoCollectionInterface <#pygeoif.types.GeoCollectionInterface>, second: GeoInterface <#pygeoif.types.GeoInterface> | GeoCollectionInterface <#pygeoif.types.GeoCollectionInterface>) -> bool
Compare two geo interfaces.
- pygeoif.functions.convex_hull(points: Iterable[tuple[float, float]]) -> Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]
Return the convex hull of a set of points using Andrew's monotone chain algorithm.
Args
points (Iterable[Point2D]): A collection of 2D points.
Returns
LineType: The convex hull, represented as a list of points.
- pygeoif.functions.dedupe(coords: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]) -> Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]
Remove duplicate Points from a LineString.
- pygeoif.functions.move_coordinate(coordinate: tuple[float, float] | tuple[float, float, float], move_by: tuple[float, float] | tuple[float, float, float]) -> tuple[float, float] | tuple[float, float, float]
Move the coordinate by the given vector.
This forcefully changes the dimensions of the coordinate to match the latter. >>> move_coordinate((0, 0), (-1, 1)) (-1, 1) >>> move_coordinate((0, 0, 0), (-1, 1)) (-1, 1) >>> move_coordinate((0, 0), (-1, 1, 0)) (-1, 1, 0)
- pygeoif.functions.move_coordinates(coordinates: tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]], move_by: tuple[float, float] | tuple[float, float, float]) -> tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]]
Move the coordinates recursively by the given vector.
This forcefully changes the dimension of each of the coordinate to match the dimensionality of the vector. >>> move_coordinates(((0, 0), (-1, 1)), (-1, 1)) ((-1, 1), (-2, 2)) >>> move_coordinates(((0, 0, 0), (-1, 1, 0)), (-1, 1)) ((-1, 1), (-2, 2)) >>> move_coordinates(((0, 0), (-1, 1)), (-1, 1, 0)) ((-1, 1, 0), (-2, 2, 0))
- pygeoif.functions.signed_area(coords: Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]) -> float
Return the signed area enclosed by a ring.
Linear time algorithm: <http://www.cgafaq.info/wiki/Polygon_Area>. A value >= 0 indicates a counter-clockwise oriented ring.
pygeoif.exceptions module
Exceptions for pygeoif.
- exception pygeoif.exceptions.DimensionError
Bases: ValueError
Geometries must have 2 or 3 dimensions.
- exception pygeoif.exceptions.InvalidGeometryError
Bases: ValueError
Geometry is not valid.
- exception pygeoif.exceptions.WKTParserError
Bases: AttributeError
WKT not supported or cannot be parsed.
pygeoif.types module
Types for geometries.
- class pygeoif.types.GeoCollectionInterface
Bases: TypedDict
Geometry Collection Interface.
type: Literal['GeometryCollection']
geometries: Sequence[GeoInterface <#pygeoif.types.GeoInterface> | GeoCollectionInterface <#pygeoif.types.GeoCollectionInterface>]
bbox: NotRequired[tuple[float, float, float, float]]
- class pygeoif.types.GeoCollectionType(*args, **kwargs)
Bases: Protocol
Any compatible type that implements the __geo_interface__.
- class pygeoif.types.GeoFeatureCollectionInterface
Bases: TypedDict
Bbox and id are optional keys for the GeoFeatureCollectionInterface.
type: Literal['FeatureCollection']
features: Sequence[GeoFeatureInterface <#pygeoif.types.GeoFeatureInterface>]
bbox: NotRequired[tuple[float, float, float, float]]
id: NotRequired[str | int]
- class pygeoif.types.GeoFeatureInterface
Bases: TypedDict
The GeoFeatureInterface has optional keys.
type: Literal['Feature']
bbox: NotRequired[tuple[float, float, float, float]]
properties: NotRequired[dict[str, Any]]
id: NotRequired[str | int]
geometry: GeoInterface <#pygeoif.types.GeoInterface>
- class pygeoif.types.GeoInterface
Bases: TypedDict
Required keys for the GeoInterface.
type: Literal['Point', 'LineString', 'LinearRing', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon']
coordinates: tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]] | Sequence[tuple[float, float] | tuple[float, float, float] | Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]] | Sequence[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]]]
bbox: NotRequired[tuple[float, float, float, float]]
- class pygeoif.types.GeoType(*args, **kwargs)
Bases: Protocol
Any compatible type that implements the __geo_interface__.
pygeoif.about module
About pygeoif.
The only purpose of this module is to provide a version number for the package.
pygeoif.hypothesis.strategies module
Data-generating strategies for property-based testing.
Coordinates are limited to 32 bit floats to avoid precision issues.
- class pygeoif.hypothesis.strategies.Srs(name: str, min_xyz: tuple[float | None, float | None, float | None], max_xyz: tuple[float | None, float | None, float | None])
Represents a spatial reference system (SRS).
Attributes
name (str): The name of the SRS. min_xyz (Tuple[Optional[float], Optional[float], Optional[float]]): - The minimum x, y, and z values of the SRS. max_xyz (Tuple[Optional[float], Optional[float], Optional[float]]): - The maximum x, y, and z values of the SRS.
name: str
min_xyz: tuple[float | None, float | None, float | None]
max_xyz: tuple[float | None, float | None, float | None]
- longitudes() -> SearchStrategy[float]
Generate a search strategy for generating longitudes.
Returns a search strategy that generates floats within the longitude bounds of the SRS.
- latitudes() -> SearchStrategy[float]
Generate a search strategy for generating latitudes.
Returns a search strategy that generates floats within the latitude bounds of the SRS.
- elevations() -> SearchStrategy[float]
Generate a search strategy for generating elevations.
Returns a search strategy that generates floats within the elevation bounds of the SRS.
- pygeoif.hypothesis.strategies.geometry_collections(*, min_geoms: int = 1, max_geoms: int = 5, max_points: int = 20, min_interiors: int = 0, max_interiors: int = 5, max_leaves: int = 3, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[GeometryCollection <#pygeoif.geometry.GeometryCollection>]
Generate a random GeometryCollection object.
Args
draw (st.DrawFn): The Hypothesis draw function. min_geoms (int): The minimum number of geometries in the collection. max_geoms (int): The maximum number of geometries in the collection. max_points (int): The maximum number of points in each geometry. min_interiors (int): The minimum number of interiors in each polygon. max_interiors (int): The maximum number of interiors in each polygon. srs (Optional[Srs], optional): The spatial reference system of the geometries. has_z (Optional[bool], optional): Whether the geometries have Z coordinates. max_leaves (int): The maximum recursion depth of the collection.
Returns
- GeometryCollection: A randomly generated GeometryCollection object, that may
contain any of the following geometries: Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection.
- pygeoif.hypothesis.strategies.line_coords(*, min_points: int, max_points: int | None = None, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None, unique: bool = False) -> SearchStrategy[Sequence[tuple[float, float]] | Sequence[tuple[float, float, float]]]
Generate a random line in either 2D or 3D space.
Args
draw: The draw function from the hypothesis library. min_points: Minimum number of points in the line max_points: Maximum number of points in the line srs: An optional parameter specifying the spatial reference system. has_z: An optional parameter specifying whether to generate 2D or 3D points. unique: Optional flag to generate unique points (default False).
Returns
A list of point coordinates representing the line in either 2D or 3D space.
- pygeoif.hypothesis.strategies.line_strings(*, max_points: int | None = None, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[LineString <#pygeoif.geometry.LineString>]
Generate a random linestring in either 2D or 3D space.
Args
draw: The draw function from the hypothesis library. max_points: Maximum number of points in the line (must be greater than 1) srs: An optional parameter specifying the spatial reference system. has_z: An optional parameter specifying whether to generate 2D or 3D lines.
Returns
A LineString representing the randomly generated linestring in either 2D or 3D space.
- pygeoif.hypothesis.strategies.linear_rings(*, max_points: int | None = None, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[LinearRing <#pygeoif.geometry.LinearRing>]
Generate a linear ring using the provided draw function.
Args
draw (st.DrawFn): The draw function used to generate the coordinates. max_points (Optional[int]): The maximum number of points in the linear ring. If not specified, there is no limit. srs (Optional[Srs]): The spatial reference system of the linear ring. If not specified, the default SRS is used. has_z (Optional[bool]): Whether the linear ring has z-coordinates. If not specified, 2D or 3D coordinates are generated.
Returns
LinearRing: The generated linear ring.
Raises
ValueError: If max_points is less than 4.
- pygeoif.hypothesis.strategies.multi_line_strings(*, min_lines: int = 1, max_lines: int = 5, max_points: int = 10, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[MultiLineString <#pygeoif.geometry.MultiLineString>]
Generate a random MultiLineString object.
Args
draw (st.DrawFn): The Hypothesis draw function. min_lines (int, optional): The minimum number of lines in the MultiLineString. max_lines (int, optional): The maximum number of lines in the MultiLineString. max_points (int, optional): The maximum number of points in each line. srs (Srs, optional): The spatial reference system of the MultiLineString. has_z (bool, optional): Whether the MultiLineString has z-coordinates.
Returns
MultiLineString: The generated MultiLineString object.
- pygeoif.hypothesis.strategies.multi_points(*, min_points: int = 1, max_points: int | None = None, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[MultiPoint <#pygeoif.geometry.MultiPoint>]
Generate a MultiPoint geometry object with random coordinates.
Args
draw (st.DrawFn): The draw function from the hypothesis library. min_points (int): The minimum number of points in the MultiPoint. Default is 1. max_points (Optional[int]): The maximum number of points in the MultiPoint. srs (Optional[Srs]): The spatial reference system of the coordinates. has_z (Optional[bool]): Whether the coordinates have a Z component. if not specified, 2D and 3D coordinates will be generated randomly.
Returns
MultiPoint: The generated MultiPoint geometry object.
- pygeoif.hypothesis.strategies.multi_polygons(*, min_polygons: int = 1, max_polygons: int = 3, max_points: int = 10, min_interiors: int = 0, max_interiors: int = 2, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[MultiPolygon <#pygeoif.geometry.MultiPolygon>]
Generate a random MultiPolygon object.
Args
draw (st.DrawFn): The Hypothesis draw function. min_polygons (int, optional): The min number of polygons in the MultiPolygon. max_polygons (int, optional): The max number of polygons in the MultiPolygon. max_points (int, optional): The maximum number of points in each polygon. min_interiors (int, optional): The minimum number of interiors in each polygon. max_interiors (int, optional): The maximum number of interiors in each polygon. srs (Optional[Srs], optional): The spatial reference system of the MultiPolygon. has_z (Optional[bool], optional): Whether the MultiPolygon has z-coordinates.
Returns
MultiPolygon: The generated MultiPolygon object.
- pygeoif.hypothesis.strategies.point_coords(*, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[tuple[float, float] | tuple[float, float, float]]
Generate a random point in either 2D or 3D space.
Args
draw: The draw function from the hypothesis library. srs: An optional parameter specifying the spatial reference system. has_z: An optional parameter specifying whether to generate 2D or 3D points.
Returns
A tuple representing the point in either 2D or 3D space.
- pygeoif.hypothesis.strategies.points(*, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[Point <#pygeoif.geometry.Point>]
Generate a random point in either 2D or 3D space.
Args
draw: The draw function from the hypothesis library. srs: An optional parameter specifying the spatial reference system. has_z: An optional parameter specifying whether to generate 2D or 3D points.
Returns
A randomly generated point in either 2D or 3D space.
- pygeoif.hypothesis.strategies.polygons(*, max_points: int | None = None, min_interiors: int = 0, max_interiors: int = 5, srs: Srs <#pygeoif.hypothesis.strategies.Srs> | None = None, has_z: bool | None = None) -> SearchStrategy[Polygon <#pygeoif.geometry.Polygon>]
Generate a random polygon using the given strategies.
Args
draw (st.DrawFn): The draw function used to generate random values. max_points (Optional[int]): The maximum number of points in the polygon. If not specified, there is no limit. min_interiors (Optional[int]): The minimum number of interior rings (holes) in the polygon. Defaults to 0. max_interiors (Optional[int]): The maximum number of interior rings (holes) in the polygon. If not specified, there is no limit. srs (Optional[Srs]): The spatial reference system of the polygon. Defaults to None. has_z (Optional[bool]): Whether the polygon has z-coordinates. If not specified, a random boolean value will be used.
Returns
Polygon: The generated polygon.
Raises
ValueError: If max_points is specified and is less than 4.
Changelog
1.6.0 (unreleased)
- drop Python 3.8 support
- add GraalPy to test matrix
1.5.1 (2024/12/05)
- expose force_2d and force_3d factories in the top-level module.
- fix WKT parsing for nested GeometryCollections.
- fix WKT output for MultiPoints.
- make hypothesis strategy for GeometryCollections recursive, so that it can generate nested collections.
- add Python 3.14 to test matrix.
1.5.0 (2024/05/11)
- fix handling of empty geometries.
- more hypothesis tests
1.4.0 (2024/03/25)
- add Hypothesis tests [Ben Shaver, Christian Ledermann]
- fix convex_hull edge-cases discovered by Hypothesis tests
- fix from_wkt to include multi geometries in GeometryCollections
- drop Python 3.7 support
1.3.0 (2024/02/05)
- add Python 3.13 to supported versions
- remove maybe_valid methods
- GeoType and GeoCollectionType protocols to use a property instead of an attribute
1.2.0 (2023/11/27)
- Geometries are now immutable (but not hashable)
- add force_2d and force_3d factories [Alex Svetkin]
1.1.1 (2023/10/27)
- Use pyproject.toml, remove setup.py and MANIFEST.in
1.1 (2023/10/13)
- Fix nested MultiGeometries
- Improve type annotations
- Add Python 3.12 to supported versions
- Last version to support Python 3.7
1.0 (2022/09/29)
- Add type annotations
- refactor
- changes to keep functionality and interface close to shapely
- remove support for python 2
- minimum python version is 3.7
- rename as_shape to shape
- add box factory
- format with black
- reconstruct objects from their representation
- Parse WKT that is not in upper case.
- Centroid for LinearRings
- Convex Hull
- implement equality __eq__ operator (==)
- is_empty and bool
- drop duplicate points when creating LineStrings
0.7 (2017/05/04)
- fix broken multipolygon [mindflayer]
- add "bbox" to __geo_interface__ output [jzmiller1]
0.6 (2015/08/04)
- Add id to feature [jzmiller1]
0.5 (2015/07/13)
- Add __iter__ method to FeatureCollection and GeometryCollection [jzmiller1].
- add pypy and pypy3 and python 3.4 to travis.
- Add tox configuration for performing local testing [Ian Lee].
- Add Travis continuous deployment.
0.4 (2013/10/25)
- after a year in production promote it to Development Status :: 5 - Production/Stable
- MultiPolygons return tuples as the __geo_interface__
0.3.1 (2012/11/15)
- specify minor python versions tested with Travis CI
- fix for signed area
0.3 (2012/11/14)
- add GeometryCollection
- len(Multi*) and len(GeometryCollection) returns the number of contained Geometries
- add orient function to get clockwise or counterclockwise oriented polygons
- add signed_area function
- add _set_orientation method to lineStrings, Polygons and MultiPolygons
0.2.1 (2012/08/02)
- as_shape also accepts an object that is neither a dictionary nor has a __geo_interface__ but can be converted into a __geo_interface__ compliant dictionary
0.2 (2012/08/01)
- change license to LGPL
- add wkt as a property
- as_shape also accepts a __geo_interface__ compliant dictionary
- test with python3
0.1 (2012/07/27)
- initial release
Contributors
- Ian Lee <<IanLee1521@gmail.com>>
- Zac Miller (jzmiller1)
- John Dees (johnpdees)
- NormWorthington
- Giorgio Salluzzo (mindflayer)
License
Copyright (C) 2012 - 2023 Christian Ledermann
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html>) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html>) for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Index <>
- Module Index <>
- Search Page <>
Author
Christian Ledermann
Copyright
2023, Christian Ledermann