5 from typing import List, Optional, Tuple
6 from xml.etree.ElementTree import ElementTree, Element
8 from geojson import Feature
9 from shapely.geometry import shape
10 from termcolor import cprint
12 from wrpylib.cli_tools import unified_diff, input_yes_no_quit, Choice
13 from wrpylib.json_tools import format_json
14 from wrpylib.mwapi import WikiSite
15 from wrpylib.wrgeojson import join_wrgeojson_ways
16 from wrpylib.wrosm import find_sledrun_relations, convert_osm_to_geojson, DeRefError, tags
19 def filter_way(feature: dict, way_type: str) -> bool:
20 return feature['geometry']['type'] == 'LineString' and feature.get('properties', {}).get('type') == way_type
23 def feature_distance(a: Feature, b: Feature) -> float:
24 return shape(a['geometry']).hausdorff_distance(shape(b['geometry']))
27 def geojson_way_sort_key(feature: Feature, reference_feature: Feature) -> Tuple[str, float]:
28 return feature.get('properties', {}).get('type', ''), feature_distance(feature, reference_feature)
31 def _update_wrgeojson_from_osm_file(wrgeojson_title: str, osm_tree: ElementTree, osm_sledrun_relation: Element,
34 wr_wrgeojson = convert_osm_to_geojson(osm_tree, osm_sledrun_relation)
36 cprint('Error: Incomplete XML - please load larger region.', 'red')
38 join_wrgeojson_ways(wr_wrgeojson)
40 wrgeojson_page = site.query_page(wrgeojson_title)
41 wrgeojson_page_content = wrgeojson_page['revisions'][0]['slots']['main']['content']
43 wr_wrgeojson_old = json.loads(wrgeojson_page_content)
44 if wr_wrgeojson_old == wr_wrgeojson:
45 cprint('No changes detected', 'red')
48 wr_wrgeojson['wr_properties']['simplified'] = False
50 wr_wrgeojson_old_str = format_json(wr_wrgeojson_old)
51 wr_wrgeojson_str = format_json(wr_wrgeojson)
53 cprint(wrgeojson_title, 'green')
54 unified_diff(wr_wrgeojson_old_str, wr_wrgeojson_str)
55 choice = input_yes_no_quit('Do you accept the changes [yes, no, quit]? ', None)
56 if choice == Choice.no:
58 elif choice == Choice.quit:
63 pageid=wrgeojson_page['pageid'],
64 text=wr_wrgeojson_str,
65 summary='Landkarte ersetzt.',
68 baserevid=wrgeojson_page['revisions'][0]['revid'],
74 def update_wrgeojson_from_osm_file(wrgeojson_title: str, osm_file: str, osm_index: Optional[int], ini_files: List[str]):
75 osm_tree = ElementTree()
76 osm_tree.parse(osm_file)
78 site = WikiSite(ini_files)
80 # Search all sledrun relations
81 osm_sledrun_list = list(find_sledrun_relations(osm_tree))
83 # Select one sledrun to work with
84 if len(osm_sledrun_list) == 0:
85 cprint('No sledruns in OSM file.', 'red')
87 elif len(osm_sledrun_list) > 1 and osm_index is None:
88 cprint(f'{len(osm_sledrun_list)} sledruns in the OSM. Please specify --osm_index:')
89 for i, osm_sledrun in enumerate(osm_sledrun_list):
91 print(f'{i}: {t.get("name", t)}')
93 osm_sledrun = osm_sledrun_list[0 if osm_index is None else osm_index]
94 _update_wrgeojson_from_osm_file(wrgeojson_title, osm_tree, osm_sledrun, site)
98 parser = argparse.ArgumentParser(
99 description='Updates sledrun wrgeojson maps with higher resolution ways from OSM files.')
100 parser.add_argument('wrgeojson_title', help='Title of an existing wrgeojson page.')
101 parser.add_argument('osm_file', help='OSM file containing high resolution ways.')
102 parser.add_argument('--osm_index', type=int, help='Index of the sledrun relation within the OSM file.')
103 parser.add_argument('ini_file', nargs='+',
104 help='inifile.ini, see: https://www.winterrodeln.org/trac/wiki/ConfigIni')
105 args = parser.parse_args()
106 update_wrgeojson_from_osm_file(args.wrgeojson_title, args.osm_file, args.osm_index, args.ini_file)
109 if __name__ == '__main__':