[GIS] Conversion of a GeoJSON into EWKB format

pythonshapelywell-known-binary

I see libraries such as shape from shapely.geometry that support conversion to WKB and WKT binaries. What I am unable to find is guidance on converting to EWKB specifically.

I suspect this is because libraries that support WKB conversion also support EWKB? How do I know if I am creating an EWKB vs WKB? Are all WKB also EWKB (but not the other way around)?

If EWKB is an extension of WKB, how would I check that, say, Shapely, supports EWKB format?

I am trying to understand if EWKB is standard or something that was just built for PostGIS (where I have seen it used) and how I can make sure that data I am producing for a function that expects EWKB can be correctly formatted.

Because of @shongololo's comment, I wanted to add a snippet of what I am going presently to generate the WKB of the shape from GeoJSON.

from shapely.geometry import shape
import binascii
# convert geom to wkb format
geom_str = json.dumps(route['geometry'])
geom_geo = geojson.loads(geom_str)
geom_shp = shape(geom_geo)
geom_wkb = geom_shp.to_wkb()
geom_cln = binascii.hexlify(geom_wkb).decode('ascii')

Best Answer

Shapely is based on GEOS, which natively reads/writes EWKB. The Z-dimension support of EWKB (different from ISO) is well supported by GEOS/Shapely, but getting/setting SRIDs is a hidden feature. Here's a quick demo:

from shapely import geos, wkb, wkt

# Show EWKB
p = wkt.loads('POINT Z(1 2 3)')
print(p.wkb_hex)  # This is little endian EWKB with just PointZ bit set
# 0101000080000000000000F03F00000000000000400000000000000840

# Change a the default mode to add this, if SRID is set
geos.WKBWriter.defaults['include_srid'] = True

# Get/Set SRID
print(geos.lgeos.GEOSGetSRID(p._geom))  # 0, or unset
# Set it to EPSG:4326
geos.lgeos.GEOSSetSRID(p._geom, 4326)
print(p.wkb_hex)  # This is little endian EWKB with SRID and PointZ bit set
# 01010000A0E6100000000000000000F03F00000000000000400000000000000840

# And for fun, change the output to big endian
geos.WKBWriter.defaults['big_endian'] = True
print(p.wkb_hex)
# 00A0000001000010E63FF000000000000040000000000000004008000000000000

Note that if SRID is not used and the geometries are simple 2D, then ISO WKB and EWKB are the same.