Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
 def LineString(self, geoStr):
     points = geoStr.strip().split(',')
     points = map(self.Point, points)
     return cg.Chain(points)