{"id":19618586,"url":"https://github.com/cleder/pygeoif","last_synced_at":"2025-05-16T08:03:22.743Z","repository":{"id":4052140,"uuid":"5154831","full_name":"cleder/pygeoif","owner":"cleder","description":"Basic implementation of the __geo_interface__ 🌐️","archived":false,"fork":false,"pushed_at":"2025-05-12T16:35:33.000Z","size":909,"stargazers_count":69,"open_issues_count":5,"forks_count":27,"subscribers_count":5,"default_branch":"develop","last_synced_at":"2025-05-12T17:53:12.937Z","etag":null,"topics":["geojson","geospatial","gis","hypothesis","wkt"],"latest_commit_sha":null,"homepage":"https://pygeoif.readthedocs.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cleder.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-07-23T17:17:27.000Z","updated_at":"2025-04-30T13:25:00.000Z","dependencies_parsed_at":"2023-07-05T20:46:43.546Z","dependency_job_id":"8cf89579-c57b-4ad7-a13b-55e4a15bdfae","html_url":"https://github.com/cleder/pygeoif","commit_stats":{"total_commits":510,"total_committers":23,"mean_commits":22.17391304347826,"dds":"0.40980392156862744","last_synced_commit":"44c98b686c4e76e6d62d51237ef9db5e05a4cbdc"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cleder%2Fpygeoif","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cleder%2Fpygeoif/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cleder%2Fpygeoif/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cleder%2Fpygeoif/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cleder","download_url":"https://codeload.github.com/cleder/pygeoif/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254493381,"owners_count":22080126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geojson","geospatial","gis","hypothesis","wkt"],"created_at":"2024-11-11T11:09:59.269Z","updated_at":"2025-05-16T08:03:22.721Z","avatar_url":"https://github.com/cleder.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"Introduction\n============\n\n.. inclusion-marker-do-not-remove\n\nPyGeoIf provides a `GeoJSON-like protocol \u003chttps://gist.github.com/2217756\u003e`_\nfor geo-spatial (GIS) vector data.\n\nOther Python programs and packages that you may have heard of that\nimplement this protocol:\n\n* `ArcPy \u003chttps://www.esri.com/about/newsroom/arcuser/geojson/\u003e`_\n* `descartes \u003chttps://docs.descarteslabs.com/\u003e`_\n* `PySAL \u003chttp://pysal.geodacenter.org/\u003e`_\n* `Shapely \u003chttps://github.com/Toblerity/Shapely\u003e`_\n* `pyshp \u003chttps://pypi.python.org/pypi/pyshp\u003e`_\n* `GeoPandas \u003chttps://geopandas.org/\u003e`_\n* `Karta \u003chttps://github.com/fortyninemaps/karta\u003e`_\n* `mapnik \u003chttps://github.com/mapnik/mapnik\u003e`_\n\nWhen you want to write your own geospatial library with support\nfor this protocol you may use pygeoif as a starting point and build\nyour functionality on top of it. It has no requirements outside the\nPython standard library and is therefore easy to integrate into your\nproject. It is tested on `CPython \u003chttps://python.org\u003e`_ and\n`PyPy \u003chttps://www.pypy.org/\u003e`_, but it should work on alternative\nPython implementations (that implement the language specification *\u003e=3.8*) as well.\n\nYou may think of pygeoif as a 'shapely ultralight' which lets you\nconstruct geometries and perform **very** basic operations like\nreading and writing geometries from/to WKT, constructing line strings\nout of points, polygons from linear rings, multi polygons from\npolygons, etc. It was inspired by shapely and implements the\ngeometries in a way that when you are familiar with pygeoif,\nyou will feel right at home with shapely or the other way round.\nIt provides Hypothesis strategies for all geometries for property based\ntesting with Hypothesis_.\n\nIt was written to provide clean and python only geometries for fastkml_\n\n|doc| |test| |cov| |hypothesis| |black| |mypy| |openhub| |factor| |commit| |py| |implement| |latest| |conda| |license| |downloads|\n\n.. |doc| image:: https://readthedocs.org/projects/pygeoif/badge/?version=latest\n    :target: https://pygeoif.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation\n\n.. |test| image:: https://github.com/cleder/pygeoif/actions/workflows/run-all-tests.yml/badge.svg?branch=main\n    :target: https://github.com/cleder/pygeoif/actions/workflows/run-all-tests.yml\n    :alt: GitHub Actions\n\n.. |cov| image:: https://codecov.io/gh/cleder/pygeoif/branch/main/graph/badge.svg?token=2EfiwBXs9X\n    :target: https://codecov.io/gh/cleder/pygeoif\n    :alt: Codecov\n\n.. |hypothesis| image:: https://img.shields.io/badge/hypothesis-tested-brightgreen.svg\n   :alt: Tested with Hypothesis\n   :target: https://hypothesis.readthedocs.io\n\n.. |black| image:: https://img.shields.io/badge/code_style-black-000000.svg\n    :target: https://github.com/psf/\n    :alt: Black\n\n.. |mypy| image:: https://img.shields.io/badge/type_checker-mypy-blue\n    :target: http://mypy-lang.org/\n    :alt: Mypy\n\n.. |openhub| image:: https://www.openhub.net/p/pygeoif/widgets/project_thin_badge.gif\n    :target: https://www.openhub.net/p/pygeoif/\n    :alt: Openhub\n\n.. |factor| image:: https://www.codefactor.io/repository/github/cleder/pygeoif/badge/main\n   :target: https://www.codefactor.io/repository/github/cleder/pygeoif/overview/main\n   :alt: CodeFactor\n\n.. |commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n\n.. |py| image:: https://img.shields.io/pypi/pyversions/pygeoif.svg\n    :target: https://pypi.python.org/pypi/pygeoif/\n    :alt: Supported Python versions\n.. |conda| image:: https://img.shields.io/conda/vn/conda-forge/pygeoif.svg\n    :target: https://anaconda.org/conda-forge/pygeoif\n    :alt: Conda Version\n\n.. |implement| image:: https://img.shields.io/pypi/implementation/pygeoif.svg\n    :target: https://pypi.python.org/pypi/pygeoif/\n    :alt: Supported Python implementations\n\n.. |latest| image:: https://img.shields.io/pypi/v/pygeoif.svg\n    :target: https://pypi.python.org/pypi/pygeoif/\n    :alt: Latest Version\n\n.. |license| image:: https://img.shields.io/pypi/l/pygeoif.svg\n    :target: https://pypi.python.org/pypi/pygeoif/\n    :alt: License\n\n.. |downloads| image:: https://img.shields.io/pypi/dm/pygeoif.svg\n    :target: https://www.pepy.tech/projects/pygeoif\n    :alt: Downloads\n\nInstallation\n------------\n\nYou can install PyGeoIf from pypi using pip::\n\n    pip install pygeoif\n\n\nExample\n========\n.. code-block:: pycon\n\n    \u003e\u003e\u003e from pygeoif import geometry\n    \u003e\u003e\u003e p = geometry.Point(1,1)\n    \u003e\u003e\u003e p.__geo_interface__\n    {'type': 'Point', 'bbox': (1, 1, 1, 1), 'coordinates': (1, 1)}\n    \u003e\u003e\u003e print(p)\n    POINT (1 1)\n    \u003e\u003e\u003e p\n    Point(1, 1)\n    \u003e\u003e\u003e l = geometry.LineString([(0.0, 0.0), (1.0, 1.0)])\n    \u003e\u003e\u003e l.bounds\n    (0.0, 0.0, 1.0, 1.0)\n    \u003e\u003e\u003e print(l)\n    LINESTRING (0.0 0.0, 1.0 1.0)\n\n\nYou find more examples in the\n`tests \u003chttps://github.com/cleder/pygeoif/tree/main/tests\u003e`_\ndirectory which cover every aspect of pygeoif or in fastkml_.\n\nClasses\n========\n\nAll classes implement the attribute:\n\n* ``__geo_interface__``: as discussed above, an interface to GeoJSON_.\n\nAll geometry classes implement the attributes:\n\n* ``geom_type``: Returns a string specifying the Geometry Type of the object\n* ``bounds``: Returns a (minx, miny, maxx, maxy) tuple that bounds the object.\n* ``wkt``: Returns the 'Well Known Text' representation of the object\n\nFor two-dimensional geometries the following methods are implemented:\n\n* ``convex_hull``: Returns a representation of the smallest convex Polygon containing\n  all the points in the object unless the number of points in the object is less than three.\n  For two points, the convex hull collapses to a LineString; for 1, a Point.\n  For three dimensional objects only their projection in the xy plane is taken into consideration.\n  Empty objects without coordinates return ``None`` for the convex_hull.\n\n\nPoint\n-----\nA zero dimensional geometry\n\nA point has zero length and zero area. A point cannot be empty.\n\nAttributes\n~~~~~~~~~~~\nx, y, z : float\n    Coordinate values\n\nExample\n~~~~~~~~\n.. code-block: pycon\n\n    \u003e\u003e\u003e from pygeoif import Point\n    \u003e\u003e\u003e p = Point(1.0, -1.0)\n    \u003e\u003e\u003e print(p)\n    POINT (1.0 -1.0)\n    \u003e\u003e\u003e p.y\n    -1.0\n    \u003e\u003e\u003e p.x\n    1.0\n\n\n\nLineString\n-----------\n\nA one-dimensional figure comprising one or more line segments\n\nA LineString has non-zero length and zero area. It may approximate a curve\nand need not be straight. Unlike a LinearRing, a LineString is not closed.\n\nAttributes\n~~~~~~~~~~~\ngeoms : sequence\n    A sequence of Points\n\nLinearRing\n-----------\n\nA closed one-dimensional geometry comprising one or more line segments\n\nA LinearRing that crosses itself or touches itself at a single point is\ninvalid and operations on it may fail.\n\nA LinearRing is self closing.\n\n\nPolygon\n--------\n\nA two-dimensional figure bounded by a linear ring\n\nA polygon has a non-zero area. It may have one or more negative-space\n\"holes\" which are also bounded by linear rings. If any rings cross each\nother, the geometry is invalid and operations on it may fail.\n\nAttributes\n~~~~~~~~~~~\n\nexterior : LinearRing\n    The ring which bounds the positive space of the polygon.\ninteriors : sequence\n    A sequence of rings which bound all existing holes.\n\nMultiPoint\n----------\nA collection of one or more points.\n\nAttributes\n~~~~~~~~~~~\n\ngeoms : sequence\n    A sequence of Points.\n\nMultiLineString\n----------------\nA collection of one or more line strings.\n\nA MultiLineString has non-zero length and zero area.\n\nAttributes\n~~~~~~~~~~~\n\ngeoms : sequence\n    A sequence of LineStrings\n\nMultiPolygon\n-------------\n\nA collection of one or more polygons.\n\nAttributes\n~~~~~~~~~~~~~\ngeoms : sequence\n    A sequence of `Polygon` instances\n\n\nGeometryCollection\n-------------------\nA heterogenous collection of geometries (Points, LineStrings, LinearRings\nand Polygons).\n\nAttributes\n~~~~~~~~~~~\ngeoms : sequence\n    A sequence of geometry instances\n\nPlease note:\n``GEOMETRYCOLLECTION`` isn't supported by the Shapefile or GeoJSON_ format.\nAnd this sub-class isn't generally supported by ordinary GIS sw (viewers and so on).\nSo it's very rarely used in the real GIS professional world.\n\nExample\n~~~~~~~~\n.. code-block:: pycon\n\n    \u003e\u003e\u003e from pygeoif import geometry\n    \u003e\u003e\u003e p = geometry.Point(1.0, -1.0)\n    \u003e\u003e\u003e p2 = geometry.Point(1.0, -1.0)\n    \u003e\u003e\u003e geoms = [p, p2]\n    \u003e\u003e\u003e c = geometry.GeometryCollection(geoms)\n    \u003e\u003e\u003e [geom for geom in geoms]\n    [Point(1.0, -1.0), Point(1.0, -1.0)]\n\nFeature\n-------\nAggregates a geometry instance with associated user-defined properties.\n\nAttributes\n~~~~~~~~~~~\ngeometry : object\n    A geometry instance\nproperties : dict\n    A dictionary linking field keys with values associated with with geometry instance\n\nExample\n~~~~~~~~\n.. code-block:: pycon\n\n      \u003e\u003e\u003e from pygeoif import Point, Feature\n      \u003e\u003e\u003e p = Point(1.0, -1.0)\n      \u003e\u003e\u003e props = {'Name': 'Sample Point', 'Other': 'Other Data'}\n      \u003e\u003e\u003e a = Feature(p, props)\n      \u003e\u003e\u003e a.properties\n      {'Name': 'Sample Point', 'Other': 'Other Data'}\n      \u003e\u003e\u003e a.properties['Name']\n      'Sample Point'\n\nFeatureCollection\n-----------------\nA heterogenous collection of Features\n\nAttributes\n~~~~~~~~~~~\nfeatures: sequence\n    A sequence of feature instances\n\nExample\n~~~~~~~~\n.. code-block:: pycon\n\n    \u003e\u003e\u003e from pygeoif import Point, Feature, FeatureCollection\n    \u003e\u003e\u003e p = Point(1.0, -1.0)\n    \u003e\u003e\u003e props = {'Name': 'Sample Point', 'Other': 'Other Data'}\n    \u003e\u003e\u003e a = Feature(p, props)\n    \u003e\u003e\u003e p2 = Point(1.0, -1.0)\n    \u003e\u003e\u003e props2 = {'Name': 'Sample Point2', 'Other': 'Other Data2'}\n    \u003e\u003e\u003e b = Feature(p2, props2)\n    \u003e\u003e\u003e features = [a, b]\n    \u003e\u003e\u003e c = FeatureCollection(features)\n    \u003e\u003e\u003e [feature for feature in c]\n    [Feature(Point(1.0, -1.0), {'Name': 'Sample Point', 'Other': 'Other Data'},...]\n\nFunctions\n=========\n\nshape\n--------\n\nCreate a pygeoif feature from an object that provides the ``__geo_interface__``\nor any GeoJSON_ compatible dictionary.\n\n.. code-block:: pycon\n\n    \u003e\u003e\u003e from shapely.geometry import Point\n    \u003e\u003e\u003e from pygeoif import geometry, shape\n    \u003e\u003e\u003e shape(Point(0,0))\n    Point(0.0, 0.0)\n\n\nfrom_wkt\n---------\n\nCreate a geometry from its WKT representation\n\n.. code-block:: pycon\n\n    \u003e\u003e\u003e from pygeoif import from_wkt\n    \u003e\u003e\u003e p = from_wkt('POINT (0 1)')\n    \u003e\u003e\u003e print(p)\n    POINT (0.0 1.0)\n\n\nsigned_area\n------------\n\nReturn the signed area enclosed by a ring.\nA value \u003e= 0 indicates a counter-clockwise oriented ring.\n\n\norient\n-------\nReturns a copy of a polygon with exteriors and interiors in the right orientation.\n\nif ccw is True than the exterior will be in counterclockwise orientation\nand the interiors will be in clockwise orientation, or\nthe other way round when ccw is False.\n\n\nbox\n---\nReturn a rectangular polygon with configurable normal vector.\n\n\nmapping\n-------\n\nReturn the ``__geo_interface__`` dictionary.\n\n\nDevelopment\n===========\n\nClone this repository, create a virtualenv with Python 3.8 or later with\n``python3 -m venv .venv`` and activate it with ``source .venv/bin/activate``.\n\nThen install the requirements with ``pip install -e \".[dev]\"``.\n\npre-commit\n----------\n\nInstall the ``pre-commit`` hook with::\n\n    pip install pre-commit\n    pre-commit install\n\nand check the code with::\n\n    pre-commit run --all-files\n\nTesting\n-------\n\nRun the unit and static tests with::\n\n    pytest tests\n    pytest --doctest-glob=\"README.rst\"\n    black pygeoif\n    ruff pygeoif\n    flake8 pygeoif\n    mypy pygeoif\n\n\n\nAcknowledgments\n================\n\nThe tests were improved with mutmut_ which discovered some nasty edge cases.\n\n.. _mutmut: https://github.com/boxed/mutmut\n.. _GeoJSON: https://geojson.org/\n.. _fastkml: http://pypi.python.org/pypi/fastkml/\n.. _Hypothesis: https://hypothesis.works\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcleder%2Fpygeoif","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcleder%2Fpygeoif","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcleder%2Fpygeoif/lists"}