예제 #1
0
    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
예제 #2
0
 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
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
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)
예제 #6
0
    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)
예제 #7
0
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
예제 #8
0
    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)
예제 #9
0
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)
예제 #10
0
    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)
예제 #11
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