跳转到主要内容

纯Python转换库,用于常见的地理空间数据格式

项目描述

GeoMet geomet

纯Python转换库,用于常见的地理空间数据格式。支持的格式包括

安装

PyPI安装最新版本

$ pip install geomet

功能

通过惯用的 load/loads/dump/dumps 接口公开转换函数。

GeoMet旨在涵盖处理2D、3D和4D几何形状(包括'Z'、'M'和'ZM')的所有常见用例。

几何形状 WKT/EWKT WKB/EWKB GeoPackage二进制 EsriJSON
线字符串
多边形
多点
多线字符串
多边形
几何形状集合

示例用法

将'点'GeoJSON对象转换为WKT

>>> from geomet import wkt
>>> point = {'type': 'Point', 'coordinates': [116.4, 45.2, 11.1]}
>>> wkt.dumps(point, decimals=4)
'POINT (116.4000 45.2000 11.1000)'

将'点'GeoJSON对象转换为WKB

>>> from geomet import wkb
>>> wkb.dumps(point)
b'\x00\x00\x00\x10\x01@]\x19\x99\x99\x99\x99\x9a@F\x99\x99\x99\x99\x99\x9a@&333333'
>>> wkb.dumps(point, big_endian=False)
b'\x01\x01\x10\x00\x00\x9a\x99\x99\x99\x99\x19]@\x9a\x99\x99\x99\x99\x99F@333333&@'

将'点'GeoJSON对象转换为GeoPackage二进制

>>> from geomet import geopackage
>>> geopackage.dumps(point)
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@&333333'
>>> geopackage.dumps(point, big_endian=False)
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&@'

将'线字符串'GeoJSON对象转换为WKT

>>> linestring = {'type':'LineString',
...               'coordinates': [[0.0, 0.0, 10.0], [2.0, 1.0, 20.0],
...                               [4.0, 2.0, 30.0], [5.0, 4.0, 40.0]]}
>>> wkt.dumps(linestring, decimals=0)
'LINESTRING (0 0 10, 2 1 20, 4 2 30, 5 4 40)'

将 'LineString' GeoJSON 对象转换为 WKB

>>> wkb.dumps(linestring)
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@>\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'
>>> wkb.dumps(linestring, big_endian=False)
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>@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00D@'

将 'LineString' GeoJSON 对象转换为 GeoPackage 二进制格式

>>> geopackage.dumps(linestring)
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@>\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'
>>> geopackage.dumps(linestring, big_endian=False)
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>@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00D@'

将 'Point' WKT 转换为 GeoJSON

>>> wkt.loads('POINT(10 20)')
{'type': 'Point', 'coordinates': [10.0, 20.0]}

将 'GeometryCollection' WKT 转换为 GeoJSON

