def __init__(self, dataset, wkt, srid=None, temporary_directory=None): super(GDALGeometryMaskMergeSource, self).__init__(dataset) srs = None srid = 4326 if srid is not None: srs = osr.SpatialReference() srs.ImportFromEPSG(srid) # create a geometry from the given WKT #geom = ogr.CreateGeometryFromWkt(wkt) # create an in-memory datasource and add one single layer ogr_mem_driver = ogr.GetDriverByName("Memory") data_source = ogr_mem_driver.CreateDataSource("xxx") layer = data_source.CreateLayer("poly", srs) # create a single feature and add the given geometry feature = ogr.Feature(layer.GetLayerDefn()) feature.SetGeometryDirectly(ogr.Geometry(wkt=str(wkt))) layer.CreateFeature(feature) temporary_ds = temporary_dataset( self.dataset.RasterXSize, self.dataset.RasterYSize, 1, temp_root=temporary_directory ) # create a temporary raster dataset with the exact same size as the # dataset to be masked with temporary_ds as mask_dataset: band = mask_dataset.GetRasterBand(1) band.Fill(1) mask_dataset.SetGeoTransform(self.dataset.GetGeoTransform()) mask_dataset.SetProjection(self.dataset.GetProjection()) # finally rasterize the vector layer to the mask dataset gdal.RasterizeLayer(mask_dataset, (1,), layer, burn_values=(0,)) source_mask_band = mask_dataset.GetRasterBand(1) self.dataset.CreateMaskBand(gdal.GMF_PER_DATASET) band = self.dataset.GetRasterBand(1) mask_band = band.GetMaskBand() block_x_size, block_y_size = source_mask_band.GetBlockSize() num_x = source_mask_band.XSize / block_x_size num_y = source_mask_band.YSize / block_y_size for x, y in product(range(num_x), range(num_y)): mask_band.WriteArray( source_mask_band.ReadAsArray( x*block_x_size, y*block_y_size, block_x_size, block_y_size ), x*block_x_size, y*block_y_size )
def __init__(self, dataset, wkt, srid=None, temporary_directory=None): super(GDALGeometryMaskMergeSource, self).__init__(dataset) srs = None srid = 4326 if srid is not None: srs = osr.SpatialReference() srs.ImportFromEPSG(srid) # create a geometry from the given WKT #geom = ogr.CreateGeometryFromWkt(wkt) # create an in-memory datasource and add one single layer ogr_mem_driver = ogr.GetDriverByName("Memory") data_source = ogr_mem_driver.CreateDataSource("xxx") layer = data_source.CreateLayer("poly", srs) # create a single feature and add the given geometry feature = ogr.Feature(layer.GetLayerDefn()) feature.SetGeometryDirectly(ogr.Geometry(wkt=str(wkt))) layer.CreateFeature(feature) temporary_ds = temporary_dataset(self.dataset.RasterXSize, self.dataset.RasterYSize, 1, temp_root=temporary_directory) # create a temporary raster dataset with the exact same size as the # dataset to be masked with temporary_ds as mask_dataset: band = mask_dataset.GetRasterBand(1) band.Fill(1) mask_dataset.SetGeoTransform(self.dataset.GetGeoTransform()) mask_dataset.SetProjection(self.dataset.GetProjection()) # finally rasterize the vector layer to the mask dataset gdal.RasterizeLayer(mask_dataset, (1, ), layer, burn_values=(0, )) source_mask_band = mask_dataset.GetRasterBand(1) self.dataset.CreateMaskBand(gdal.GMF_PER_DATASET) band = self.dataset.GetRasterBand(1) mask_band = band.GetMaskBand() block_x_size, block_y_size = source_mask_band.GetBlockSize() num_x = source_mask_band.XSize / block_x_size num_y = source_mask_band.YSize / block_y_size for x, y in product(range(num_x), range(num_y)): mask_band.WriteArray( source_mask_band.ReadAsArray(x * block_x_size, y * block_y_size, block_x_size, block_y_size), x * block_x_size, y * block_y_size)
def generate_footprint_wkt(ds, simplification_factor=2): """ Generate a fooptrint from a raster, using black/no-data as exclusion """ # create an empty boolean array initialized as 'False' to store where # values exist as a mask array. nodata_map = np.zeros((ds.RasterYSize, ds.RasterXSize), dtype=np.bool) for idx in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(idx) raster_data = band.ReadAsArray() nodata = band.GetNoDataValue() if nodata is None: nodata = 0 # apply the output to the map nodata_map |= (raster_data != nodata) # create a temporary in-memory dataset and write the nodata mask # into its single band with temporary_dataset(ds.RasterXSize + 2, ds.RasterYSize + 2, 1, gdal.GDT_Byte) as tmp_ds: copy_projection(ds, tmp_ds) tmp_band = tmp_ds.GetRasterBand(1) tmp_band.WriteArray(nodata_map.astype(np.uint8)) # create an OGR in memory layer to hold the created polygon sr = osr.SpatialReference() sr.ImportFromWkt(ds.GetProjectionRef()) ogr_ds = ogr.GetDriverByName('Memory').CreateDataSource('out') layer = ogr_ds.CreateLayer('poly', sr.sr, ogr.wkbPolygon) fd = ogr.FieldDefn('DN', ogr.OFTInteger) layer.CreateField(fd) # polygonize the mask band and store the result in the OGR layer gdal.Polygonize(tmp_band, tmp_band, layer, 0) if layer.GetFeatureCount() != 1: # if there is more than one polygon, compute the minimum bounding polygon geometry = ogr.Geometry(ogr.wkbPolygon) while True: feature = layer.GetNextFeature() if not feature: break geometry = geometry.Union(feature.GetGeometryRef()) # TODO: improve this for a better minimum bounding polygon geometry = geometry.ConvexHull() else: # obtain geometry from the first (and only) layer feature = layer.GetNextFeature() geometry = feature.GetGeometryRef() if geometry.GetGeometryType() not in (ogr.wkbPolygon, ogr.wkbMultiPolygon): raise RuntimeError("Error during poligonization. Wrong geometry " "type.") # check if reprojection to latlon is necessary if not sr.IsGeographic(): dst_sr = osr.SpatialReference() dst_sr.ImportFromEPSG(4326) try: geometry.TransformTo(dst_sr.sr) except RuntimeError: geometry.Transform(osr.CoordinateTransformation(sr.sr, dst_sr.sr)) gt = ds.GetGeoTransform() resolution = min(abs(gt[1]), abs(gt[5])) simplification_value = simplification_factor * resolution # simplify the polygon. the tolerance value is *really* vague try: # SimplifyPreserveTopology() available since OGR 1.9.0 geometry = geometry.SimplifyPreserveTopology(simplification_value) except AttributeError: # use GeoDjango bindings if OGR is too old geometry = ogr.CreateGeometryFromWkt( GEOSGeometry(geometry.ExportToWkt()).simplify( simplification_value, True).wkt) return geometry.ExportToWkt()
def generate_footprint_wkt(ds, simplification_factor=2): """ Generate a fooptrint from a raster, using black/no-data as exclusion """ # create an empty boolean array initialized as 'False' to store where # values exist as a mask array. nodata_map = np.zeros((ds.RasterYSize, ds.RasterXSize), dtype=np.bool) for idx in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(idx) raster_data = band.ReadAsArray() nodata = band.GetNoDataValue() if nodata is None: nodata = 0 # apply the output to the map nodata_map |= (raster_data != nodata) # create a temporary in-memory dataset and write the nodata mask # into its single band with temporary_dataset(ds.RasterXSize + 2, ds.RasterYSize + 2, 1, gdal.GDT_Byte) as tmp_ds: copy_projection(ds, tmp_ds) tmp_band = tmp_ds.GetRasterBand(1) tmp_band.WriteArray(nodata_map.astype(np.uint8)) # create an OGR in memory layer to hold the created polygon sr = osr.SpatialReference() sr.ImportFromWkt(ds.GetProjectionRef()) ogr_ds = ogr.GetDriverByName('Memory').CreateDataSource('out') layer = ogr_ds.CreateLayer('poly', sr.sr, ogr.wkbPolygon) fd = ogr.FieldDefn('DN', ogr.OFTInteger) layer.CreateField(fd) # polygonize the mask band and store the result in the OGR layer gdal.Polygonize(tmp_band, tmp_band, layer, 0) if layer.GetFeatureCount() != 1: # if there is more than one polygon, compute the minimum bounding polygon geometry = ogr.Geometry(ogr.wkbPolygon) while True: feature = layer.GetNextFeature() if not feature: break geometry = geometry.Union(feature.GetGeometryRef()) # TODO: improve this for a better minimum bounding polygon geometry = geometry.ConvexHull() else: # obtain geometry from the first (and only) layer feature = layer.GetNextFeature() geometry = feature.GetGeometryRef() if geometry.GetGeometryType() not in (ogr.wkbPolygon, ogr.wkbMultiPolygon): raise RuntimeError("Error during poligonization. Wrong geometry " "type.") # check if reprojection to latlon is necessary if not sr.IsGeographic(): dst_sr = osr.SpatialReference() dst_sr.ImportFromEPSG(4326) try: geometry.TransformTo(dst_sr.sr) except RuntimeError: geometry.Transform(osr.CoordinateTransformation(sr.sr, dst_sr.sr)) gt = ds.GetGeoTransform() resolution = min(abs(gt[1]), abs(gt[5])) simplification_value = simplification_factor * resolution # simplify the polygon. the tolerance value is *really* vague try: # SimplifyPreserveTopology() available since OGR 1.9.0 geometry = geometry.SimplifyPreserveTopology(simplification_value) except AttributeError: # use GeoDjango bindings if OGR is too old geometry = ogr.CreateGeometryFromWkt( GEOSGeometry( geometry.ExportToWkt() ).simplify(simplification_value, True).wkt ) return geometry.ExportToWkt()