source: subversion/applications/rendering/parking/mapnik/generate_parking_layer_xml.py @ 27496

Last change on this file since 27496 was 26691, checked in by kdrangmeister, 8 years ago

Add a third transparent layer in order to make the whole areas less transparent.

  • Property svn:mime-type set to text/plain
File size: 17.9 KB
Line 
1# -*- coding: utf-8 -*-
2# by kay
3
4import sys,os,subprocess,shutil
5from optparse import OptionParser
6#from xml.dom.minidom import parse, parseString
7import pxdom
8
9#import colorsys
10
11condition_colors = {
12    'free': '7fff00',
13    'disc': '50a100',
14    'cust': 'b68529',
15    'resi': '785534',
16    'priv': '3f2920',
17    'fee':  '67a1eb',
18    'unkn': 'bc73e2' # purple:'bc73e2' ; bluegreen:'6fc58a'
19    }
20
21forbidden_colors = {
22    'nopa': 'f8b81f',
23    'nost': 'f85b1f',
24    'fire': 'f81f1f'
25    }
26
27
28"""
29def dom_convert_to_grey(document):
30    els = document.getElementsByTagName("CssParameter")
31    #print "els=",els
32    for el in els:
33        at = el.getAttribute("name")
34        if at=="stroke" or at=="fill":
35            col=el.firstChild.nodeValue
36            bw=rgb_to_css(color_to_bw(parse_color(col)))
37            print "converted {typ} from {a} to {bw}." .format(typ=at,a=col,bw=bw)
38            el.firstChild.nodeValue=bw
39
40    #<Map bgcolor="---" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over" minimum_version="0.7.1">
41    els = document.getElementsByTagName("Map")
42    for el in els:
43        col = el.getAttribute("bgcolor")
44        assert(col!='')
45        assert(col!=None)
46        bw=rgb_to_css(color_to_bw(parse_color(col)))
47        print "converted {typ} from {a} to {bw}." .format(typ='bgcolor',a=col,bw=bw)
48        el.setAttribute("bgcolor",bw)
49
50    #<TextSymbolizer ... fill="#6699cc"/>
51    els = document.getElementsByTagName("TextSymbolizer")
52    for el in els:
53        col = el.getAttribute("fill")
54        assert(col!='')
55        assert(col!=None)
56        bw=rgb_to_css(color_to_bw(parse_color(col)))
57        print "converted {typ} from {a} to {bw}." .format(typ='TS-fill',a=col,bw=bw)
58        el.setAttribute("fill",bw)
59        #<TextSymbolizer halo_fill="#fed7a5"/> (optional)
60        col = el.getAttribute("halo_fill")
61        assert(col!=None)
62        if col!='':
63            bw=rgb_to_css(color_to_bw(parse_color(col)))
64            print "converted {typ} from {a} to {bw}." .format(typ='TS-halo_fill',a=col,bw=bw)
65            el.setAttribute("halo_fill",bw)
66"""
67
68def dom_strip_style_and_layer(document,stylename,layername):
69    removeElements=[]
70    # remove <Style name="points"> and <Layer name="amenity-points">
71    els = document.getElementsByTagName("Style")
72    for el in els:
73        if el.getAttribute("name")==stylename:
74            removeElements.append(el)
75    els = document.getElementsByTagName("Layer")
76    for el in els:
77        if el.getAttribute("name")==layername:
78            removeElements.append(el)
79    print "removing the following elements:"
80    print removeElements
81    for el in removeElements:
82        parent = el.parentNode
83        parent.removeChild(el)
84
85def dom_strip_icons(document):
86    dom_strip_style_and_layer(document,"points","amenity-points")
87    dom_strip_style_and_layer(document,"power_line","power_line")
88    dom_strip_style_and_layer(document,"power_minorline","power_minorline")
89    dom_strip_style_and_layer(document,"power_towers","power_towers")
90    dom_strip_style_and_layer(document,"power_poles","power_poles")
91
92def transmogrify_file(sf,dfgrey,dfnoicons):
93    dom= pxdom.getDOMImplementation('')
94    parser= dom.createLSParser(dom.MODE_SYNCHRONOUS, None)
95    parser.domConfig.setParameter('entities', 0) # 1 -> exception if attribute values is set
96    #parser.domConfig.setParameter('disallow-doctype', 1)
97    parser.domConfig.setParameter('pxdom-resolve-resources', 1) # 1 -> replace &xyz; with text
98    document = parser.parseURI(sf)
99
100#    dom_convert_to_grey(document)
101   
102    output= document.implementation.createLSOutput()
103    output.systemId= dfgrey
104    output.encoding= 'utf-8'
105    serialiser= document.implementation.createLSSerializer()
106    serialiser.write(document, output)
107
108"""
109    dom_strip_icons(document)
110   
111    output= document.implementation.createLSOutput()
112    output.systemId= dfnoicons
113    output.encoding= 'utf-8'
114    serialiser= document.implementation.createLSSerializer()
115    serialiser.write(document, output)
116"""
117
118def strip_doctype(f):
119    p = subprocess.Popen(['sed','-i','2,10 d',f]) # -i means 'in place'
120    p.wait()
121
122def create_parking_icons(source_symbols_dir,dest_symbols_dir):
123    create_parking_lane_icons(source_symbols_dir,dest_symbols_dir)
124    create_parking_area_icons(source_symbols_dir,dest_symbols_dir)
125    create_parking_point_icons(source_symbols_dir,dest_symbols_dir)
126   
127def create_parking_lane_icons(source_symbols_dir,dest_symbols_dir):
128    # first create mirror images (from left to right)
129    image_files = os.listdir(source_symbols_dir)
130    image_files = [f for f in image_files if f.startswith('park-l') and f.endswith('png')]
131    for f in image_files:
132        sf = os.path.join(source_symbols_dir,f)
133        df = os.path.join(source_symbols_dir,f) # this is changed so that we write in the source dir
134        hflip_icon(sf,df.replace('-l','-r'))
135
136    # then, create the colors
137    image_files = os.listdir(source_symbols_dir)
138    image_files = [f for f in image_files if f.endswith('source.png')]
139    for f in image_files:
140        # convert ./original-mapnik/symbols/*.png -fx '0.25*r + 0.62*g + 0.13*b' ./bw-mapnik/symbols/*.png
141        sf = os.path.join(source_symbols_dir,f)
142        df = os.path.join(dest_symbols_dir,f)
143        if 'n-' in f:      # then it's a non-parking thing
144            for c in forbidden_colors.iterkeys():
145                colorize_icon(sf,df.replace('source',c),forbidden_colors.get(c))
146        else:
147            for c in condition_colors.iterkeys():
148                colorize_icon(sf,df.replace('source',c),condition_colors.get(c))
149
150def create_parking_area_icons(source_symbols_dir,dest_symbols_dir):
151    tempf = "/tmp/2347856893476512873465.png"
152    df = os.path.join(dest_symbols_dir,"parking_area_source.png")
153    stampf = os.path.join(source_symbols_dir,"parking_area_stamp.png")
154    for c in condition_colors.iterkeys():
155        # step 1: colorize a "stamp" template image
156        p = subprocess.Popen(['convert','-size','16x16','xc:#'+condition_colors.get(c),stampf,'-compose','Darken','-composite',tempf])
157        p.wait()
158        # step 2: make it 50% transparent
159        # convert -size 16x16 parking_area_free.png xc:grey -alpha off -compose Copy_Opacity -composite  /tmp/a.png && gwenview /tmp/a.png
160        p = subprocess.Popen(['convert','-size','16x16',tempf,'xc:gray','-alpha','off','-compose','Copy_Opacity','-composite',df.replace('source',c)])
161        p.wait()
162
163
164def create_parking_point_icons(source_symbols_dir,dest_symbols_dir):
165    tempf = "/tmp/2347856893476512873465.png"
166    stampf = os.path.join(source_symbols_dir,"parking_node_stamp.png")
167    # for now there's only the parking-vending icon
168    copy_files(source_symbols_dir,dest_symbols_dir,['parking-vending.png'])
169    # parking nodes
170    for condition in condition_colors.keys():
171        # convert ./original-mapnik/symbols/*.png -fx '0.25*r + 0.62*g + 0.13*b' ./bw-mapnik/symbols/*.png
172        sf = os.path.join(source_symbols_dir,'parking_node_source.png')
173        df = os.path.join(dest_symbols_dir,'parking_node_{cond}.png'.format(cond=condition))
174        colorize_icon(sf,tempf,condition_colors.get(condition))
175        p = subprocess.Popen(['convert','-size','16x16',tempf,stampf,'-compose','Darken','-composite',df])
176        print (['convert','-size','16x16',tempf,stampf,'-compose','Darken','-composite',df])
177        p.wait()
178
179def copy_files(src,dest,files):
180    for f in files:
181        if type(f) is tuple:
182            shutil.copy2(os.path.join(src,f[0]),os.path.join(dest,f[1]))
183        else:
184            shutil.copy2(os.path.join(src,f),os.path.join(dest,f))
185
186def colorize_icon(sf,df,color):
187    p = subprocess.Popen(['convert',sf,'-fill','#'+color,'-colorize','100',df])
188    p.wait()
189
190def hflip_icon(sf,df):
191    p = subprocess.Popen(['convert',sf,'-flip',df])
192    p.wait()
193
194def stamp_icon(sf,df,stampf):
195    p = subprocess.Popen(['convert',sf,stampf,'-compose','Darken','-composite',df])
196    p.wait()
197
198def add_license_files(dirname):
199    f = open(os.path.join(dirname,"CONTACT"), 'w')
200    f.write("This style is created by kayd@toolserver.org")
201    f.close
202    f = open(os.path.join(dirname,"LICENSE"), 'w')
203    f.write("This derived work is published by the author, Kay Drangmeister, under the same license as the original OSM mapnik style sheet (found here: http://svn.openstreetmap.org/applications/rendering/mapnik)")
204    f.close
205
206def main_parktrans(options):
207    style_name = options['stylename']
208    source_dir = options['sourcedir']
209    source_file = options['sourcefile']
210    #source_symbols_dir_mapnik = os.path.join(source_dir,"symbols")
211    source_symbols_dir_style = os.path.join(source_dir,"parking-symbols-src")
212    dest_dir = options['destdir']
213
214    # parktrans - transparent layer to be put on top of mapnik or bw-noicons base layer
215   
216    dest_dir_style = os.path.join(dest_dir,style_name)
217    dest_dir_style_symbols = os.path.join(dest_dir_style,"symbols")
218    dest_file_style = 'osm-{style}.xml'.format(style=style_name)
219    style_file = os.path.join(dest_dir_style,dest_file_style)
220    if not os.path.exists(dest_dir_style_symbols):
221        os.makedirs(dest_dir_style_symbols)
222
223    create_parking_icons(source_symbols_dir_style,dest_dir_style_symbols)
224    transmogrify_file(os.path.join(source_dir,source_file),style_file,"")
225    strip_doctype(style_file)
226    add_license_files(dest_dir_style)
227
228def main_parking(options):
229    style_name = options['stylename']
230    source_bwn_dir = options['sourcebwndir']
231    source_bwn_file = options['sourcebwnfile']
232    source_p_dir = options['sourcepdir']
233    source_p_file = options['sourcepfile']
234    source_symbols_dir_style = os.path.join(source_p_dir,"parking-symbols-src")
235    dest_dir = options['destdir']
236
237    dest_dir_style = os.path.join(dest_dir,style_name)
238    dest_dir_style_symbols = os.path.join(dest_dir_style,"symbols")
239    dest_file_style = 'osm-{style}.xml'.format(style=style_name)
240    style_file = os.path.join(dest_dir_style,dest_file_style)
241    if not os.path.exists(dest_dir_style_symbols):
242        os.makedirs(dest_dir_style_symbols)
243
244    create_parking_icons(source_symbols_dir_style,dest_dir_style_symbols)
245    merge_bw_noicons_and_parktrans_style(os.path.join(source_bwn_dir,source_bwn_file),os.path.join(source_p_dir,source_p_file),style_file)
246    #strip_doctype(style_file)
247    add_license_files(dest_dir_style)
248
249def merge_bw_noicons_and_parktrans_style(bwnoicons_style_file,parktrans_style_file,dest_parking_style_file):
250    dom= pxdom.getDOMImplementation('')
251    parser= dom.createLSParser(dom.MODE_SYNCHRONOUS, None)
252    parser.domConfig.setParameter('entities', 0) # 1 -> exception if attribute values is set
253    #parser.domConfig.setParameter('disallow-doctype', 1)
254    parser.domConfig.setParameter('pxdom-resolve-resources', 1) # 1 -> replace &xyz; with text
255    dest_parking_style_document = parser.parseURI(bwnoicons_style_file)
256    parktrans_style_document = parser.parseURI(parktrans_style_file)
257
258    parking_area_style = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parking-area'))
259    parking_area_layer = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parking-area'))
260    things=[parking_area_style,parking_area_layer]
261    #better put parking area layer earlier, before all roads
262    parking_dom_insert_things_before_layer(dest_parking_style_document,things,'turning_circle-casing')
263    # duplicate the parking-area layer in order to make it less transparent
264    clone_of_parking_area_layer = parking_dom_clone_layer(dest_parking_style_document,'parking-area')
265    clone_of_parking_area_layer.setAttribute('name','parking-area-double')
266    parking_dom_insert_things_before_layer(dest_parking_style_document,clone_of_parking_area_layer,'turning_circle-casing')
267
268    #add a second parking area layer on top of the parking-aisle roads.
269    parking_area_top_layer = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parking-area-top'))
270    things=[parking_area_top_layer]
271    parking_dom_insert_things_before_layer(dest_parking_style_document,things,'direction_pre_bridges')
272
273    # handle the parking lanes
274    pllno = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-left-no'))
275    plrno = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-right-no'))
276    pllin = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-left-parallel'))
277    plrin = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-right-parallel'))
278    plldi = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-left-diagonal'))
279    plrdi = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-right-diagonal'))
280    pllor = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-left-perpendicular'))
281    plror = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parkinglane-right-perpendicular'))
282    pll = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parkinglane-left'))
283    plr = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parkinglane-right'))
284    things=[pllno,plrno,pllin,plrin,plldi,plrdi,pllor,plror,pll,plr]
285    parking_dom_insert_things_before_layer(dest_parking_style_document,things,'direction_pre_bridges')
286
287    # handle the parking points / nodes
288    parking_points_style = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parking-points'))
289    parking_points_layer = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parking-points'))
290    parking_area_text_style = dest_parking_style_document.adoptNode(parking_dom_cut_style(parktrans_style_document,'parking-area-text'))
291    parking_area_text_layer = dest_parking_style_document.adoptNode(parking_dom_cut_layer(parktrans_style_document,'parking-area-text'))
292    things=[parking_points_style,parking_points_layer,parking_area_text_style,parking_area_text_layer]
293    parking_dom_insert_things_before_layer(dest_parking_style_document,things,'direction_pre_bridges')
294
295    output= dest_parking_style_document.implementation.createLSOutput()
296    output.systemId= dest_parking_style_file
297    output.encoding= 'utf-8'
298    serialiser= dest_parking_style_document.implementation.createLSSerializer()
299    serialiser.write(dest_parking_style_document, output)
300
301    ''' write a "rest" file to check if everything has been cut out
302    output= parktrans_style_document.implementation.createLSOutput()
303    output.systemId= 'rest.xml'
304    output.encoding= 'utf-8'
305    serialiser= parktrans_style_document.implementation.createLSSerializer()
306    serialiser.write(parktrans_style_document, output)
307    '''
308
309def parking_dom_insert_things_before_layer(document,things,here):
310    # insert things after the "leisure" layer
311    els = document.getElementsByTagName("Layer")
312    #print "els="
313    #print els
314    for el in els:
315        #print "layername={ln}".format(ln=el.getAttribute("name"))
316        if el.getAttribute("name")==here:
317            #print "found it"
318            if type(things) is list:
319                for s in things:
320                    el.parentNode.insertBefore(s,el)
321            else:
322                el.parentNode.insertBefore(things,el)
323            return
324    raise 'Layer name not found'
325
326def parking_dom_clone_layer(document,what):
327    els = document.getElementsByTagName("Layer")
328    for el in els:
329        #print "layername={ln}".format(ln=el.getAttribute("name"))
330        if el.getAttribute("name")==what:
331            #print "found it"
332            clone = el.cloneNode(True)
333            return clone
334    raise BaseException('Layer name {ln} not found'.format(ln=what))
335
336def parking_dom_cut_layer(document,what):
337    els = document.getElementsByTagName("Layer")
338    for el in els:
339        #print "layername={ln}".format(ln=el.getAttribute("name"))
340        if el.getAttribute("name")==what:
341            #print "found it"
342            el.parentNode.removeChild(el)
343            return el
344    raise BaseException('Layer name {ln} not found'.format(ln=what))
345
346def parking_dom_cut_style(document,what):
347    els = document.getElementsByTagName("Style")
348    for el in els:
349        #print "layername={ln}".format(ln=el.getAttribute("name"))
350        if el.getAttribute("name")==what:
351            #print "found it"
352            el.parentNode.removeChild(el)
353            return el
354    raise BaseException('Style name {sn} not found'.format(sn=what))
355
356"""
357./generate_xml.py osm-parking-src.xml    osm-parking.xml    --accept-none --host sql-mapnik --dbname osm_mapnik --prefix planet --inc ./parking-inc --symbols ./parking-symbols/ --world_boundaries /home/project/o/s/m/osm/data/world_boundaries/ --password ''
358./generate_xml.py osm-parking-bw-src.xml osm-parking-bw.xml --accept-none --host sql-mapnik --dbname osm_mapnik --prefix planet --inc ./parking-inc --symbols ./parking-symbols/ --world_boundaries /home/project/o/s/m/osm/data/world_boundaries/ --password ''
359./generate_xml.py osm-parkerr-src.xml    osm-parkerr.xml    --accept-none --host sql-mapnik --dbname osm_mapnik --prefix planet --inc ./parking-inc --symbols ./parking-symbols/ --world_boundaries /home/project/o/s/m/osm/data/world_boundaries/ --password ''
360"""
361
362if __name__ == '__main__':
363    parser = OptionParser()
364    parser.add_option("-s", "--sourcedir", dest="sourcedir", help="path to the source directory", default=".")
365    parser.add_option("-f", "--sourcefile", dest="sourcefile", help="source filename, default is 'osm.xml')", default="osm.xml")
366    parser.add_option("-d", "--destdir", dest="destdir", help="path to the destination directory, further dirs are created within. default is '/tmp'", default="/tmp")
367    (options, args) = parser.parse_args()
368    options['stylename'] = "parktrans"
369    print options
370    main_parktrans(options.__dict__)
371    options['sourcefile'] = "osm-parking-src.xml"
372    options['stylename'] = "parking"
373    main_parking(options.__dict__)
374    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.