>>> wkt.loads('GEOMETRYCOLLECTION(POINT(10 20),POLYGON(((0 0), (10 30), (30 10), (0 0)))')
{'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]]]}]}

EWKT/EWKB 也支持所有几何类型。这使用 GeoJSON 标准的扩展来通过转换保留 SRID 信息。例如

>>> wkt.loads('SRID=4326;POINT(10 20)')
{'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}}
>>> wkt.dumps({'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}, 'crs': {'properties': {'name': 'EPSG4326'}, 'type': 'name'}})
'SRID=4326;POINT (10.0000000000000000 20.0000000000000000)'
>>> wkb.loads('\x00 \x00\x00\x01\x00\x00\x10\xe6@$\x00\x00\x00\x00\x00\x00@4\x00\x00\x00\x00\x00\x00')
{'meta': {'srid': '4326'}, 'type': 'Point', 'coordinates': [10.0, 20.0]}
>>> wkb.dumps({'type': 'Point', 'coordinates': [10.0, 20.0], 'meta': {'srid': '4326'}, 'crs': {'properties': {'name': 'EPSG4326'}, 'type': 'name'}})
'\x00 \x00\x00\x01\x00\x00\x10\xe6@$\x00\x00\x00\x00\x00\x00@4\x00\x00\x00\x00\x00\x00'

GeoPackage 二进制格式支持编码 SRID 和边界框信息。如果您的 GeoPackage 中指定了边界框,则它将被添加到结果 GeoJSON 的 'bbox' 键中

>>> 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@'
>>> geopackage.loads(gpkg)
>>> {'type': 'Point', 'coordinates': [9.615277517659223, 38.55870291467437], 'bbox': (9.615277517659223, 38.55870291467437, 9.615277517659223, 38.55870291467437)}

同样地,如果 dumps-ed 几何对象上存在 'bbox' 键,它将被添加到 GeoPackage 几何对象的头部

>>> 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)}
>>> geopackage.dumps(polygon)
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'

如果 'meta' 键(例如 'meta': {'srid': 4326})中存在整数 SRID 标识符,则 SRID 将包含在 GeoPackage 头部。

历史

这个库最初是在与另一个项目的错误报告有关的情况下创建的:[https://bugs.launchpad.net/openquake-old/+bug/1073909](https://bugs.launchpad.net/openquake-old/+bug/1073909)。这个问题的主要原因是依赖于 [https://libgeos.org/](https://libgeos.org/),这是一个用 C/C++ 编写的库。依赖于 GEOS 需要任何数据转换错误修复都在上游发生,这需要时间和精力。最终,这成为了创建一个更轻量级、纯 Python 转换库的灵感,作为在各种地理空间格式之间可靠转换数据的替代工具。

“GeoMet” 这个名字是受德语中 蜂蜜 这个词“mead”的启发。它也是“geometry”这个词的缩写。

限制

不支持输出到二进制格式的“空”几何体

尝试将空几何体输出到二进制格式将引发异常:ValueError: Empty geometries cannot be represented in WKB. Reason: The dimensionality of the WKB would be ambiguous. 这个限制有几个原因

  • 任何 EMPTY 几何体(例如,POINT EMPTYMULTIPOLYGON EMPTY 等)都不能转换为二进制格式,因为 WKB 等二进制格式需要显式的维度类型(2d,Z,M 或 ZM)。这意味着某些对象无法以 双射 方式从一种格式可靠地转换为另一种格式。
  • GeoJSON 标准 有一种表示空几何体的方法;然而,细节很少,此类对象的维度仍然是模糊的。
  • 将某些几何类型(如点和线)表示为“空”本身就有严重缺陷。[http://aleph0.clarku.edu/~djoyce/elements/bookI/defI1.html](http://aleph0.clarku.edu/~djoyce/elements/bookI/defI1.html)。例如,一个点可以表示 2d、3d 或 4d 空间中的任何位置。然而,点无穷小(它没有大小),它不能包含任何东西(它不能是“满的”),因此,点“空”没有意义。

因此,GeoMet 选择不尝试解决这个问题,而是引发异常。

示例

>>> import geomet
>>> import geomet.wkt as wkt
>>> import geomet.wkb as wkb
>>> pt = wkt.loads('POINT EMPTY')
>>> pt
{'type': 'Point', 'coordinates': []}
>>> wkb.dumps(pt)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jdoe/geomet/geomet/wkb.py", line 216, in dumps
    return _dumps(obj, big_endian)
File "/home/jdoe/geomet/geomet/wkb.py", line 238, in _dumps
    raise ValueError(
ValueError: Empty geometries cannot be represented in WKB. Reason: The dimensionality of the WKB would be ambiguous.

另请参阅

  • wellknown:Node.js 的类似包。
  • geo:Elixir 的几乎相同的包。

项目详细信息


下载文件

下载适用于您平台上的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源代码分发

geomet-1.1.0.tar.gz (28.7 kB 查看哈希值)

上传时间 源代码

构建分发

geomet-1.1.0-py3-none-any.whl (31.5 kB 查看哈希值)

上传时间 Python 3