{"id":13557728,"url":"https://github.com/geomet/geomet","last_synced_at":"2025-10-20T16:04:17.889Z","repository":{"id":7829534,"uuid":"9200780","full_name":"geomet/geomet","owner":"geomet","description":"GeoMet - Pure Python conversion library for common geospatial data formats","archived":false,"fork":false,"pushed_at":"2023-11-14T15:48:58.000Z","size":371,"stargazers_count":167,"open_issues_count":5,"forks_count":32,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-25T20:43:34.741Z","etag":null,"topics":["esri","ewkb","ewkt","geojson","geopackage","geospatial","gis","spatial","wkb","wkt"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geomet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-03T17:39:15.000Z","updated_at":"2024-06-18T13:51:47.488Z","dependencies_parsed_at":"2023-11-12T16:06:49.895Z","dependency_job_id":"e431e86b-f26e-4435-bc57-6e8f2cad9042","html_url":"https://github.com/geomet/geomet","commit_stats":{"total_commits":372,"total_committers":12,"mean_commits":31.0,"dds":0.2553763440860215,"last_synced_commit":"8d2b8f281ef7a919fa0cc9dd5230304d9ff71bd2"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geomet%2Fgeomet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geomet%2Fgeomet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geomet%2Fgeomet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geomet%2Fgeomet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geomet","download_url":"https://codeload.github.com/geomet/geomet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247002198,"owners_count":20867422,"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":["esri","ewkb","ewkt","geojson","geopackage","geospatial","gis","spatial","wkb","wkt"],"created_at":"2024-08-01T12:04:30.861Z","updated_at":"2025-10-20T16:04:17.882Z","avatar_url":"https://github.com/geomet.png","language":"Python","funding_links":[],"categories":["Python","gis"],"sub_categories":[],"readme":"# GeoMet\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ff3)\n[![geomet](https://circleci.com/gh/geomet/geomet.svg?style=shield)](https://app.circleci.com/pipelines/github/geomet)\n[![PyPI version](https://badge.fury.io/py/geomet.svg)](https://badge.fury.io/py/geomet)\n\nPure-Python conversion library for common geospatial data formats.\nSupported formats include:\n- [GeoJSON](http://www.geojson.org/geojson-spec.html)\n- [WKT/WKB](http://en.wikipedia.org/wiki/Well-known_text) (Well-Known Text/Binary)\n- [Extended WKB/WKT](https://postgis.net/docs/using_postgis_dbmanagement.html#EWKB_EWKT)\n- [GeoPackage Binary](http://www.geopackage.org/spec/#gpb_format)\n\n\n## Install\n\nInstall the latest version from [PyPI](https://pypi.org/project/geomet/):\n\n    $ pip install geomet\n\n## Functionality\n\nConversion functions are exposed through idiomatic `load/loads/dump/dumps`\ninterfaces.\n\nGeoMet is intended to cover all common use cases for dealing with 2D, 3D, and\n4D geometries (including 'Z', 'M', and 'ZM').\n\n| Geometry | WKT/EWKT | WKB/EWKB | GeoPackage Binary | EsriJSON |\n| -------- | :------: | :------: | :---------------: | :------: |\n| Point    | ✅ | ✅ | ✅| ✅ |\n| LineString    | ✅ | ✅ | ✅| ✅ |\n| Polygon    | ✅ | ✅ | ✅| ✅ |\n| MultiPoint    | ✅ | ✅ | ✅| ✅ |\n| MultiLineString    | ✅ | ✅ | ✅| ✅ |\n| MultiPolygon    | ✅ | ✅ | ✅| ✅ |\n| GeometryCollection    | ✅ | ✅ | ✅| ✅ |\n\n## Example usage\n\nConverting a 'Point' GeoJSON object to WKT:\n\n    \u003e\u003e\u003e from geomet import wkt\n    \u003e\u003e\u003e point = {'type': 'Point', 'coordinates': [116.4, 45.2, 11.1]}\n    \u003e\u003e\u003e wkt.dumps(point, decimals=4)\n    'POINT (116.4000 45.2000 11.1000)'\n\nConverting a 'Point' GeoJSON object to WKB:\n\n    \u003e\u003e\u003e from geomet import wkb\n    \u003e\u003e\u003e wkb.dumps(point)\n    b'\\x00\\x00\\x00\\x10\\x01@]\\x19\\x99\\x99\\x99\\x99\\x9a@F\\x99\\x99\\x99\\x99\\x99\\x9a@\u0026333333'\n    \u003e\u003e\u003e wkb.dumps(point, big_endian=False)\n    b'\\x01\\x01\\x10\\x00\\x00\\x9a\\x99\\x99\\x99\\x99\\x19]@\\x9a\\x99\\x99\\x99\\x99\\x99F@333333\u0026@'\n\nConverting a 'Point' GeoJSON object to GeoPackage Binary:\n\n    \u003e\u003e\u003e from geomet import geopackage\n    \u003e\u003e\u003e geopackage.dumps(point)\n    b'GP\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xe9@]\\x19\\x99\\x99\\x99\\x99\\x9a@F\\x99\\x99\\x99\\x99\\x99\\x9a@\u0026333333'\n    \u003e\u003e\u003e geopackage.dumps(point, big_endian=False)\n    b'GP\\x00\\x01\\x00\\x00\\x00\\x00\\x01\\xe9\\x03\\x00\\x00\\x9a\\x99\\x99\\x99\\x99\\x19]@\\x9a\\x99\\x99\\x99\\x99\\x99F@333333\u0026@'\n\n\nConverting a 'LineString' GeoJSON object to WKT:\n\n    \u003e\u003e\u003e linestring = {'type':'LineString',\n    ...               'coordinates': [[0.0, 0.0, 10.0], [2.0, 1.0, 20.0],\n    ...                               [4.0, 2.0, 30.0], [5.0, 4.0, 40.0]]}\n    \u003e\u003e\u003e wkt.dumps(linestring, decimals=0)\n    'LINESTRING (0 0 10, 2 1 20, 4 2 30, 5 4 40)'\n\nConverting a 'LineString' GeoJSON object to WKB:\n\n    \u003e\u003e\u003e wkb.dumps(linestring)\n    b'\\x00\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@$\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00?\\xf0\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00@\\x10\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\u003e\\x00\\x00\\x00\\x00\\x00\\x00@\\x14\\x00\\x00\\x00\\x00\\x00\\x00@\\x10\\x00\\x00\\x00\\x00\\x00\\x00@D\\x00\\x00\\x00\\x00\\x00\\x00'\n    \u003e\u003e\u003e wkb.dumps(linestring, big_endian=False)\n    b'\\x01\\x02\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00$@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\xf0?\\x00\\x00\\x00\\x00\\x00\\x004@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\u003e@\\x00\\x00\\x00\\x00\\x00\\x00\\x14@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@\\x00\\x00\\x00\\x00\\x00\\x00D@'\n\nConverting a 'LineString' GeoJSON object to GeoPackage Binary:\n\n    \u003e\u003e\u003e geopackage.dumps(linestring)\n    b'GP\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@$\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00?\\xf0\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00@\\x10\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\u003e\\x00\\x00\\x00\\x00\\x00\\x00@\\x14\\x00\\x00\\x00\\x00\\x00\\x00@\\x10\\x00\\x00\\x00\\x00\\x00\\x00@D\\x00\\x00\\x00\\x00\\x00\\x00'\n    \u003e\u003e\u003e geopackage.dumps(linestring, big_endian=False)\n    b'GP\\x00\\x01\\x00\\x00\\x00\\x00\\x01\\x02\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00$@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\xf0?\\x00\\x00\\x00\\x00\\x00\\x004@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\u003e@\\x00\\x00\\x00\\x00\\x00\\x00\\x14@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@\\x00\\x00\\x00\\x00\\x00\\x00D@'\n\nConverting 'Point' WKT to GeoJSON:\n\n    \u003e\u003e\u003e wkt.loads('POINT(10 20)')\n    {'type': 'Point', 'coordinates': [10.0, 20.0]}\n\nConverting 'GeometryCollection' WKT to GeoJSON:\n\n    \u003e\u003e\u003e wkt.loads('GEOMETRYCOLLECTION(POINT(10 20),POLYGON(((0 0), (10 30), (30 10), (0 0)))')\n    {'type': 'GeometryCollection', 'geometries': [{'type': 'Point', 'coordinates': [10.0, 20.0]}, {'type': 'Polygon', 'coordinates': [[[0.0, 0.0]], [[10.0, 30.0]], [[30.0, 10.0]], [[0.0, 0.0]]]}]}\n\n[EWKT/EWKB](http://postgis.net/documentation/manual-2.1/using_postgis_dbmanagement.html#EWKB_EWKT) \nare also supported for all geometry types. This uses a custom extension\nto the GeoJSON standard in order to preserve SRID information through conversions.\nFor example:\n\n    \u003e\u003e\u003e wkt.loads('SRID=4326;POINT(10 20)')\n    {'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}}\n    \u003e\u003e\u003e wkt.dumps({'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}, 'crs': {'properties': {'name': 'EPSG4326'}, 'type': 'name'}})\n    'SRID=4326;POINT (10.0000000000000000 20.0000000000000000)'\n    \u003e\u003e\u003e wkb.loads('\\x00 \\x00\\x00\\x01\\x00\\x00\\x10\\xe6@$\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00')\n    {'meta': {'srid': '4326'}, 'type': 'Point', 'coordinates': [10.0, 20.0]}\n    \u003e\u003e\u003e wkb.dumps({'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}, 'crs': {'properties': {'name': 'EPSG4326'}, 'type': 'name'}})\n    '\\x00 \\x00\\x00\\x01\\x00\\x00\\x10\\xe6@$\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00'\n\nGeoPackage binary supports encoding of SRID and envelope information. If your geopackage\nhas an envelope specified, then it will be added into the resulting GeoJSON in a key \ncalled `'bbox'`:\n\n    \u003e\u003e\u003e gpkg = b'GP\\x00\\x03\\x00\\x00\\x00\\x00\\xf0\\x9e\\xa0\\xa7\\x05;#@hZ\\xbd\\x93\\x83GC@\\xf0\\x9e\\xa0\\xa7\\x05;#@hZ\\xbd\\x93\\x83GC@\\x01\\x01\\x00\\x00\\x00\\xf0\\x9e\\xa0\\xa7\\x05;#@hZ\\xbd\\x93\\x83GC@'\n    \u003e\u003e\u003e geopackage.loads(gpkg)\n    \u003e\u003e\u003e {'type': 'Point', 'coordinates': [9.615277517659223, 38.55870291467437], 'bbox': (9.615277517659223, 38.55870291467437, 9.615277517659223, 38.55870291467437)}\n    \nIn the same way, if a 'bbox' key is present on a `dumps`-ed geometry, it will be added to the \nheader of the GeoPackage geometry:\n\n    \u003e\u003e\u003e polygon = {'type': 'Polygon', 'coordinates': [[[20.0, 20.0], [34.0, 124.0], [70.0, 140.0], [130.0, 130.0], [70.0, 100.0], [110.0, 70.0], [170.0, 20.0], [90.0, 10.0], [20.0, 20.0]]], 'bbox': (20.0, 170.0, 10.0, 140.0)}\n    \u003e\u003e\u003e geopackage.dumps(polygon)\n    b'GP\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004@\\x00\\x00\\x00\\x00\\x00@e@\\x00\\x00\\x00\\x00\\x00\\x00$@\\x00\\x00\\x00\\x00\\x00\\x80a@\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\t@4\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00@A\\x00\\x00\\x00\\x00\\x00\\x00@_\\x00\\x00\\x00\\x00\\x00\\x00@Q\\x80\\x00\\x00\\x00\\x00\\x00@a\\x80\\x00\\x00\\x00\\x00\\x00@`@\\x00\\x00\\x00\\x00\\x00@`@\\x00\\x00\\x00\\x00\\x00@Q\\x80\\x00\\x00\\x00\\x00\\x00@Y\\x00\\x00\\x00\\x00\\x00\\x00@[\\x80\\x00\\x00\\x00\\x00\\x00@Q\\x80\\x00\\x00\\x00\\x00\\x00@e@\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00@V\\x80\\x00\\x00\\x00\\x00\\x00@$\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00@4\\x00\\x00\\x00\\x00\\x00\\x00'\n\nIf an integer SRID identifier is present in a `'meta'` key (like `'meta': {'srid': 4326}`), then the SRID will be included in the\nGeoPackage header.\n\n## History\n\nThis library was originally created as the result of a bug report related\nto another project: https://bugs.launchpad.net/openquake-old/+bug/1073909.\nThe source of this issue was largely due to a dependency on\n[GEOS](https://libgeos.org/), which is written in C/C++. Depending on GEOS\nrequires any data conversion bug fixes to happen upstream, which takes time\nand effort. Ultimately, this was the inspiration to create a more\nlightweight, pure-Python conversion library as an alternative tool for\nreliably converting data between various geospatial formats.\n\nThe name \"GeoMet\" was inspired by \"met\", the German word for\n[mead](http://en.wikipedia.org/wiki/Mead). It is also a shortened version of\nthe word \"geometry\".\n\n## Limitations\n\n### Outputting \"empty\" geometries to binary formats is not supported\n\nAttempting to output an empty geometry to a binary format will result in an exception: `ValueError: Empty geometries cannot be represented in WKB. Reason: The dimensionality of the WKB would be ambiguous.` There are a few reasons for this limitation:\n- Any `EMTPY` geometry (e.g., `POINT EMPTY`, `MULTIPOLYGON EMPTY`, etc.) cannot be converted into binary format because binary formats such as WKB require an explicit dimension type (2d, Z, M, or ZM). This means that some objects cannot be reliably converted to and from different formats in a [bijective](https://en.wikipedia.org/wiki/Bijection) manner.\n- The [GeoJSON standard](https://www.rfc-editor.org/rfc/rfc7946) does have a way of representing empty geometries; however, details are minimal and the dimensionality of such an object remains ambiguous.\n- Representing some geometry types (such as points and lines) as \"empty\" is [deeply flawed to begin with](http://aleph0.clarku.edu/~djoyce/elements/bookI/defI1.html). For example, a point can represent any location in 2d, 3d, or 4d space. However, a point is infinitesimally small (it has no size) and it can't contain anything (it can't be \"full\"), therefore, it doesn't make sense for a point to be \"empty\".\n\nAs a result, GeoMet has chosen to not attempt to address these problems, and\nsimply raise an exception instead.\n\nExample:\n\n    \u003e\u003e\u003e import geomet\n    \u003e\u003e\u003e import geomet.wkt as wkt\n    \u003e\u003e\u003e import geomet.wkb as wkb\n    \u003e\u003e\u003e pt = wkt.loads('POINT EMPTY')\n    \u003e\u003e\u003e pt\n    {'type': 'Point', 'coordinates': []}\n    \u003e\u003e\u003e wkb.dumps(pt)\n    Traceback (most recent call last):\n    File \"\u003cstdin\u003e\", line 1, in \u003cmodule\u003e\n    File \"/home/jdoe/geomet/geomet/wkb.py\", line 216, in dumps\n        return _dumps(obj, big_endian)\n    File \"/home/jdoe/geomet/geomet/wkb.py\", line 238, in _dumps\n        raise ValueError(\n    ValueError: Empty geometries cannot be represented in WKB. Reason: The dimensionality of the WKB would be ambiguous.\n\n\n## See also\n\n- [wellknown](https://github.com/mapbox/wellknown): A similar package for Node.js.\n- [geo](https://github.com/bryanjos/geo): A nearly-identical package for Elixir.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeomet%2Fgeomet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeomet%2Fgeomet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeomet%2Fgeomet/lists"}