Last active
February 26, 2024 07:19
-
-
Save maxcollombin/817ff444e5d2ca11da04ab00774a8315 to your computer and use it in GitHub Desktop.
This script generates a JSON and XML representation of a an OGC 2D tile matrix set definition for use with geographical data services.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Swiss Tile Matrix Set Generation Script | |
| This script generates a JSON and XML representation of a an OGC 2D tile matrix set definition | |
| for use with geographical data services. | |
| Author: [Maxime Collombin] | |
| Date: [14/08/2023] | |
| """ | |
| # -*- coding: utf-8 -*- | |
| import json | |
| import pandas as pd | |
| import xml.etree.ElementTree as ET | |
| from lxml import etree | |
| from xml.dom import minidom | |
| cell_sizes = [4000, 2000, 1000, 500, 250, 100, 50, 20, 10, 5, 2.5, 1, 0.5, 0.25, 0.1, 0.05] | |
| # cell_sizes = [4000, 3750, 3500, 3250, 3000, 2750, 2500, 2250, 2000, 1750, 1500, 1250, 1000, 750, 650, 500, 250, 100, 50, 20, 10, 5, 2.5, 2, 1.5, 1, 0.5, 0.25, 0.1, 0.05] | |
| tile_width = 256 | |
| tile_height = 256 | |
| bbox = [2419995.7488073637, 1030006.663199476, 2900009.727428728, 1350004.292478851] | |
| point_of_origin = [bbox[0], bbox[3]] | |
| scale_denominator = [cell_size / (0.28 * 10**-3) for cell_size in cell_sizes] | |
| matrix_width = [max(1, int(round((bbox[2] - bbox[0]) / (cell_size * tile_width), 0))) for cell_size in cell_sizes] | |
| matrix_height = [max(1, int(round((bbox[3] - bbox[1]) / (cell_size * tile_height), 0))) for cell_size in cell_sizes] | |
| tms_data = { | |
| 'ScaleDenominator': scale_denominator, | |
| 'CellSize': cell_sizes, | |
| 'MatrixWidth': matrix_width, | |
| 'MatrixHeight': matrix_height | |
| } | |
| tms = pd.DataFrame(tms_data) | |
| tms['tmsc:Identifier'] = tms.index | |
| tms['CornerOfOrigin'] = 'topLeft' | |
| tms['PointOfOrigin'] = str(point_of_origin) | |
| tms['PointOfOrigin'] = tms['PointOfOrigin'].str.replace('[','').str.replace(']','').str.split(',').apply(lambda x: [float(i) for i in x]) | |
| tms['TileWidth'] = tile_width | |
| tms['TileHeight'] = tile_height | |
| tms.loc[0, ['MatrixWidth', 'MatrixHeight']] = 1 | |
| tms_xml = tms.copy() | |
| tms_json = tms_xml.copy() | |
| column_name_mapping = { | |
| 'tmsc:Identifier': 'id', | |
| 'ScaleDenominator': 'scaleDenominator', | |
| 'CellSize': 'cellSize', | |
| 'CornerOfOrigin': 'cornerOfOrigin', | |
| 'PointOfOrigin': 'pointOfOrigin', | |
| 'TileWidth': 'tileWidth', | |
| 'TileHeight': 'tileHeight', | |
| 'MatrixWidth': 'matrixWidth', | |
| 'MatrixHeight': 'matrixHeight' | |
| } | |
| tms_json.rename(columns=column_name_mapping, inplace=True) | |
| header_xml = { | |
| 'tmsc:Title': 'Switzerland 2D tile matrix set definition', | |
| 'tmsc:Identifier': 'SwissLV95CellSizes', | |
| 'uri': 'http://www.opengis.net/def/tilematrixset/OGC/1.0/SwissLV95CellSizes', | |
| 'tmsc:CRS': 'http://www.opengis.net/def/crs/EPSG/0/2056', | |
| 'OrderedAxes': ['E', 'N'], | |
| 'tileMatrices': tms_xml.to_dict('records') | |
| } | |
| header_json = { | |
| 'title': 'Switzerland 2D tile matrix set definition', | |
| 'id': 'SwissLV95CellSizes', | |
| 'uri': 'http://www.opengis.net/def/tilematrixset/OGC/1.0/SwissLV95CellSizes', | |
| 'crs': 'http://www.opengis.net/def/crs/EPSG/0/2056', | |
| 'orderedAxes': ['E', 'N'], | |
| 'tileMatrices': tms_json.to_dict('records') | |
| } | |
| with open('SwissLV95CellSizes.json', 'w') as outfile: | |
| json.dump(header_json, outfile, indent=4, sort_keys=False) | |
| root = ET.Element('TileMatrixSet') | |
| root.set('id', 'SwissLV95CellSizes') | |
| root.set('xmlns', 'http://www.opengis.net/tms/2.0') | |
| root.set('xmlns:tmsc', 'http://www.opengis.net/tms/2.0/common') | |
| root.set('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') | |
| root.set('xsi:schemaLocation', 'http://www.opengis.net/tms/2.0 https://schemas.opengis.net/tms/2.0/xml/tilematrixset.xsd') | |
| for key, value in header_xml.items(): | |
| if key == 'tileMatrices': | |
| for item in value: | |
| tile_matrix_element = ET.SubElement(root, 'TileMatrix') | |
| for sub_key, sub_value in item.items(): | |
| sub_key_element = ET.SubElement(tile_matrix_element, sub_key) | |
| if sub_key == 'PointOfOrigin': | |
| sub_key_element.text = ' '.join(map(str, sub_value)) # Convert list to string with space separator | |
| else: | |
| sub_key_element.text = str(sub_value) | |
| elif key == 'tmsc:CRS': | |
| crs_element = ET.SubElement(root, key) | |
| uri_element = ET.SubElement(crs_element, 'tmsc:URI') | |
| uri_element.text = str(value) | |
| else: | |
| key_element = ET.SubElement(root, key) | |
| key_element.text = str(value) | |
| xml_string = ET.tostring(root, encoding='utf-8') | |
| pretty_xml_string = minidom.parseString(xml_string).toprettyxml(indent=' ') | |
| with open('SwissLV95CellSizes.xml', 'w') as xml_outfile: | |
| xml_outfile.write(pretty_xml_string) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
2do:
Adapt the script to have convenient naming in both json and xml files.
The CRS in the xml root should also be:
and not
<tmsc:CRS>http://www.opengis.net/def/crs/EPSG/0/2056</tmsc:CRS>