Exemplo n.º 1
0
    def __call__(self, src_ds, footprint_wkt):
        logger.info("Applying AlphaBandOptimization")
        dt = src_ds.GetRasterBand(1).DataType
        if src_ds.RasterCount == 3:
            src_ds.AddBand(dt)
        elif src_ds.RasterCount == 4:
            pass  # okay
        else:
            raise Exception("Cannot add alpha band, as the current number of "
                            "bands '%d' does not match" % src_ds.RasterCount)

        # initialize the alpha band with zeroes (completely transparent)
        band = src_ds.GetRasterBand(4)
        band.Fill(0)

        # set up the layer with geometry
        ogr_ds = ogr.GetDriverByName('Memory').CreateDataSource('wkt')

        sr = osr.SpatialReference()
        sr.ImportFromEPSG(4326)
        layer = ogr_ds.CreateLayer('poly', srs=sr.sr)

        feat = ogr.Feature(layer.GetLayerDefn())
        feat.SetGeometryDirectly(ogr.Geometry(wkt=footprint_wkt))
        layer.CreateFeature(feat)

        # rasterize the polygon, burning the opaque value into the alpha band
        gdal.RasterizeLayer(src_ds, [4],
                            layer,
                            burn_values=[get_limits(dt)[1]])
Exemplo 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)
Exemplo n.º 3
0
    def generate_contours(self, ds, contour_steps, out_file):
        logger.debug("Generating contours for file %s" % ds.GetFileList()[0])
        driver = ogr.GetDriverByName('ESRI Shapefile')
        ogr_ds = driver.CreateDataSource(out_file)
        ogr_lyr = ogr_ds.CreateLayer('contour')
        field_defn = ogr.FieldDefn('ID', ogr.OFTInteger)
        ogr_lyr.CreateField(field_defn)
        field_defn = ogr.FieldDefn('elev', ogr.OFTReal)
        ogr_lyr.CreateField(field_defn)

        gdal.ContourGenerate(ds.GetRasterBand(1), contour_steps, 0, [], 0, 0,
                             ogr_lyr, 0, 1)

        logger.debug("Finished generating contours for file %s" %
                     ds.GetFileList()[0])
        return ogr_ds
