def test_loads_m(self): exp_pt = self.pt3d.copy() exp_pt['coordinates'].insert(2, 0.0) pt_wkb = b'\x00\x00\x00\x07\xd1' pt_wkb += self.pt3d_wkb[5:] self.assertEqual(exp_pt, wkb.loads(pt_wkb))
def test_loads_m(self): exp_gc = dict(type='GeometryCollection', geometries=[ dict(type='Point', coordinates=[0.0, 1.0, 0.0, 2.0]), dict(type='LineString', coordinates=[[102.0, 2.0, 0.0, 6.0], [103.0, 3.0, 0.0, 7.0], [104.0, 4.0, 0.0, 8.0]]), ]) gc_wkb = ( b'\x01' # little endian b'\xd7\x07\x00\x00' b'\x02\x00\x00\x00' # 2 geometries in the collection b'\x01' b'\xd1\x07\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x01' b'\xd2\x07\x00\x00' b'\x03\x00\x00\x00' # 3 vertices b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x18@' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x1c@' b'\x00\x00\x00\x00\x00\x00Z@' b'\x00\x00\x00\x00\x00\x00\x10@' b'\x00\x00\x00\x00\x00\x00 @') self.assertEqual(exp_gc, wkb.loads(gc_wkb))
def test_loads_m(self): exp_mp = self.multipoint3d.copy() for pt in exp_mp['coordinates']: pt.insert(2, 0.0) mp_wkb = ( b'\x01' # little endian b'\xd4\x07\x00\x00' # number of points: 3 b'\x03\x00\x00\x00' # point 3d b'\x01' # little endian b'\xd1\x07\x00\x00' b'\x9a\x99\x99\x99\x99\x99\x01@' # 2.2 b'\x9a\x99\x99\x99\x99\x99\x11@' # 4.4 b'\x00\x00\x00\x00\x00\x00\x08@' # 3.0 # point 3d b'\x01' # little endian b'\xd1\x07\x00\x00' b'\x00\x00\x00\x00\x00\x00$@' # 10.0 b'\xcd\xcc\xcc\xcc\xcc\xcc\x08@' # 3.1 b'\x00\x00\x00\x00\x00\x00\x00@' # 2.0 # point 3d b'\x01' # little endian b'\xd1\x07\x00\x00' b'ffffff\x14@' # 5.1 b'\x00\x00\x00\x00\x00\x004@' # 20.0 b'\x9a\x99\x99\x99\x99\x99\x11@' # 4.4 ) self.assertEqual(exp_mp, wkb.loads(mp_wkb))
def wkb_to_shape(wkb_element): """ Create a 2D Shapely shape from a WKB value. 3D and 4D geometries are turned into 2D geometries. """ assert (isinstance(wkb_element, WKBElement)) geometry = wkb.loads(bytes(wkb_element.data)) return shape(_force_2d(geometry))
def test_loads_m(self): exp_gc = dict(type='GeometryCollection', geometries=[ dict(type='Point', coordinates=[0.0, 1.0, 0.0, 2.0]), dict(type='LineString', coordinates=[ [102.0, 2.0, 0.0, 6.0], [103.0, 3.0, 0.0, 7.0], [104.0, 4.0, 0.0, 8.0] ]), ]) gc_wkb = ( b'\x01' # little endian b'\xd7\x07\x00\x00' b'\x02\x00\x00\x00' # 2 geometries in the collection b'\x01' b'\xd1\x07\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x01' b'\xd2\x07\x00\x00' b'\x03\x00\x00\x00' # 3 vertices b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x18@' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x1c@' b'\x00\x00\x00\x00\x00\x00Z@' b'\x00\x00\x00\x00\x00\x00\x10@' b'\x00\x00\x00\x00\x00\x00 @' ) self.assertEqual(exp_gc, wkb.loads(gc_wkb))
def bin_decode(self, value): try: return self.json_decode(self.schema.strip(wkb.loads(value))) except Exception as e: raise s.SchemaError( f"invalid WKB representation of {self.__class__.__name__}" ) from e
def wkb_to_shape(wkb_element): """ Create a 2D Shapely shape from a WKB value. 3D and 4D geometries are turned into 2D geometries. """ assert(isinstance(wkb_element, WKBElement)) geometry = wkb.loads(bytes(wkb_element.data)) return shape(_force_2d(geometry))
def test_loads_m(self): exp_mls = self.mls3d.copy() for ls in exp_mls['coordinates']: for vert in ls: vert.insert(2, 0.0) mls_wkb = ( b'\x00' b'\x00\x00\x07\xd5' b'\x00\x00\x00\x02' # number of linestrings b'\x00' b'\x00\x00\x07\xd2' b'\x00\x00\x00\x03' b'@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 b'\x00\x00\x00\x00\x00\x00\x00\x00' # 0.0 b'@\x11\x99\x99\x99\x99\x99\x9a' # 4.4 b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd' # 3.1 b'@\x14ffffff' # 5.1 b'@\x14ffffff' # 5.1 b'@\x14ffffff' # 5.1 b'@4\x00\x00\x00\x00\x00\x00' # 20.0 b'\x00\x00\x00\x00\x00\x00\x00\x00' # 0.0 b'\x00' b'\x00\x00\x07\xd2' b'\x00\x00\x00\x02' b'@4\x00\x00\x00\x00\x00\x00' # 20.0 b'@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 b'@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 b'\x00\x00\x00\x00\x00\x00\x00\x00' # 0.0 b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd' # 3.1 b'@\x11\x99\x99\x99\x99\x99\x9a' # 4.4 ) self.assertEqual(exp_mls, wkb.loads(mls_wkb))
def test_loads_m(self): exp_ls = self.ls3d.copy() for vert in exp_ls['coordinates']: vert.insert(2, 0.0) ls_wkb = b'\x01\xd2\x07\x00\x00' ls_wkb += self.ls3d_wkb[5:] self.assertEqual(exp_ls, wkb.loads(ls_wkb))
def decode_wkb(geom: bytes) -> dict: """ Convert the given WKB geometry to GeoJSON. :param geom: the WKB geometry bytes. :return: the corresponding GeoJSON. """ return wkb.loads(geom)
def test_z(self): pt = ( b'\x00' # big endian b'\x00\x00\x10\x01' # type b'@\x01\x99\x99\x99\x99\x99\x9a' b'@\x11\x99\x99\x99\x99\x99\x9a' b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd') expected = dict(type='Point', coordinates=[2.2, 4.4, 3.1]) self.assertEqual(expected, wkb.loads(pt))
def test_loads_m(self): exp_poly = self.poly3d.copy() for ring in exp_poly['coordinates']: for vert in ring: vert.insert(2, 0.0) poly_wkb = b'\x00\x00\x00\x07\xd3' poly_wkb += self.poly3d_wkb[5:] poly_wkb = bytes(poly_wkb) self.assertEqual(exp_poly, wkb.loads(poly_wkb))
def test_2d(self): pt = ( '\x01' # little endian '\x01\x00\x00\x00' # type '\x00\x00\x00\x00\x00\x00\x00\x00' # 0.0 '\x00\x00\x00\x00\x00\x00\xf0?' # 1.0 ) expected = dict(type='Point', coordinates=[0.0, 1.0]) self.assertEqual(expected, wkb.loads(pt))
def test_z(self): pt = ( '\x00' # big endian '\x00\x00\x10\x01' # type '@\x01\x99\x99\x99\x99\x99\x9a' '@\x11\x99\x99\x99\x99\x99\x9a' '@\x08\xcc\xcc\xcc\xcc\xcc\xcd' ) expected = dict(type='Point', coordinates=[2.2, 4.4, 3.1]) self.assertEqual(expected, wkb.loads(pt))
def test_2d(self): pt = ( b'\x01' # little endian b'\x01\x00\x00\x00' # type b'\x00\x00\x00\x00\x00\x00\x00\x00' # 0.0 b'\x00\x00\x00\x00\x00\x00\xf0?' # 1.0 ) expected = dict(type='Point', coordinates=[0.0, 1.0]) self.assertEqual(expected, wkb.loads(pt))
def loads(string): """ Construct a GeoJSON `dict` from geopackage (string). This function strips the geopackage header from the string and passes the remaining WKB geometry to the `geomet.wkb.loads` function. The envelope, if present, is added to the GeoJSON as a key called 'bbox' as per the GeoJSON spec, [1]. If an SRID is specified in the geopackage header AND the wkb header, the SRID in the geopackage header will take precedence and will replace that SRID in the returned dict. [1] https://tools.ietf.org/html/rfc7946#section-5 :param bytes string: geopackage byte string. :return dict: GeoJSON represented the parsed geopackage binary. """ string = iter(string) header = _as_bin_str(_take(_GeoPackage.HEADER_LEN, string)) _check_is_valid(header) g, p, version, empty, envelope_indicator, is_little_endian, srid = ( _parse_header(header) ) wkb_offset = _get_wkb_offset(envelope_indicator) left_to_take = (wkb_offset - _GeoPackage.HEADER_LEN) envelope_data = _as_bin_str(_take(left_to_take, string)) if envelope_data: envelope = _parse_envelope( envelope_indicator, envelope_data, is_little_endian ) result = _wkb.loads(string) if srid: result['meta'] = {'srid': int(srid)} result['crs'] = { 'type': 'name', 'properties': {'name': 'EPSG%s' % srid}, } if envelope_data: result['bbox'] = envelope return result
def test_zm(self): pt = ( b'\x00' # big endian b'\x00\x00\x30\x01' # type b'@\x01\x99\x99\x99\x99\x99\x9a' b'@\x11\x99\x99\x99\x99\x99\x9a' b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd' b'\x00\x00\x00\x00\x00\x00\x00\x00' ) expected = dict(type='Point', coordinates=[2.2, 4.4, 3.1, 0.0]) self.assertEqual(expected, wkb.loads(pt))
def test_m(self): pt = ( b'\x00' # big endian b'\x00\x00\x20\x01' # type b'@\x01\x99\x99\x99\x99\x99\x9a' b'@\x11\x99\x99\x99\x99\x99\x9a' b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd') # The generated GeoJSON is treated as XYZM, sidestep the ambiguity # created by XYM and XYZ geometries. The default value for Z is set to # 0.0. expected = dict(type='Point', coordinates=[2.2, 4.4, 0.0, 3.1]) self.assertEqual(expected, wkb.loads(pt))
def _get_gjson(self, tablename, geom_column="GEOMETRY"): gjson = {"type": "FeatureCollection", "features": []} for row in self.session.query(self.metadata.tables[tablename]): feat = {"type": "Feature", "geometry": {}, "properties": {}} feat["GEOMETRY"] = wkb.loads(getattr(row, geom_column)) attributes = row._asdict() attributes.pop(geom_column, None) feat["properties"] = attributes gjson["features"].append(feat) return gjson
def test_2d(self): linestring = ( b'\x00' # big endian b'\x00\x00\x00\x02' b'@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 b'@\x11\x99\x99\x99\x99\x99\x9a' # 4.4 b'@\x08\xcc\xcc\xcc\xcc\xcc\xcd' # 3.1 b'@\x14ffffff' # 5.1 ) expected = dict(type='LineString', coordinates=[[2.2, 4.4], [3.1, 5.1]]) self.assertEqual(expected, wkb.loads(linestring))
def test_2d(self): linestring = ( '\x00' # big endian '\x00\x00\x00\x02' '@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 '@\x11\x99\x99\x99\x99\x99\x9a' # 4.4 '@\x08\xcc\xcc\xcc\xcc\xcc\xcd' # 3.1 '@\x14ffffff' # 5.1 ) expected = dict(type='LineString', coordinates=[[2.2, 4.4], [3.1, 5.1]]) self.assertEqual(expected, wkb.loads(linestring))
def test_m(self): pt = ( '\x00' # big endian '\x00\x00\x20\x01' # type '@\x01\x99\x99\x99\x99\x99\x9a' '@\x11\x99\x99\x99\x99\x99\x9a' '@\x08\xcc\xcc\xcc\xcc\xcc\xcd' ) # The generated GeoJSON is treated as XYZM, sidestep the ambiguity # created by XYM and XYZ geometries. The default value for Z is set to # 0.0. expected = dict(type='Point', coordinates=[2.2, 4.4, 0.0, 3.1]) self.assertEqual(expected, wkb.loads(pt))
def test_m(self): linestring = ( '\x01' # little endian '\x02\x20\x00\x00' '\x9a\x99\x99\x99\x99\x99\x01@' # 2.2 '\x9a\x99\x99\x99\x99\x99\x11@' # 4.4 '\x00\x00\x00\x00\x00\x00$@' # 10.0 '\xcd\xcc\xcc\xcc\xcc\xcc\x08@' # 3.1 'ffffff\x14@' # 5.1 '\x00\x00\x00\x00\x00\x004@' # 20.0 ) expected = dict(type='LineString', coordinates=[[2.2, 4.4, 0.0, 10.0], [3.1, 5.1, 0.0, 20.0]]) self.assertEqual(expected, wkb.loads(linestring))
def test_z(self): linestring = ( b'\x01' # little endian b'\x02\x10\x00\x00' b'\x9a\x99\x99\x99\x99\x99\x01@' # 2.2 b'\x9a\x99\x99\x99\x99\x99\x11@' # 4.4 b'\x00\x00\x00\x00\x00\x00$@' # 10.0 b'\xcd\xcc\xcc\xcc\xcc\xcc\x08@' # 3.1 b'ffffff\x14@' # 5.1 b'\x00\x00\x00\x00\x00\x004@' # 20.0 ) expected = dict(type='LineString', coordinates=[[2.2, 4.4, 10.0], [3.1, 5.1, 20.0]]) self.assertEqual(expected, wkb.loads(linestring))
def _get_gjson(self, tablename, geom_column="GEOMETRY"): gjson = { "type": "FeatureCollection", "features": []} for row in self.session.query(self.metadata.tables[tablename]): feat = {"type": "Feature", "geometry": {}, "properties":{}} feat["GEOMETRY"] = wkb.loads(getattr(row,geom_column)) attributes = row._asdict() attributes.pop(geom_column, None) feat["properties"] = attributes gjson["features"].append(feat) return gjson
def test_zm(self): linestring = ( '\x00' # big endian '\x00\x00\x30\x02' '@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 '\xc0\x11\x99\x99\x99\x99\x99\x9a' # -4.4 '\xc0$\x00\x00\x00\x00\x00\x00' # -10.0 '?\xb9\x99\x99\x99\x99\x99\x9a' # 0.1 '\xc0\x08\xcc\xcc\xcc\xcc\xcc\xcd' # -3.1 '@\x14ffffff' # 5.1 '@4\x00\x00\x00\x00\x00\x00' # 20.0 '\xbf\xec\xcc\xcc\xcc\xcc\xcc\xcd' # -0.9 ) expected = dict(type='LineString', coordinates=[[2.2, -4.4, -10.0, 0.1], [-3.1, 5.1, 20.0, -0.9]]) self.assertEqual(expected, wkb.loads(linestring))
def test_zm(self): linestring = ( b'\x00' # big endian b'\x00\x00\x30\x02' b'@\x01\x99\x99\x99\x99\x99\x9a' # 2.2 b'\xc0\x11\x99\x99\x99\x99\x99\x9a' # -4.4 b'\xc0$\x00\x00\x00\x00\x00\x00' # -10.0 b'?\xb9\x99\x99\x99\x99\x99\x9a' # 0.1 b'\xc0\x08\xcc\xcc\xcc\xcc\xcc\xcd' # -3.1 b'@\x14ffffff' # 5.1 b'@4\x00\x00\x00\x00\x00\x00' # 20.0 b'\xbf\xec\xcc\xcc\xcc\xcc\xcc\xcd' # -0.9 ) expected = dict(type='LineString', coordinates=[[2.2, -4.4, -10.0, 0.1], [-3.1, 5.1, 20.0, -0.9]]) self.assertEqual(expected, wkb.loads(linestring))
def translate(text, output_format='json', indent=None, precision=-1): if text.startswith('{'): geom = json.loads(text) elif text.startswith(('G', 'L', 'M', 'P')): geom = wkt.loads(text) else: geom = wkb.loads(a2b_hex(text)) if output_format == 'wkb': output = b2a_hex(wkb.dumps(geom)) elif output_format == 'wkt': kwds = {} if precision >= 0: kwds['decimals'] = precision output = wkt.dumps(geom, **kwds) else: if precision >= 0: geom = util.round_geom(geom, precision) output = json.dumps(geom, indent=indent, sort_keys=True) return output
def test_loads_z(self): self.assertEqual(self.pt3d, wkb.loads(self.pt3d_wkb))
def test_loads_m(self): exp_mpoly = self.mpoly3d.copy() for polygon in exp_mpoly['coordinates']: for ring in polygon: for vert in ring: vert.insert(2, 0.0) mpoly_wkb = ( b'\x01' # little endian b'\xd6\x07\x00\x00' # m multipolygon b'\x02\x00\x00\x00' # two polygons b'\x01' # little endian b'\xd3\x07\x00\x00' # m polygon b'\x01\x00\x00\x00' # 1 ring b'\x05\x00\x00\x00' # 5 vertices b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x10@' b'\x01' # little endian b'\xd3\x07\x00\x00' # m polygon b'\x02\x00\x00\x00' # 2 rings b'\x05\x00\x00\x00' # first ring, 5 vertices b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x14@' b'\x00\x00\x00\x00\x00@Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x18@' b'\x00\x00\x00\x00\x00@Y@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00\x1c@' b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00 @' b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00"@' b'\x05\x00\x00\x00' # second ring, 5 vertices b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00$@' b'333333Y@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00&@' b'333333Y@' b'\x9a\x99\x99\x99\x99\x99\xe9?' b'\x00\x00\x00\x00\x00\x00(@' b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xe9?' b'\x00\x00\x00\x00\x00\x00*@' b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00,@') self.assertEqual(exp_mpoly, wkb.loads(mpoly_wkb))
def test_loads_2d(self): self.assertEqual(self.pt2d, wkb.loads(self.pt2d_wkb))
def geojson_from_wkbelement(wkb_element): geometry = wkb.loads(bytes(wkb_element.data)) return geojson.dumps(geometry)
def test_loads_zm(self): self.assertEqual(self.mpoly4d, wkb.loads(self.mpoly4d_wkb))
def test_loads_zm(self): self.assertEqual(self.multipoint4d, wkb.loads(self.multipoint4d_wkb))
def test_loads_2d(self): self.assertEqual(self.multipoint2d, wkb.loads(self.multipoint2d_wkb))
def _load_feature(self, data: bytes) -> Feature: feature = cbor2.loads(zlib.decompress(data)) feature["geometry"] = wkb.loads(feature["geometry"]) return self._construct_feature(feature)
def test_loads_m(self): exp_mpoly = self.mpoly3d.copy() for polygon in exp_mpoly['coordinates']: for ring in polygon: for vert in ring: vert.insert(2, 0.0) mpoly_wkb = ( b'\x01' # little endian b'\xd6\x07\x00\x00' # m multipolygon b'\x02\x00\x00\x00' # two polygons b'\x01' # little endian b'\xd3\x07\x00\x00' # m polygon b'\x01\x00\x00\x00' # 1 ring b'\x05\x00\x00\x00' # 5 vertices b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\xc0Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x00\x08@' b'\x00\x00\x00\x00\x00\x80Y@' b'\x00\x00\x00\x00\x00\x00\x00@' b'\x00\x00\x00\x00\x00\x00\x10@' b'\x01' # little endian b'\xd3\x07\x00\x00' # m polygon b'\x02\x00\x00\x00' # 2 rings b'\x05\x00\x00\x00' # first ring, 5 vertices b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x14@' b'\x00\x00\x00\x00\x00@Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x18@' b'\x00\x00\x00\x00\x00@Y@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00\x1c@' b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\xf0?' b'\x00\x00\x00\x00\x00\x00 @' b'\x00\x00\x00\x00\x00\x00Y@' b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00"@' b'\x05\x00\x00\x00' # second ring, 5 vertices b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00$@' b'333333Y@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00&@' b'333333Y@' b'\x9a\x99\x99\x99\x99\x99\xe9?' b'\x00\x00\x00\x00\x00\x00(@' b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xe9?' b'\x00\x00\x00\x00\x00\x00*@' b'\xcd\xcc\xcc\xcc\xcc\x0cY@' b'\x9a\x99\x99\x99\x99\x99\xc9?' b'\x00\x00\x00\x00\x00\x00,@' ) self.assertEqual(exp_mpoly, wkb.loads(mpoly_wkb))