Package: pygeoif
IntroductionPyGeoIf provides aGeoJSON-like protocolfor geo-spatial (GIS) vector data.Other Python programs and packages that you may have heard of that
implement this protocol:ArcPydescartesPySALShapelypyshpGeoPandasKartamapnikWhen 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 onCPythonandPyPy, but it should work on alternative
Python implementations (that implement the language specification>=3.8) as well.You may think of pygeoif as a ‘shapely ultralight’ which lets you
construct geometries and performverybasic 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 was written to provide clean and python only geometries forfastkmlInstallationYou can install PyGeoIf from pypi using pip:pip install pygeoifExample>>> 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 thetestsdirectory which cover every aspect of pygeoif or infastkml.ClassesAll classes implement the attribute:__geo_interface__: as discussed above, an interface toGeoJSON.All geometry classes implement the attributes:geom_type: Returns a string specifying the Geometry Type of the objectbounds: Returns a (minx, miny, maxx, maxy) tuple that bounds the object.wkt: Returns the ‘Well Known Text’ representation of the objectFor 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 returnNonefor the convex_hull.PointA zero dimensional geometryA point has zero length and zero area. A point cannot be empty.Attributesx, y, zfloatCoordinate valuesExample>>> from pygeoif import Point
>>> p = Point(1.0, -1.0)
>>> print(p)
POINT (1.0 -1.0)
>>> p.y
-1.0
>>> p.x
1.0LineStringA one-dimensional figure comprising one or more line segmentsA 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.AttributesgeomssequenceA sequence of PointsLinearRingA closed one-dimensional geometry comprising one or more line segmentsA LinearRing that crosses itself or touches itself at a single point is
invalid and operations on it may fail.A LinearRing is self closing.PolygonA two-dimensional figure bounded by a linear ringA 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.AttributesexteriorLinearRingThe ring which bounds the positive space of the polygon.interiorssequenceA sequence of rings which bound all existing holes.maybe_valid: booleanWhen a polygon has obvious problems such as self crossing
lines or holes that are outside the exterior bounds this will
return False. Even if this returns True the geometry may still be invalid,
but if this returns False you do have a problem.MultiPointA collection of one or more points.AttributesgeomssequenceA sequence of Points.MultiLineStringA collection of one or more line strings.A MultiLineString has non-zero length and zero area.AttributesgeomssequenceA sequence of LineStringsMultiPolygonA collection of one or more polygons.AttributesgeomssequenceA sequence ofPolygoninstancesGeometryCollectionA heterogenous collection of geometries (Points, LineStrings, LinearRings
and Polygons).AttributesgeomssequenceA sequence of geometry instancesPlease note:GEOMETRYCOLLECTIONisn’t supported by the Shapefile orGeoJSONformat.
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)]FeatureAggregates a geometry instance with associated user-defined properties.AttributesgeometryobjectA geometry instancepropertiesdictA dictionary linking field keys with values associated with with geometry instanceExample>>> 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'FeatureCollectionA heterogenous collection of FeaturesAttributesfeatures: sequenceA sequence of feature instancesExample>>> 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'},...]FunctionsshapeCreate a pygeoif feature from an object that provides the__geo_interface__or anyGeoJSONcompatible dictionary.>>> from shapely.geometry import Point
>>> from pygeoif import geometry, shape
>>> shape(Point(0,0))
Point(0.0, 0.0)from_wktCreate 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_areaReturn the signed area enclosed by a ring.
A value >= 0 indicates a counter-clockwise oriented ring.orientReturns 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.boxReturn a rectangular polygon with configurable normal vector.mappingReturn the__geo_interface__dictionary.DevelopmentClone this repository, create a virtualenv with Python 3.8 or later withpython3-mvenv .venvand activate it withsource .venv/bin/activate.Then install the requirements withpip install-e".[dev]".pre-commitInstall thepre-commithook with:pip install pre-commit
pre-commit installand check the code with:pre-commit run --all-filesTestingRun the unit and static tests with:pytest tests
pytest --doctest-glob="README.rst"
black pygeoif
ruff pygeoif
flake8 pygeoif
mypy pygeoifAcknowledgmentsThe tests were improved withmutmutwhich discovered some nasty edge cases.