def get_bbox(instance, crs='EPSG:3857'): if crs is None: crs = 'EPSG:3857' minlon = min(float(instance.bbox_x0), float(instance.bbox_x1)) minlat = min(float(instance.bbox_y0), float(instance.bbox_y1)) maxlon = max(float(instance.bbox_x0), float(instance.bbox_x1)) maxlat = max(float(instance.bbox_y0), float(instance.bbox_y1)) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range # create a buffer minlon = max(-180, minlon - lon_range * .1) minlat = max(-90, minlat - lat_range * .1) maxlon = min(180, maxlon + lon_range * .1) maxlat = min(90, maxlat + lat_range * .1) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range if ratio < 200.0 / 150.0: lon_shift = abs(.5 * ((200.0 / 150.0 * lat_range) - lon_range)) minlon = max(-180, minlon - lon_shift) maxlon = min(180, maxlon + lon_shift) else: adjusted_range = 150.0 / 200.0 * lon_range range_delta = adjusted_range - lat_range lat_shift = abs(.5 * range_delta) minlat = max(-90, minlat - lat_shift) maxlat = min(90, maxlat + lat_shift) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range height = int(200 / ratio) logger.debug('height: %s', height) if crs == 'EPSG:3857': # create bbox in 3857 minx, miny = forward_mercator([minlon, max(-85.0, minlat)]) maxx, maxy = forward_mercator([maxlon, min(85.0, maxlat)]) bbox = '%s,%s,%s,%s' % (minx, miny, maxx, maxy) return bbox, height elif crs == 'EPSG:4326': # deal with weird bbox order for geographic coords in wms 1.3.0 bbox = '%s,%s,%s,%s' % (minlat, minlon, maxlat, maxlon) return bbox, height elif crs == 'CRS:84': # crs84 bbox bbox = '%s,%s,%s,%s' % (minlon, minlat, maxlon, maxlat) return bbox, height logger.debug('***************Could not determine BBOX***********')
def test_forward_mercator(self): arctic = forward_mercator((0, 85)) antarctic = forward_mercator((0, -85)) hawaii = forward_mercator((-180, 0)) phillipines = forward_mercator((180, 0)) ne = forward_mercator((180, 90)) sw = forward_mercator((-180, -90)) inf_test = forward_mercator( (-8.988465674311579e+307, -8.988465674311579e+307) ) self.assertEqual(inf_test[0], float('-inf')) self.assertEqual(inf_test[1], float('-inf')) self.assertEqual(round(arctic[0]), 0, "Arctic longitude is correct") self.assertEqual( round( arctic[1]), 19971869, "Arctic latitude is correct") self.assertEqual( round( antarctic[0]), 0, "Antarctic longitude is correct") self.assertEqual( round( antarctic[1]), -19971869, "Antarctic latitude is correct") self.assertEqual( round( hawaii[0]), -20037508, "Hawaiian lon is correct") self.assertEqual(round(hawaii[1]), 0, "Hawaiian lat is correct") self.assertEqual( round( phillipines[0]), 20037508, "Phillipines lon is correct") self.assertEqual( round( phillipines[1]), 0, "Phillipines lat is correct") self.assertEqual(round(ne[0]), 20037508, "NE lon is correct") self.assertTrue(ne[1] > 50000000, "NE lat is correct") self.assertEqual(round(sw[0]), -20037508, "SW lon is correct") self.assertTrue(math.isinf(sw[1]), "SW lat is correct") # verify behavior for invalid y values self.assertEqual(float('-inf'), forward_mercator((0, 135))[1]) self.assertEqual(float('-inf'), forward_mercator((0, -135))[1])
def set_bounds_from_bbox(self, bbox): """ Calculate zoom level and center coordinates in mercator. :param bbox: BBOX is in the format: [x0, x1, y0, y1], which is: [min lon, max lon, min lat, max lat] or [xmin, xmax, ymin, ymax] :type bbox: list """ self.set_latlon_bounds(bbox) minx, maxx, miny, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 (center_x, center_y) = forward_mercator((x, y)) xdiff = maxx - minx ydiff = maxy - miny zoom = 0 if xdiff > 0 and ydiff > 0: width_zoom = math.log(360 / xdiff, 2) height_zoom = math.log(360 / ydiff, 2) zoom = math.ceil(min(width_zoom, height_zoom)) self.zoom = zoom self.center_x = center_x self.center_y = center_y
def create_from_layer_list(self, user, layers, title, abstract): self.owner = user self.title = title self.abstract = abstract self.projection="EPSG:900913" self.zoom = 0 self.center_x = 0 self.center_y = 0 map_layers = [] bbox = None index = 0 DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() layer_objects = [] for layer in layers: try: layer = Layer.objects.get(typename=layer) except ObjectDoesNotExist: continue # Raise exception? if not user.has_perm('maps.view_layer', obj=layer): # invisible layer, skip inclusion or raise Exception? continue # Raise Exception layer_objects.append(layer) map_layers.append(MapLayer( map = self, name = layer.typename, ows_url = settings.GEOSERVER_BASE_URL + "wms", stack_order = index, visibility = True )) bbox = self.set_bounds_from_layers(layer_objects) if bbox is not None: minx, maxx, miny, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 (self.center_x,self.center_y) = forward_mercator((x,y)) width_zoom = math.log(360 / (maxx - minx), 2) height_zoom = math.log(360 / (maxy - miny), 2) self.zoom = math.ceil(min(width_zoom, height_zoom)) index += 1 self.save() for bl in DEFAULT_BASE_LAYERS: bl.map = self #bl.save() for ml in map_layers: ml.map = self # update map_id after saving map ml.save() self.set_default_permissions()
def create_from_layer_list(self, user, layers, title, abstract): self.owner = user self.title = title self.abstract = abstract self.projection="EPSG:900913" self.zoom = 0 self.center_x = 0 self.center_y = 0 map_layers = [] bbox = None index = 0 DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() layer_objects = [] for layer in layers: try: layer = Layer.objects.get(typename=layer) except ObjectDoesNotExist: continue # Raise exception? if not user.has_perm('maps.view_layer', obj=layer): # invisible layer, skip inclusion or raise Exception? continue # Raise Exception layer_objects.append(layer) map_layers.append(MapLayer( map = self, name = layer.typename, ows_url = layer.ows_url(), stack_order = index, visibility = True )) bbox = self.set_bounds_from_layers(layer_objects) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 (self.center_x,self.center_y) = forward_mercator((x,y)) width_zoom = math.log(360 / (maxx - minx), 2) height_zoom = math.log(360 / (maxy - miny), 2) self.zoom = math.ceil(min(width_zoom, height_zoom)) index += 1 self.save() for bl in DEFAULT_BASE_LAYERS: bl.map = self #bl.save() for ml in map_layers: ml.map = self # update map_id after saving map ml.save() self.set_default_permissions()
def test_inverse_mercator(self): arctic = inverse_mercator(forward_mercator((0, 85))) antarctic = inverse_mercator(forward_mercator((0, -85))) hawaii = inverse_mercator(forward_mercator((-180, 0))) phillipines = inverse_mercator(forward_mercator((180, 0))) ne = inverse_mercator(forward_mercator((180, 90))) sw = inverse_mercator(forward_mercator((-180, -90))) self.assertAlmostEqual(arctic[0], 0.0, msg="Arctic longitude is correct") self.assertAlmostEqual(arctic[1], 85.0, msg="Arctic latitude is correct") self.assertAlmostEqual(antarctic[0], 0.0, msg="Antarctic longitude is correct") self.assertAlmostEqual(antarctic[1], -85.0, msg="Antarctic latitude is correct") self.assertAlmostEqual(hawaii[0], -180.0, msg="Hawaiian lon is correct") self.assertAlmostEqual(hawaii[1], 0.0, msg="Hawaiian lat is correct") self.assertAlmostEqual(phillipines[0], 180.0, msg="Phillipines lon is correct") self.assertAlmostEqual(phillipines[1], 0.0, msg="Phillipines lat is correct") self.assertAlmostEqual(ne[0], 180.0, msg="NE lon is correct") self.assertAlmostEqual(ne[1], 90.0, msg="NE lat is correct") self.assertAlmostEqual(sw[0], -180.0, msg="SW lon is correct") self.assertAlmostEqual(sw[1], -90.0, msg="SW lat is correct")
def set_bounds_from_bbox(self, bbox, srid): """ Calculate zoom level and center coordinates in mercator. :param bbox: BBOX is in the format: [x0, x1, y0, y1], which is: [min lon, max lon, min lat, max lat] or [xmin, xmax, ymin, ymax] :type bbox: list """ if not bbox or len(bbox) < 4: raise ValidationError( 'Bounding Box cannot be empty %s for a given resource' % self.name) if not srid: raise ValidationError( 'Projection cannot be empty %s for a given resource' % self.name) self.bbox_x0 = bbox[0] self.bbox_x1 = bbox[1] self.bbox_y0 = bbox[2] self.bbox_y1 = bbox[3] self.srid = srid if srid == "EPSG:4326": minx, maxx, miny, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 (center_x, center_y) = forward_mercator((x, y)) xdiff = maxx - minx ydiff = maxy - miny zoom = 0 if xdiff > 0 and ydiff > 0: width_zoom = math.log(360 / xdiff, 2) height_zoom = math.log(360 / ydiff, 2) zoom = math.ceil(min(width_zoom, height_zoom)) try: self.zoom = zoom self.center_x = center_x self.center_y = center_y except BaseException: pass
def set_bounds_from_bbox(bbox): """ Calculate zoom level and center coordinates in mercator. """ minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 (center_x, center_y) = forward_mercator((y, x)) xdiff = maxx - minx ydiff = maxy - miny zoom = 0 if xdiff > 0 and ydiff > 0: width_zoom = math.log(360 / xdiff, 2) height_zoom = math.log(360 / ydiff, 2) zoom = math.ceil(min(width_zoom, height_zoom)) zoom = zoom center_x = center_x center_y = center_y return zoom, center_x, center_y
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user, access_token) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be sent to remote services. ogc_server_url = urlparse.urlsplit(ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url+'?access_token='+access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name})) else: ogc_server_url = urlparse.urlsplit(ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url+'?access_token='+access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.typename, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True ) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json( request.user, access_token, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def layer_detail(request, layername, template='layers/layer_detail.html'): layer = _resolve_layer( request, layername, 'base.view_resourcebase', _("You are not permitted to view this layer")) # assert False, str(layer_bbox) config = layer.attribute_config() # Add required parameters for GXP lazy-loading layer_bbox = layer.bbox bbox = [float(coord) for coord in list(layer_bbox[0:4])] config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) config["title"] = layer.title config["queryable"] = True if layer.default_style: config["styles"] = layer.default_style.name if layer.storeType == "remoteStore": source_srid = None # Only grab the service proj/bbox if it is valid if None not in layer.service.bbox[0:4]: bbox = [float(coord) for coord in list(layer.service.bbox[0:4])] source_srid = layer.service.srid # Otherwise try the service directly # This is needed since previous services registered # did not store the bbox/srid in the model else: try: service_handler = get_service_handler( base_url=layer.service.base_url, service_type=layer.service.type) if getattr(service_handler.parsed_service, 'initialExtent', None): bbox[0] = service_handler.parsed_service.initialExtent[ 'xmin'] bbox[1] = service_handler.parsed_service.initialExtent[ 'ymin'] bbox[2] = service_handler.parsed_service.initialExtent[ 'xmax'] bbox[3] = service_handler.parsed_service.initialExtent[ 'ymax'] else: logger.info('Could not retrieve extent from service: {0}' .format(layer.service)) if getattr(service_handler.parsed_service, 'spatialReference', None): source_srid = \ service_handler.parsed_service.spatialReference[ 'latestWkid'] else: logger.info('Could not retrieve srid from service: {0}' .format(layer.service)) except Exception as e: logger.info('Failed to access service endpoint: {0}' .format(layer.service.base_url)) logger.info('Caught error: {0}'.format(e)) if source_srid is None: source_srid = layer.srid target_srid = 3857 if config["srs"] == 'EPSG:900913' else config["srs"] reprojected_bbox = bbox_to_projection(bbox, source_srid=source_srid, target_srid=target_srid) bbox = reprojected_bbox[:4] config['bbox'] = [float(coord) for coord in bbox] service = layer.service source_url = service.base_url use_proxy = (callable(uses_proxy_route) and uses_proxy_route(service.base_url)) components = urlsplit(service.base_url) query_params = None if components.query: query_params = OrderedDict( parse_qsl(components.query, keep_blank_values=True)) removed_query = [components.scheme, components.netloc, components.path, None, components.fragment] source_url = urlunsplit(removed_query) source_params = { "ptype": service.ptype, "remote": True, "url": source_url, "name": service.name, "use_proxy": use_proxy} if query_params is not None: source_params["params"] = query_params if layer.alternate is not None: config["layerid"] = layer.alternate maplayer = GXPLayer( name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer( name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter( id=layer.id).update(popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap( projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) granules = None all_granules = None filter = None if layer.is_mosaic: try: cat = gs_catalog cat._cache.clear() store = cat.get_store(layer.name) coverages = cat.mosaic_coverages(store) filter = None try: if request.GET["filter"]: filter = request.GET["filter"] except: pass offset = 10 * (request.page - 1) granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, limit=10, offset=offset, filter=filter) all_granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, filter=filter) except: granules = {"features": []} all_granules = {"features": []} context_dict = { "resource": layer, 'perms_list': get_perms(request.user, layer.get_self_resource()), "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "granules": granules, "all_granules": all_granules, "filter": filter, } if 'access_token' in request.session: access_token = request.session['access_token'] else: u = uuid.uuid1() access_token = u.hex if bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if layer.is_remote or getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, access_token, *(default_map_config(request)[1] + [maplayer]))) context_dict["preview"] = getattr( settings, 'LAYER_PREVIEW_LIBRARY', 'leaflet') context_dict["crs"] = getattr( settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) links_view = [item for idx, item in enumerate(links) if item.url and 'wms' in item.url or 'gwc' in item.url] links_download = [item for idx, item in enumerate(links) if item.url and 'wms' not in item.url and 'gwc' not in item.url] for item in links_view: if item.url and access_token: item.url = "%s&access_token=%s&time=%s" % \ (item.url, access_token, "0/9999") for item in links_download: if item.url and access_token: item.url = "%s&access_token=%s" % (item.url, access_token) if request.user.has_perm('view_resourcebase', layer.get_self_resource()): context_dict["links"] = links_view if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links_download"] = links_download if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) return render_to_response(template, RequestContext(request, context_dict))
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map( projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name })) else: maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json(request.user, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def layer_detail(request, layername, template='layers/layer_detail.html'): layer = _resolve_layer(request, layername, 'base.view_resourcebase', _("You are not permitted to view this layer")) # assert False, str(layer_bbox) config = layer.attribute_config() # Add required parameters for GXP lazy-loading layer_bbox = layer.bbox bbox = [float(coord) for coord in list(layer_bbox[0:4])] config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) config["title"] = layer.title config["queryable"] = True if layer.default_style: config["styles"] = layer.default_style.name if layer.storeType == "remoteStore": source_srid = None # Only grab the service proj/bbox if it is valid if None not in layer.service.bbox[0:4]: bbox = [float(coord) for coord in list(layer.service.bbox[0:4])] source_srid = layer.service.srid # Otherwise try the service directly # This is needed since previous services registered # did not store the bbox/srid in the model else: try: service_handler = get_service_handler( base_url=layer.service.base_url, service_type=layer.service.type) if getattr(service_handler.parsed_service, 'initialExtent', None): bbox[0] = service_handler.parsed_service.initialExtent[ 'xmin'] bbox[1] = service_handler.parsed_service.initialExtent[ 'ymin'] bbox[2] = service_handler.parsed_service.initialExtent[ 'xmax'] bbox[3] = service_handler.parsed_service.initialExtent[ 'ymax'] else: logger.info( 'Could not retrieve extent from service: {0}'.format( layer.service)) if getattr(service_handler.parsed_service, 'spatialReference', None): source_srid = \ service_handler.parsed_service.spatialReference[ 'latestWkid'] else: logger.info( 'Could not retrieve srid from service: {0}'.format( layer.service)) except Exception as e: logger.info('Failed to access service endpoint: {0}'.format( layer.service.base_url)) logger.info('Caught error: {0}'.format(e)) if source_srid is None: source_srid = layer.srid target_srid = 3857 if config["srs"] == 'EPSG:900913' else config["srs"] reprojected_bbox = bbox_to_projection(bbox, source_srid=source_srid, target_srid=target_srid) bbox = reprojected_bbox[:4] config['bbox'] = [float(coord) for coord in bbox] service = layer.service source_url = service.base_url use_proxy = (callable(uses_proxy_route) and uses_proxy_route(service.base_url)) components = urlsplit(service.base_url) query_params = None if components.query: query_params = OrderedDict( parse_qsl(components.query, keep_blank_values=True)) removed_query = [ components.scheme, components.netloc, components.path, None, components.fragment ] source_url = urlunsplit(removed_query) source_params = { "ptype": service.ptype, "remote": True, "url": source_url, "name": service.name, "use_proxy": use_proxy } if query_params is not None: source_params["params"] = query_params if layer.alternate is not None: config["layerid"] = layer.alternate maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter(id=layer.id).update( popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap( projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) granules = None all_granules = None filter = None if layer.is_mosaic: try: cat = gs_catalog cat._cache.clear() store = cat.get_store(layer.name) coverages = cat.mosaic_coverages(store) filter = None try: if request.GET["filter"]: filter = request.GET["filter"] except: pass offset = 10 * (request.page - 1) granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, limit=10, offset=offset, filter=filter) all_granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, filter=filter) except: granules = {"features": []} all_granules = {"features": []} context_dict = { "resource": layer, 'perms_list': get_perms(request.user, layer.get_self_resource()), "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "granules": granules, "all_granules": all_granules, "filter": filter, } if 'access_token' in request.session: access_token = request.session['access_token'] else: u = uuid.uuid1() access_token = u.hex if bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if layer.is_remote or getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, access_token, *(default_map_config(request)[1] + [maplayer]))) context_dict["preview"] = getattr(settings, 'LAYER_PREVIEW_LIBRARY', 'leaflet') context_dict["crs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) links_view = [ item for idx, item in enumerate(links) if item.url and 'wms' in item.url or 'gwc' in item.url ] links_download = [ item for idx, item in enumerate(links) if item.url and 'wms' not in item.url and 'gwc' not in item.url ] for item in links_view: if item.url and access_token: item.url = "%s&access_token=%s&time=%s" % \ (item.url, access_token, "0/9999") for item in links_download: if item.url and access_token: item.url = "%s&access_token=%s" % (item.url, access_token) if request.user.has_perm('view_resourcebase', layer.get_self_resource()): context_dict["links"] = links_view if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links_download"] = links_download if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) return render_to_response(template, RequestContext(request, context_dict))
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) bbox = None layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not layer.is_published: # invisible layer, skip inclusion continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for a WM layer title = 'No title' if layer.title: title = layer.title config["title"] = title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be # sent to remote services. ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc access_token = request.session[ 'access_token'] if request and 'access_token' in request.session else None if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url + '?access_token=' + access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name })) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox is not None: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json(request, *layers_to_add) config['fromLayer'] = True return config
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None bbox = None layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not layer.is_published: # invisible layer, skip inclusion continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["wrapDateLine"] = True config["srs"] = getattr( settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be # sent to remote services. ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url + '?access_token=' + access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name})) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True ) layers.append(maplayer) if bbox is not None: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr( settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json( request.user, access_token, *layers_to_add) config['fromLayer'] = True return config
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None bbox = [] layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not layer.is_published: # invisible layer, skip inclusion continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox[0:4] bbox = layer_bbox[:] bbox[0] = layer_bbox[0] bbox[1] = layer_bbox[2] bbox[2] = layer_bbox[1] bbox[3] = layer_bbox[3] # assert False, str(layer_bbox) def decimal_encode(bbox): import decimal _bbox = [] for o in [float(coord) for coord in bbox]: if isinstance(o, decimal.Decimal): o = (str(o) for o in [o]) _bbox.append(o) return _bbox def sld_definition(style): from urllib import quote _sld = { "title": style.sld_title or style.name, "legend": { "height": "40", "width": "22", "href": layer.ows_url + "?service=wms&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=" + quote(layer.service_typename, safe=''), "format": "image/png" }, "name": style.name } return _sld config = layer.attribute_config() if hasattr(layer, 'srid'): config['crs'] = {'type': 'name', 'properties': layer.srid} # Add required parameters for GXP lazy-loading attribution = "%s %s" % ( layer.owner.first_name, layer.owner.last_name ) if layer.owner.first_name or layer.owner.last_name else str( layer.owner) srs = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') srs_srid = int(srs.split(":")[1]) if srs != "EPSG:900913" else 3857 config[ "attribution"] = "<span class='gx-attribution-title'>%s</span>" % attribution config["format"] = getattr(settings, 'DEFAULT_LAYER_FORMAT', 'image/png') config["title"] = layer.title config["wrapDateLine"] = True config["visibility"] = True config["srs"] = srs config["bbox"] = decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=int(srs.split(":")[1]))[:4]) config["capability"] = { "abstract": layer.abstract, "name": layer.alternate, "title": layer.title, "queryable": True, "bbox": { layer.srid: { "srs": layer.srid, "bbox": decimal_encode(bbox) }, srs: { "srs": srs, "bbox": decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=srs_srid)[:4]) }, "EPSG:4326": { "srs": "EPSG:4326", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4]) }, "EPSG:900913": { "srs": "EPSG:900913", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:900913' else decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=3857)[:4]) } }, "srs": { srs: True }, "formats": [ "image/png", "application/atom xml", "application/atom+xml", "application/json;type=utfgrid", "application/openlayers", "application/pdf", "application/rss xml", "application/rss+xml", "application/vnd.google-earth.kml", "application/vnd.google-earth.kml xml", "application/vnd.google-earth.kml+xml", "application/vnd.google-earth.kml+xml;mode=networklink", "application/vnd.google-earth.kmz", "application/vnd.google-earth.kmz xml", "application/vnd.google-earth.kmz+xml", "application/vnd.google-earth.kmz;mode=networklink", "atom", "image/geotiff", "image/geotiff8", "image/gif", "image/gif;subtype=animated", "image/jpeg", "image/png8", "image/png; mode=8bit", "image/svg", "image/svg xml", "image/svg+xml", "image/tiff", "image/tiff8", "image/vnd.jpeg-png", "kml", "kmz", "openlayers", "rss", "text/html; subtype=openlayers", "utfgrid" ], "attribution": { "title": attribution }, "infoFormats": [ "text/plain", "application/vnd.ogc.gml", "text/xml", "application/vnd.ogc.gml/3.1.1", "text/xml; subtype=gml/3.1.1", "text/html", "application/json" ], "styles": [sld_definition(s) for s in layer.styles.all()], "prefix": layer.alternate.split(":")[0] if ":" in layer.alternate else "", "keywords": [k.name for k in layer.keywords.all()] if layer.keywords else [], "llbbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4]) } if layer.storeType == "remoteStore": service = layer.remote_service source_params = { "ptype": service.ptype, "remote": True, "url": service.service_url, "name": service.name, "title": "[R] %s" % service.title } maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps(source_params)) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox is not None: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json(request.user, access_token, *layers_to_add) config['fromLayer'] = True return config
def new_map_config(request): """ View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. """ DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == "GET" and "copy" in request.GET: mapid = request.GET["copy"] map_obj = _resolve_map(request, mapid, "maps.view_map") map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json() del config["id"] else: if request.method == "GET": params = request.GET elif request.method == "POST": params = request.POST else: return HttpResponse(status=405) if "layer" in params: bbox = None map_obj = Map(projection="EPSG:900913") layers = [] for layer_name in params.getlist("layer"): try: layer = Layer.objects.get(typename=layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm("layers.view_layer", obj=layer): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) layers.append( MapLayer( map=map_obj, name=layer.typename, ows_url=ogc_server_settings.public_url + "wms", layer_params=json.dumps(layer.attribute_config()), visibility=True, ) ) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 center = forward_mercator((x, y)) if center[1] == float("-inf"): center[1] = 0 if maxx == minx: width_zoom = 15 else: width_zoom = math.log(360 / (maxx - minx), 2) if maxy == miny: height_zoom = 15 else: height_zoom = math.log(360 / (maxy - miny), 2) map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json(*(DEFAULT_BASE_LAYERS + layers)) config["fromLayer"] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' # 3 cases in this function # 1. copy a map # 2. a new map with one or more layers # 3. a new map with no layers DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None # TODO support map copy if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user, access_token) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) # a new map with a layer if 'layer' in params: bbox = None map_obj = Map( projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be sent to remote services. ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url + '?access_token=' + access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name })) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.typename, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json(request.user, access_token, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True geoexplorer2worldmap(config, map_obj, layers) else: # a new map with no layer config = DEFAULT_MAP_CONFIG geoexplorer2worldmap(config, map_obj) return json.dumps(config)
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'maps.view_map') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json() del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection="EPSG:900913") layers = [] for layer_name in params.getlist('layer'): try: layer = Layer.objects.get(typename=layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm('layers.view_layer', obj=layer): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) layers.append( MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url(), layer_params=json.dumps(layer.attribute_config()), visibility=True)) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 center = forward_mercator((x, y)) if center[1] == float('-inf'): center[1] = 0 if maxx == minx: width_zoom = 15 else: width_zoom = math.log(360 / (maxx - minx), 2) if maxy == miny: height_zoom = 15 else: height_zoom = math.log(360 / (maxy - miny), 2) map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json(*(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def map_embed_widget(request, mapid, template='leaflet/maps/map_embed_widget.html'): """Display code snippet for embedding widget. :param request: The request from the frontend. :type request: HttpRequest :param mapid: The id of the map. :type mapid: String :return: formatted code. """ map_obj = _resolve_map(request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) map_bbox = map_obj.bbox_string.split(',') map_layers = MapLayer.objects.filter(map_id=mapid).order_by('stack_order') layers = [] for layer in map_layers: if layer.group != 'background': layers.append(layer) if map_obj.srid != 'EPSG:3857': map_bbox = [float(coord) for coord in map_bbox] else: map_bbox = llbbox_to_mercator([float(coord) for coord in map_bbox]) if map_bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in map_bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS') == "EPSG:3857": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) context = {'resource': map_obj, 'map_bbox': map_bbox, 'map_layers': layers} message = render(request, template, context) return HttpResponse(message)
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) bbox = [] layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue except Http404: # can't find the layer, skip it. continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox[0:4] bbox = layer_bbox[:] bbox[0] = layer_bbox[0] bbox[1] = layer_bbox[2] bbox[2] = layer_bbox[1] bbox[3] = layer_bbox[3] # assert False, str(layer_bbox) def decimal_encode(bbox): import decimal _bbox = [] for o in [float(coord) for coord in bbox]: if isinstance(o, decimal.Decimal): o = (str(o) for o in [o]) _bbox.append(o) # Must be in the form : [x0, x1, y0, y1 return [_bbox[0], _bbox[2], _bbox[1], _bbox[3]] def sld_definition(style): _sld = { "title": style.sld_title or style.name, "legend": { "height": "40", "width": "22", "href": layer.ows_url + "?service=wms&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=" + quote(layer.service_typename, safe=''), "format": "image/png" }, "name": style.name } return _sld config = layer.attribute_config() if hasattr(layer, 'srid'): config['crs'] = {'type': 'name', 'properties': layer.srid} # Add required parameters for GXP lazy-loading attribution = "%s %s" % ( layer.owner.first_name, layer.owner.last_name ) if layer.owner.first_name or layer.owner.last_name else str( layer.owner) srs = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') srs_srid = int(srs.split(":")[1]) if srs != "EPSG:900913" else 3857 config[ "attribution"] = "<span class='gx-attribution-title'>%s</span>" % attribution config["format"] = getattr(settings, 'DEFAULT_LAYER_FORMAT', 'image/png') config["title"] = layer.title config["wrapDateLine"] = True config["visibility"] = True config["srs"] = srs config["bbox"] = decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=int(srs.split(":")[1]))[:4]) config["capability"] = { "abstract": layer.abstract, "store": layer.store, "name": layer.alternate, "title": layer.title, "queryable": True, "storeType": layer.storeType, "bbox": { layer.srid: { "srs": layer.srid, "bbox": decimal_encode(bbox) }, srs: { "srs": srs, "bbox": decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=srs_srid)[:4]) }, "EPSG:4326": { "srs": "EPSG:4326", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4] }, "EPSG:900913": { "srs": "EPSG:900913", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:900913' else bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=3857)[:4] } }, "srs": { srs: True }, "formats": [ "image/png", "application/atom xml", "application/atom+xml", "application/json;type=utfgrid", "application/openlayers", "application/pdf", "application/rss xml", "application/rss+xml", "application/vnd.google-earth.kml", "application/vnd.google-earth.kml xml", "application/vnd.google-earth.kml+xml", "application/vnd.google-earth.kml+xml;mode=networklink", "application/vnd.google-earth.kmz", "application/vnd.google-earth.kmz xml", "application/vnd.google-earth.kmz+xml", "application/vnd.google-earth.kmz;mode=networklink", "atom", "image/geotiff", "image/geotiff8", "image/gif", "image/gif;subtype=animated", "image/jpeg", "image/png8", "image/png; mode=8bit", "image/svg", "image/svg xml", "image/svg+xml", "image/tiff", "image/tiff8", "image/vnd.jpeg-png", "kml", "kmz", "openlayers", "rss", "text/html; subtype=openlayers", "utfgrid" ], "attribution": { "title": attribution }, "infoFormats": [ "text/plain", "application/vnd.ogc.gml", "text/xml", "application/vnd.ogc.gml/3.1.1", "text/xml; subtype=gml/3.1.1", "text/html", "application/json" ], "styles": [sld_definition(s) for s in layer.styles.all()], "prefix": layer.alternate.split(":")[0] if ":" in layer.alternate else "", "keywords": [k.name for k in layer.keywords.all()] if layer.keywords else [], "llbbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4] } all_times = None if check_ogc_backend(geoserver.BACKEND_PACKAGE): if layer.has_time: from geonode.geoserver.views import get_capabilities workspace, layername = layer.alternate.split( ":") if ":" in layer.alternate else (None, layer.alternate) # WARNING Please make sure to have enabled DJANGO CACHE as per # https://docs.djangoproject.com/en/2.0/topics/cache/#filesystem-caching wms_capabilities_resp = get_capabilities(request, layer.id, tolerant=True) if wms_capabilities_resp.status_code >= 200 and wms_capabilities_resp.status_code < 400: wms_capabilities = wms_capabilities_resp.getvalue() if wms_capabilities: from defusedxml import lxml as dlxml namespaces = { 'wms': 'http://www.opengis.net/wms', 'xlink': 'http://www.w3.org/1999/xlink', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance' } e = dlxml.fromstring(wms_capabilities) for atype in e.findall( "./[wms:Name='%s']/wms:Dimension[@name='time']" % (layer.alternate), namespaces): dim_name = atype.get('name') if dim_name: dim_name = str(dim_name).lower() if dim_name == 'time': dim_values = atype.text if dim_values: all_times = dim_values.split(",") break if all_times: config["capability"]["dimensions"] = { "time": { "name": "time", "units": "ISO8601", "unitsymbol": None, "nearestVal": False, "multipleVal": False, "current": False, "default": "current", "values": all_times } } if layer.storeType == "remoteStore": service = layer.remote_service source_params = {} if service.type in ('REST_MAP', 'REST_IMG'): source_params = { "ptype": service.ptype, "remote": True, "url": service.service_url, "name": service.name, "title": "[R] %s" % service.title } maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps(source_params)) else: ogc_server_url = urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlsplit(layer.ows_url).netloc access_token = request.session[ 'access_token'] if request and 'access_token' in request.session else None if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = '%s?access_token=%s' % (layer.ows_url, access_token) else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox and len(bbox) >= 4: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json(request, *layers_to_add) config['fromLayer'] = True return config
def map_embed_widget(request, mapid, template='leaflet/maps/map_embed_widget.html'): """Display code snippet for embedding widget. :param request: The request from the frontend. :type request: HttpRequest :param mapid: The id of the map. :type mapid: String :return: formatted code. """ map_obj = _resolve_map(request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) map_bbox = map_obj.bbox_string.split(',') # Sanity Checks for coord in map_bbox: if not coord: return map_layers = MapLayer.objects.filter( map_id=mapid).order_by('stack_order') layers = [] for layer in map_layers: if layer.group != 'background': layers.append(layer) if map_obj.srid != 'EPSG:3857': map_bbox = [float(coord) for coord in map_bbox] else: map_bbox = llbbox_to_mercator([float(coord) for coord in map_bbox]) if map_bbox and len(map_bbox) >= 4: minx, miny, maxx, maxy = [float(coord) for coord in map_bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS') == "EPSG:3857": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) context = { 'resource': map_obj, 'map_bbox': map_bbox, 'map_layers': layers } message = render(request, template, context) return HttpResponse(message)
def add_layers_to_map_config( request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) bbox = [] layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue except Http404: # can't find the layer, skip it. continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox[0:4] bbox = layer_bbox[:] bbox[0] = layer_bbox[0] bbox[1] = layer_bbox[2] bbox[2] = layer_bbox[1] bbox[3] = layer_bbox[3] # assert False, str(layer_bbox) def decimal_encode(bbox): import decimal _bbox = [] for o in [float(coord) for coord in bbox]: if isinstance(o, decimal.Decimal): o = (str(o) for o in [o]) _bbox.append(o) # Must be in the form : [x0, x1, y0, y1 return [_bbox[0], _bbox[2], _bbox[1], _bbox[3]] def sld_definition(style): from urllib import quote _sld = { "title": style.sld_title or style.name, "legend": { "height": "40", "width": "22", "href": layer.ows_url + "?service=wms&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=" + quote(layer.service_typename, safe=''), "format": "image/png" }, "name": style.name } return _sld config = layer.attribute_config() if hasattr(layer, 'srid'): config['crs'] = { 'type': 'name', 'properties': layer.srid } # Add required parameters for GXP lazy-loading attribution = "%s %s" % (layer.owner.first_name, layer.owner.last_name) if layer.owner.first_name or layer.owner.last_name else str( layer.owner) srs = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') srs_srid = int(srs.split(":")[1]) if srs != "EPSG:900913" else 3857 config["attribution"] = "<span class='gx-attribution-title'>%s</span>" % attribution config["format"] = getattr( settings, 'DEFAULT_LAYER_FORMAT', 'image/png') config["title"] = layer.title config["wrapDateLine"] = True config["visibility"] = True config["srs"] = srs config["bbox"] = decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [layer.srid, ], target_srid=int(srs.split(":")[1]))[:4]) config["capability"] = { "abstract": layer.abstract, "name": layer.alternate, "title": layer.title, "queryable": True, "storeType": layer.storeType, "bbox": { layer.srid: { "srs": layer.srid, "bbox": decimal_encode(bbox) }, srs: { "srs": srs, "bbox": decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [layer.srid, ], target_srid=srs_srid)[:4]) }, "EPSG:4326": { "srs": "EPSG:4326", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode(bbox_to_projection( [float(coord) for coord in layer_bbox] + [layer.srid, ], target_srid=4326)[:4]) }, "EPSG:900913": { "srs": "EPSG:900913", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:900913' else decimal_encode(bbox_to_projection( [float(coord) for coord in layer_bbox] + [layer.srid, ], target_srid=3857)[:4]) } }, "srs": { srs: True }, "formats": ["image/png", "application/atom xml", "application/atom+xml", "application/json;type=utfgrid", "application/openlayers", "application/pdf", "application/rss xml", "application/rss+xml", "application/vnd.google-earth.kml", "application/vnd.google-earth.kml xml", "application/vnd.google-earth.kml+xml", "application/vnd.google-earth.kml+xml;mode=networklink", "application/vnd.google-earth.kmz", "application/vnd.google-earth.kmz xml", "application/vnd.google-earth.kmz+xml", "application/vnd.google-earth.kmz;mode=networklink", "atom", "image/geotiff", "image/geotiff8", "image/gif", "image/gif;subtype=animated", "image/jpeg", "image/png8", "image/png; mode=8bit", "image/svg", "image/svg xml", "image/svg+xml", "image/tiff", "image/tiff8", "image/vnd.jpeg-png", "kml", "kmz", "openlayers", "rss", "text/html; subtype=openlayers", "utfgrid"], "attribution": { "title": attribution }, "infoFormats": ["text/plain", "application/vnd.ogc.gml", "text/xml", "application/vnd.ogc.gml/3.1.1", "text/xml; subtype=gml/3.1.1", "text/html", "application/json"], "styles": [sld_definition(s) for s in layer.styles.all()], "prefix": layer.alternate.split(":")[0] if ":" in layer.alternate else "", "keywords": [k.name for k in layer.keywords.all()] if layer.keywords else [], "llbbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode(bbox_to_projection( [float(coord) for coord in layer_bbox] + [layer.srid, ], target_srid=4326)[:4]) } all_times = None if check_ogc_backend(geoserver.BACKEND_PACKAGE): from geonode.geoserver.views import get_capabilities workspace, layername = layer.alternate.split( ":") if ":" in layer.alternate else (None, layer.alternate) # WARNING Please make sure to have enabled DJANGO CACHE as per # https://docs.djangoproject.com/en/2.0/topics/cache/#filesystem-caching wms_capabilities_resp = get_capabilities( request, layer.id, tolerant=True) if wms_capabilities_resp.status_code >= 200 and wms_capabilities_resp.status_code < 400: wms_capabilities = wms_capabilities_resp.getvalue() if wms_capabilities: import xml.etree.ElementTree as ET namespaces = {'wms': 'http://www.opengis.net/wms', 'xlink': 'http://www.w3.org/1999/xlink', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} e = ET.fromstring(wms_capabilities) for atype in e.findall( "./[wms:Name='%s']/wms:Dimension[@name='time']" % (layer.alternate), namespaces): dim_name = atype.get('name') if dim_name: dim_name = str(dim_name).lower() if dim_name == 'time': dim_values = atype.text if dim_values: all_times = dim_values.split(",") break if all_times: config["capability"]["dimensions"] = { "time": { "name": "time", "units": "ISO8601", "unitsymbol": None, "nearestVal": False, "multipleVal": False, "current": False, "default": "current", "values": all_times } } if layer.storeType == "remoteStore": service = layer.remote_service source_params = {} if service.type in ('REST_MAP', 'REST_IMG'): source_params = { "ptype": service.ptype, "remote": True, "url": service.service_url, "name": service.name, "title": "[R] %s" % service.title} maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps(source_params) ) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc access_token = request.session['access_token'] if request and 'access_token' in request.session else None if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = '%s?access_token=%s' % (layer.ows_url, access_token) else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True ) layers.append(maplayer) if bbox and len(bbox) >= 4: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr( settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json( request, *layers_to_add) config['fromLayer'] = True return config
def get_context_data(self, **kwargs): request = self.request if request and 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) layers = Layer.objects.all() if request.method == 'GET' and 'copy' in request.GET: """Prepare context data.""" request = self.request mapid = self.request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) config = map_obj.viewer_json(request) # list all required layers map_layers = MapLayer.objects.filter( map_id=mapid).order_by('stack_order') context = { 'config': json.dumps(config), 'create': False, 'layers': layers, 'map': map_obj, 'map_layers': map_layers, 'preview': getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'leaflet') } return context else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return self.render_to_response(status=405) if 'layer' in params: bbox = None map_obj = Map(projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857')) for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = min(bbox[1], layer_bbox[1]) bbox[2] = max(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') config["bbox"] = bbox if config["srs"] != 'EPSG:3857' \ else llbbox_to_mercator( [float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.remote_service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be sent to remote services. ogc_server_url = urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and \ 'access_token' not in service.base_url: url = '%s?access_token=%s' % (service.base_url, access_token) else: url = service.base_url map_layers = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name, "title": "[R] %s" % service.title })) else: ogc_server_url = urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and \ 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + \ access_token else: url = layer.ows_url map_layers = MapLayer( map=map_obj, name=layer.typename, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) if bbox and len(bbox) >= 4: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() config = map_obj.viewer_json(request) config['fromLayer'] = True context = { 'config': json.dumps(config), 'create': True, 'layers': layers, 'map': map_obj, 'map_layers': map_layers, 'preview': getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'leaflet') } else: # list all required layers layers = Layer.objects.all() context = {'create': True, 'layers': layers} return context
def get_bbox(instance, crs='EPSG:3857'): if crs is None: crs = 'EPSG:3857' minlon = min(float(instance.bbox_x0), float(instance.bbox_x1)) minlat = min(float(instance.bbox_y0), float(instance.bbox_y1)) maxlon = max(float(instance.bbox_x0), float(instance.bbox_x1)) maxlat = max(float(instance.bbox_y0), float(instance.bbox_y1)) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range # create a buffer minlon = max(-180, minlon - lon_range * .1) minlat = max(-90, minlat - lat_range * .1) maxlon = min(180, maxlon + lon_range * .1) maxlat = min(90, maxlat + lat_range * .1) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range if ratio < 200.0 / 150.0: lon_shift = abs(.5 * ((200.0 / 150.0 * lat_range) - lon_range)) minlon = max(-180, minlon - lon_shift) maxlon = min(180, maxlon + lon_shift) else: adjusted_range = 150.0 / 200.0 * lon_range range_delta = adjusted_range - lat_range lat_shift = abs(.5 * range_delta) minlat = max(-90, minlat - lat_shift) maxlat = min(90, maxlat + lat_shift) lon_range = maxlon - minlon lat_range = maxlat - minlat ratio = lon_range / lat_range height = int(200 / ratio) logger.debug('height: %s', height) if crs == 'EPSG:3857': # create bbox in 3857 minx, miny = forward_mercator([minlon, max(-85.0, minlat)]) maxx, maxy = forward_mercator([maxlon, min(85.0, maxlat)]) bbox = '%s,%s,%s,%s' % ( minx, miny, maxx, maxy ) return bbox, height elif crs == 'EPSG:4326': # deal with weird bbox order for geographic coords in wms 1.3.0 bbox = '%s,%s,%s,%s' % ( minlat, minlon, maxlat, maxlon ) return bbox, height elif crs == 'CRS:84': # crs84 bbox bbox = '%s,%s,%s,%s' % ( minlon, minlat, maxlon, maxlat ) return bbox, height logger.debug('***************Could not determine BBOX***********')
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection="EPSG:900913") layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["srs"] = layer.srid config["title"] = layer.title config["bbox"] = [ float(coord) for coord in bbox] if layer.srid == "EPSG:4326" else llbbox_to_mercator( [ float(coord) for coord in bbox]) config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name})) else: maplayer = MapLayer( map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True ) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json( request.user, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def get_context_data(self, **kwargs): request = self.request if request and 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None snapshot = self.kwargs.get('snapshot') DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) layers = Layer.objects.all() if request.method == 'GET' and 'copy' in request.GET: """Prepare context data.""" request = self.request mapid = self.request.GET['copy'] map_obj = _resolve_map( request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) if snapshot is None: config = map_obj.viewer_json(request) else: config = snapshot_config(snapshot, map_obj, request) # list all required layers map_layers = MapLayer.objects.filter( map_id=mapid).order_by('stack_order') context = { 'config': json.dumps(config), 'create': False, 'layers': layers, 'map': map_obj, 'map_layers': map_layers, 'preview': getattr( settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', '') } return context else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return self.render_to_response(status=405) if 'layer' in params: bbox = None map_obj = Map(projection=getattr( settings, 'DEFAULT_MAP_CRS', 'EPSG:3857')) for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = min(bbox[1], layer_bbox[1]) bbox[2] = max(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') config["bbox"] = bbox if config["srs"] != 'EPSG:3857' \ else llbbox_to_mercator( [float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.remote_service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be sent to remote services. ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit( service.base_url).netloc if access_token and ogc_server_url == service_url and \ 'access_token' not in service.base_url: url = '%s?access_token=%s' % (service.base_url, access_token) else: url = service.base_url map_layers = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name, "title": "[R] %s" % service.title})) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and \ 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + \ access_token else: url = layer.ows_url map_layers = MapLayer( map=map_obj, name=layer.typename, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps( config, cls=DjangoJSONEncoder), visibility=True ) if bbox and len(bbox) >= 4: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if snapshot is None: config = map_obj.viewer_json(request) else: config = snapshot_config(snapshot, map_obj, request) config['fromLayer'] = True context = { 'config': json.dumps(config), 'create': True, 'layers': layers, 'map': map_obj, 'map_layers': map_layers, 'preview': getattr( settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', '') } else: # list all required layers layers = Layer.objects.all() context = { 'create': True, 'layers': layers } return context