#!python3 # -*- coding: utf-8 __author__ = "Přemek Hnilica" __date__ = "$May 1, 2015 1:04:50 PM$" from xml.etree import ElementTree as et from argparse import ArgumentParser import os import re from bisect import bisect_left # 1 - some debug messages # 3 - more debug messages debug = 0; allRels = [] allRefs = {} tagsToCopy_tourist = ( (('kct_red', 'kct_blue', 'kct_green', 'kct_yellow'),('major', 'local', 'learning', 'ruin', 'peak', 'spring', 'interesting_object', 'horse', 'ski', 'bicycle', 'wheelchair')), ) tagsToCopy_cycle = ( (('route',),('bicycle',)), (('network',),('ncn','rcn','lcn',)), ) outFileName = 'map/mergedMap.osm' ################ Functions ############### def findRel(ref): return root.find("relation[@id='"+ref+"']") # function for precosseing relation # it searches some tag which needs to be copied and saves it # node - current relation # checker - if I have some tag to copy # desiredTags - tags to copy def processNode(node,checker,checkerRefs,desiredTags,desiredRefs): # checker = 0 - I dont have tag # checker = 1 - I have tag for tourist route # checker = 2 - O have tag for cycle route if debug > 2: print('procesing relation: '+node.get('id')) relatedWays = [] if (checker > 0): for child in node.getchildren(): if (child.get("type") == "way"): relatedWays.append(child.get("ref")) elif (child.get("type") == "relation"): # because osm allows super relations (relation containing other relations) rel = findRel(child.get("ref")) if rel is not None: processNode(rel,checker,checkerRefs,desiredTags,desiredRefs) elif (child.get("type") == "tag"): # if I reached tags, I can finish break else: for child in reversed(node.getchildren()): # going reverse through all children of relation if child.tag == "tag": k = child.get('k') v = child.get('v') if debug > 2: print(' found tag: '+k+'='+v) for group in tagsToCopy_tourist:# loop through all tag groups I want to copy if(k in group[0] and v in group[1]): # if actual tag matches tags that I want to copy checker = 1 if debug > 1: print('do',desiredTags,'pridavam T',k,v) desiredTags.append([k, v]) # save it # Si ----------------------- osmc_color = (re.search(r'kct_([a-z]+)', k)).group(1) # extract OSMC color if debug > 1: print('do ',desiredTags,' pridavam osmc_color=',osmc_color) desiredTags.append(['osmc', 'yes']) # save it desiredTags.append(['osmc_color', osmc_color]) # save it # Si ----------------------- break if(checker != 1): for group in tagsToCopy_cycle:# loop through all tag groups I want to copy if(k in group[0] and v in group[1]): # if actual tag matches tags that I want to copy checker = 2 if debug > 1: print('do',desiredTags,'pridavam C',k,v) desiredTags.append([k, v]) # save it break if (checker == 2): if(k == 'ref'): checkerRefs = True desiredRefs = v else: # here I am at the end of tags, I can finish searching for tags if (checker > 0): if (child.get("type") == "way"): wayID = child.get("ref") relatedWays.append(wayID) if (checkerRefs): if (wayID in allRefs): allRefs[wayID].append(desiredRefs) else: allRefs[wayID] = [desiredRefs] elif (child.get("type") == "relation"): # because osm allows super relations (relation containing other relations) rel = findRel(child.get("ref")) if rel is not None: processNode(rel,checker,checkerRefs,desiredTags,desiredRefs) if (checker > 0): # if I have some tag to copy if debug > 2: print('found tags to copy: '+repr(desiredTags)+" to ways "+repr(relatedWays)) for i in desiredTags: # loop through all saved tags newTag = True # assume I have got new tag to be added for j in allRels: # go through all previously saved tags if debug > 2: print('matching '+repr(i)+' to '+repr(j[0])) #print("allRels1 {"+repr(allRels)+"}\n") if (i == j[0]): # if I already have saved same tag j[1].extend(relatedWays) if debug > 2: print("allRels2 {"+repr(allRels)+"}\n") newTag = False # found out I already have this tag saved break if (newTag == True): # if it is really new tag if debug > 2: print("append allRels {"+repr(i)+"}\n") allRels.append([i,relatedWays[:]]) # save it checker = 0 checkerRefs = False if debug > 2: for r in allRels: print("allRels{"+repr(r)+"}\n") # binary search over a sorted list def index(list, x): i = bisect_left(list, x) if i != len(list) and list[i] == x: return i else: return -1 ################## Program ################### parser = ArgumentParser(description="OSM copy tags from relations to ways") parser.add_argument("filename") args = parser.parse_args() # Divide file into 3 files - nodes, ways, relations print ("Splitting source file into temporary files...") outFile = open(outFileName,'w') testString = '': # If reached end of the file outFile.write(line) break elif testString == '' #set search string outFile.close() outFile = open('relations.xml','w') # set relations as outFile outFile.write("\n") else: # if I am still looking for ways outFile.close() outFile = open('ways.xml','w') #set ways as outFile testString = ' 0: for r in allRels: print("allRels{"+repr(r)+"}\n") ## Merge the documents again status = 2 # for status printing (20%,40%,60%,80%) print("Writing final result...") outFile = open(outFileName,'a') with open('ways.xml','r') as inFile: counter = 0 way_id = None for line in inFile: if ('\n')# write it here if (way_id in allRefs): for a in allRefs[way_id]: outFile.write('\n')# write it here #TODO here I can remove allRefs[way_id] from dict? way_id = None outFile.write(line) # and then write the tag else: outFile.write(line) # some nd or other info that has to be just copied # some status printout counter += 1 if ((counter % 10000) == 0): if ((status == 8) and ((os.path.getsize(outFileName) - sourceNodesFileSize) > sourceWaysFileSize80)): print("80% processed ") status = 10 elif ((status == 6) and ((os.path.getsize(outFileName) - sourceNodesFileSize) > sourceWaysFileSize60)): print("60% processed") status = 8 elif ((status == 4) and ((os.path.getsize(outFileName) - sourceNodesFileSize) > sourceWaysFileSize40)): print("40% processed") status = 6 elif ((status == 2) and ((os.path.getsize(outFileName) - sourceNodesFileSize) > sourceWaysFileSize20)): print("20% processed") status = 4 with open('relations.xml','r') as f: next(f) # I dont want to print that (manually added) for line in f: outFile.write(line) outFile.close() print("Done") print("Removing temporary files...") os.remove('ways.xml') os.remove('relations.xml') print("Done")