Exemplo 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()
Exemplo n.º 5
0
    def _generate_footprint_wkt(self, ds):
        """ Generate a footprint 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 = numpy.zeros((ds.RasterYSize, ds.RasterXSize),
                                 dtype=numpy.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
        tmp_ds = create_mem(ds.RasterXSize + 2, ds.RasterYSize + 2, 1,
                            gdal.GDT_Byte)
        copy_projection(ds, tmp_ds)
        tmp_band = tmp_ds.GetRasterBand(1)
        tmp_band.WriteArray(nodata_map.astype(numpy.uint8))

        # Remove unwanted small areas of nodata
        # www.gdal.org/gdal__alg_8h.html#a33309c0a316b223bd33ae5753cc7f616
        no_pixels = tmp_ds.RasterXSize * tmp_ds.RasterYSize
        threshold = 4
        max_threshold = (no_pixels / 16)
        if self.sieve_max_threshold > 0:
            max_threshold = self.sieve_max_threshold
        while threshold <= max_threshold and threshold < 2147483647:
            gdal.SieveFilter(tmp_band, None, tmp_band, threshold, 4)
            threshold *= 4

        #for debugging:
        #gdal.GetDriverByName('GTiff').CreateCopy('/tmp/test.tif', tmp_ds)

        # 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, 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)

        tmp_ds = None

        if layer.GetFeatureCount() > 1:
            # if there is more than one polygon, compute the minimum
            # bounding polygon
            logger.debug("Merging %s features in footprint." %
                         layer.GetFeatureCount())

            # union all features in one multi-polygon
            geometry = ogr.Geometry(ogr.wkbMultiPolygon)
            while True:
                feature = layer.GetNextFeature()
                if not feature:
                    break
                geometry.AddGeometry(feature.GetGeometryRef())
            geometry = geometry.UnionCascaded()

            # TODO: improve this for a better minimum bounding polygon
            geometry = geometry.ConvexHull()

        elif layer.GetFeatureCount() < 1:
            # there was an error during polygonization
            raise RuntimeError("Error during polygonization. No feature "
                               "obtained.")
        else:
            # obtain geometry from the first (and only) layer
            feature = layer.GetNextFeature()
            geometry = feature.GetGeometryRef()

        if geometry.GetGeometryType() != ogr.wkbPolygon:
            raise RuntimeError(
                "Error during polygonization. Wrong geometry "
                "type: %s" %
                ogr.GeometryTypeToName(geometry.GetGeometryType()))

        # check if reprojection to latlon is necessary
        if not sr.IsGeographic():
            dst_sr = osr.SpatialReference()
            dst_sr.ImportFromEPSG(4326)
            try:
                geometry.TransformTo(dst_sr)
            except RuntimeError:
                geometry.Transform(osr.CoordinateTransformation(sr, dst_sr))

        gt = ds.GetGeoTransform()
        resolution = min(abs(gt[1]), abs(gt[5]))

        simplification_value = self.simplification_factor * resolution

        #for debugging:
        #geometry.GetGeometryRef(0).GetPointCount()

        # 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()
Exemplo n.º 6
0
 def get_driver(self):
     """ Get the OGR driver.
     """
     return ogr.GetDriverByName(self.driver_name)
Exemplo n.º 7
0
    def render(self, layers, bbox, crs, size, frmt, time, elevation, styles):
        if not time:
            raise RenderException("Missing mandatory 'time' parameter.")

        try:
            time = time.value
        except AttributeError:
            raise RenderException(
                "Parameter 'time' must be a slice and not a range.")

        llbbox = self.get_llbbox(bbox, crs)

        mapfile_path = get_eoxserver_config().get("wmm", "mapfile")
        map_ = ms.mapObj(mapfile_path)  #TODO: path to map
        map_.setMetaData("ows_enable_request", "*")
        map_.setProjection("EPSG:4326")
        map_.imagecolor.setRGB(0, 0, 0)

        # set supported CRSs
        decoder = crss.CRSsConfigReader(get_eoxserver_config())
        crss_string = " ".join(
            map(lambda crs: "EPSG:%d" % crs, decoder.supported_crss_wms))
        map_.setMetaData("ows_srs", crss_string)
        map_.setMetaData("wms_srs", crss_string)

        datasources = []
        datasets = []

        for layer_name in layers:
            layer = map_.getLayerByName(layer_name)
            if not layer:
                continue

            product = layer.metadata.get("wmm_product")

            filename = self.generate_filename("tif")
            ds = self.create_dataset(llbbox, time, elevation, size, product,
                                     filename)
            datasets.append(ds)

            if layer.type == ms.MS_LAYER_LINE:
                flavor = layer.metadata.get("wmm_flavor")
                contour_steps = self.get_contour_intervals(
                    flavor, llbbox, size)
                filename = self.generate_filename("shp")
                self.generate_contours(ds, contour_steps, filename)

                layer.connectiontype = ms.MS_OGR
                layer.connection = filename
                layer.data, _ = splitext(basename(filename))

                datasources.append(filename)

        ms_request = ms.create_request(
            (("service", "WMS"), ("version", "1.3.0"), ("request", "GetMap"),
             ("layers", ",".join(layers)),
             ("bbox", "%f,%f,%f,%f" % (bbox[1], bbox[0], bbox[3], bbox[2])),
             ("crs", crs), ("width", str(size[0])), ("height", str(size[1])),
             ("styles", ",".join(styles)), ("format", frmt)))

        raw_result = ms.dispatch(map_, ms_request)
        result = result_set_from_raw_data(raw_result)

        shp_drv = ogr.GetDriverByName("ESRI Shapefile")
        # cleanup datasources and datasets
        for filename in datasources:
            shp_drv.DeleteDataSource(filename)

        for ds in datasets:
            driver = ds.GetDriver()
            for filename in ds.GetFileList():
                os.remove(filename)

        return result, get_content_type(result)