为什么 shapely/geos 可以解析这个“无效”的众所周知的二进制文件?

Ror*_*ory 3 gis specifications geospatial geos shapely

我正在尝试解析众所周知的二进制,这是地理信息系统(GIS)中使用的几何对象的二进制编码。我正在使用ESRI 的此规范(与 esri 的结果相同)。我有来自Osmosis的输入数据,这是一个解析 OpenStreetMap 数据的工具,特别是pgsimp-dump 格式,它给出了二进制文件的十六进制表示。

ESRI 文档说 a 应该只有 21 个字节Point,字节顺序为 1 个字节,typeid 为 uint32 为 4 个字节,double x 为 8 个字节,double y 为 8 个字节。

渗透的一个示例是这个(十六进制)示例:0101000020E6100000DB81DF2B5F7822C0DFBB7262B4744A40,其长度为 25 个字节。

Shapely是一个解析 WKB(等)的 python 程序,它基于流行的 C 库GEOS 能够解析这个字符串:

>>> import shapely.wkb
>>> shapely.wkb.loads("0101000020E6100000DB81DF2B5F7822C0DFBB7262B4744A40", hex=True)
<shapely.geometry.point.Point object at 0x7f221f2581d0>
Run Code Online (Sandbox Code Playgroud)

当我要求 Shapely 解析然后转换为 WKB 时,我得到 21 个字节。

>>> shapely.wkb.loads("0101000020E6100000DB81DF2B5F7822C0DFBB7262B4744A40", hex=True).wkb.encode("hex").upper()
'0101000000DB81DF2B5F7822C0DFBB7262B4744A40'
Run Code Online (Sandbox Code Playgroud)

区别在于中间的 4 个字节,对于 typeif=d 来说,在 uint32 中出现了 3 个字节

01010000**20E61000**00DB81DF2B5F7822C0DFBB7262B4744A40
Run Code Online (Sandbox Code Playgroud)

为什么 shapely/geos 可以在无效 WKB 的情况下解析该 WKB?这些字节是什么意思?

Mik*_*e T 6

GEOS / Shapely 使用 WKT/WKB 的扩展变体,称为 EWKT / EWKB,由 PostGIS记录。如果您有权访问 PostGIS,您可以看到这里发生了什么:

SELECT ST_AsEWKT('0101000020E6100000DB81DF2B5F7822C0DFBB7262B4744A40'::geometry);
Run Code Online (Sandbox Code Playgroud)

返回 EWKT SRID=4326;POINT(-9.2351011 52.9117549)。所以额外的数据就是空间参考标识符(SRID)。具体来说, WGS 84 的EPSG:4326

Shapely不支持 SRID,但是有一些技巧,例如:

from shapely import geos
geos.WKBWriter.defaults['include_srid'] = True
Run Code Online (Sandbox Code Playgroud)

现在应该生成wkbwkb_hex输出 EWKB,其中包括 SRID。默认值为False,它将输出 2D 几何图形的 ISO WKB(但不输出 3D 几何图形)。

所以看来您的目标是将 EWKB 转换为 ISO WKB,您只能使用 GEOS / Shapely 对于 2D 几何图形来完成此操作。如果您有 3D(Z 或 M)或 4D (ZM) 几何图形,则只有 PostGIS 能够执行此转换。