def loads(s): """ WKBGeometry { union { WKBPoint point; WKBLineString linestring; WKBPolygon polygon; WKBGeometryCollection collection; WKBMultiPoint mpoint; WKBMultiLineString mlinestring; WKBMultiPolygon mpolygon; } }; """ # To allow recursive calls, read only the bytes we need. if hasattr(s, 'read'): dat = s else: dat = StringIO(s) endian = ENDIAN[dat.read(1)] typ = struct.unpack('I', dat.read(4))[0] if typ == 1: """ WKBPoint { byte byteOrder; uint32 wkbType; 1 Point point; } Point { double x; double y; }; """ x, y = struct.unpack(endian + 'dd', dat.read(16)) return cg.Point((x, y)) elif typ == 2: """ WKBLineString { byte byteOrder; uint32 wkbType; 2 uint32 numPoints; Point points[numPoints]; } """ n = struct.unpack(endian + 'I', dat.read(4))[0] xy = struct.unpack(endian + '%dd' % (n * 2), dat.read(n * 2 * 8)) return cg.Chain([cg.Point(xy[i:i + 2]) for i in range(0, n * 2, 2)]) elif typ == 3: """ WKBPolygon { byte byteOrder; uint32 wkbType; 3 uint32 numRings; LinearRing rings[numRings]; } WKBPolygon has exactly 1 outer ring and n holes. multipart Polygons are NOT support by WKBPolygon. """ nrings = struct.unpack(endian + 'I', dat.read(4))[0] load_ring = load_ring_little if endian == '<' else load_ring_big rings = [load_ring(dat) for _ in range(nrings)] return cg.Polygon(rings[0], rings[1:]) elif typ == 4: """ WKBMultiPoint { byte byteOrder; uint32 wkbType; 4 uint32 num_wkbPoints; WKBPoint WKBPoints[num_wkbPoints]; } """ npts = struct.unpack(endian + 'I', dat.read(4))[0] return [loads(dat) for _ in range(npts)] elif typ == 5: """ WKBMultiLineString { byte byteOrder; uint32 wkbType; 5 uint32 num_wkbLineStrings; WKBLineString WKBLineStrings[num_wkbLineStrings]; } """ nparts = struct.unpack(endian + 'I', dat.read(4))[0] chains = [loads(dat) for _ in range(nparts)] return cg.Chain(sum([c.parts for c in chains], [])) elif typ == 6: """ wkbMultiPolygon { byte byteOrder; uint32 wkbType; 6 uint32 num_wkbPolygons; WKBPolygon wkbPolygons[num_wkbPolygons]; } """ npolys = struct.unpack(endian + 'I', dat.read(4))[0] polys = [loads(dat) for _ in range(npolys)] parts = sum([p.parts for p in polys], []) holes = sum([p.holes for p in polys if p.holes[0]], []) # MULTIPOLYGON EMPTY, isn't well supported by pysal shape types. if not parts: return None return cg.Polygon(parts, holes) elif typ == 7: """ WKBGeometryCollection { byte byte_order; uint32 wkbType; 7 uint32 num_wkbGeometries; WKBGeometry wkbGeometries[num_wkbGeometries] } """ ngeoms = struct.unpack(endian + 'I', dat.read(4))[0] return [loads(dat) for _ in range(ngeoms)] raise TypeError('Type (%d) is unknown or unsupported.' % typ)
def LineString(self, geoStr): points = geoStr.strip().split(',') points = map(self.Point, points) return cg.Chain(points)