def write_extent(bbox, nsmap): ''' Generate BBOX extent ''' if bbox is not None: try: bbox2 = util.wkt2geom(bbox) except: return None where = etree.Element(util.nspath_eval('georss:where', NAMESPACES)) envelope = etree.SubElement(where, util.nspath_eval('gml:Envelope', nsmap), srsName='http://www.opengis.net/def/crs/EPSG/0/4326') etree.SubElement(envelope, util.nspath_eval('gml:lowerCorner', nsmap)).text = '%s %s' % (bbox2[1], bbox2[0]) etree.SubElement(envelope, util.nspath_eval('gml:upperCorner', nsmap)).text = '%s %s' % (bbox2[3], bbox2[2]) return where return None
def write_extent(bbox, nsmap): ''' Generate BBOX extent ''' if bbox is not None: try: bbox2 = util.wkt2geom(bbox) except: return None bounding_box = etree.Element(util.nspath_eval('gm03:GM03_2_1Core.Core.EX_GeographicBoundingBox', NAMESPACES)) etree.SubElement(bounding_box, util.nspath_eval('gm03:northBoundLatitude', nsmap)).text = str(bbox2[3]) etree.SubElement(bounding_box, util.nspath_eval('gm03:southBoundLatitude', nsmap)).text = str(bbox2[1]) etree.SubElement(bounding_box, util.nspath_eval('gm03:eastBoundLongitude', nsmap)).text = str(bbox2[0]) etree.SubElement(bounding_box, util.nspath_eval('gm03:westBoundLongitude', nsmap)).text = str(bbox2[2]) return bounding_box return None
def write_extent(bbox): ''' Generate BBOX extent ''' if bbox is not None: try: bbox2 = util.wkt2geom(bbox) except: return None spdom = etree.Element('spdom') bounding = etree.SubElement(spdom, 'bounding') etree.SubElement(bounding, 'westbc').text = str(bbox2[0]) etree.SubElement(bounding, 'eastbc').text = str(bbox2[2]) etree.SubElement(bounding, 'northbc').text = str(bbox2[3]) etree.SubElement(bounding, 'southbc').text = str(bbox2[1]) return spdom return None
def write_extent(bbox, nsmap): ''' Generate BBOX extent ''' from shapely.wkt import loads if bbox is not None: try: bbox2 = util.wkt2geom(bbox) except: return None extent = etree.Element(util.nspath_eval('dif:Spatial_Coverage', nsmap)) etree.SubElement(extent, util.nspath_eval('dif:Southernmost_Latitude', nsmap)).text = str(bbox2[1]) etree.SubElement(extent, util.nspath_eval('dif:Northernmost_Latitude', nsmap)).text = str(bbox2[3]) etree.SubElement(extent, util.nspath_eval('dif:Westernmost_Longitude', nsmap)).text = str(bbox2[0]) etree.SubElement(extent, util.nspath_eval('dif:Easternmost_Longitude', nsmap)).text = str(bbox2[2]) return extent return None
def write_record(result, esn, context, url=None): """ Return csw:SearchResults child as lxml.etree.Element """ node = etree.Element("collection") etree.SubElement(node, "stac_version").text = STAC_VERSION val = util.getqattr(result, "identifier") if val: etree.SubElement(node, "id").text = val val = util.getqattr(result, "abstract") if val: etree.SubElement(node, "description").text = val val = util.getqattr(result, "conditionapplyingtoaccessanduse") if val: etree.SubElement(node, "license").text = val val = util.getqattr(result, "title") if val: etree.SubElement(node, "title").text = val val = util.getqattr(result, "keywords") for keyword in val.split(","): etree.SubElement(node, "keywords").text = keyword extent = etree.SubElement(node, "extent") ext_temporal = etree.SubElement(extent, "temporal") interval_str = '[[' + format_time(util.getqattr( result, "time_begin")) + ',' + format_time( util.getqattr(result, "time_end")) + ']]' etree.SubElement(ext_temporal, "interval").text = interval_str ext_spatial = etree.SubElement(extent, "spatial") val = util.getqattr(result, context.md_core_model["mappings"]["pycsw:BoundingBox"]) if val: bbox = util.wkt2geom(val) etree.SubElement(ext_spatial, "bbox").text = '[' + str(list(bbox)) + ']' return node
def record_to_dict(record): # TODO: check for correct order. bbox = wkt2geom(record.wkt_geometry) min_x, min_y, max_x, max_y = bbox[0], bbox[1], bbox[2], bbox[3] record_dict = { 'title': record.title.encode('ascii', 'ignore').decode('utf-8'), 'abstract': record.abstract, 'bbox': bbox, 'min_x': min_x, 'min_y': min_y, 'max_x': max_x, 'max_y': max_y, 'layer_date': record.date_modified, 'layer_originator': record.creator, # 'rectangle': box(min_x, min_y, max_x, max_y), 'layer_geoshape': { 'type': 'envelope', 'coordinates': [[min_x, max_y], [max_x, min_y]] } } return record_dict
def write_extent(bbox, nsmap): ''' Generate BBOX extent ''' if bbox is not None: try: bbox2 = util.wkt2geom(bbox) except: return None extent = etree.Element(util.nspath_eval('gmd:extent', nsmap)) ex_extent = etree.SubElement(extent, util.nspath_eval('gmd:EX_Extent', nsmap)) ge = etree.SubElement(ex_extent, util.nspath_eval('gmd:geographicElement', nsmap)) gbb = etree.SubElement(ge, util.nspath_eval('gmd:EX_GeographicBoundingBox', nsmap)) west = etree.SubElement(gbb, util.nspath_eval('gmd:westBoundLongitude', nsmap)) east = etree.SubElement(gbb, util.nspath_eval('gmd:eastBoundLongitude', nsmap)) south = etree.SubElement(gbb, util.nspath_eval('gmd:southBoundLatitude', nsmap)) north = etree.SubElement(gbb, util.nspath_eval('gmd:northBoundLatitude', nsmap)) etree.SubElement(west, util.nspath_eval('gco:Decimal', nsmap)).text = str(bbox2[0]) etree.SubElement(south, util.nspath_eval('gco:Decimal', nsmap)).text = str(bbox2[1]) etree.SubElement(east, util.nspath_eval('gco:Decimal', nsmap)).text = str(bbox2[2]) etree.SubElement(north, util.nspath_eval('gco:Decimal', nsmap)).text = str(bbox2[3]) return extent return None
def record2json(record): """ OGC API - Records record generator from core pycsw record model :param record: pycsw record object :returns: `dict` of record GeoJSON """ record_dict = { 'id': record.identifier, 'type': 'Feature', 'geometry': None, 'properties': {} } record_dict['properties']['externalId'] = record.identifier record_dict['properties']['recordUpdated'] = record.insert_date if record.type: record_dict['properties']['type'] = record.type if record.date_creation: record_dict['properties']['created'] = record.date_creation if record.date_modified: record_dict['properties']['updated'] = record.date_modified if record.language: record_dict['properties']['language'] = record.language if record.title: record_dict['properties']['title'] = record.title if record.abstract: record_dict['properties']['description'] = record.abstract if record.format: record_dict['properties']['formats'] = [record.format] if record.keywords: record_dict['properties']['keywords'] = [ x for x in record.keywords.split(',') ] if record.links: record_dict['associations'] = [] for link in jsonify_links(record.links): association = { 'href': link['url'], 'name': link['name'], 'description': link['description'], 'type': link['protocol'] } if 'type' in link: association['rel'] = link['type'] record_dict['associations'].append(association) if record.wkt_geometry: minx, miny, maxx, maxy = wkt2geom(record.wkt_geometry) geometry = { 'type': 'Polygon', 'coordinates': [[[minx, miny], [minx, maxy], [maxx, maxy], [maxx, miny], [minx, miny]]] } record_dict['geometry'] = geometry record_dict['properties']['extents'] = { 'spatial': { 'bbox': [[minx, miny, maxx, maxy]], 'crs': 'http://www.opengis.net/def/crs/OGC/1.3/CRS84' } } return record_dict
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False): """Creates a mapproxy config for a given layer-like object. Compatible with django-registry and GeoNode. """ bbox = list(wkt2geom(layer.wkt_geometry)) # TODO: Check for correct url url = 'http://test.registry.org' # url = str(layer.service.url) layer_name = str(layer.title) srs = 'EPSG:4326' bbox_srs = 'EPSG:4326' grid_srs = 'EPSG:3857' default_source = { 'type': 'wms', 'coverage': { 'bbox': bbox, 'srs': srs, 'bbox_srs': bbox_srs, 'supported_srs': ['EPSG:4326', 'EPSG:900913', 'EPSG:3857'], }, 'req': { 'layers': str(layer.title), 'url': url, 'transparent': True, }, } if layer.type == 'ESRI:ArcGIS:MapServer' or layer.type == 'ESRI:ArcGIS:ImageServer': # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = 'EPSG:3857' bbox_srs = 'EPSG:3857' default_source = { 'type': 'arcgis', 'req': { 'url': url, 'grid': 'default_grid', 'transparent': True, }, } # A source is the WMS config sources = {'default_source': default_source} # A grid is where it will be projects (Mercator in our case) grids = { 'default_grid': { 'tile_size': [256, 256], 'srs': grid_srs, 'origin': 'nw', } } # A cache that does not store for now. It needs a grid and a source. caches = { 'default_cache': { 'disable_storage': True, 'grids': ['default_grid'], 'sources': ['default_source'] }, } # The layer is connected to the cache layers = [ { 'name': layer_name, 'sources': ['default_cache'], 'title': str(layer.title), }, ] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { 'wms': { 'image_formats': ['image/png'], 'md': { 'abstract': 'This is the Harvard HyperMap Proxy.', 'title': 'Harvard HyperMap Proxy' }, 'srs': ['EPSG:4326', 'EPSG:3857'], 'versions': ['1.1.1'] }, 'wmts': { 'restful': True, 'restful_template': '/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png', }, 'tms': { 'origin': 'nw', }, 'demo': None, } global_config = { 'http': { 'ssl_no_cert_checks': True }, } # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Populate a dictionary with custom config changes extra_config = { 'caches': caches, 'grids': grids, 'layers': layers, 'services': services, 'sources': sources, 'globals': global_config, } yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False # Merge both load_config(conf_options, config_dict=extra_config) # TODO: Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: LOGGER.warn(error) if not informal_only or (errors and not ignore_warnings): raise ConfigurationError('invalid configuration') errors = validate_references(conf_options) for error in errors: LOGGER.warn(error) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) return app, yaml_config
def test_wkt2geom(wkt, bounds, expected): result = util.wkt2geom(wkt, bounds=bounds) assert result == expected
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False, config_as_yaml=True): """Creates a mapproxy config for a given layer-like object. Compatible with django-registry and GeoNode. """ bbox = list(wkt2geom(layer.wkt_geometry)) bbox = ",".join([format(x, '.4f') for x in bbox]) url = str(layer.source) layer_name = str(layer.title) srs = 'EPSG:4326' bbox_srs = 'EPSG:4326' grid_srs = 'EPSG:3857' default_source = { 'type': 'wms', 'coverage': { 'bbox': bbox, 'srs': srs, 'bbox_srs': bbox_srs, 'supported_srs': ['EPSG:4326', 'EPSG:900913', 'EPSG:3857'], }, 'req': { 'layers': str(layer.title), 'url': url, 'transparent': True, }, } if layer.type == 'ESRI:ArcGIS:MapServer' or layer.type == 'ESRI:ArcGIS:ImageServer': # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = 'EPSG:3857' bbox_srs = 'EPSG:4326' default_source = { 'type': 'arcgis', 'req': { 'url': url.split('?')[0], 'grid': 'default_grid', 'transparent': True, }, } # A source is the WMS config sources = {'default_source': default_source} # A grid is where it will be projects (Mercator in our case) grids = { 'default_grid': { 'tile_size': [256, 256], 'srs': grid_srs, 'origin': 'nw', } } # A cache that does not store for now. It needs a grid and a source. caches = { 'default_cache': { 'disable_storage': True, 'grids': ['default_grid'], 'sources': ['default_source'] }, } # The layer is connected to the cache layers = [ { 'name': layer_name, 'sources': ['default_cache'], 'title': "%s" % layer.title, }, ] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { 'wms': { 'image_formats': ['image/png'], 'md': { 'abstract': 'This is the Harvard HyperMap Proxy.', 'title': 'Harvard HyperMap Proxy' }, 'srs': ['EPSG:4326', 'EPSG:3857'], 'srs_bbox': 'EPSG:4326', 'bbox': bbox, 'versions': ['1.1.1'] }, 'wmts': { 'restful': True, 'restful_template': '/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png', }, 'tms': { 'origin': 'nw', }, 'demo': None, } global_config = { 'http': { 'ssl_no_cert_checks': True }, } # Populate a dictionary with custom config changes extra_config = { 'caches': caches, 'grids': grids, 'layers': layers, 'services': services, 'sources': sources, 'globals': global_config, } yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False conf = configure_mapproxy(extra_config) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) # Wrap it in an object that allows to get requests by path as a string. if (config_as_yaml): return app, yaml_config return app, extra_config
def record2json(record, stac_item=False): """ OGC API - Records record generator from core pycsw record model :param record: pycsw record object :returns: `dict` of record GeoJSON """ if record.metadata_type == 'application/json': LOGGER.debug('Returning native JSON representation') return json.loads(record.metadata) record_dict = { 'id': record.identifier, 'type': 'Feature', 'geometry': None, 'properties': { 'externalId': [{'value': record.identifier}], 'datetime': record.date, 'start_datetime': record.time_begin, 'end_datetime': record.time_end }, 'links': [], 'assets': {} } if stac_item: record_dict['stac_version'] = '1.0.0' record_dict['collection'] = 'metadata:main' record_dict['properties']['externalId'] = record.identifier record_dict['properties']['recordUpdated'] = record.insert_date if record.type: record_dict['properties']['type'] = record.type if record.date_creation: record_dict['properties']['created'] = record.date_creation if record.date_modified: record_dict['properties']['updated'] = record.date_modified if record.language: record_dict['properties']['language'] = record.language if record.title: record_dict['properties']['title'] = record.title if record.abstract: record_dict['properties']['description'] = record.abstract if record.format: record_dict['properties']['formats'] = [record.format] if record.keywords: record_dict['properties']['keywords'] = [x for x in record.keywords.split(',')] if record.links: rdl = record_dict['links'] for link in jsonify_links(record.links): link = { 'href': link['url'], 'name': link['name'], 'description': link['description'], 'type': link['protocol'] } if 'type' in link: link['rel'] = link['type'] rdl.append(link) if record.wkt_geometry: minx, miny, maxx, maxy = wkt2geom(record.wkt_geometry) geometry = { 'type': 'Polygon', 'coordinates': [[ [minx, miny], [minx, maxy], [maxx, maxy], [maxx, miny], [minx, miny] ]] } record_dict['geometry'] = geometry record_dict['properties']['extent'] = { 'spatial': { 'bbox': [[minx, miny, maxx, maxy]], 'crs': 'http://www.opengis.net/def/crs/OGC/1.3/CRS84' } } return record_dict