source: subversion/applications/rendering/parking/mapnik/mapnik_to_bw.py @ 28125

Last change on this file since 28125 was 28066, checked in by kdrangmeister, 8 years ago

removed also layer amenity-points-poly from osm-mapnik for noicons style

File size: 16.6 KB
Line 
1# -*- coding: utf-8 -*-
2# by kay
3
4import sys,os,subprocess
5from optparse import OptionParser
6#from xml.dom.minidom import parse, parseString
7import pxdom
8#import colorsys
9
10simple_colors = {
11    'aliceblue': 'f0f8ff',
12    'antiquewhite': 'faebd7',
13    'aqua': '00ffff',
14    'aquamarine': '7fffd4',
15    'azure': 'f0ffff',
16    'beige': 'f5f5dc',
17    'bisque': 'ffe4c4',
18    'black': '000000',
19    'blanchedalmond': 'ffebcd',
20    'blue': '0000ff',
21    'blueviolet': '8a2be2',
22    'brown': 'a52a2a',
23    'burlywood': 'deb887',
24    'cadetblue': '5f9ea0',
25    'chartreuse': '7fff00',
26    'chocolate': 'd2691e',
27    'coral': 'ff7f50',
28    'cornflowerblue': '6495ed',
29    'cornsilk': 'fff8dc',
30    'crimson': 'dc143c',
31    'cyan': '00ffff',
32    'darkblue': '00008b',
33    'darkcyan': '008b8b',
34    'darkgoldenrod': 'b8860b',
35    'darkgray': 'a9a9a9',
36    'darkgreen': '006400',
37    'darkkhaki': 'bdb76b',
38    'darkmagenta': '8b008b',
39    'darkolivegreen': '556b2f',
40    'darkorange': 'ff8c00',
41    'darkorchid': '9932cc',
42    'darkred': '8b0000',
43    'darksalmon': 'e9967a',
44    'darkseagreen': '8fbc8f',
45    'darkslateblue': '483d8b',
46    'darkslategray': '2f4f4f',
47    'darkturquoise': '00ced1',
48    'darkviolet': '9400d3',
49    'deeppink': 'ff1493',
50    'deepskyblue': '00bfff',
51    'dimgray': '696969',
52    'dodgerblue': '1e90ff',
53    'feldspar': 'd19275',
54    'firebrick': 'b22222',
55    'floralwhite': 'fffaf0',
56    'forestgreen': '228b22',
57    'fuchsia': 'ff00ff',
58    'gainsboro': 'dcdcdc',
59    'ghostwhite': 'f8f8ff',
60    'gold': 'ffd700',
61    'goldenrod': 'daa520',
62    'gray': '808080',
63    'green': '008000',
64    'greenyellow': 'adff2f',
65    'grey': '808080',
66    'honeydew': 'f0fff0',
67    'hotpink': 'ff69b4',
68    'indianred ': 'cd5c5c',
69    'indigo ': '4b0082',
70    'ivory': 'fffff0',
71    'khaki': 'f0e68c',
72    'lavender': 'e6e6fa',
73    'lavenderblush': 'fff0f5',
74    'lawngreen': '7cfc00',
75    'lemonchiffon': 'fffacd',
76    'lightblue': 'add8e6',
77    'lightcoral': 'f08080',
78    'lightcyan': 'e0ffff',
79    'lightgoldenrodyellow': 'fafad2',
80    'lightgrey': 'd3d3d3',
81    'lightgreen': '90ee90',
82    'lightpink': 'ffb6c1',
83    'lightsalmon': 'ffa07a',
84    'lightseagreen': '20b2aa',
85    'lightskyblue': '87cefa',
86    'lightslateblue': '8470ff',
87    'lightslategray': '778899',
88    'lightsteelblue': 'b0c4de',
89    'lightyellow': 'ffffe0',
90    'lime': '00ff00',
91    'limegreen': '32cd32',
92    'linen': 'faf0e6',
93    'magenta': 'ff00ff',
94    'maroon': '800000',
95    'mediumaquamarine': '66cdaa',
96    'mediumblue': '0000cd',
97    'mediumorchid': 'ba55d3',
98    'mediumpurple': '9370d8',
99    'mediumseagreen': '3cb371',
100    'mediumslateblue': '7b68ee',
101    'mediumspringgreen': '00fa9a',
102    'mediumturquoise': '48d1cc',
103    'mediumvioletred': 'c71585',
104    'midnightblue': '191970',
105    'mintcream': 'f5fffa',
106    'mistyrose': 'ffe4e1',
107    'moccasin': 'ffe4b5',
108    'navajowhite': 'ffdead',
109    'navy': '000080',
110    'oldlace': 'fdf5e6',
111    'olive': '808000',
112    'olivedrab': '6b8e23',
113    'orange': 'ffa500',
114    'orangered': 'ff4500',
115    'orchid': 'da70d6',
116    'palegoldenrod': 'eee8aa',
117    'palegreen': '98fb98',
118    'paleturquoise': 'afeeee',
119    'palevioletred': 'd87093',
120    'papayawhip': 'ffefd5',
121    'peachpuff': 'ffdab9',
122    'peru': 'cd853f',
123    'pink': 'ffc0cb',
124    'plum': 'dda0dd',
125    'powderblue': 'b0e0e6',
126    'purple': '800080',
127    'red': 'ff0000',
128    'rosybrown': 'bc8f8f',
129    'royalblue': '4169e1',
130    'saddlebrown': '8b4513',
131    'salmon': 'fa8072',
132    'sandybrown': 'f4a460',
133    'seagreen': '2e8b57',
134    'seashell': 'fff5ee',
135    'sienna': 'a0522d',
136    'silver': 'c0c0c0',
137    'skyblue': '87ceeb',
138    'slateblue': '6a5acd',
139    'slategray': '708090',
140    'snow': 'fffafa',
141    'springgreen': '00ff7f',
142    'steelblue': '4682b4',
143    'tan': 'd2b48c',
144    'teal': '008080',
145    'thistle': 'd8bfd8',
146    'tomato': 'ff6347',
147    'turquoise': '40e0d0',
148    'violet': 'ee82ee',
149    'violetred': 'd02090',
150    'wheat': 'f5deb3',
151    'white': 'ffffff',
152    'whitesmoke': 'f5f5f5',
153    'yellow': 'ffff00',
154    'yellowgreen': '9acd32'
155    }
156
157def color_to_bw(rgb):
158    r,g,b=rgb
159    #method 1:
160    #y = 0.229*r + 0.587*g + 0.114*b
161    y = 0.25*r + 0.62*g + 0.13*b
162    return (y,y,y)
163    """
164    #method 2:
165    h,l,s = colorsys.rgb_to_hls(r, g, b)
166    s *= 0   # desaturate
167    return colorsys.hls_to_rgb(h,l,s)
168    """
169
170def parse_color(s):
171    """ Parses color string in format #ABC or #AABBCC to RGB tuple. """
172    s = s.lower()
173    if simple_colors.has_key(s):  # translate color names to rgb
174        s = '#'+simple_colors.get(s)
175    l = len(s)
176    assert(l in (4,7))
177#    print "s=",s
178    if l==4:
179        return tuple(int(ch * 2, 16)/255.0 for ch in s[1:])
180    else:
181        return tuple(int(ch1 + ch2, 16)/255.0 for ch1, ch2 in \
182                     zip(
183                        (ch1 for ch1 in s[1::2]),
184                        (ch2 for ch2 in s[2::2])
185                        )
186                    )
187
188def rgb_to_css(rgb):
189    r,g,b=rgb
190    return "#{r:02x}{g:02x}{b:02x}".format(r=int(r*255.0),g=int(g*255.0),b=int(b*255.0))
191
192def element_convert_attibute_to_grey(document,elementName,attributeName):
193    els = document.getElementsByTagName(elementName)
194    for el in els:
195        col = el.getAttribute(attributeName)
196        assert(col!='')
197        assert(col!=None)
198        bw=rgb_to_css(color_to_bw(parse_color(col)))
199        #print "converted {ele}:{att} from {a} to {bw}." .format(ele=elementName,att=attributeName,a=col,bw=bw)
200        el.setAttribute(attributeName,bw)
201
202def dom_convert_to_grey(document):
203    element_convert_attibute_to_grey(document,"Map","background-color")
204    """ vorher: CssParameter fuer die Farben bei LineSymbolizer und PolygonSymbolizer
205    els = document.getElementsByTagName("CssParameter")
206    #print "els=",els
207    for el in els:
208        at = el.getAttribute("name")
209        if at=="stroke" or at=="fill":
210            col=el.firstChild.nodeValue
211            bw=rgb_to_css(color_to_bw(parse_color(col)))
212            #print "converted {typ} from {a} to {bw}." .format(typ=at,a=col,bw=bw)
213            el.firstChild.nodeValue=bw
214    """
215    element_convert_attibute_to_grey(document,"LineSymbolizer","stroke")
216    element_convert_attibute_to_grey(document,"PolygonSymbolizer","fill")
217
218    #<TextSymbolizer ... fill="#6699cc"/>
219    els = document.getElementsByTagName("TextSymbolizer")
220    for el in els:
221        col = el.getAttribute("fill")
222        assert(col!='')
223        assert(col!=None)
224        bw=rgb_to_css(color_to_bw(parse_color(col)))
225        #print "converted {typ} from {a} to {bw}." .format(typ='TS-fill',a=col,bw=bw)
226        el.setAttribute("fill",bw)
227        #<TextSymbolizer halo-fill="#fed7a5"/> (optional)
228        col = el.getAttribute("halo-fill")
229        assert(col!=None)
230        if col!='':
231            bw=rgb_to_css(color_to_bw(parse_color(col)))
232            #print "converted {typ} from {a} to {bw}." .format(typ='TS-halo-fill',a=col,bw=bw)
233            el.setAttribute("halo-fill",bw)
234
235
236def dom_strip_style_and_layer(document,stylename,layername):
237    removeElements=[]
238    # remove <Style name="points"> and <Layer name="amenity-points">
239    els = document.getElementsByTagName("Style")
240    for el in els:
241        if el.getAttribute("name")==stylename:
242            removeElements.append(el)
243    els = document.getElementsByTagName("Layer")
244    for el in els:
245        if el.getAttribute("name")==layername:
246            removeElements.append(el)
247    print removeElements
248    for el in removeElements:
249        parent = el.parentNode
250        parent.removeChild(el)
251
252def dom_strip_rules_from_style(document,stylename,filters):
253#    print '    filter val = "'+filter+'"'
254    filterSet = set(filters)
255    removeElements=[]
256    # find the style
257    thestyle = None
258    els = document.getElementsByTagName("Style")
259    for el in els:
260        if el.getAttribute("name")==stylename:
261            thestyle = el
262            break
263    assert(thestyle != None)
264    # find the rule where the filter matches
265    print thestyle
266    rules = thestyle.childNodes
267    for rule in rules:
268        #print "new rule"
269        ruleElements = rule.childNodes
270        for re in ruleElements:
271            #print "  ruleelement "+re.nodeName
272            if re.nodeName=="Filter":
273                filterValue=re.firstChild.nodeValue
274                #print '    filter val = "'+filterValue+'"'
275                if filterValue in filterSet:
276                    removeElements.append(rule)
277                    filterSet.remove(filterValue)
278    if (len(filterSet)!=0): # not all filters have been found
279        for filter in filterSet:
280            print 'Filter "{f}" not found'.format(f=filter)
281    for el in removeElements:
282        parent = el.parentNode
283        parent.removeChild(el)
284   
285def dom_strip_POIs(document):
286    removeTexts=[
287                 "[amenity]='pub' or [amenity]='restaurant' or [amenity]='cafe' or [amenity]='fast_food' or [amenity]='biergarten'",
288                 "[amenity]='bar'",
289                 "[amenity]='library' or [amenity]='theatre' or [amenity]='courthouse'",
290                 "[amenity]='cinema'",
291                 "[amenity]='parking' and ([access] = 'public' or not [access] != '')",
292                 "[amenity]='parking' and ([access] != '' and not [access] = 'public')",
293                 "[amenity] = 'police'",
294                 "[amenity] = 'fire_station'",
295#                 "[amenity] = 'place_of_worship'",
296#                 "[natural] = 'wood'",
297#                 "[natural] = 'peak'",
298#                 "[natural] = 'peak' and not [name] != ''",
299#                 "[natural] = 'peak' and [name] != ''",
300#                 "[natural] = 'volcano'",
301#                 "[natural] = 'volcano' and not [name] != ''",
302#                 "[natural] = 'volcano' and [name] != ''",
303#                 "[natural] = 'cave_entrance'",
304                 "[historic] = 'memorial' or [historic]='archaeological_site'",
305#                 "[natural] = 'water' or [natural] = 'lake' or [landuse] = 'reservoir' or [landuse] = 'basin'",
306                 "([leisure] != '' or [landuse] != '') and [point] = 'yes'",
307                 "[natural] = 'bay'",
308                 "[natural] = 'spring'",
309                 "[tourism] = 'alpine_hut'",
310                 "[tourism] = 'alpine_hut'",
311                 "[amenity]='shelter'",
312                 "[amenity] = 'bank'",
313                 "[tourism] = 'hotel' or [tourism]='hostel' or [tourism]='chalet'",
314                 "[amenity] = 'embassy'",
315                 "[tourism]='guest_house'",
316                 "[tourism]='bed_and_breakfast'",
317                 "[amenity] = 'fuel' or [amenity]='bus_station'",
318                 "[tourism] = 'camp_site'",
319                 "[tourism] = 'caravan_site'",
320                 "[waterway] = 'lock'",
321                 "[leisure] = 'marina'",
322                 "[leisure] = 'marina'",
323                 "[tourism] = 'theme_park'",
324                 "[tourism] = 'theme_park'",
325                 "[tourism]='museum'",
326                 "[amenity]='prison'",
327                 "[tourism] = 'attraction'",
328                 "[amenity] = 'university'",
329                 "[amenity] = 'school' or [amenity] = 'college'",
330                 "[amenity] = 'kindergarten'",
331                 "[man_made] = 'lighthouse'",
332                 "[man_made] = 'windmill'",
333                 "[amenity] = 'hospital'",
334                 "[amenity] = 'pharmacy'",
335                 "[shop]='bakery' or [shop]='clothes' or [shop]='fashion' or [shop]='convenience' or [shop]='doityourself' or [shop]='hairdresser' or [shop]='butcher' or [shop]='car' or [shop]='car_repair' or [shop]='bicycle' or [shop]='florist'",
336                 "[shop]='supermarket' or [shop]='department_store'",
337                 "[military] = 'danger_area'",
338                 "[aeroway] = 'gate'"
339                 ]
340    dom_strip_rules_from_style(document,"text",removeTexts)
341
342def dom_strip_icons(document):
343    dom_strip_style_and_layer(document,"points","amenity-points")
344    dom_strip_style_and_layer(document,"points","amenity-points-poly")
345    dom_strip_POIs(document)
346    dom_strip_style_and_layer(document,"power_line","power_line")
347    dom_strip_style_and_layer(document,"power_minorline","power_minorline")
348    dom_strip_style_and_layer(document,"power_towers","power_towers")
349    dom_strip_style_and_layer(document,"power_poles","power_poles")
350
351def dom_adjust_map_element(document):
352    # in (e.g.) <Map background-color=... srs="&srs900913;" minimum-version="2.0.0"> <!ENTITY srs900913 "+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">
353    # out <Map background-color=... srs="+init=epsg:3857" minimum-version="2.0.0" buffer-size="512" maximum-extent="-20037508.342789244,-20037508.342780735,20037508.342789244,20037508.342780709">
354    map = document.getElementsByTagName("Map")[0]
355    srs = map.getAttribute("srs")
356    print('old map srs="{srs}"'.format(srs=srs))
357    srs = "+init=epsg:3857"
358    print('new map srs="{srs}"'.format(srs=srs))
359    map.setAttribute("srs",srs)
360    map.setAttribute("buffer-size","512")
361    map.setAttribute("maximum-extent","-20037508.342789244,-20037508.342780735,20037508.342789244,20037508.342780709")
362
363def transmogrify_file(sf,dfgrey,dfnoicons):
364    dom= pxdom.getDOMImplementation('') 
365    parser= dom.createLSParser(dom.MODE_SYNCHRONOUS, None)
366    parser.domConfig.setParameter('entities', 0) # 1 -> exception if attribute values is set
367    #parser.domConfig.setParameter('disallow-doctype', 1)
368    parser.domConfig.setParameter('pxdom-resolve-resources', 1) # 1 -> replace &xyz; with text
369    document = parser.parseURI(sf)
370
371    dom_adjust_map_element(document)
372    dom_convert_to_grey(document)
373
374    output= document.implementation.createLSOutput() 
375    output.systemId= dfgrey
376    output.encoding= 'utf-8' 
377    serialiser= document.implementation.createLSSerializer() 
378    serialiser.write(document, output)
379
380    dom_strip_icons(document)
381   
382    output= document.implementation.createLSOutput() 
383    output.systemId= dfnoicons
384    output.encoding= 'utf-8' 
385    serialiser= document.implementation.createLSSerializer() 
386    serialiser.write(document, output)
387
388def strip_doctype(f):
389    p = subprocess.Popen(['sed','-i','2,5 d',f]) # -i means 'in place'
390    p.wait()
391
392def convert_icons_to_bw(source_symbols_dir,dest_symbols_dir):
393    image_files = os.listdir(source_symbols_dir)
394    image_files = [f for f in image_files if f.endswith('png')]
395    for f in image_files:
396        # convert ./original-mapnik/symbols/*.png -fx '0.25*r + 0.62*g + 0.13*b' ./bw-mapnik/symbols/*.png
397        sf = os.path.join(source_symbols_dir,f)
398        df = os.path.join(dest_symbols_dir,f)
399        p = subprocess.Popen(['convert',sf,'-fx','0.25*r + 0.62*g + 0.13*b',df])
400        p.wait()
401
402def add_license_files(dirname):
403    f = open(os.path.join(dirname,"CONTACT"), 'w')
404    f.write("This style is created by kayd@toolserver.org")
405    f.close
406    f = open(os.path.join(dirname,"LICENSE"), 'w')
407    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)")
408    f.close
409
410def main(options):
411    source_dir = options['sourcedir']
412    source_file = options['sourcefile']
413    source_symbols_dir = os.path.join(source_dir,"symbols")
414    dest_dir = options['destdir']
415
416    dest_dir_bw = os.path.join(dest_dir,"bw-mapnik")
417    dest_dir_bw_symbols = os.path.join(dest_dir_bw,"symbols")
418    dest_file_bw = 'osm-bw.xml'
419    bw_file = os.path.join(dest_dir_bw,dest_file_bw)
420    if not os.path.exists(dest_dir_bw_symbols):
421        os.makedirs(dest_dir_bw_symbols)
422
423    dest_dir_bw_noicons = os.path.join(dest_dir,"bw-noicons")
424    dest_dir_bw_noicons_symbols = os.path.join(dest_dir_bw_noicons,"symbols")
425    dest_file_bw_noicons = 'osm-bw-noicons.xml'
426    bw_noicons_file = os.path.join(dest_dir_bw_noicons,dest_file_bw_noicons)
427    if not os.path.exists(dest_dir_bw_noicons_symbols):
428        os.makedirs(dest_dir_bw_noicons_symbols)
429
430    convert_icons_to_bw(source_symbols_dir,dest_dir_bw_symbols)
431    convert_icons_to_bw(source_symbols_dir,dest_dir_bw_noicons_symbols)
432    transmogrify_file(os.path.join(source_dir,source_file),bw_file,bw_noicons_file)
433    strip_doctype(bw_file)
434    strip_doctype(bw_noicons_file)
435    add_license_files(dest_dir_bw)
436    add_license_files(dest_dir_bw_noicons)
437
438if __name__ == '__main__':
439    parser = OptionParser()
440    parser.add_option("-s", "--sourcedir", dest="sourcedir", help="path to the source directory", default=".")
441    parser.add_option("-f", "--sourcefile", dest="sourcefile", help="source filename, default is 'osm.xml')", default="osm.xml")
442    parser.add_option("-d", "--destdir", dest="destdir", help="path to the destination directory, further dirs are created within. default is '/tmp'", default="/tmp")
443    (options, args) = parser.parse_args()
444    print options
445    main(options.__dict__)
446    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.