]> ToastFreeware Gitweb - philipp/winterrodeln/wrpylib.git/blob - scripts/update_wrgeojson_from_osm_file.py
VAO is missing important streets in Switzerland.
[philipp/winterrodeln/wrpylib.git] / scripts / update_wrgeojson_from_osm_file.py
1 #!/usr/bin/python3
2 import argparse
3 import json
4 import sys
5 from typing import List, Optional, Tuple
6 from xml.etree.ElementTree import ElementTree, Element
7
8 from geojson import Feature
9 from shapely.geometry import shape
10 from termcolor import cprint
11
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
17
18
19 def filter_way(feature: dict, way_type: str) -> bool:
20     return feature['geometry']['type'] == 'LineString' and feature.get('properties', {}).get('type') == way_type
21
22
23 def feature_distance(a: Feature, b: Feature) -> float:
24     return shape(a['geometry']).hausdorff_distance(shape(b['geometry']))
25
26
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)
29
30
31 def _update_wrgeojson_from_osm_file(wrgeojson_title: str, osm_tree: ElementTree, osm_sledrun_relation: Element,
32                                     site: WikiSite):
33     try:
34         wr_wrgeojson = convert_osm_to_geojson(osm_tree, osm_sledrun_relation)
35     except DeRefError:
36         cprint('Error: Incomplete XML - please load larger region.', 'red')
37         return
38     join_wrgeojson_ways(wr_wrgeojson)
39
40     wrgeojson_page = site.query_page(wrgeojson_title)
41     wrgeojson_page_content = wrgeojson_page['revisions'][0]['slots']['main']['content']
42
43     wr_wrgeojson_old = json.loads(wrgeojson_page_content)
44     if wr_wrgeojson_old == wr_wrgeojson:
45         cprint('No changes detected', 'red')
46         return
47
48     wr_wrgeojson['wr_properties']['simplified'] = False
49
50     wr_wrgeojson_old_str = format_json(wr_wrgeojson_old)
51     wr_wrgeojson_str = format_json(wr_wrgeojson)
52
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:
57         return
58     elif choice == Choice.quit:
59         sys.exit(0)
60
61     site(
62         'edit',
63         pageid=wrgeojson_page['pageid'],
64         text=wr_wrgeojson_str,
65         summary='Landkarte ersetzt.',
66         minor=1,
67         bot=1,
68         baserevid=wrgeojson_page['revisions'][0]['revid'],
69         nocreate=1,
70         token=site.token(),
71     )
72
73
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)
77
78     site = WikiSite(ini_files)
79
80     # Search all sledrun relations
81     osm_sledrun_list = list(find_sledrun_relations(osm_tree))
82
83     # Select one sledrun to work with
84     if len(osm_sledrun_list) == 0:
85         cprint('No sledruns in OSM file.', 'red')
86         return
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):
90             t = tags(osm_sledrun)
91             print(f'{i}: {t.get("name", t)}')
92         return
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)
95
96
97 def main():
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)
107
108
109 if __name__ == '__main__':
110     main()