def handle(self, **options): c = connections[DB_NAME].cursor() c.execute("DELETE FROM coastline WHERE ogc_fid >= 1000000;") transaction.commit(using=DB_NAME) c.execute("SELECT ogc_fid, wkb_geometry, elevation FROM coastline ORDER BY ogc_fid;") for row in c.fetchall(): src_fid = row[0] src_geom = GEOSGeometry(row[1]) src_elevation = row[2] print "OGC_FID: % 5d - VERTICES: % 8d" % (row[0], src_geom.num_points,) if src_geom.num_points > SPLIT_THRESHOLD: for start in range(0, src_geom.num_points, SPLIT_AMOUNT): new_fid = src_fid * 1000000 + start new_geom = LineString(src_geom[start:start + SPLIT_AMOUNT + 1]) new_geom.srid = src_geom.srid c.execute("INSERT INTO coastline (ogc_fid, wkb_geometry, elevation) VALUES (%d, '%s', %f)" % (new_fid, new_geom.hexewkb, src_elevation)) c.execute("DELETE FROM coastline WHERE ogc_fid = %d;" % (src_fid)) transaction.commit(using=DB_NAME) print " * SPLIT INTO OGC_FID: % 10d - VERTICES: % 8d" % (new_fid, new_geom.num_points)
def filter(self, queryset, containment="overlaps"): if not len(self): return queryset qs = queryset bbox = [None, None, None, None] srid = self.srid if srid is None: srid = 4326 max_extent = crss.crs_bounds(srid) tolerance = crss.crs_tolerance(srid) for subset in self: if isinstance(subset, Slice): is_slice = True value = subset.value elif isinstance(subset, Trim): is_slice = False low = subset.low high = subset.high if subset.is_temporal: if is_slice: qs = qs.filter( begin_time__lte=value, end_time__gte=value ) else: if high is not None: qs = qs.filter( begin_time__lte=high ) if low is not None: qs = qs.filter( end_time__gte=low ) # check if the temporal bounds must be strictly contained if containment == "contains": if high is not None: qs = qs.filter( end_time__lte=high ) if low is not None: qs = qs.filter( begin_time__gte=low ) else: if is_slice: if subset.is_x: line = LineString( (value, max_extent[1]), (value, max_extent[3]) ) else: line = LineString( (max_extent[0], value), (max_extent[2], value) ) line.srid = srid if srid != 4326: line.transform(4326) qs = qs.filter(footprint__intersects=line) else: if subset.is_x: bbox[0] = subset.low bbox[2] = subset.high else: bbox[1] = subset.low bbox[3] = subset.high if bbox != [None, None, None, None]: bbox = map( lambda v: v[0] if v[0] is not None else v[1], zip(bbox, max_extent) ) bbox[0] -= tolerance; bbox[1] -= tolerance bbox[2] += tolerance; bbox[3] += tolerance logger.debug( "Applying BBox %s with containment '%s'." % (bbox, containment) ) poly = Polygon.from_bbox(bbox) poly.srid = srid if srid != 4326: poly.transform(4326) if containment == "overlaps": qs = qs.filter(footprint__intersects=poly) elif containment == "contains": qs = qs.filter(footprint__within=poly) return qs
def render_static(request, height=None, width=None, format='png', background='satellite', bounds=None, center=None, render_srid=3857): # width and height width = int(width) height = int(height) if width > settings.MAX_IMAGE_DIMENSION or \ height > settings.MAX_IMAGE_DIMENSION or \ width <= 1 or height <= 1: logging.debug("Invalid size") return HttpResponseBadRequest("Invalid image size, both dimensions must be in range %i-%i" % (1, settings.MAX_IMAGE_DIMENSION)) # image format if format not in IMAGE_FORMATS: logging.error("unknown image format %s" % format) return HttpResponseBadRequest("Unknown image format, available formats: " + ", ".join(IMAGE_FORMATS)) if format.startswith('png'): mimetype = 'image/png' elif format.startswith('jpeg'): mimetype = 'image/jpeg' # bounds bounds_box = None if bounds: bounds_components = bounds.split(',') if len(bounds_components) != 4: return HttpResponseBadRequest("Invalid bounds, must be 4 , separated numbers") bounds_components = [float(f) for f in bounds_components] if not (-180 < bounds_components[0] < 180) or not (-180 < bounds_components[2] < 180): logging.error("x out of range %f or %f" % (bounds_components[0], bounds_components[2])) return HttpResponseBadRequest("x out of range %f or %f" % (bounds_components[0], bounds_components[2])) if not (-90 < bounds_components[1] < 90) or not (-90 < bounds_components[3] < 90): logging.error("y out of range %f or %f" % (bounds_components[1], bounds_components[3])) return HttpResponseBadRequest("y out of range %f or %f" % (bounds_components[1], bounds_components[3])) ll = Point(bounds_components[0], bounds_components[1], srid=4326) ll.transform(render_srid) ur = Point(bounds_components[2], bounds_components[3], srid=4326) ur.transform(render_srid) bounds_box = mapnik.Box2d(ll.x, ll.y, ur.x, ur.y) elif center: center_components = center.split(',') if len(center_components) != 3: return HttpResponseBadRequest() lon = float(center_components[0]) lat = float(center_components[1]) zoom = int(center_components[2]) # todo calc bounds from center and zoom # baselayer if background not in settings.BASE_LAYERS and background != 'none': return HttpResponseNotFound("Background not found") # GeoJSON post data if request.method == "POST" and len(request.body): input_data = json.loads(request.body) else: input_data = None if not bounds and not center and not input_data: return HttpResponseBadRequest("Bounds, center, or post data is required.") # initialize map m = mapnik.Map(width, height) m.srs = '+init=epsg:' + str(render_srid) # add a tile source as a background if background != "none": background_file = settings.BASE_LAYERS[background] background_style = mapnik.Style() background_rule = mapnik.Rule() background_rule.symbols.append(mapnik.RasterSymbolizer()) background_style.rules.append(background_rule) m.append_style('background style', background_style) tile_layer = mapnik.Layer('background') tile_layer.srs = '+init=epsg:' + str(render_srid) tile_layer.datasource = mapnik.Gdal(base=settings.BASE_LAYER_DIR, file=background_file) tile_layer.styles.append('background style') m.layers.append(tile_layer) # add features from geojson if input_data and input_data['type'] == "Feature": features = [input_data] elif input_data and input_data['type'] == "FeatureCollection": if 'features' not in input_data: return HttpResponseBadRequest() features = input_data['features'] else: features = [] logging.debug("Adding %d features to map" % len(features)) geometries = [] point_features = [] fid = 0 for feature in features: if 'geometry' not in feature: logging.debug("feature does not have geometry") return HttpResponseBadRequest("Feature does not have a geometry") if 'type' not in feature['geometry']: logging.debug("geometry does not have type") return HttpResponseBadRequest("Geometry does not have a type") fid += 1 style_name = str(fid) if feature['geometry']['type'] == 'Point': point_features.append(feature) elif feature['geometry']['type'] in ('LineString', 'MultiLineString'): if feature['geometry']['type'] == 'LineString': geos_feature = LineString(feature['geometry']['coordinates']) elif feature['geometry']['type'] == 'MultiLineString': rings = feature['geometry']['coordinates'] rings = [[(c[0], c[1]) for c in r] for r in rings] if len(rings) == 1: geos_feature = LineString(rings[0]) else: linestrings = [] for ring in rings: try: linestrings.append(LineString(ring)) except Exception, e: logging.error("Error adding ring: %s", e) geos_feature = MultiLineString(linestrings) geos_feature.srid = 4326 geos_feature.transform(render_srid) geometries.append(geos_feature) style = mapnik.Style() line_rule = mapnik.Rule() style_dict = None if 'style' in feature: style_dict = feature['style'] elif 'properties' in feature: style_dict = feature['properties'] line_rule.symbols.append(line_symbolizer(style_dict)) style.rules.append(line_rule) m.append_style(style_name, style) wkt = geos_feature.wkt line_layer = mapnik.Layer(style_name + ' layer') line_layer.datasource = mapnik.CSV(inline='wkt\n' + '"' + wkt + '"') line_layer.styles.append(style_name) line_layer.srs = '+init=epsg:' + str(render_srid) m.layers.append(line_layer) elif feature['geometry']['type'] == 'Polygon' or feature['geometry']['type'] == 'MultiPolygon': geos_feature = GEOSGeometry(json.dumps(feature['geometry'])) geos_feature.srid = 4326 geos_feature.transform(render_srid) geometries.append(geos_feature) style = mapnik.Style() rule = mapnik.Rule() style_dict = None if 'style' in feature: style_dict = feature['style'] elif 'properties' in feature: style_dict = feature['properties'] rule.symbols.append(polygon_symbolizer(style_dict)) rule.symbols.append(line_symbolizer(style_dict)) style.rules.append(rule) m.append_style(style_name, style) wkt = geos_feature.wkt layer = mapnik.Layer(style_name + ' layer') layer.datasource = mapnik.CSV(inline='wkt\n' + '"' + wkt + '"') layer.styles.append(style_name) layer.srs = '+init=epsg:' + str(render_srid) m.layers.append(layer)
def render_static(request, height=None, width=None, format='png', background='satellite', bounds=None, center=None, render_srid=3857): # width and height width = int(width) height = int(height) if width > settings.MAX_IMAGE_DIMENSION or \ height > settings.MAX_IMAGE_DIMENSION or \ width <= 1 or height <= 1: logging.debug("Invalid size") return HttpResponseBadRequest( "Invalid image size, both dimensions must be in range %i-%i" % (1, settings.MAX_IMAGE_DIMENSION)) # image format if format not in IMAGE_FORMATS: logging.error("unknown image format %s" % format) return HttpResponseBadRequest( "Unknown image format, available formats: " + ", ".join(IMAGE_FORMATS)) if format.startswith('png'): mimetype = 'image/png' elif format.startswith('jpeg'): mimetype = 'image/jpeg' # bounds bounds_box = None if bounds: bounds_components = bounds.split(',') if len(bounds_components) != 4: return HttpResponseBadRequest( "Invalid bounds, must be 4 , separated numbers") bounds_components = [float(f) for f in bounds_components] if not (-180 < bounds_components[0] < 180) or not (-180 < bounds_components[2] < 180): logging.error("x out of range %f or %f" % (bounds_components[0], bounds_components[2])) return HttpResponseBadRequest( "x out of range %f or %f" % (bounds_components[0], bounds_components[2])) if not (-90 < bounds_components[1] < 90) or not (-90 < bounds_components[3] < 90): logging.error("y out of range %f or %f" % (bounds_components[1], bounds_components[3])) return HttpResponseBadRequest( "y out of range %f or %f" % (bounds_components[1], bounds_components[3])) ll = Point(bounds_components[0], bounds_components[1], srid=4326) ll.transform(render_srid) ur = Point(bounds_components[2], bounds_components[3], srid=4326) ur.transform(render_srid) bounds_box = mapnik.Box2d(ll.x, ll.y, ur.x, ur.y) elif center: center_components = center.split(',') if len(center_components) != 3: return HttpResponseBadRequest() lon = float(center_components[0]) lat = float(center_components[1]) zoom = int(center_components[2]) # todo calc bounds from center and zoom # baselayer if background not in settings.BASE_LAYERS and background != 'none': return HttpResponseNotFound("Background not found") # GeoJSON post data if request.method == "POST" and len(request.body): input_data = json.loads(request.body) else: input_data = None if not bounds and not center and not input_data: return HttpResponseBadRequest( "Bounds, center, or post data is required.") # initialize map m = mapnik.Map(width, height) m.srs = '+init=epsg:' + str(render_srid) # add a tile source as a background if background != "none": background_file = settings.BASE_LAYERS[background] background_style = mapnik.Style() background_rule = mapnik.Rule() background_rule.symbols.append(mapnik.RasterSymbolizer()) background_style.rules.append(background_rule) m.append_style('background style', background_style) tile_layer = mapnik.Layer('background') tile_layer.srs = '+init=epsg:' + str(render_srid) tile_layer.datasource = mapnik.Gdal(base=settings.BASE_LAYER_DIR, file=background_file) tile_layer.styles.append('background style') m.layers.append(tile_layer) # add features from geojson if input_data and input_data['type'] == "Feature": features = [input_data] elif input_data and input_data['type'] == "FeatureCollection": if 'features' not in input_data: return HttpResponseBadRequest() features = input_data['features'] else: features = [] logging.debug("Adding %d features to map" % len(features)) geometries = [] point_features = [] fid = 0 for feature in features: if 'geometry' not in feature: logging.debug("feature does not have geometry") return HttpResponseBadRequest("Feature does not have a geometry") if 'type' not in feature['geometry']: logging.debug("geometry does not have type") return HttpResponseBadRequest("Geometry does not have a type") fid += 1 style_name = str(fid) if feature['geometry']['type'] == 'Point': point_features.append(feature) elif feature['geometry']['type'] in ('LineString', 'MultiLineString'): if feature['geometry']['type'] == 'LineString': geos_feature = LineString(feature['geometry']['coordinates']) elif feature['geometry']['type'] == 'MultiLineString': rings = feature['geometry']['coordinates'] rings = [[(c[0], c[1]) for c in r] for r in rings] if len(rings) == 1: geos_feature = LineString(rings[0]) else: linestrings = [] for ring in rings: try: linestrings.append(LineString(ring)) except Exception, e: logging.error("Error adding ring: %s", e) geos_feature = MultiLineString(linestrings) geos_feature.srid = 4326 geos_feature.transform(render_srid) geometries.append(geos_feature) style = mapnik.Style() line_rule = mapnik.Rule() style_dict = None if 'style' in feature: style_dict = feature['style'] elif 'properties' in feature: style_dict = feature['properties'] line_rule.symbols.append(line_symbolizer(style_dict)) style.rules.append(line_rule) m.append_style(style_name, style) wkt = geos_feature.wkt line_layer = mapnik.Layer(style_name + ' layer') line_layer.datasource = mapnik.CSV(inline='wkt\n' + '"' + wkt + '"') line_layer.styles.append(style_name) line_layer.srs = '+init=epsg:' + str(render_srid) m.layers.append(line_layer) elif feature['geometry']['type'] == 'Polygon': geos_feature = GEOSGeometry(json.dumps(feature['geometry'])) geos_feature.srid = 4326 geos_feature.transform(render_srid) geometries.append(geos_feature) style = mapnik.Style() rule = mapnik.Rule() style_dict = None if 'style' in feature: style_dict = feature['style'] elif 'properties' in feature: style_dict = feature['properties'] rule.symbols.append(polygon_symbolizer(style_dict)) rule.symbols.append(line_symbolizer(style_dict)) style.rules.append(rule) m.append_style(style_name, style) wkt = geos_feature.wkt layer = mapnik.Layer(style_name + ' layer') layer.datasource = mapnik.CSV(inline='wkt\n' + '"' + wkt + '"') layer.styles.append(style_name) layer.srs = '+init=epsg:' + str(render_srid) m.layers.append(layer)
def get_filters(self, containment="overlaps"): """ Filter a :class:`Django QuerySet <django.db.models.query.QuerySet>` of objects inheriting from :class:`EOObject <eoxserver.resources.coverages.models.EOObject>`. :param queryset: the ``QuerySet`` to filter :param containment: either "overlaps" or "contains" :returns: a ``dict`` with the filters """ filters = {} if not len(self): return filters bbox = [None, None, None, None] srid = self.srid if srid is None: srid = 4326 max_extent = crss.crs_bounds(srid) tolerance = crss.crs_tolerance(srid) # check if time intervals are configured as "open" or "closed" config = get_eoxserver_config() reader = SubsetConfigReader(config) if reader.time_interval_interpretation == "closed": gt_op = "__gte" lt_op = "__lte" else: gt_op = "__gt" lt_op = "__lt" for subset in self: if isinstance(subset, Slice): is_slice = True value = subset.value elif isinstance(subset, Trim): is_slice = False low = subset.low high = subset.high # we need the value in case low == high value = low if subset.is_temporal: if is_slice or (high == low and containment == "overlaps"): filters['begin_time__lte'] = value filters['end_time__gte'] = value elif high == low: filters['begin_time__gte'] = value filters['end_time__lte'] = value else: # check if the temporal bounds must be strictly contained if containment == "contains": if high is not None: filters['end_time' + lt_op] = high if low is not None: filters['begin_time' + gt_op] = low # or just overlapping else: if high is not None: filters['begin_time' + lt_op] = high if low is not None: filters['end_time' + gt_op] = low else: if is_slice: if subset.is_x: line = LineString( (value, max_extent[1]), (value, max_extent[3]) ) else: line = LineString( (max_extent[0], value), (max_extent[2], value) ) line.srid = srid if srid != 4326: line.transform(4326) filters['footprint__intersects'] = line else: if subset.is_x: bbox[0] = subset.low bbox[2] = subset.high else: bbox[1] = subset.low bbox[3] = subset.high if bbox != [None, None, None, None]: bbox = list(map( lambda v: v[0] if v[0] is not None else v[1], zip(bbox, max_extent) )) bbox[0] -= tolerance bbox[1] -= tolerance bbox[2] += tolerance bbox[3] += tolerance logger.debug( "Applying BBox %s with containment '%s'." % (bbox, containment) ) poly = Polygon.from_bbox(bbox) poly.srid = srid if srid != 4326: poly.transform(4326) if containment == "overlaps": filters['footprint__intersects'] = poly elif containment == "contains": filters['footprint__within'] = poly return filters
def matches(self, eo_object, containment="overlaps"): """ Check if the given :class:`EOObject <eoxserver.resources.coverages.models.EOObject>` matches the given subsets. :param eo_object: the ``EOObject`` to match :param containment: either "overlaps" or "contains" :returns: a boolean value indicating if the object is contained in the given subsets """ if not len(self): return True bbox = [None, None, None, None] srid = self.srid if srid is None: srid = 4326 max_extent = crss.crs_bounds(srid) tolerance = crss.crs_tolerance(srid) # check if time intervals are configured as "open" or "closed" config = get_eoxserver_config() reader = SubsetConfigReader(config) # note that the operator is inverted from filter() above as the # filters use an inclusive search whereas here it's exclusive if reader.time_interval_interpretation == "closed": gt_op = operator.gt lt_op = operator.lt else: gt_op = operator.ge lt_op = operator.le footprint = eo_object.footprint begin_time = eo_object.begin_time end_time = eo_object.end_time for subset in self: if isinstance(subset, Slice): is_slice = True value = subset.value elif isinstance(subset, Trim): is_slice = False low = subset.low high = subset.high # we need the value in case low == high value = low if subset.is_temporal: if is_slice or (low == high and containment == "overlaps"): if begin_time > value or end_time < value: return False elif low == high: if begin_time < value or end_time > value: return False else: # check if the temporal bounds must be strictly contained if containment == "contains": if high is not None: if gt_op(end_time, high): return False if low is not None: if lt_op(begin_time, low): return False # or just overlapping else: if high is not None: if gt_op(begin_time, high): return False if low is not None: if lt_op(end_time, low): return False else: if is_slice: if subset.is_x: line = LineString( (value, max_extent[1]), (value, max_extent[3]) ) else: line = LineString( (max_extent[0], value), (max_extent[2], value) ) line.srid = srid if srid != 4326: line.transform(4326) if not line.intersects(footprint): return False else: if subset.is_x: bbox[0] = subset.low bbox[2] = subset.high else: bbox[1] = subset.low bbox[3] = subset.high if bbox != [None, None, None, None]: bbox = map( lambda v: v[0] if v[0] is not None else v[1], zip(bbox, max_extent) ) bbox[0] -= tolerance bbox[1] -= tolerance bbox[2] += tolerance bbox[3] += tolerance logger.debug( "Applying BBox %s with containment '%s'." % (bbox, containment) ) poly = Polygon.from_bbox(bbox) poly.srid = srid if srid != 4326: poly.transform(4326) if containment == "overlaps": if not footprint.intersects(poly): return False elif containment == "contains": if not footprint.within(poly): return False return True
def filter(self, queryset, containment="overlaps"): """ Filter a :class:`Django QuerySet <django.db.models.query.QuerySet>` of objects inheriting from :class:`EOObject <eoxserver.resources.coverages.models.EOObject>`. :param queryset: the ``QuerySet`` to filter :param containment: either "overlaps" or "contains" :returns: a ``QuerySet`` with additional filters applied """ if not len(self): return queryset qs = queryset bbox = [None, None, None, None] srid = self.srid if srid is None: srid = 4326 max_extent = crss.crs_bounds(srid) tolerance = crss.crs_tolerance(srid) # check if time intervals are configured as "open" or "closed" config = get_eoxserver_config() reader = SubsetConfigReader(config) if reader.time_interval_interpretation == "closed": gt_op = "__gte" lt_op = "__lte" else: gt_op = "__gt" lt_op = "__lt" for subset in self: if isinstance(subset, Slice): is_slice = True value = subset.value elif isinstance(subset, Trim): is_slice = False low = subset.low high = subset.high # we need the value in case low == high value = low if subset.is_temporal: if is_slice or (high == low and containment == "overlaps"): qs = qs.filter( begin_time__lte=value, end_time__gte=value ) elif high == low: qs = qs.filter( begin_time__gte=value, end_time__lte=value ) else: # check if the temporal bounds must be strictly contained if containment == "contains": if high is not None: qs = qs.filter(**{ "end_time" + lt_op: high }) if low is not None: qs = qs.filter(**{ "begin_time" + gt_op: low }) # or just overlapping else: if high is not None: qs = qs.filter(**{ "begin_time" + lt_op: high }) if low is not None: qs = qs.filter(**{ "end_time" + gt_op: low }) else: if is_slice: if subset.is_x: line = LineString( (value, max_extent[1]), (value, max_extent[3]) ) else: line = LineString( (max_extent[0], value), (max_extent[2], value) ) line.srid = srid if srid != 4326: line.transform(4326) qs = qs.filter(footprint__intersects=line) else: if subset.is_x: bbox[0] = subset.low bbox[2] = subset.high else: bbox[1] = subset.low bbox[3] = subset.high if bbox != [None, None, None, None]: bbox = map( lambda v: v[0] if v[0] is not None else v[1], zip(bbox, max_extent) ) bbox[0] -= tolerance bbox[1] -= tolerance bbox[2] += tolerance bbox[3] += tolerance logger.debug( "Applying BBox %s with containment '%s'." % (bbox, containment) ) poly = Polygon.from_bbox(bbox) poly.srid = srid if srid != 4326: poly.transform(4326) if containment == "overlaps": qs = qs.filter(footprint__intersects=poly) elif containment == "contains": qs = qs.filter(footprint__within=poly) return qs
def matches(self, eo_object, containment="overlaps"): if not len(self): return True bbox = [None, None, None, None] srid = self.srid if srid is None: srid = 4326 max_extent = crss.crs_bounds(srid) tolerance = crss.crs_tolerance(srid) footprint = eo_object.footprint begin_time = eo_object.begin_time end_time = eo_object.end_time for subset in self: if isinstance(subset, Slice): is_slice = True value = subset.value elif isinstance(subset, Trim): is_slice = False low = subset.low high = subset.high if subset.is_temporal: if is_slice: if begin_time > value or end_time < value: return False elif low is None and high is not None: if begin_time > high: return False elif low is not None and high is None: if end_time < low: return False else: if begin_time > high or end_time < low: return False else: if is_slice: if subset.is_x: line = LineString( (value, max_extent[1]), (value, max_extent[3]) ) else: line = LineString( (max_extent[0], value), (max_extent[2], value) ) line.srid = srid if srid != 4326: line.transform(4326) if not line.intersects(footprint): return False else: if subset.is_x: bbox[0] = subset.low bbox[2] = subset.high else: bbox[1] = subset.low bbox[3] = subset.high if bbox != [None, None, None, None]: bbox = map( lambda v: v[0] if v[0] is not None else v[1], zip(bbox, max_extent) ) bbox[0] -= tolerance bbox[1] -= tolerance bbox[2] += tolerance bbox[3] += tolerance logger.debug( "Applying BBox %s with containment '%s'." % (bbox, containment) ) poly = Polygon.from_bbox(bbox) poly.srid = srid if srid != 4326: poly.transform(4326) if containment == "overlaps": if not footprint.intersects(poly): return False elif containment == "contains": if not footprint.within(poly): return False return True
def line(self): geom = LineString([(x, y) for x, y, _, _ in self.gcps]) geom.srid = self._srid if self._srid != 4326: geom.transform(4326) return geom
def path(self): points = map(lambda cm: cm.mark.location, self.coursemark_set.all()) if len(points): path = LineString(*points) path.srid = SRID return path