def get_transformed_extent(extent, source_projection, target_projection): """ Return extent transformed from source projection to target projection. """ polygon = vectors.Geometry.fromextent(*extent).envelope transformation = osr.CoordinateTransformation( projections.get_spatial_reference(source_projection), projections.get_spatial_reference(target_projection), ) polygon.Transform(transformation) return vectors.Geometry(geometry=polygon).extent
def get_bounds(dataset, projection): """ Return dictionary. Dictionary contains the boundaries of the dataset and its first pixel, transformed to projection when necessary. Transformation is considered unnecessary if the outline changes less then 1 % of the pixelsize by transformation. The outline is shrunk by 1% of the shortest pixelside, to prevent edge intersections. """ transformation = osr.CoordinateTransformation( projections.get_spatial_reference(dataset.GetProjection()), projections.get_spatial_reference(projection), ) # outline raster_org = dataset2outlinepolygon(dataset) raster_trf = raster_org.Clone() raster_trf.Transform(transformation) # pixel pixel_org = dataset2pixelpolygon(dataset) pixel_trf = pixel_org.Clone() pixel_trf.Transform(transformation) # verdict pixel_trf_size = geometry2envelopesize(pixel_trf) diff = max(map(lambda x, y: abs(x - y), raster_trf.GetEnvelope(), raster_org.GetEnvelope())) transform = 100 * diff > min(pixel_trf_size) # return if transform: pixel = pixel_trf raster = raster_trf.Buffer(-0.01 * min(pixel_trf_size)) else: pixel = pixel_org raster = raster_org.Buffer(-0.01 * min(pixel_trf_size)) return dict(raster=raster, pixel=pixel)
def get_leafno(geometry): """ Return leafno based on geometry. """ index = ogr.Open(os.path.join(settings.DATA_DIR, 'index')) layer = index[0] wkb = ogr.CreateGeometryFromWkt(geometry['wkt']) ct = osr.CoordinateTransformation( projections.get_spatial_reference(geometry['crs']), layer.GetSpatialRef(), ) wkb.Transform(ct) layer.SetSpatialFilter(wkb) return layer.next().GetField(b'BLADNR')
def _dataset(self, level, tile, mode='r'): """ Return a gdal dataset. If the file corresponding to level and tile does not exist: In (r)ead mode, return mem dataset with nodata In (w)rite mode, create and return tif dataset with nodata """ path = os.path.join(self.path, str(level), '{}_{}.tif'.format(*tile)) if os.path.exists(path): # Open existing file with correct gdal access mode if mode == 'w': access = gdal.GA_Update logging.debug('Update {}'.format(path)) else: access = gdal.GA_ReadOnly return gdal.Open(str(path), access) create_args = [str(path), self.tilesize[0], self.tilesize[1], 1, self.datatype, ['TILED=YES', 'COMPRESS={}'.format(self.compression)]] if mode == 'w': # Use gtiff driver driver = gdal.GetDriverByName(b'gtiff') logging.debug('Create {}'.format(path)) # Create directory if necessary try: os.makedirs(os.path.dirname(path)) except OSError: pass # It existed. else: # mode == 'r' # Use mem driver driver = gdal.GetDriverByName(b'mem') create_args.pop() # No compression for mem driver # Actual create dataset = driver.Create(*create_args) dataset.SetProjection( projections.get_spatial_reference(self.projection).ExportToWkt(), ) dataset.SetGeoTransform( self._geometry(level=level, tile=tile).geotransform(), ) band = dataset.GetRasterBand(1) band.SetNoDataValue(self.nodatavalue) band.Fill(self.nodatavalue) return dataset
def get_data_for_polygon(self, wkb, crs, size): """ Return a numpy array for the data. """ # Quick out if polygon bounds match polygon geometry = vectors.Geometry(wkb) envelope = geometry.envelope extent = geometry.extent nodatavalue = self.manager.no_data_value datatype = self.manager.data_type # Initialize resulting array to nodatavalue dtype = gdal_array.flip_code(datatype) array = np.ones( (1, size[1], size[0]), dtype=dtype, ) * dtype(nodatavalue) # Create dataset and use it to retrieve data from the store array_dict = dict( array=array, no_data_value=nodatavalue, projection=projections.get_wkt(crs), geo_transform=rasters.get_geotransform( extent=extent, width=size[0], height=size[1], ), ) dataset = rasters.dict2dataset(array_dict) self.warpinto(dataset) dataset.FlushCache() # Cut when necessary if not envelope.Equals(wkb): source = OGR_MEM_DRIVER.CreateDataSource('') sr = projections.get_spatial_reference(crs) layer = source.CreateLayer(b'', sr) defn = layer.GetLayerDefn() feature = ogr.Feature(defn) feature.SetGeometry(envelope.Difference(wkb)) layer.CreateFeature(feature) gdal.RasterizeLayer(dataset, (1,), layer, burn_values=(nodatavalue,)) dataset.FlushCache() return np.ma.masked_equal(array, nodatavalue, copy=False)
def get_profile(wktline, src_srs=900913, rastersize=512): """ get raster values for pixels under linestring for Pyramid as set in PYRAMID_PATH in config file :param wktline: WKT linestring for which profile should be extracted :param src_srs: spatial reference system EPSG code :param rastersize: size of longest side of raster subset :returns: list with pairs of [cumlength, rastervalue] """ # setup pyramid pyramid = pyramids.Pyramid(config.PYRAMID_PATH) # setup srs try: srs = projections.get_spatial_reference(src_srs) except: return "Malformed EPSG code: %s" % (src_srs) # convert linestring to geometric object with shapely try: linestring = wkt.loads(wktline) except: return "Malformed geometry: %s" % (wktline) bounds = linestring.bounds points = list(linestring.coords) # set longest side to fixed size width = bounds[2] - bounds[0] length = bounds[3] - bounds[1] longside = max(width, length) if longside == width: xsize = rastersize cellsize = width / rastersize ysize = int(max(math.ceil(length / cellsize), 1)) else: ysize = rastersize cellsize = length / rastersize xsize = int(max(math.ceil(width / cellsize), 1)) # setup dataset in memory based on bounds mem_drv = gdal.GetDriverByName('MEM') mem_ds = mem_drv.Create(b'', xsize, ysize, 1, GDT_Float32) geotransform = (bounds[0], cellsize, 0, bounds[3], 0, -cellsize) mem_ds.SetGeoTransform(geotransform) mem_ds.SetProjection(srs.ExportToWkt()) origin = np.array([[mem_ds.GetGeoTransform()[0], mem_ds.GetGeoTransform()[3]]]) # warp values from pyramid into mem dataset pyramid.warpinto(mem_ds) # make magicline from linestring vertices magicline = MagicLine(points) magicline = magicline.pixelize(cellsize) # Determine indices for these points indices = tuple(np.uint64((magicline.centers - origin) / cellsize, ).transpose())[::-1] values = mem_ds.ReadAsArray()[indices] # set nodata values to empty nodata = mem_ds.GetRasterBand(1).GetNoDataValue() values = np.where(values == nodata, None, values) # make array with distance from origin (x values for graph) distances = map(float, np.arange(len(values)) * linestring.length / len(values)) profile_data = [list(a) for a in zip(distances, values)] mem_ds = None return profile_data
def get_profile(wktline, src_srs=900913, rastersize=512): """ get raster values for pixels under linestring for Pyramid as set in PYRAMID_PATH in config file :param wktline: WKT linestring for which profile should be extracted :param src_srs: spatial reference system EPSG code :param rastersize: size of longest side of raster subset :returns: list with pairs of [cumlength, rastervalue] """ # setup pyramid pyramid = pyramids.Pyramid(config.PYRAMID_PATH) # setup srs try: srs = projections.get_spatial_reference(src_srs) except: return "Malformed EPSG code: %s" % (src_srs) # convert linestring to geometric object with shapely try: linestring = wkt.loads(wktline) except: return "Malformed geometry: %s" % (wktline) bounds = linestring.bounds points = list(linestring.coords) # set longest side to fixed size width = bounds[2] - bounds[0] length = bounds[3] - bounds[1] longside = max(width, length) if longside == width: xsize = rastersize cellsize = width / rastersize ysize = int(max(math.ceil(length / cellsize), 1)) else: ysize = rastersize cellsize = length / rastersize xsize = int(max(math.ceil(width / cellsize), 1)) # setup dataset in memory based on bounds mem_drv = gdal.GetDriverByName('MEM') mem_ds = mem_drv.Create(b'', xsize, ysize, 1, GDT_Float32) geotransform = (bounds[0], cellsize, 0, bounds[3], 0, -cellsize) mem_ds.SetGeoTransform(geotransform) mem_ds.SetProjection(srs.ExportToWkt()) origin = np.array( [[mem_ds.GetGeoTransform()[0], mem_ds.GetGeoTransform()[3]]]) # warp values from pyramid into mem dataset pyramid.warpinto(mem_ds) # make magicline from linestring vertices magicline = MagicLine(points) magicline = magicline.pixelize(cellsize) # Determine indices for these points indices = tuple( np.uint64((magicline.centers - origin) / cellsize, ).transpose())[::-1] values = mem_ds.ReadAsArray()[indices] # set nodata values to empty nodata = mem_ds.GetRasterBand(1).GetNoDataValue() values = np.where(values == nodata, None, values) # make array with distance from origin (x values for graph) distances = map(float, np.arange(len(values)) * linestring.length / len(values)) profile_data = [list(a) for a in zip(distances, values)] mem_ds = None return profile_data