def get_tile_range(self): """ Compute a xyz tile range from the query parameters. If no bbox parameter is found, the range defaults to the maximum extent of all input raster layers. """ # Get raster layers layers = RasterLayer.objects.filter(id__in=self.get_ids().values()) # Establish zoom level if self.request.GET.get('zoom', None): zlevel = int(self.request.GET.get('zoom')) else: # Get highest zoom level of all input layers zlevel = max([layer.metadata.max_zoom for layer in layers]) # Use bounding box to compute tile range if self.request.GET.get('bbox', None): bbox = Polygon.from_bbox(self.request.GET.get('bbox').split(',')) bbox.srid = 4326 bbox.transform(WEB_MERCATOR_SRID) tile_range = tile_index_range(bbox.extent, zlevel) else: # Get list of tile ranges layer_ranges = [] for layer in layers: layer_ranges.append(tile_index_range(layer.extent(), zlevel)) # Estabish overlap of tile index ranges tile_range = [ min([rng[0] for rng in layer_ranges]), min([rng[1] for rng in layer_ranges]), max([rng[2] for rng in layer_ranges]), max([rng[3] for rng in layer_ranges]), ] return [ zlevel, ] + tile_range
def get_tile_range(self): """ Compute a xyz tile range from the query parameters. If no bbox parameter is found, the range defaults to the maximum extent of all input raster layers. """ # Get raster layers layers = RasterLayer.objects.filter(id__in=self.get_ids().values()) # Establish zoom level if self.request.GET.get('zoom', None): zlevel = int(self.request.GET.get('zoom')) else: # Get highest zoom level of all input layers zlevel = max([layer.metadata.max_zoom for layer in layers]) # Use bounding box to compute tile range if self.request.GET.get('bbox', None): bbox = Polygon.from_bbox(self.request.GET.get('bbox').split(',')) bbox.srid = 4326 bbox.transform(WEB_MERCATOR_SRID) tile_range = tile_index_range(bbox.extent, zlevel) else: # Get list of tile ranges layer_ranges = [] for layer in layers: layer_ranges.append(tile_index_range(layer.extent(), zlevel)) # Estabish overlap of tile index ranges tile_range = [ min([rng[0] for rng in layer_ranges]), min([rng[1] for rng in layer_ranges]), max([rng[2] for rng in layer_ranges]), max([rng[3] for rng in layer_ranges]), ] return [zlevel, ] + tile_range
def test_tile_index_range(self): bounds = tile_bounds(43, 67, 8) geom = OGRGeometry.from_bbox(bounds) # With the default tolerance 0, the edging tiles are # included. idx = tile_index_range(geom.extent, 11) self.assertEqual(idx[2] - idx[0], 2**3) self.assertEqual(idx[3] - idx[1], 2**3) # With a larger tolerance, the strictly overlaping tiles are included. idx = tile_index_range(geom.extent, 11, tolerance=1e-3) self.assertEqual(idx[2] - idx[0], 2**3 - 1) self.assertEqual(idx[3] - idx[1], 2**3 - 1)
def test_tile_index_range(self): bounds = tile_bounds(43, 67, 8) geom = OGRGeometry.from_bbox(bounds) # With the default tolerance 0, the edging tiles are # included. idx = tile_index_range(geom.extent, 11) self.assertEqual(idx[2] - idx[0], 2 ** 3) self.assertEqual(idx[3] - idx[1], 2 ** 3) # With a larger tolerance, the strictly overlaping tiles are included. idx = tile_index_range(geom.extent, 11, tolerance=1e-3) self.assertEqual(idx[2] - idx[0], 2 ** 3 - 1) self.assertEqual(idx[3] - idx[1], 2 ** 3 - 1)
def nr_of_tiles(self, zoom): """ Compute the number of tiles for the rasterlayer on a given zoom level. """ bbox = self.dataset.extent indexrange = utils.tile_index_range(bbox, zoom) return (indexrange[2] - indexrange[0] + 1) * (indexrange[3] - indexrange[1] + 1)
def nr_of_tiles(self, zoom): """ Compute the number of tiles for the rasterlayer on a given zoom level. """ bbox = self.dataset.extent indexrange = utils.tile_index_range(bbox, zoom) return (indexrange[2] - indexrange[0] + 1) * (indexrange[3] - indexrange[1] + 1)
def get_tile(self, layer_id, zlevel=None): """ Returns a tile for rendering. If the tile does not exists, higher level tiles are searched and warped to lower level if found. """ if self.is_pixel_request: tilez = self.max_zoom # Derive the tile index from the input coordinates. xcoord = float(self.kwargs.get('xcoord')) ycoord = float(self.kwargs.get('ycoord')) bbox = [xcoord, ycoord, xcoord, ycoord] indexrange = tile_index_range(bbox, tilez) tilex = indexrange[0] tiley = indexrange[1] else: # Get tile indices from the request url parameters. tilez = int(self.kwargs.get('z')) tilex = int(self.kwargs.get('x')) tiley = int(self.kwargs.get('y')) return get_raster_tile(layer_id, tilez, tilex, tiley)
def __init__(self, layer_dict, formula, zoom=None, geom=None, acres=True, grouping='auto', all_touched=True, memory_efficient=False, hist_range=None): # Set defining parameter for this aggregator self.layer_dict = layer_dict self.formula = formula self.geom = geom self.acres = acres self.rastgeom = None self.all_touched = all_touched self.memory_efficient = memory_efficient self.hist_range = hist_range # Get layers from input dict self.layers = RasterLayer.objects.filter(id__in=layer_dict.values()) # Compute zoom if not provided if zoom is None: zoom = min(self.layers.values_list('metadata__max_zoom', flat=True)) self.zoom = zoom # Compute tilerange for this area and the given zoom level if geom: # Transform geom to web mercator if geom.srid != WEB_MERCATOR_SRID: geom.transform(WEB_MERCATOR_SRID) # Clip against max extent for limiting nr of tiles. # This is important for requests on large areas for small rasters. max_extent = MultiPolygon([Polygon.from_bbox(lyr.extent()) for lyr in self.layers]).envelope max_extent = geom.intersection(max_extent) # Abort if there is no spatial overlay if max_extent.empty: self.tilerange = None return else: # Compute tile index range for geometry and given zoom level self.tilerange = tile_index_range(max_extent.extent, zoom) else: # Get index range set for the input layers index_ranges = [tile_index_range(lyr.extent(), zoom) for lyr in self.layers] # Compute intersection of index ranges self.tilerange = [ max([dat[0] for dat in index_ranges]), max([dat[1] for dat in index_ranges]), min([dat[2] for dat in index_ranges]), min([dat[3] for dat in index_ranges]) ] # Auto determine grouping based on input data if grouping == 'auto': all_discrete = all((lyr.datatype in (RasterLayer.CATEGORICAL, RasterLayer.MASK) for lyr in self.layers)) grouping = 'discrete' if all_discrete else 'continuous' elif grouping in ('discrete', 'continuous'): pass else: try: legend_id = int(grouping) grouping = Legend.objects.get(id=legend_id) except ValueError: pass except ObjectDoesNotExist: raise RasterAggregationException( 'Invalid legend ID found in grouping value for valuecount.' ) self.grouping = grouping
def __init__(self, layer_dict, formula, zoom=None, geom=None, acres=True, grouping='auto'): # Set defining parameter for this aggregator self.layer_dict = layer_dict self.formula = formula self.geom = geom self.acres = acres self.rastgeom = None # Get layers from input dict self.layers = RasterLayer.objects.filter(id__in=layer_dict.values()) # Compute zoom if not provided if zoom is None: zoom = min(self.layers.values_list('metadata__max_zoom', flat=True)) self.zoom = zoom # Compute tilerange for this area and the given zoom level if geom: # Transform geom to web mercator if geom.srid != WEB_MERCATOR_SRID: geom.transform(WEB_MERCATOR_SRID) # Clip against max extent for limiting nr of tiles. # This is important for requests on large areas for small rasters. max_extent = MultiPolygon([ Polygon.from_bbox(lyr.extent()) for lyr in self.layers ]).envelope max_extent = geom.intersection(max_extent) # Abort if there is no spatial overlay if max_extent.empty: self.tilerange = None return else: # Compute tile index range for geometry and given zoom level self.tilerange = tile_index_range(max_extent.extent, zoom) else: # Get index range set for the input layers index_ranges = [ tile_index_range(lyr.extent(), zoom) for lyr in self.layers ] # Compute intersection of index ranges self.tilerange = [ max([dat[0] for dat in index_ranges]), max([dat[1] for dat in index_ranges]), min([dat[2] for dat in index_ranges]), min([dat[3] for dat in index_ranges]) ] # Auto determine grouping based on input data if grouping == 'auto': all_discrete = all( [lyr.datatype in ['ca', 'ma'] for lyr in self.layers]) grouping = 'discrete' if all_discrete else 'continuous' elif grouping in ('discrete', 'continuous'): pass else: try: legend_id = int(grouping) grouping = Legend.objects.get(id=legend_id) except ValueError: pass except ObjectDoesNotExist: raise RasterAggregationException( 'Invalid legend ID found in grouping value for valuecount.' ) self.grouping = grouping