def _create_geometry_class(color_name, background_color_name=None, fill_opacity=None): cls_obj = ms.classObj() outline_style_obj = ms.styleObj() try: color = ms.colorObj(*BASE_COLORS[color_name]) except KeyError: raise # TODO outline_style_obj.outlinecolor = color cls_obj.insertStyle(outline_style_obj) if fill_opacity is not None: fill_style_obj = ms.styleObj() fill_style_obj.color = ms.colorObj( color.red, color.green, color.blue, int(255 * fill_opacity) ) cls_obj.insertStyle(fill_style_obj) if background_color_name: outline_style_obj.backgroundcolor = ms.colorObj( *BASE_COLORS[background_color_name] ) cls_obj.group = color_name return cls_obj
def apply_styles(self, layer, fill=False, default=None): """ Add style metadata. """ for name, r, g, b in self.STYLES: cls = ms.classObj() style = ms.styleObj() style.outlinecolor = ms.colorObj(r, g, b) if fill: style.color = ms.colorObj(r, g, b) style.opacity = 50 cls.insertStyle(style) cls.group = name layer.insertClass(cls) layer.classgroup = (default or self.DEFAULT_STYLE)
def apply_styles(self, layer, fill=False): # add style info for name, r, g, b in self.STYLES: cls = ms.classObj() style = ms.styleObj() style.outlinecolor = ms.colorObj(r, g, b) if fill: style.color = ms.colorObj(r, g, b) cls.insertStyle(style) cls.group = name layer.insertClass(cls) layer.classgroup = self.DEFAULT_STYLE
def _create_raster_layer_objs(map_obj, extent, sr, data, filename_generator, resample=None): layer_obj = ms.layerObj(map_obj) layer_obj.type = ms.MS_LAYER_RASTER layer_obj.status = ms.MS_ON layer_obj.data = data layer_obj.offsite = ms.colorObj(0, 0, 0) if extent: layer_obj.setMetaData("wms_extent", "%f %f %f %f" % extent) layer_obj.setExtent(*extent) if sr.srid is not None: short_epsg = "EPSG:%d" % sr.srid layer_obj.setMetaData("ows_srs", short_epsg) layer_obj.setMetaData("wms_srs", short_epsg) layer_obj.setProjection(sr.proj) if resample: layer_obj.setProcessingKey('RESAMPLE', resample) if extent and sr.srid and extent_crosses_dateline(extent, sr.srid): wrapped_extent = wrap_extent_around_dateline(extent, sr.srid) wrapped_layer_obj = ms.layerObj(map_obj) wrapped_layer_obj.type = ms.MS_LAYER_RASTER wrapped_layer_obj.status = ms.MS_ON wrapped_data = filename_generator.generate() vrt.with_extent(data, wrapped_extent, wrapped_data) wrapped_layer_obj.data = wrapped_data wrapped_layer_obj.offsite = ms.colorObj(0, 0, 0) wrapped_layer_obj.setMetaData("ows_srs", short_epsg) wrapped_layer_obj.setMetaData("wms_srs", short_epsg) wrapped_layer_obj.setProjection(sr.proj) wrapped_layer_obj.setExtent(*wrapped_extent) wrapped_layer_obj.setMetaData( "wms_extent", "%f %f %f %f" % wrapped_extent ) return [layer_obj, wrapped_layer_obj] else: return [layer_obj]
def create_polygon_layer(self, coverage, name): layer = self._create_layer(coverage, name, coverage.extent) self._set_projection(layer, coverage.spatial_reference) layer.type = ms.MS_LAYER_POLYGON layer.dump = True layer.offsite = ms.colorObj(0, 0, 0) return layer
def offsite_color_from_range_type(self, range_type, band_indices=None): """ Helper function to create an offsite color for a given range type and optionally band indices. """ if band_indices is None: if len(range_type) == 1: band_indices = [0, 0, 0] elif len(range_type) >= 3: band_indices = [0, 1, 2] else: # no offsite color possible return None if len(band_indices) != 3: raise ValueError( "Wrong number of band indices to calculate offsite color." ) values = [] for index in band_indices: band = range_type[index] nil_value_set = band.nil_value_set if nil_value_set and len(nil_value_set) > 0: values.append(nil_value_set[0].value) else: return None return ms.colorObj(*values)
def _create_polygon_layer(self, name): layer = ms.layerObj() layer.name = name layer.type = ms.MS_LAYER_POLYGON self.apply_styles(layer) srid = 4326 layer.setProjection(crss.asProj4Str(srid)) layer.setMetaData("ows_srs", crss.asShortCode(srid)) layer.setMetaData("wms_srs", crss.asShortCode(srid)) layer.dump = True layer.header = os.path.join(settings.PROJECT_DIR, "conf", "outline_template_header.html") layer.template = os.path.join(settings.PROJECT_DIR, "conf", "outline_template_dataset.html") layer.footer = os.path.join(settings.PROJECT_DIR, "conf", "outline_template_footer.html") layer.setMetaData("gml_include_items", "all") layer.setMetaData("wms_include_items", "all") layer.addProcessing("ITEMS=identifier") layer.offsite = ms.colorObj(0, 0, 0) return layer
def offsite_color_from_range_type(self, range_type, band_indices=None): """ Helper function to create an offsite color for a given range type and optionally band indices. """ if band_indices is None: if len(range_type) == 1: band_indices = [0, 0, 0] elif len(range_type) >= 3: band_indices = [0, 1, 2] else: # no offsite color possible return None if len(band_indices) != 3: raise ValueError( "Wrong number of band indices to calculate offsite color." ) values = [] for index in band_indices: band = range_type[index] nil_value_set = band.nil_value_set # we only support offsite colors for "Byte" bands if nil_value_set and nil_value_set.data_type != gdal.GDT_Byte: return None if nil_value_set and len(nil_value_set) > 0: values.append(nil_value_set[0].value) else: return None return ms.colorObj(*values)
def _offsite_color(range_type, indices=None): """ Cretate an offsite color for a given range type and optional list of band indices. The bands' offise colors are set either from the nil-values of the range type or set to zero if there is no nil-value available. """ # TODO: Review the offsite color method. if indices == None: if len(range_type) >= 3: band_indices = [0, 1, 2] elif len(range_type) == 2: band_indices = [0, 1, 1] elif len(range_type) == 1: band_indices = [0, 0, 0] else: # no offsite color possible return None else: band_indices = [v-1 for v in indices] if len(band_indices) < 3 or len(band_indices) > 4: raise ValueError("Wrong number of band indices to calculate" " the offsite color.") values = [] for index in band_indices: nilvalset = range_type[index].nil_value_set values.append(nilvalset[0].value if nilvalset else 0) return ms.colorObj(*values)
def _create_polygon_layer(map_obj): layer_obj = ms.layerObj(map_obj) layer_obj.type = ms.MS_LAYER_POLYGON layer_obj.status = ms.MS_ON layer_obj.offsite = ms.colorObj(0, 0, 0) srid = 4326 layer_obj.setProjection(crss.asProj4Str(srid)) layer_obj.setMetaData("ows_srs", crss.asShortCode(srid)) layer_obj.setMetaData("wms_srs", crss.asShortCode(srid)) layer_obj.dump = True return layer_obj
def _create_raster_style(name, layer, minvalue=0, maxvalue=255, nil_values=None): colors = COLOR_SCALES[name] nil_values = [float(nil_value) for nil_value in nil_values or []] if nil_values: offsite = ms.colorObj(*OFFSITE_COLORS.get(name, (0, 0, 0))) layer.offsite = offsite for nil_value in nil_values: cls = ms.classObj() cls.setExpression("([pixel] = %s)" % nil_value) cls.group = name style = ms.styleObj() style.color = offsite style.opacity = 0 style.rangeitem = "" cls.insertStyle(style) layer.insertClass(cls) low_nil_values = [ nil_value for nil_value in nil_values if nil_value <= minvalue ] high_nil_values = [ nil_value for nil_value in nil_values if nil_value >= maxvalue ] # Create style for values below range, but make sure to not collide # with nil-values if low_nil_values: low_nil = max(low_nil_values) cls = ms.classObj() cls.setExpression( "([pixel] <= %s AND [pixel] > %s)" % (minvalue, low_nil) ) cls.group = name style = ms.styleObj() style.color = ms.colorObj(*colors[0][1]) cls.insertStyle(style) layer.insertClass(cls) else: cls = ms.classObj() cls.setExpression("([pixel] <= %s)" % (minvalue)) cls.group = name style = ms.styleObj() style.color = ms.colorObj(*colors[0][1]) cls.insertStyle(style) layer.insertClass(cls) interval = (maxvalue - minvalue) for prev_item, next_item in pairwise_iterative(colors): prev_perc, prev_color = prev_item next_perc, next_color = next_item cls = ms.classObj() cls.setExpression("([pixel] >= %s AND [pixel] < %s)" % ( (minvalue + prev_perc * interval), (minvalue + next_perc * interval) )) cls.group = name style = ms.styleObj() style.mincolor = ms.colorObj(*prev_color) style.maxcolor = ms.colorObj(*next_color) style.minvalue = minvalue + prev_perc * interval style.maxvalue = minvalue + next_perc * interval style.rangeitem = "" cls.insertStyle(style) layer.insertClass(cls) # Create style for values above range, but make sure to not collide with # nil-values if high_nil_values: high_nil = min(high_nil_values) cls = ms.classObj() cls.setExpression( "([pixel] > %s AND [pixel] < %s)" % (maxvalue, high_nil) ) cls.group = name style = ms.styleObj() style.color = ms.colorObj(*colors[0][1]) cls.insertStyle(style) layer.insertClass(cls) else: cls = ms.classObj() cls.setExpression("([pixel] > %s)" % (maxvalue)) cls.group = name style = ms.styleObj() style.color = ms.colorObj(*colors[-1][1]) cls.insertStyle(style) layer.insertClass(cls)
def create_coverage_layer(self, map_obj, coverage, fields, style=None, ranges=None): """ Creates a mapserver layer object for the given coverage """ filename_generator = FilenameGenerator( '/vsimem/{uuid}.{extension}', 'vrt' ) field_locations = [ (field, coverage.get_location_for_field(field)) for field in fields ] locations = [ location for _, location in field_locations ] # TODO: apply subsets in time/elevation dims num_locations = len(set(locations)) if num_locations == 1: if not coverage.grid.is_referenceable: location = field_locations[0][1] data = location.path ms.set_env(map_obj, location.env, True) else: vrt_path = filename_generator.generate() e = map_obj.extent resx = (e.maxx - e.minx) / map_obj.width resy = (e.maxy - e.miny) / map_obj.height wkt = osr.SpatialReference(map_obj.getProjection()).wkt # TODO: env? reftools.create_rectified_vrt( field_locations[0][1].path, vrt_path, order=1, max_error=10, resolution=(resx, -resy), srid_or_wkt=wkt ) data = vrt_path elif num_locations > 1: paths_set = set( field_location[1].path for field_location in field_locations ) if len(paths_set) == 1: location = field_locations[0][1] data = location.path ms.set_env(map_obj, location.env, True) else: # TODO _build_vrt(coverage.size, field_locations) if not coverage.grid.is_referenceable: extent = coverage.extent sr = coverage.grid.spatial_reference else: map_extent = map_obj.extent extent = ( map_extent.minx, map_extent.miny, map_extent.maxx, map_extent.maxy ) sr = osr.SpatialReference(map_obj.getProjection()) layer_objs = _create_raster_layer_objs( map_obj, extent, sr, data, filename_generator ) for i, layer_obj in enumerate(layer_objs): layer_obj.name = '%s__%d' % (coverage.identifier, i) layer_obj.setProcessingKey("CLOSE_CONNECTION", "CLOSE") if num_locations == 1: for layer_obj in layer_objs: layer_obj.setProcessingKey("BANDS", ",".join([ str(coverage.get_band_index_for_field(field)) for field in fields ])) elif num_locations > 1: for layer_obj in layer_objs: if len(field_locations) == 3: layer_obj.setProcessingKey("BANDS", "1,2,3") else: layer_obj.setProcessingKey("BANDS", "1") # make a color-scaled layer if len(fields) == 1: field = fields[0] if ranges: range_ = ranges[0] else: range_ = _get_range(field) for layer_obj in layer_objs: _create_raster_style( style or "blackwhite", layer_obj, range_[0], range_[1], [ nil_value[0] for nil_value in field.nil_values ] ) elif len(fields) in (3, 4): for i, field in enumerate(fields, start=1): if ranges: if len(ranges) == 1: range_ = ranges[0] else: range_ = ranges[i - 1] else: range_ = _get_range(field) for layer_obj in layer_objs: layer_obj.setProcessingKey( "SCALE_%d" % i, "%s,%s" % range_ ) layer_obj.offsite = ms.colorObj(0, 0, 0) else: raise Exception("Too many bands specified") return filename_generator