from qgisrest.vectorformats.Feature import Feature from qgisrest.vectorformats.Formats.Format import Format try: import simplejson except ImportError: print "simplejson package is required..." try: import osgeo.ogr as ogr except ImportError: try: import ogr except ImportError: print "ogr >= 1.50 required..." import re, xml.dom.minidom as m class OGR(Format): ds = None driver = "Memory" dsname = "vectorformats_output" layername = "features" save_on_encode = False def encode(self, features): self.ds = ogr.GetDriverByName(self.driver).CreateDataSource(self.dsname) layer = self.ds.CreateLayer(self.layername) props = [] for feature in features: for prop, value in feature.properties.items(): if not prop: continue if prop not in props: props.append(prop) prop = str(prop) defn = ogr.FieldDefn(prop) defn.SetWidth(len(value)) layer.CreateField(defn) for feature in features: f = ogr.Feature(feature_def=layer.GetLayerDefn()) for prop, value in feature.properties.items(): prop = str(prop) if isinstance(value, unicode): value = value.encode("utf-8", "replace") f.SetField(prop, value) g = self.CreateGeometryFromJson(simplejson.dumps(feature.geometry)) f.SetGeometryDirectly(g) layer.CreateFeature(f) if self.save_on_encode: layer.SyncToDisk() return layer def decode(self, layer): features = [] layer.ResetReading() feature = layer.GetNextFeature() while feature: id = feature.GetFID() geometry = self.ExportToJson(feature.GetGeometryRef()) props = {} for i in range(feature.GetFieldCount()): props[feature.GetFieldDefnRef(i).GetName()] = feature.GetFieldAsString(i) features.append(Feature(id, geometry, props)) feature = layer.GetNextFeature() return features def CreateGeometryFromJson(self, input): try: input['type'] except TypeError: try: import simplejson except ImportError: raise ImportError, "You must have 'simplejson' installed to be able to use this functionality" input = simplejson.loads(input) types = { 'Point': ogr.wkbPoint, 'LineString': ogr.wkbLineString, 'Polygon': ogr.wkbPolygon, 'MultiPoint': ogr.wkbMultiPoint, 'MultiLineString': ogr.wkbMultiLineString, 'MultiPolygon': ogr.wkbMultiPolygon, 'GeometryCollection': ogr.wkbGeometryCollection } type = input['type'] gtype = types[type] geometry = ogr.Geometry(type=gtype) coordinates = input['coordinates'] if type == 'Point': geometry.AddPoint_2D(coordinates[0], coordinates[1]) elif type == 'MultiPoint': for point in coordinates: gring = ogr.Geometry(type=ogr.wkbPoint) gring.AddPoint_2D(point[0], point[1]) geometry.AddGeometry(gring) elif type == 'LineString': for coordinate in coordinates: geometry.AddPoint_2D(coordinate[0], coordinate[1]) elif type == 'MultiLineString': for ring in coordinates: gring = ogr.Geometry(type=ogr.wkbLineString) for coordinate in ring: gring.AddPoint_2D(coordinate[0], coordinate[1]) geometry.AddGeometry(gring) elif type == 'Polygon': for ring in coordinates: gring = ogr.Geometry(type=ogr.wkbLinearRing) for coordinate in ring: gring.AddPoint_2D(coordinate[0], coordinate[1]) geometry.AddGeometry(gring) elif type == 'MultiPolygon': for poly in coordinates: gpoly = ogr.Geometry(type=ogr.wkbPolygon) for ring in poly: gring = ogr.Geometry(type=wkbLinearRing) for coordinate in ring: gring.AddPoint_2D(coordinate[0], coordinate[1]) gpoly.AddGeometry(gring) geometry.AddGeometry(gpoly) return geometry def ExportToJson(self, geometry): def get_coordinates(geometry): gtype = geometry.GetGeometryType() geom_count = geometry.GetGeometryCount() coordinates = [] if gtype == ogr.wkbPoint or gtype == ogr.wkbPoint25D: return [geometry.GetX(0), geometry.GetY(0)] if gtype == ogr.wkbMultiPoint or gtype == ogr.wkbMultiPoint25D: geom_count = geometry.GetGeometryCount() for g in range(geom_count): geom = geometry.GetGeometryRef(g) coordinates.append(get_coordinates(geom)) return coordinates if gtype == ogr.wkbLineString or gtype == ogr.wkbLineString25D: points = [] point_count = geometry.GetPointCount() for i in range(point_count): points.append([geometry.GetX(i), geometry.GetY(i)]) return points if gtype == ogr.wkbMultiLineString or gtype == ogr.wkbMultiLineString25D: coordinates = [] geom_count = geometry.GetGeometryCount() for g in range(geom_count): geom = geometry.GetGeometryRef(g) coordinates.append(get_coordinates(geom)) return coordinates if gtype == ogr.wkbPolygon or gtype == ogr.wkbPolygon25D: geom = geometry.GetGeometryRef(0) coordinates = get_coordinates(geom) return [coordinates] if gtype == ogr.wkbMultiPolygon or gtype == ogr.wkbMultiPolygon25D: coordinates = [] geom_count = geometry.GetGeometryCount() for g in range(geom_count): geom = geometry.GetGeometryRef(g) coordinates.append(get_coordinates(geom)) return coordinates types = { ogr.wkbPoint:'Point', ogr.wkbLineString: 'LineString', ogr.wkbPolygon: 'Polygon', ogr.wkbMultiPoint: 'MultiPoint', ogr.wkbMultiLineString: 'MultiLineString', ogr.wkbMultiPolygon: 'MultiPolygon', ogr.wkbGeometryCollection: 'GeometryCollection' } output = {'type': types[geometry.GetGeometryType()], 'coordinates': get_coordinates(geometry)} return output