Ejemplo n.º 1
0
    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
                )
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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()