def as_ogr_layer(self, name, sr): sql = """ select ST_AsBinary(ST_Force2D({geom_column})), {name} from {schema}.{table} where {geom_column} && ST_GeometryFromText('{box}') """.format(name=name, schema=self.schema, table=self.table, box=self.box, geom_column=self.geom_column) cursor = self.connection.cursor() cursor.execute(sql) data_source = DRIVER_OGR_MEMORY.CreateDataSource('') layer = data_source.CreateLayer(str(''), sr) layer.CreateField(ogr.FieldDefn(str(name), ogr.OFTInteger)) layer_defn = layer.GetLayerDefn() for wkb, value in cursor: feature = ogr.Feature(layer_defn) feature[str(name)] = value try: feature.SetGeometry(ogr.CreateGeometryFromWkb(str(wkb))) except RuntimeError: pass layer.CreateFeature(feature) return data_source, layer
def get_ogr_data_source(self, geometry): """ Return geometry wrapped as ogr data source. """ data_source = DRIVER_OGR_MEM.CreateDataSource('') layer = data_source.CreateLayer(str(''), self.sr) layer_defn = layer.GetLayerDefn() feature = ogr.Feature(layer_defn) feature.SetGeometry(geometry) layer.CreateFeature(feature) return data_source
def rasterize_region(self, index_feature): # prepare or abort path = self.path(index_feature) if exists(path): return # target array target_dataset = self.create_target_dataset(index_feature) # fetch geometries from postgis data_source = self.postgis_source.get_data_source( table=self.table, geometry=index_feature.geometry(), ) source_layer = data_source[0] # create a second layer for the succesfully determined geometries sr = source_layer.GetSpatialRef() target_layer = data_source.CreateLayer('target', srs=sr) # add a column for the floor level field_defn = ogr.FieldDefn(FLOOR_ATTRIBUTE, ogr.OFTReal) target_layer.CreateField(field_defn) target_layer_defn = target_layer.GetLayerDefn() # compute floor levels any_computed = False feature_count = source_layer.GetFeatureCount() for i in range(feature_count): bag_feature = source_layer[i] floor_level = self.determine_floor_level(feature=bag_feature) if floor_level is not None: target_feature = ogr.Feature(target_layer_defn) target_feature.SetGeometry(bag_feature.geometry()) target_feature[FLOOR_ATTRIBUTE] = floor_level target_layer.CreateFeature(target_feature) any_computed = True # do not write an empty geotiff if not any_computed: return # rasterize options = ['attribute=%s' % FLOOR_ATTRIBUTE] gdal.RasterizeLayer(target_dataset, [1], target_layer, options=options) # save options = ['compress=deflate'] os.makedirs(dirname(path), exist_ok=True) DRIVER_GDAL_GTIFF.CreateCopy(path, target_dataset, options=options)
def _add_feature(self, feature): """ Add converted feature. """ # create feature layer_definition = self.layer.GetLayerDefn() new_feature = ogr.Feature(layer_definition) # copy attributes for key, value in feature.items().items(): new_feature[key] = value # set geometry and add to layer geometry = self._convert(source_geometry=feature.geometry()) new_feature.SetGeometry(geometry) self.layer.CreateFeature(new_feature)
def burn_value(dataset, geometry, value): """ Burn value where geometry is into dataset. """ sr = geometry.GetSpatialReference() # put geometry into temporary layer datasource = DRIVER_OGR_MEMORY.CreateDataSource('') layer = datasource.CreateLayer(str(''), sr) layer_defn = layer.GetLayerDefn() feature = ogr.Feature(layer_defn) feature.SetGeometry(geometry) layer.CreateFeature(feature) # burn no data burn_values = [value] gdal.RasterizeLayer(dataset, [1], layer, burn_values=burn_values)
def _add_feature(self, feature_id, feature): """ Add converted features. """ layer_definition = self.layer.GetLayerDefn() segments = self._convert(source_geometry=feature.geometry()) for geometry, elevation in segments: # create feature new_feature = ogr.Feature(layer_definition) # copy attributes for key, value in feature.items().items(): new_feature[key] = value # add special attributes new_feature[str(self.elevation_attribute)] = elevation new_feature[str(self.feature_id_attribute)] = feature_id # set geometry and add to layer new_feature.SetGeometry(geometry) self.layer.CreateFeature(new_feature)
def clip(kwargs, geometry): """ Clip kwargs in place. """ # do not touch original kwargs kwargs = kwargs.copy() array = kwargs.pop('array') mask = np.ones_like(array, 'u1') # create an ogr datasource source = MEM_DRIVER.CreateDataSource('') layer = source.CreateLayer(str(''), SR) defn = layer.GetLayerDefn() feature = ogr.Feature(defn) feature.SetGeometry(geometry) layer.CreateFeature(feature) # clip with datasets.Dataset(mask, **kwargs) as dataset: gdal.RasterizeLayer(dataset, [1], layer, burn_values=[0]) # alter array with result array[mask.astype('b1')] = NO_DATA_VALUE
def vectorize(self, index_feature): # target path name = index_feature[str('name')] path = os.path.join(self.target_path, name[:3], '{}'.format(name)) if os.path.exists(path): return # create directory try: os.makedirs(os.path.dirname(path)) except OSError: pass # no problem index_geometry = index_feature.geometry() geo_transform = self.geo_transform.shifted(index_geometry) # data with one pixel margin on all sides indices = self.geo_transform.get_indices(index_geometry) indices = (indices[0] - 1, indices[1] - 1, indices[2] + 1, indices[3] + 1) direction = self.direction_group.read(indices) accumulation = self.accumulation_group.read(indices) # processing data_source = SHAPE.CreateDataSource(str(path)) layer_sr = osr.SpatialReference(self.projection) layer_name = str(os.path.basename(path)) layer = data_source.CreateLayer(layer_name, layer_sr) layer.CreateField(ogr.FieldDefn(str('class'), ogr.OFTReal)) layer_defn = layer.GetLayerDefn() generator = vectorize(direction=direction, accumulation=accumulation) for klass, indices in generator: feature = ogr.Feature(layer_defn) points = geo_transform.get_coordinates(indices) feature[str('class')] = klass geometry = ogr.Geometry(ogr.wkbLineString) for p in zip(*points): geometry.AddPoint_2D(*p) feature.SetGeometry(geometry) layer.CreateFeature(feature)
def reindex(source_path, target_path, size): source_data_source = ogr.Open(source_path) source_layer = source_data_source[0] sr = source_layer.GetSpatialRef() checker = Checker(source_layer) extent = source_layer.GetExtent() target_data_source = driver.CreateDataSource(target_path) target_layer_name = os.path.basename(target_path) target_layer = target_data_source.CreateLayer(target_layer_name, sr) target_layer.CreateField(ogr.FieldDefn(str('name'), ogr.OFTString)) target_layer_defn = target_layer.GetLayerDefn() xcorners = range(int(extent[0]), int(extent[2]), size) ycorners = range(int(extent[3]), int(extent[1]), -size) total = len(ycorners) chars = string.ascii_lowercase ogr.TermProgress_nocb(0) for m, y in enumerate(ycorners): for n, x in enumerate(xcorners): x1, y1, x2, y2 = x, y - size, x + size, y feature = ogr.Feature(target_layer_defn) xname = (chars[n // (26 * 26)] + chars[(n // 26) % 26] + chars[n % 26] + '{:04.0f}'.format(n)) feature[str('name')] = xname ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint_2D(x1, y1) ring.AddPoint_2D(x2, y1) ring.AddPoint_2D(x2, y2) ring.AddPoint_2D(x1, y2) ring.AddPoint_2D(x1, y1) geometry = ogr.Geometry(ogr.wkbPolygon) geometry.AddGeometry(ring) if not checker.intersects(geometry): continue geometry.AssignSpatialReference(sr) feature.SetGeometry(geometry) target_layer.CreateFeature(feature) ogr.TermProgress_nocb((m + 1) / total)
def get_mask(self, geometry, shape): # create an ogr datasource driver = ogr.GetDriverByName(str('Memory')) source = driver.CreateDataSource(str('')) sr = osr.SpatialReference(self.projection) layer = source.CreateLayer(str(''), sr) defn = layer.GetLayerDefn() feature = ogr.Feature(defn) feature.SetGeometry(geometry) layer.CreateFeature(feature) # burn where data should be mask = np.zeros(shape, dtype='u1') geo_transform = self.geo_transform.shifted(geometry) kwargs = { 'geo_transform': geo_transform, 'projection': self.projection } with datasets.Dataset(mask, **kwargs) as dataset: gdal.RasterizeLayer(dataset, (1, ), layer, burn_values=(1, )) return mask.astype('b1').repeat(3, axis=0)
def command(gardens_path, aerial_image_path, target_path, min_green, max_green, check_rast, part, pk): # open input shapefile shape_gardens = ogr.Open(gardens_path) layer_gardens = shape_gardens[0] # check projection of input shapefile sr = layer_gardens.GetSpatialRef() check_sr = get_projection(sr) if check_sr is None: print('[!] ERROR : EPSG projection code missing from shape.') hint = '[*] INFO : Use this command: gdalsrsinfo -o wkt EPSG:28992 > ' print(hint, gardens_path.replace('.shp', '.prj')) return 1 # check spaces in aerial_image_path if ' ' in aerial_image_path: hint = '[!] ERROR : There is a space in the aerial image path: ' print(hint, aerial_image_path) return 1 # check if raster exists if not os.path.isfile(aerial_image_path): hint = '[!] ERROR : The specified file could not be found: ' print(hint, aerial_image_path) return 1 # get raster info and check rasterformat rasterfmt = os.path.splitext(aerial_image_path)[1] if (rasterfmt == '.ecw' or rasterfmt == '.tif' or rasterfmt == '.vrt'): pixelsize, envelope_aerial_image = gdalinfo(aerial_image_path) else: hint = '[!] ERROR : No supported raster format selected: ' print(hint, rasterfmt, ' (use .tif, .vrt or .ecw)') return 1 # delete any existing target driver = ogr.GetDriverByName(str('ESRI Shapefile')) try: driver.DeleteDataSource(str(target_path)) except RuntimeError: pass # prepare target dataset target_shape = driver.CreateDataSource(str(target_path)) target_layer_name = os.path.basename(target_path) target_layer = target_shape.CreateLayer(target_layer_name, sr) wkt = osr.GetUserInputAsWKT(str('EPSG:28992')) open(target_path.replace('.shp', '.prj'), 'w').write(wkt) target_layer_defn = layer_gardens.GetLayerDefn() for i in range(target_layer_defn.GetFieldCount()): target_field_defn = target_layer_defn.GetFieldDefn(i) target_layer.CreateField(target_field_defn) target_field_defn = ogr.FieldDefn(str('green_perc'), ogr.OFTReal) target_field_defn.SetWidth(5) target_field_defn.SetPrecision(3) target_layer.CreateField(target_field_defn) target_field_defn = ogr.FieldDefn(str('green_area'), ogr.OFTReal) target_field_defn.SetWidth(10) target_field_defn.SetPrecision(2) target_layer.CreateField(target_field_defn) # create tmp_dir for files tmp_dirname = os.path.join(os.path.dirname(target_path), 'tmp_greenfactor') if not os.path.exists(tmp_dirname): os.makedirs(tmp_dirname) # initialise progress bar total = layer_gardens.GetFeatureCount() ogr.TermProgress_nocb(0) index = datasources.PartialDataSource(gardens_path) if part is not None: index = index.select(part) # main loop for count, feature_garden in enumerate(index): # get envelope and convert it to the projwin for ecw_gdal_translate geometry_garden = feature_garden.geometry() garden_name = feature_garden.GetFieldAsString(str(pk)) envelope_garden = geometry_garden.GetEnvelope() skip_large_size = check_envelopes_input(garden_name, envelope_garden, envelope_aerial_image) if not skip_large_size == 1: x1, x2, y1, y2 = envelope_garden x1, y1 = np.floor(np.divide((x1, y1), pixelsize)) * pixelsize x2, y2 = np.ceil(np.divide((x2, y2), pixelsize)) * pixelsize envelope_garden_round = (x1, x2, y1, y2) projwin_garden = '%s %s %s %s' % (x1, y2, x2, y1) # create filename clipped aerial image geotiff tmp_aerial_tif = os.path.join(tmp_dirname, garden_name + '.tif') tmp_mask_tif = os.path.join(tmp_dirname, garden_name + '_mask.tif') tmp_green_tif = os.path.join(tmp_dirname, garden_name + '_green.tif') # prepare rgbt-array for green factor calculation rgbt, rasterdata = prepare_aerial_array(tmp_aerial_tif, aerial_image_path, projwin_garden, sr) # prepare mask-array for green factor calculation z = rgbt[:1, :, :] * 0 rasterdata['fillvalue'] = 1 array = create_filled_rasterarray(z, geometry_garden, tmp_mask_tif, rasterdata, print_rast=0) m = array[0].astype('b1') # Call function to determine the green factor result = determine_green_factor(rgbt, m, min_green, max_green) greenfactor, greengarden_percentage, greengarden_pixels = result greengarden_area = greengarden_pixels * pixelsize**2 # Create raster to check green factor if check_rast == 1: rasterdata['fillvalue'] = rasterdata['no_data_value'] = -9999 polygon_envelope_garden = get_envelope_polygon( envelope_garden_round, rasterdata['sr'], ) outside = polygon_envelope_garden.Difference(geometry_garden) create_filled_rasterarray(greenfactor[np.newaxis], outside, tmp_green_tif, rasterdata, print_rast=1) # Create a new feature in shapefile attributes_garden = feature_garden.items() feature = ogr.Feature(target_layer.GetLayerDefn()) feature.SetGeometry(geometry_garden) for key, value in attributes_garden.items(): feature[str(key)] = value feature[str('green_perc')] = greengarden_percentage feature[str('green_area')] = greengarden_area target_layer.CreateFeature(feature) # remove raster os.remove(tmp_aerial_tif) # progress bar ogr.TermProgress_nocb((count + 1) / total) return 0