diff --git a/src/komap.py b/src/komap.py index 0086d34..9a5f039 100755 --- a/src/komap.py +++ b/src/komap.py @@ -17,35 +17,39 @@ from debug import debug, Timer from mapcss import MapCSS + import mapcss.webcolors whatever_to_hex = mapcss.webcolors.webcolors.whatever_to_hex -import sys +import sys reload(sys) sys.setdefaultencoding("utf-8") import os -import Image + +try: + import Image +except ImportError: + pass + + + + + from optparse import OptionParser import ConfigParser +import csv +import math config = ConfigParser.ConfigParser() - -try: - import psyco - psyco.full() -except ImportError: - pass - - def relaxedFloat(x): - try: - return float(x) if int(float(x)) != float(x) else int(x) + try: + return float(x) if int(float(x)) != float(x) else int(x) - except ValueError: - return float(str(x).replace(",", ".")) + except ValueError: + return float(str(x).replace(",", ".")) parser = OptionParser() parser.add_option("-r", "--renderer", dest="renderer", default="mapnik", @@ -56,7 +60,7 @@ parser.add_option("-f", "--minzoom", dest="minzoom", default=0, type="int", help="minimal available zoom level", metavar="ZOOM") parser.add_option("-t", "--maxzoom", dest="maxzoom", default=19, type="int", help="maximal available zoom level", metavar="ZOOM") -parser.add_option("-l", "--locale", dest="locale", +parser.add_option("-l", "--locale", dest="locale", help="language that should be used for labels (ru, en, be, uk..)", metavar="LANG") parser.add_option("-o", "--output-file", dest="outfile", default="-", help="output filename (defaults to stdout)", metavar="FILE") @@ -69,904 +73,819 @@ parser.add_option("-T", "--text-scale", dest="textscale", default=1, type="float parser.add_option("-c", "--config", dest="conffile", default="komap.conf", help="config file name", metavar="FILE") - - (options, args) = parser.parse_args() -#print (options, args) + if (options.filename == None): parser.error("MapCSS stylesheet filename is required") -import libkomapnik -config.read(['komap.conf', os.path.expanduser('~/.komap/komap.conf'), options.conffile]) -libkomapnik.map_proj = config.get("mapnik", "map_proj") -libkomapnik.db_proj = config.get("mapnik", "db_proj") -libkomapnik.table_prefix = config.get("mapnik", "table_prefix") -libkomapnik.db_user = config.get("mapnik", "db_user") -libkomapnik.db_name = config.get("mapnik", "db_name") -libkomapnik.db_srid = config.get("mapnik", "db_srid") -libkomapnik.icons_path = config.get("mapnik", "icons_path") -libkomapnik.world_bnd_path = config.get("mapnik", "world_bnd_path") -libkomapnik.cleantopo_dem_path = config.get("mapnik", "cleantopo_dem_path") -libkomapnik.srtm_dem_path = config.get("mapnik", "srtm_dem_path") -libkomapnik.cleantopo_hs_path = config.get("mapnik", "cleantopo_hs_path") -libkomapnik.srtm_hs_path = config.get("mapnik", "srtm_hs_path") -libkomapnik.text_scale = options.textscale - - -from libkomapnik import * - - - - - - - - -minzoom = options.minzoom -maxzoom = options.maxzoom+1 -locale = options.locale - - -if options.outfile == "-": - mfile = sys.stdout -else: - mfile = open(options.outfile,"w") - - - - - - - -osm2pgsql_avail_keys = {} # "column" : ["node", "way"] -if options.osm2pgsqlstyle != "-": - mf = open(options.osm2pgsqlstyle, "r") - for line in mf: - line = line.strip().split() - if line and line[0][0] != "#" and not ("phstore" in line): - osm2pgsql_avail_keys[line[1]] = tuple(line[0].split(",")) - osm2pgsql_avail_keys["tags"] = ("node","way") - - def escape_sql_column(name, type="way", asname = False): - if name in mapped_cols: - return name # already escaped - name = name.strip().strip('"') - type = {'line':'way', 'area':'way'}.get(type,type) - if type in osm2pgsql_avail_keys.get(name, ()) or not osm2pgsql_avail_keys: - return '"'+name+'"' - elif not asname: - return "(tags->'"+name+"')" - else: - return "(tags->'"+name+"') as \"" +name+'"' + if name in mapped_cols: + return name # already escaped + name = name.strip().strip('"') + type = {'line':'way', 'area':'way'}.get(type,type) + if type in osm2pgsql_avail_keys.get(name, ()) or not osm2pgsql_avail_keys: + return '"'+name+'"' + elif not asname: + return "(tags->'"+name+"')" + else: + return "(tags->'"+name+"') as \"" +name+'"' - - - - - - -style = MapCSS(minzoom, maxzoom) #zoom levels +style = MapCSS(options.minzoom, options.maxzoom+1) #zoom levels style.parse(open(options.filename,"r").read()) +if options.renderer == "mapswithme": + from libkomwm import * + komap_mapswithme(options, style) + exit() + +if options.outfile == "-": + mfile = sys.stdout +else: + mfile = open(options.outfile,"w") + if options.renderer == "js": - subjs = {"canvas": ("canvas",),"way": ("Polygon","LineString"), "line":("Polygon","LineString"), "area": ("Polygon",), "node": ("Point",), "*":("Point","Polygon","LineString") } - mfile.write("function restyle (prop, zoom, type){") - mfile.write("style = new Object;") - mfile.write('style["default"] = new Object;') - for chooser in style.choosers: - condition = "" - subclass = "default" - for i in chooser.ruleChains[0]: - if condition: - condition += "||" - rule = " zoom >= %s && zoom <= %s"%(i.minZoom, i.maxZoom) - for z in i.conditions: - t = z.type - params = z.params - if params[0] == "::class": - subclass = params[1][2:] - continue - if rule: - rule += " && " - if t == 'eq': - rule += 'prop["%s"] == "%s"'%(params[0], params[1]) - if t == 'ne': - rule += 'prop["%s"] != "%s"'%(params[0], params[1]) - if t == 'regex': - rule += 'prop["%s"].match(RegExp("%s"))'%(params[0], params[1]) - if t == 'true': - rule += 'prop["%s"] == "yes"'%(params[0]) - if t == 'untrue': - rule += 'prop["%s"] != "yes"'%(params[0]) - if t == 'set': - rule += '"%s" in prop'%(params[0]) - if t == 'unset': - rule += '!("%s"in prop)'%(params[0]) - if t == '<': - rule += 'prop["%s"] < %s'%(params[0], params[1]) - if t == '<=': - rule += 'prop["%s"] <= %s'%(params[0], params[1]) - if t == '>': - rule += 'prop["%s"] > %s'%(params[0], params[1]) - if t == '>=': - rule += 'prop["%s"] >= %s'%(params[0], params[1]) - if rule: - rule = "&&" + rule - condition += "(("+"||".join(['type == "%s"'%z for z in subjs[i.subject]])+") "+ rule + ")" - #print chooser.styles - styles = "" - if subclass != "default": - styles = 'if(!("%s" in style)){style["%s"] = new Object;}'%(subclass,subclass) - for k, v in chooser.styles[0].iteritems(): - - if type(v) == str: - try: - v = str(float(v)) - styles += 'style["'+subclass+'"]["'+k+'"] = '+v + ';' - except: - styles += 'style["'+subclass+'"]["'+k+'"] = "' + v + '";' - - mfile.write("if(%s) {%s};\n"%(condition,styles)) - mfile.write("return style;}") - + from libkojs import * + komap_js(mfile, style) if options.renderer == "mapnik": + import libkomapnik - columnmap = {} + config.read(['komap.conf', os.path.expanduser('~/.komap/komap.conf'), options.conffile]) + libkomapnik.map_proj = config.get("mapnik", "map_proj") + libkomapnik.db_proj = config.get("mapnik", "db_proj") + libkomapnik.table_prefix = config.get("mapnik", "table_prefix") + libkomapnik.db_user = config.get("mapnik", "db_user") + libkomapnik.db_name = config.get("mapnik", "db_name") + libkomapnik.db_srid = config.get("mapnik", "db_srid") + libkomapnik.icons_path = config.get("mapnik", "icons_path") + libkomapnik.world_bnd_path = config.get("mapnik", "world_bnd_path") + libkomapnik.cleantopo_dem_path = config.get("mapnik", "cleantopo_dem_path") + libkomapnik.srtm_dem_path = config.get("mapnik", "srtm_dem_path") + libkomapnik.cleantopo_hs_path = config.get("mapnik", "cleantopo_hs_path") + libkomapnik.srtm_hs_path = config.get("mapnik", "srtm_hs_path") + libkomapnik.text_scale = options.textscale - if locale == "en": - columnmap["name"] = (u"""COALESCE( - "name:en", - "int_name", - replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace - (replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace - (replace(replace - (replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(translate("name:be",'АБВГДЖЗІЙКЛМНОПРСТУЎФЦЧШЫЭабвгджзійклмнопрстуўфцчшыэ', 'ABVHDŽZIJKLMNOPRSTUŬFСČŠYEabvhdžzijklmnoprstuŭfсčšye'), 'х', 'ch'), 'Х', 'Ch'), 'BЕ', 'BIe'), 'BЁ', 'BIo'), 'BЮ', 'BIu'), 'BЯ', 'BIa'), 'Bе', 'Bie'), 'Bё', 'Bio'), 'Bю', 'Biu'), 'Bя', 'Bia'), 'VЕ', 'VIe'), 'VЁ', 'VIo'), 'VЮ', 'VIu'), 'VЯ', 'VIa'), 'Vе', 'Vie'), 'Vё', 'Vio'), 'Vю', 'Viu'), 'Vя', 'Via'), 'HЕ', - 'HIe'), 'HЁ', - 'HIo'), 'HЮ', 'HIu'), 'HЯ', 'HIa'), 'Hе', 'Hie'), 'Hё', 'Hio'), 'Hю', 'Hiu'), 'Hя', 'Hia'), 'DЕ', 'DIe'), 'DЁ', 'DIo'), 'DЮ', 'DIu'), 'DЯ', 'DIa'), 'Dе', 'Die'), 'Dё', 'Dio'), 'Dю', 'Diu'), 'Dя', 'Dia'), 'ŽЕ', 'ŽIe'), 'ŽЁ', 'ŽIo'), 'ŽЮ', 'ŽIu'), 'ŽЯ', 'ŽIa'), 'Žе', 'Žie'), 'Žё', 'Žio'), 'Žю', 'Žiu'), 'Žя', 'Žia'), 'ZЕ', 'ZIe'), 'ZЁ', 'ZIo'), 'ZЮ', 'ZIu'), 'ZЯ', 'ZIa'), 'Zе', 'Zie'), 'Zё', 'Zio'), 'Zю', 'Ziu'), 'Zя', 'Zia'), 'JЕ', 'JIe'), 'JЁ', 'JIo'), 'JЮ', 'JIu'), 'JЯ', 'JIa'), 'Jе', 'Jie'), 'Jё', 'Jio'), 'Jю', 'Jiu'), - 'Jя', 'Jia'), 'КЕ', 'КIe'), 'КЁ', 'КIo'), 'КЮ', 'КIu'), 'КЯ', 'КIa'), 'Ке', 'Кie'), 'Кё', 'Кio'), 'Кю', 'Кiu'), 'Кя', 'Кia'), 'LЕ', 'LIe'), 'LЁ', 'LIo'), 'LЮ', 'LIu'), 'LЯ', 'LIa'), 'Lе', 'Lie'), 'Lё', 'Lio'), 'Lю', 'Liu'), 'Lя', 'Lia'), 'MЕ', 'MIe'), 'MЁ', 'MIo'), 'MЮ', 'MIu'), 'MЯ', 'MIa'), 'Mе', 'Mie'), 'Mё', 'Mio'), 'Mю', 'Miu'), 'Mя', 'Mia'), 'NЕ', 'NIe'), 'NЁ', 'NIo'), 'NЮ', 'NIu'), 'NЯ', 'NIa'), 'Nе', 'Nie'), 'Nё', 'Nio'), 'Nю', 'Niu'), 'Nя', 'Nia'), 'PЕ', 'PIe'), 'PЁ', 'PIo'), 'PЮ', - 'PIu'), 'PЯ', 'PIa'), 'Pе', 'Pie'), 'Pё', 'Pio'), 'Pю', 'Piu'), 'Pя', 'Pia'), 'RЕ', 'RIe'), 'RЁ', 'RIo'), 'RЮ', 'RIu'), 'RЯ', 'RIa'), 'Rе', 'Rie'), 'Rё', 'Rio'), 'Rю', 'Riu'), 'Rя', 'Ria'), 'SЕ', 'SIe'), 'SЁ', 'SIo'), 'SЮ', 'SIu'), 'SЯ', 'SIa'), 'Sе', 'Sie'), 'Sё', 'Sio'), 'Sю', 'Siu'), 'Sя', 'Sia'), 'TЕ', 'TIe'), 'TЁ', 'TIo'), 'TЮ', 'TIu'), 'TЯ', 'TIa'), 'Tе', 'Tie'), 'Tё', 'Tio'), 'Tю', 'Tiu'), 'Tя', 'Tia'), 'ŬЕ', 'ŬIe'), 'ŬЁ', 'ŬIo'), 'ŬЮ', 'ŬIu'), 'ŬЯ', 'ŬIa'), 'Ŭе', 'Ŭie'), 'Ŭё', 'Ŭio'), 'Ŭю', 'Ŭiu'), 'Ŭя', 'Ŭia'), 'FЕ', 'FIe'), 'FЁ', 'FIo'), 'FЮ', 'FIu'), 'FЯ', 'FIa'), 'Fе', 'Fie'), 'Fё', 'Fio'), 'Fю', 'Fiu'), 'Fя', 'Fia'), 'СЕ', 'СIe'), 'СЁ', 'СIo'), 'СЮ', 'СIu'), - 'СЯ', 'СIa'), 'Се', 'Сie'), 'Сё', 'Сio'), 'Сю', 'Сiu'), 'Ся', 'Сia'), 'ČЕ', 'ČIe'), 'ČЁ', 'ČIo'), 'ČЮ', 'ČIu'), 'ČЯ', 'ČIa'), 'Čе', 'Čie'), 'Čё', 'Čio'), 'Čю', 'Čiu'), 'Čя', 'Čia'), 'ŠЕ', 'ŠIe'), 'ŠЁ', 'ŠIo'), 'ŠЮ', 'ŠIu'), 'ŠЯ', 'ŠIa'), 'Šе', 'Šie'), 'Šё', 'Šio'), 'Šю', 'Šiu'), 'Šя', 'Šia'), 'bЕ', 'bIe'), 'bЁ', 'bIo'), 'bЮ', 'bIu'), 'bЯ', - 'bIa'), 'bе', 'bie'), 'bё', 'bio'), 'bю', 'biu'), 'bя', 'bia'), 'vЕ', 'vIe'), 'vЁ', 'vIo'), 'vЮ', 'vIu'), 'vЯ', 'vIa'), 'vе', 'vie'), 'vё', 'vio'), 'vю', 'viu'), 'vя', 'via'), 'hЕ', 'hIe'), 'hЁ', 'hIo'), 'hЮ', 'hIu'), 'hЯ', 'hIa'), 'hе', 'hie'), 'hё', 'hio'), 'hю', 'hiu'), 'hя', 'hia'), 'dЕ', 'dIe'), 'dЁ', 'dIo'), 'dЮ', 'dIu'), 'dЯ', 'dIa'), 'dе', 'die'), 'dё', 'dio'), 'dю', 'diu'), 'dя', 'dia'), 'žЕ', 'žIe'), 'žЁ', 'žIo'), 'žЮ', 'žIu'), 'žЯ', 'žIa'), 'žе', 'žie'), 'žё', 'žio'), 'žю', 'žiu'), 'žя', 'žia'), 'zЕ', 'zIe'), 'zЁ', 'zIo'), 'zЮ', 'zIu'), 'zЯ', 'zIa'), 'zе', 'zie'), 'zё', 'zio'), 'zю', 'ziu'), 'zя', 'zia'), 'jЕ', 'jIe'), 'jЁ', 'jIo'), 'jЮ', 'jIu'), 'jЯ', 'jIa'), 'jе', 'jie'), 'jё', 'jio'), 'jю', 'jiu'), 'jя', 'jia'), 'кЕ', 'кIe'), 'кЁ', 'кIo'), 'кЮ', 'кIu'), 'кЯ', 'кIa'), 'ке', 'кie'), 'кё', 'кio'), 'кю', 'кiu'), 'кя', 'кia'), 'lЕ', 'lIe'), - 'lЁ', 'lIo'), 'lЮ', 'lIu'), 'lЯ', 'lIa'), 'lе', 'lie'), 'lё', 'lio'), 'lю', 'liu'), 'lя', 'lia'), 'mЕ', 'mIe'), 'mЁ', 'mIo'), 'mЮ', 'mIu'), 'mЯ', 'mIa'), 'mе', 'mie'), 'mё', 'mio'), 'mю', 'miu'), 'mя', 'mia'), 'nЕ', 'nIe'), 'nЁ', 'nIo'), 'nЮ', 'nIu'), 'nЯ', 'nIa'), 'nе', 'nie'), 'nё', 'nio'), 'nю', 'niu'), 'nя', 'nia'), 'pЕ', 'pIe'), 'pЁ', 'pIo'), 'pЮ', 'pIu'), 'pЯ', 'pIa'), 'pе', 'pie'), 'pё', 'pio'), 'pю', 'piu'), 'pя', 'pia'), 'rЕ', 'rIe'), 'rЁ', 'rIo'), 'rЮ', 'rIu'), 'rЯ', 'rIa'), 'rе', 'rie'), 'rё', 'rio'), 'rю', 'riu'), 'rя', 'ria'), 'sЕ', 'sIe'), 'sЁ', - 'sIo'), 'sЮ', 'sIu'), 'sЯ', 'sIa'), 'sе', 'sie'), 'sё', 'sio'), 'sю', 'siu'), 'sя', 'sia'), 'tЕ', 'tIe'), 'tЁ', 'tIo'), 'tЮ', 'tIu'), 'tЯ', 'tIa'), 'tе', 'tie'), 'tё', 'tio'), 'tю', 'tiu'), 'tя', 'tia'), 'ŭЕ', 'ŭIe'), 'ŭЁ', 'ŭIo'), 'ŭЮ', 'ŭIu'), 'ŭЯ', 'ŭIa'), 'ŭе', 'ŭie'), 'ŭё', 'ŭio'), 'ŭю', 'ŭiu'), 'ŭя', 'ŭia'), 'fЕ', 'fIe'), 'fЁ', 'fIo'), 'fЮ', 'fIu'), 'fЯ', 'fIa'), 'fе', 'fie'), 'fё', 'fio'), 'fю', 'fiu'), 'fя', 'fia'), 'сЕ', 'сIe'), 'сЁ', 'сIo'), 'сЮ', 'сIu'), 'сЯ', 'сIa'), 'се', 'сie'), 'сё', 'сio'), 'сю', 'сiu'), 'ся', 'сia'), 'čЕ', 'čIe'), 'čЁ', 'čIo'), 'čЮ', 'čIu'), 'čЯ', 'čIa'), 'čе', 'čie'), 'čё', - 'čio'), 'čю', 'čiu'), 'čя', 'čia'), 'šЕ', 'šIe'), 'šЁ', 'šIo'), 'šЮ', 'šIu'), 'šЯ', 'šIa'), 'šе', 'šie'), 'šё', 'šio'), 'šю', 'šiu'), 'šя', 'šia'), 'Е', 'Je'), 'Ё', 'Jo'), 'Ю', 'Ju'), 'Я', 'Ja'), 'е', 'je'), 'ё', 'jo'), 'ю', 'ju'), 'я', 'ja'), 'Ь', '\u0301'), 'ь', '\u0301'),'’', ''), - replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(translate("name",'абвгдезиклмнопрстуфьАБВГДЕЗИКЛМНОПРСТУФЬ','abvgdeziklmnoprstuf’ABVGDEZIKLMNOPRSTUF’'),'х','kh'),'Х','Kh'),'ц','ts'),'Ц','Ts'),'ч','ch'),'Ч','Ch'),'ш','sh'),'Ш','Sh'),'щ','shch'),'Щ','Shch'),'ъ','”'),'Ъ','”'),'ё','yo'),'Ё','Yo'),'ы','y'),'Ы','Y'),'э','·e'),'Э','E'),'ю','yu'),'Ю','Yu'),'й','y'),'Й','Y'),'я','ya'),'Я','Ya'),'ж','zh'),'Ж','Zh')) AS name""",('name:en','int_name','name:be')) -#a = 'STUFF' -#for i in u"BVHDŽZJКLMNPRSTŬFСČŠbvhdžzjкlmnprstŭfсčš": -# for j, k in [("Е", "Ie"), ("Ё", "Io"), ("Ю", "Iu"), ("Я", "Ia"), ("е", "ie"), ("ё", "io"), ("ю", "iu"), ("я", "ia")]: -# a = "replace(" + a + ", '"+ i+ j + "', '"+ i+ k + "')" - elif locale == "be": - columnmap["name"] = ("""COALESCE("name:be", - (select kot__nab from (select "name:be" as kot__nab, name as kot__name, way as kot__way from %sline) z where kot__name = name and kot__nab is not null order by st_distance(kot__way, !bbox!) limit 1), - (select kot__nab from (select "name:be" as kot__nab, name as kot__name, way as kot__way from %spoint) z where kot__name = name and kot__nab is not null order by st_distance(kot__way, !bbox!) limit 1), - (select kot__nab from (select "name:be" as kot__nab, name as kot__name, way as kot__way from %spolygon) z where kot__name = name and kot__nab is not null order by st_distance(kot__way, !bbox!) limit 1), - "name:ru", - "int_name", - "name:en", - "name" - ) AS name"""%(table_prefix,table_prefix,table_prefix),('name:be', "name:ru", "int_name", "name:en")) - elif locale and ("name:"+locale in osm2pgsql_avail_keys or not osm2pgsql_avail_keys): - columnmap["name"] = ('COALESCE("name:'+locale+'", "name") AS name',('name:'+locale,)) - elif locale: - columnmap["name"] = ("COALESCE(tags->'name:"+locale+'\', "name") AS name',('tags',)) + from libkomapnik import * - mapped_cols = [i[0] for i in columnmap.values()] - numerics = set() # set of number-compared things, like "population<10000" needs population as number, not text - mapniksheet = {} - # {zoom: {z-index: [{sql:sql_hint, cond: mapnikfiltercondition, subject: subj, style: {a:b,c:d..}},{r2}...]...}...} - coast = {} - fonts = set() - demhack = False - for zoom in range (minzoom, maxzoom): - mapniksheet[zoom] = {} - zsheet = mapniksheet[zoom] - for chooser in style.choosers: - if chooser.get_sql_hints(chooser.ruleChains[0][0].subject, zoom)[1]: - #sys.stderr.write(str(chooser.get_sql_hints(chooser.ruleChains[0][0].subject, zoom)[1])+"\n") - styles = chooser.styles[0] - zindex = styles.get("z-index",0) - if zindex not in zsheet: - zsheet[zindex] = [] - chooser_entry = {} - - chooser_entry["type"] = chooser.ruleChains[0][0].subject - - sql = "("+ chooser.get_sql_hints(chooser.ruleChains[0][0].subject,zoom)[1] +")" - sql = sql.split('"') - sq = "" - odd = True - for i in sql: - if not odd: - sq += escape_sql_column(i, chooser_entry["type"]) - else: - sq += i - odd = not odd - - chooser_entry["sql"] = sq - chooser_entry["style"] = styles - fonts.add(styles.get("font-family","DejaVu Sans Book")) - - chooser_entry["rule"] = [i.conditions for i in chooser.ruleChains[0] if i.test_zoom(zoom)] - numerics.update(chooser.get_numerics()) - #print chooser_entry["rule"] - chooser_entry["rulestring"] = " or ".join([ "("+ " and ".join([i.get_mapnik_filter() for i in rule if i.get_mapnik_filter()]) + ")" for rule in chooser_entry["rule"]]) - chooser_entry["chooser"] = chooser - if chooser_entry["type"] == "ele": - demhack = True - if chooser_entry["type"] == "area" and "[natural] = 'coastline'" in chooser_entry["rulestring"]: - coast[zoom] = chooser_entry["style"] + + osm2pgsql_avail_keys = {} # "column" : ["node", "way"] + if options.osm2pgsqlstyle != "-": + mf = open(options.osm2pgsqlstyle, "r") + for line in mf: + line = line.strip().split() + if line and line[0][0] != "#" and not ("phstore" in line): + osm2pgsql_avail_keys[line[1]] = tuple(line[0].split(",")) + osm2pgsql_avail_keys["tags"] = ("node","way") + + columnmap = {} + + if options.locale == "en": + columnmap["name"] = (u"""COALESCE( + "name:en", + "int_name", + replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace + (replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace + (replace(replace + (replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(translate("name:be",'АБВГДЖЗІЙКЛМНОПРСТУЎФЦЧШЫЭабвгджзійклмнопрстуўфцчшыэ', 'ABVHDŽZIJKLMNOPRSTUŬFСČŠYEabvhdžzijklmnoprstuŭfсčšye'), 'х', 'ch'), 'Х', 'Ch'), 'BЕ', 'BIe'), 'BЁ', 'BIo'), 'BЮ', 'BIu'), 'BЯ', 'BIa'), 'Bе', 'Bie'), 'Bё', 'Bio'), 'Bю', 'Biu'), 'Bя', 'Bia'), 'VЕ', 'VIe'), 'VЁ', 'VIo'), 'VЮ', 'VIu'), 'VЯ', 'VIa'), 'Vе', 'Vie'), 'Vё', 'Vio'), 'Vю', 'Viu'), 'Vя', 'Via'), 'HЕ', + 'HIe'), 'HЁ', + 'HIo'), 'HЮ', 'HIu'), 'HЯ', 'HIa'), 'Hе', 'Hie'), 'Hё', 'Hio'), 'Hю', 'Hiu'), 'Hя', 'Hia'), 'DЕ', 'DIe'), 'DЁ', 'DIo'), 'DЮ', 'DIu'), 'DЯ', 'DIa'), 'Dе', 'Die'), 'Dё', 'Dio'), 'Dю', 'Diu'), 'Dя', 'Dia'), 'ŽЕ', 'ŽIe'), 'ŽЁ', 'ŽIo'), 'ŽЮ', 'ŽIu'), 'ŽЯ', 'ŽIa'), 'Žе', 'Žie'), 'Žё', 'Žio'), 'Žю', 'Žiu'), 'Žя', 'Žia'), 'ZЕ', 'ZIe'), 'ZЁ', 'ZIo'), 'ZЮ', 'ZIu'), 'ZЯ', 'ZIa'), 'Zе', 'Zie'), 'Zё', 'Zio'), 'Zю', 'Ziu'), 'Zя', 'Zia'), 'JЕ', 'JIe'), 'JЁ', 'JIo'), 'JЮ', 'JIu'), 'JЯ', 'JIa'), 'Jе', 'Jie'), 'Jё', 'Jio'), 'Jю', 'Jiu'), + 'Jя', 'Jia'), 'КЕ', 'КIe'), 'КЁ', 'КIo'), 'КЮ', 'КIu'), 'КЯ', 'КIa'), 'Ке', 'Кie'), 'Кё', 'Кio'), 'Кю', 'Кiu'), 'Кя', 'Кia'), 'LЕ', 'LIe'), 'LЁ', 'LIo'), 'LЮ', 'LIu'), 'LЯ', 'LIa'), 'Lе', 'Lie'), 'Lё', 'Lio'), 'Lю', 'Liu'), 'Lя', 'Lia'), 'MЕ', 'MIe'), 'MЁ', 'MIo'), 'MЮ', 'MIu'), 'MЯ', 'MIa'), 'Mе', 'Mie'), 'Mё', 'Mio'), 'Mю', 'Miu'), 'Mя', 'Mia'), 'NЕ', 'NIe'), 'NЁ', 'NIo'), 'NЮ', 'NIu'), 'NЯ', 'NIa'), 'Nе', 'Nie'), 'Nё', 'Nio'), 'Nю', 'Niu'), 'Nя', 'Nia'), 'PЕ', 'PIe'), 'PЁ', 'PIo'), 'PЮ', + 'PIu'), 'PЯ', 'PIa'), 'Pе', 'Pie'), 'Pё', 'Pio'), 'Pю', 'Piu'), 'Pя', 'Pia'), 'RЕ', 'RIe'), 'RЁ', 'RIo'), 'RЮ', 'RIu'), 'RЯ', 'RIa'), 'Rе', 'Rie'), 'Rё', 'Rio'), 'Rю', 'Riu'), 'Rя', 'Ria'), 'SЕ', 'SIe'), 'SЁ', 'SIo'), 'SЮ', 'SIu'), 'SЯ', 'SIa'), 'Sе', 'Sie'), 'Sё', 'Sio'), 'Sю', 'Siu'), 'Sя', 'Sia'), 'TЕ', 'TIe'), 'TЁ', 'TIo'), 'TЮ', 'TIu'), 'TЯ', 'TIa'), 'Tе', 'Tie'), 'Tё', 'Tio'), 'Tю', 'Tiu'), 'Tя', 'Tia'), 'ŬЕ', 'ŬIe'), 'ŬЁ', 'ŬIo'), 'ŬЮ', 'ŬIu'), 'ŬЯ', 'ŬIa'), 'Ŭе', 'Ŭie'), 'Ŭё', 'Ŭio'), 'Ŭю', 'Ŭiu'), 'Ŭя', 'Ŭia'), 'FЕ', 'FIe'), 'FЁ', 'FIo'), 'FЮ', 'FIu'), 'FЯ', 'FIa'), 'Fе', 'Fie'), 'Fё', 'Fio'), 'Fю', 'Fiu'), 'Fя', 'Fia'), 'СЕ', 'СIe'), 'СЁ', 'СIo'), 'СЮ', 'СIu'), + 'СЯ', 'СIa'), 'Се', 'Сie'), 'Сё', 'Сio'), 'Сю', 'Сiu'), 'Ся', 'Сia'), 'ČЕ', 'ČIe'), 'ČЁ', 'ČIo'), 'ČЮ', 'ČIu'), 'ČЯ', 'ČIa'), 'Čе', 'Čie'), 'Čё', 'Čio'), 'Čю', 'Čiu'), 'Čя', 'Čia'), 'ŠЕ', 'ŠIe'), 'ŠЁ', 'ŠIo'), 'ŠЮ', 'ŠIu'), 'ŠЯ', 'ŠIa'), 'Šе', 'Šie'), 'Šё', 'Šio'), 'Šю', 'Šiu'), 'Šя', 'Šia'), 'bЕ', 'bIe'), 'bЁ', 'bIo'), 'bЮ', 'bIu'), 'bЯ', + 'bIa'), 'bе', 'bie'), 'bё', 'bio'), 'bю', 'biu'), 'bя', 'bia'), 'vЕ', 'vIe'), 'vЁ', 'vIo'), 'vЮ', 'vIu'), 'vЯ', 'vIa'), 'vе', 'vie'), 'vё', 'vio'), 'vю', 'viu'), 'vя', 'via'), 'hЕ', 'hIe'), 'hЁ', 'hIo'), 'hЮ', 'hIu'), 'hЯ', 'hIa'), 'hе', 'hie'), 'hё', 'hio'), 'hю', 'hiu'), 'hя', 'hia'), 'dЕ', 'dIe'), 'dЁ', 'dIo'), 'dЮ', 'dIu'), 'dЯ', 'dIa'), 'dе', 'die'), 'dё', 'dio'), 'dю', 'diu'), 'dя', 'dia'), 'žЕ', 'žIe'), 'žЁ', 'žIo'), 'žЮ', 'žIu'), 'žЯ', 'žIa'), 'žе', 'žie'), 'žё', 'žio'), 'žю', 'žiu'), 'žя', 'žia'), 'zЕ', 'zIe'), 'zЁ', 'zIo'), 'zЮ', 'zIu'), 'zЯ', 'zIa'), 'zе', 'zie'), 'zё', 'zio'), 'zю', 'ziu'), 'zя', 'zia'), 'jЕ', 'jIe'), 'jЁ', 'jIo'), 'jЮ', 'jIu'), 'jЯ', 'jIa'), 'jе', 'jie'), 'jё', 'jio'), 'jю', 'jiu'), 'jя', 'jia'), 'кЕ', 'кIe'), 'кЁ', 'кIo'), 'кЮ', 'кIu'), 'кЯ', 'кIa'), 'ке', 'кie'), 'кё', 'кio'), 'кю', 'кiu'), 'кя', 'кia'), 'lЕ', 'lIe'), + 'lЁ', 'lIo'), 'lЮ', 'lIu'), 'lЯ', 'lIa'), 'lе', 'lie'), 'lё', 'lio'), 'lю', 'liu'), 'lя', 'lia'), 'mЕ', 'mIe'), 'mЁ', 'mIo'), 'mЮ', 'mIu'), 'mЯ', 'mIa'), 'mе', 'mie'), 'mё', 'mio'), 'mю', 'miu'), 'mя', 'mia'), 'nЕ', 'nIe'), 'nЁ', 'nIo'), 'nЮ', 'nIu'), 'nЯ', 'nIa'), 'nе', 'nie'), 'nё', 'nio'), 'nю', 'niu'), 'nя', 'nia'), 'pЕ', 'pIe'), 'pЁ', 'pIo'), 'pЮ', 'pIu'), 'pЯ', 'pIa'), 'pе', 'pie'), 'pё', 'pio'), 'pю', 'piu'), 'pя', 'pia'), 'rЕ', 'rIe'), 'rЁ', 'rIo'), 'rЮ', 'rIu'), 'rЯ', 'rIa'), 'rе', 'rie'), 'rё', 'rio'), 'rю', 'riu'), 'rя', 'ria'), 'sЕ', 'sIe'), 'sЁ', + 'sIo'), 'sЮ', 'sIu'), 'sЯ', 'sIa'), 'sе', 'sie'), 'sё', 'sio'), 'sю', 'siu'), 'sя', 'sia'), 'tЕ', 'tIe'), 'tЁ', 'tIo'), 'tЮ', 'tIu'), 'tЯ', 'tIa'), 'tе', 'tie'), 'tё', 'tio'), 'tю', 'tiu'), 'tя', 'tia'), 'ŭЕ', 'ŭIe'), 'ŭЁ', 'ŭIo'), 'ŭЮ', 'ŭIu'), 'ŭЯ', 'ŭIa'), 'ŭе', 'ŭie'), 'ŭё', 'ŭio'), 'ŭю', 'ŭiu'), 'ŭя', 'ŭia'), 'fЕ', 'fIe'), 'fЁ', 'fIo'), 'fЮ', 'fIu'), 'fЯ', 'fIa'), 'fе', 'fie'), 'fё', 'fio'), 'fю', 'fiu'), 'fя', 'fia'), 'сЕ', 'сIe'), 'сЁ', 'сIo'), 'сЮ', 'сIu'), 'сЯ', 'сIa'), 'се', 'сie'), 'сё', 'сio'), 'сю', 'сiu'), 'ся', 'сia'), 'čЕ', 'čIe'), 'čЁ', 'čIo'), 'čЮ', 'čIu'), 'čЯ', 'čIa'), 'čе', 'čie'), 'čё', + 'čio'), 'čю', 'čiu'), 'čя', 'čia'), 'šЕ', 'šIe'), 'šЁ', 'šIo'), 'šЮ', 'šIu'), 'šЯ', 'šIa'), 'šе', 'šie'), 'šё', 'šio'), 'šю', 'šiu'), 'šя', 'šia'), 'Е', 'Je'), 'Ё', 'Jo'), 'Ю', 'Ju'), 'Я', 'Ja'), 'е', 'je'), 'ё', 'jo'), 'ю', 'ju'), 'я', 'ja'), 'Ь', '\u0301'), 'ь', '\u0301'),'’', ''), + replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(translate("name",'абвгдезиклмнопрстуфьАБВГДЕЗИКЛМНОПРСТУФЬ','abvgdeziklmnoprstuf’ABVGDEZIKLMNOPRSTUF’'),'х','kh'),'Х','Kh'),'ц','ts'),'Ц','Ts'),'ч','ch'),'Ч','Ch'),'ш','sh'),'Ш','Sh'),'щ','shch'),'Щ','Shch'),'ъ','”'),'Ъ','”'),'ё','yo'),'Ё','Yo'),'ы','y'),'Ы','Y'),'э','·e'),'Э','E'),'ю','yu'),'Ю','Yu'),'й','y'),'Й','Y'),'я','ya'),'Я','Ya'),'ж','zh'),'Ж','Zh')) AS name""",('name:en','int_name','name:be')) + + elif options.locale == "be": + columnmap["name"] = ("""COALESCE("name:be", + "name:ru", + "int_name", + "name:en", + "name" + ) AS name"""%(table_prefix,table_prefix,table_prefix),('name:be', "name:ru", "int_name", "name:en")) + elif options.locale and ("name:"+options.locale in osm2pgsql_avail_keys or not osm2pgsql_avail_keys): + columnmap["name"] = ('COALESCE("name:'+options.locale+'", "name") AS name',('name:'+options.locale,)) + elif options.locale: + columnmap["name"] = ("COALESCE(tags->'name:"+options.locale+'\', "name") AS name',('tags',)) + + mapped_cols = [i[0] for i in columnmap.values()] + numerics = set() # set of number-compared things, like "population<10000" needs population as number, not text + mapniksheet = {} + + # {zoom: {z-index: [{sql:sql_hint, cond: mapnikfiltercondition, subject: subj, style: {a:b,c:d..}},{r2}...]...}...} + coast = {} + fonts = set() + demhack = False + for zoom in xrange (options.minzoom, options.maxzoom+1): + mapniksheet[zoom] = {} + zsheet = mapniksheet[zoom] + for chooser in style.choosers: + if chooser.get_sql_hints(chooser.ruleChains[0].subject, zoom)[1]: + #sys.stderr.write(str(chooser.get_sql_hints(chooser.ruleChains[0][0].subject, zoom)[1])+"\n") + styles = chooser.styles[0] + zindex = styles.get("z-index",0) + if zindex not in zsheet: + zsheet[zindex] = [] + chooser_entry = {} + + chooser_entry["type"] = chooser.ruleChains[0].subject + + sql = "("+ chooser.get_sql_hints(chooser.ruleChains[0].subject,zoom)[1] +")" + sql = sql.split('"') + sq = "" + odd = True + for i in sql: + if not odd: + sq += escape_sql_column(i, chooser_entry["type"]) + else: + sq += i + odd = not odd + + chooser_entry["sql"] = sq + chooser_entry["style"] = styles + fonts.add(styles.get("font-family","DejaVu Sans Book")) + + chooser_entry["rule"] = [i.conditions for i in chooser.ruleChains if i.test_zoom(zoom)] + numerics.update(chooser.get_numerics()) + #print chooser_entry["rule"] + chooser_entry["rulestring"] = " or ".join([ "("+ " and ".join([i.get_mapnik_filter() for i in rule if i.get_mapnik_filter()]) + ")" for rule in chooser_entry["rule"]]) + chooser_entry["chooser"] = chooser + if chooser_entry["type"] == "ele": + demhack = True + if chooser_entry["type"] == "area" and "[natural] = 'coastline'" in chooser_entry["rulestring"]: + coast[zoom] = chooser_entry["style"] + else: + zsheet[zindex].append(chooser_entry) + + #sys.stderr.write(str(numerics)+"\n") + #print mapniksheet + + def add_numerics_to_itags(itags, escape = True): + tt = set() + nitags = set() + if escape: + escape = escape_sql_column else: - zsheet[zindex].append(chooser_entry) + def escape(i, asname=False): + if i in mapped_cols: + return i # already escaped + return '"'+i+'"' + for i in itags: + if i in numerics: + tt.add("""(CASE WHEN %s ~ E'^[[:digit:]]+([.][[:digit:]]+)?$' THEN CAST (%s AS FLOAT) ELSE NULL END) as %s__num"""%(escape(i),escape(i),i)) + nitags.add(escape(i, asname = True)) + itags = nitags + itags.update(tt) + return itags - #sys.stderr.write(str(numerics)+"\n") - #print mapniksheet - def add_numerics_to_itags(itags, escape = True): - tt = set() - nitags = set() - if escape: - escape = escape_sql_column + + bgcolor = style.get_style("canvas", {}, options.maxzoom+1)[0].get("fill-color", "") + opacity = style.get_style("canvas", {}, options.maxzoom+1)[0].get("opacity", 1) + hshack = style.get_style("canvas", {}, options.maxzoom+1)[0].get("-x-kot-hs-hack", False) + + if (opacity == 1) and bgcolor: + mfile.write(xml_start(bgcolor)) else: - def escape(i, asname=False): - if i in mapped_cols: - return i # already escaped - return '"'+i+'"' - for i in itags: - if i in numerics: - tt.add("""(CASE WHEN %s ~ E'^[[:digit:]]+([.][[:digit:]]+)?$' THEN CAST (%s AS FLOAT) ELSE NULL END) as %s__num"""%(escape(i),escape(i),i)) - nitags.add(escape(i, asname = True)) - itags = nitags - itags.update(tt) - return itags + mfile.write(xml_start("transparent")) - - bgcolor = style.get_style("canvas", {}, maxzoom)[0].get("fill-color", "") - opacity = style.get_style("canvas", {}, maxzoom)[0].get("opacity", 1) - hshack = style.get_style("canvas", {}, maxzoom)[0].get("-x-mapnik-hs-hack", False) - - if (opacity == 1) and bgcolor: - mfile.write(xml_start(bgcolor)) - else: - mfile.write(xml_start("transparent")) + conf_full_layering = style.get_style("canvas", {}, options.maxzoom+1)[0].get("-x-kot-true-layers", "true").lower() == 'true' - conf_full_layering = style.get_style("canvas", {}, maxzoom)[0].get("-x-mapnik-true-layers", "true").lower() == 'true' + for font in fonts: + mfile.write(xml_fontset(font, True)) + for zoom, zsheet in mapniksheet.iteritems(): + x_scale = xml_scaledenominator(zoom) + ta = zsheet.keys() + ta.sort(key=float) + demcolors = {} + demramp = {"ground":"", "ocean":""} - for font in fonts: - mfile.write(xml_fontset(font, True)) + if demhack: + for zindex in ta: + for entry in zsheet[zindex]: + if entry["type"] in ("ele",): + ele = int(entry["rule"][0][0].params[0]) + demcolors[ele] = (whatever_to_hex(entry["style"].get('fill-color', '#ffffff')), entry["style"].get('fill-opacity', '1')) + dk = demcolors.keys() + dk.sort() + for ele in dk: + (color, opacity) = demcolors[ele] + demramp["ocean"] += '' %(ele+10701, int(color[1:3],16), int(color[3:5],16), int(color[5:7],16), opacity) + demramp["ground"] += '' %(ele, int(color[1:3],16), int(color[3:5],16), int(color[5:7],16), opacity) - for zoom, zsheet in mapniksheet.iteritems(): - x_scale = xml_scaledenominator(zoom) - ta = zsheet.keys() - ta.sort(key=float) - demcolors = {} - demramp = {"ground":"", "ocean":""} - - if demhack: - for zindex in ta: - for entry in zsheet[zindex]: - if entry["type"] in ("ele",): - ele = int(entry["rule"][0][0].params[0]) - demcolors[ele] = (whatever_to_hex(entry["style"].get('fill-color', '#ffffff')), entry["style"].get('fill-opacity', '1')) - dk = demcolors.keys() - dk.sort() - for ele in dk: - (color, opacity) = demcolors[ele] - demramp["ocean"] += '' %(ele+10701, int(color[1:3],16), int(color[3:5],16), int(color[5:7],16), opacity) - demramp["ground"] += '' %(ele, int(color[1:3],16), int(color[3:5],16), int(color[5:7],16), opacity) - - if demhack and zoom >= 7: - xml = xml_cleantopo(zoom, x_scale, demramp["ocean"]) - mfile.write(xml) - if zoom in coast: - xml = xml_style_start() - xml += xml_rule_start() - xml += x_scale - if "fill-color" in coast[zoom]: - xml += xml_polygonsymbolizer(coast[zoom].get("fill-color", "#ffffff"), relaxedFloat(coast[zoom].get("fill-opacity", "1")), relaxedFloat(coast[zoom].get("smooth","0"))) - if "fill-image" in coast[zoom]: - xml += xml_polygonpatternsymbolizer(coast[zoom].get("fill-image", "")) - xml += xml_rule_end() - xml += xml_style_end() - xml += xml_layer("coast", zoom=zoom) - mfile.write(xml) - - if demhack and zoom < 7: - xml = xml_cleantopo(zoom, x_scale, demramp["ocean"]) - mfile.write(xml) - - if demhack and zoom >= 7: - xml = xml_srtm(zoom, x_scale, demramp["ground"]) - mfile.write(xml) - - sql_g = set() - there_are_dashed_lines = False - itags_g = set() - xml_g = "" - for zindex in ta: - ## background areas pass - sql = set() - itags = set() - xml = xml_style_start() - for entry in zsheet[zindex]: - if entry["type"] in ("way", "area", "polygon"): - if ("fill-color" in entry["style"] or "fill-image" in entry["style"]) and (entry["style"].get("fill-position", "foreground")=="background"): + if demhack and zoom >= 7: + xml = xml_cleantopo(zoom, x_scale, demramp["ocean"]) + mfile.write(xml) + if zoom in coast: + xml = xml_style_start() xml += xml_rule_start() xml += x_scale - xml += xml_filter(entry["rulestring"]) - if "fill-color" in entry["style"]: - xml += xml_polygonsymbolizer(entry["style"].get("fill-color", "black"), relaxedFloat(entry["style"].get("fill-opacity", "1")), relaxedFloat(entry["style"].get("smooth","0"))) - if "fill-image" in entry["style"]: - xml += xml_polygonpatternsymbolizer(entry["style"].get("fill-image", "")) - sql.add(entry["sql"]) - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + if "fill-color" in coast[zoom]: + xml += xml_polygonsymbolizer(coast[zoom].get("fill-color", "#ffffff"), relaxedFloat(coast[zoom].get("fill-opacity", "1")), relaxedFloat(coast[zoom].get("smooth","0"))) + if "fill-image" in coast[zoom]: + xml += xml_polygonpatternsymbolizer(coast[zoom].get("fill-image", "")) xml += xml_rule_end() - xml += xml_style_end() - sql.discard("()") - if sql: - sql_g.update(sql) - xml_g += xml - itags_g.update(itags) - else: - xml_nosubstyle() - sql = sql_g - itags = itags_g - if sql: - mfile.write(xml_g) - sql = "(" + " OR ".join(sql) + ")"# and way && !bbox!" - itags = add_numerics_to_itags(itags) - mfile.write(xml_layer("postgis", "polygon", itags, sql, zoom=zoom )) - else: - xml_nolayer() - - if hshack: - xml = xml_hillshade(zoom, x_scale) - mfile.write(xml) + xml += xml_style_end() + xml += xml_layer("coast", zoom=zoom) + mfile.write(xml) + + if demhack and zoom < 7: + xml = xml_cleantopo(zoom, x_scale, demramp["ocean"]) + mfile.write(xml) + + if demhack and zoom >= 7: + xml = xml_srtm(zoom, x_scale, demramp["ground"]) + mfile.write(xml) - index_range = range(-6,7) - full_layering = conf_full_layering - if (zoom < 9) or not conf_full_layering : - index_range = (-6,0,6) - full_layering = False - def check_if_roads_table(rulestring): - roads = set([ - "[highway] = 'secondary'", - "[highway] = 'secondary_link'", - "[highway] = 'primary'", - "[highway] = 'primary_link'", - "[highway] = 'trunk'", - "[highway] = 'trunk_link'", - "[highway] = 'motorway'", - "[highway] = 'motorway_link'", - "[boundary] = 'administrative'", - "[railway] " - ]) - for a in rulestring.split(') or ('): - for r in roads: - if r not in a: - return False - return True - for zlayer in index_range: - for layer_type, entry_types in [("line",("way", "line")),("polygon",("way","area"))]: sql_g = set() there_are_dashed_lines = False itags_g = set() xml_g = "" - roads = (layer_type == 'line') # whether to use planet_osm_roads - ## casings pass for zindex in ta: - sql = set() - itags = set() - xml = xml_style_start() - for entry in zsheet[zindex]: - if entry["type"] in entry_types: - if "-x-mapnik-layer" in entry["style"]: - if zlayer != -6 and entry["style"]["-x-mapnik-layer"] == "bottom": - continue - if zlayer != 6 and entry["style"]["-x-mapnik-layer"] == "top": - continue - elif zlayer not in range(-5,6): - continue - if "casing-width" in entry["style"]: - xml += xml_rule_start() - xml += x_scale - xml += xml_filter(entry["rulestring"]) - if not check_if_roads_table(entry["rulestring"]): - roads = False - twidth = 2*float(entry["style"].get("casing-width", 1))+float(entry["style"].get("width", 0)); - tlinejoin = "round" - if twidth < 3: - tlinejoin = "miter" - xml += xml_linesymbolizer(color=entry["style"].get("casing-color", "black"), - width=twidth, - opacity=relaxedFloat(entry["style"].get("casing-opacity", entry["style"].get("opacity","1"))), - linecap=entry["style"].get("casing-linecap", entry["style"].get("linecap","butt")), - linejoin=entry["style"].get("casing-linejoin", entry["style"].get("linejoin", "round")), - dashes=entry["style"].get("casing-dashes",entry["style"].get("dashes", "")), - smooth=relaxedFloat(entry["style"].get("smooth","0")), - zoom=zoom) - - sql.add(entry["sql"]) - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) - xml += xml_rule_end() - - xml += xml_style_end() - sql.discard("()") - if sql: - sql_g.update(sql) - xml_g += xml - itags_g.update(itags) - else: - xml_nosubstyle() - + ## background areas pass + sql = set() + itags = set() + xml = xml_style_start() + for entry in zsheet[zindex]: + if entry["type"] in ("way", "area", "polygon"): + if ("fill-color" in entry["style"] or "fill-image" in entry["style"]) and (entry["style"].get("fill-position", "foreground")=="background"): + xml += xml_rule_start() + xml += x_scale + xml += xml_filter(entry["rulestring"]) + if "fill-color" in entry["style"]: + xml += xml_polygonsymbolizer(entry["style"].get("fill-color", "black"), relaxedFloat(entry["style"].get("fill-opacity", "1")), relaxedFloat(entry["style"].get("smooth","0"))) + if "fill-image" in entry["style"]: + xml += xml_polygonpatternsymbolizer(entry["style"].get("fill-image", "")) + sql.add(entry["sql"]) + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() + xml += xml_style_end() + sql.discard("()") + if sql: + sql_g.update(sql) + xml_g += xml + itags_g.update(itags) + else: + xml_nosubstyle() sql = sql_g itags = itags_g if sql: - mfile.write(xml_g) - sql = "(" + " OR ".join(sql) + ")"# and way && !bbox!" - if zlayer == 0 and full_layering: - sql = "("+ sql +') and ("layer" not in ('+ ", ".join(['\'%s\''%i for i in range(-5,6) if i != 0])+") or \"layer\" is NULL)" - elif zlayer <=5 and zlayer >= -5 and full_layering: - sql = "("+ sql +') and "layer" = \'%s\''%zlayer - itags = add_numerics_to_itags(itags) - if roads: - layer_type = 'roads' - mfile.write(xml_layer("postgis", layer_type, itags, sql, zoom=zoom )) - else: - xml_nolayer() - - for zindex in ta: - for layer_type, entry_types in [("line",("way", "line")),("polygon",("way","area"))]: - ## lines and polygons pass - sql_g = set() - there_are_dashed_lines = False - there_are_line_patterns = False - itags_g = set() - roads = (layer_type == 'line')# whether to use planet_osm_roads - xml_g = "" - - sql = set() - itags = set() - xml = xml_style_start() - for entry in zsheet[zindex]: - if entry["type"] in entry_types: - if "-x-mapnik-layer" in entry["style"]: - if zlayer != -6 and entry["style"]["-x-mapnik-layer"] == "bottom": - continue - if zlayer != 6 and entry["style"]["-x-mapnik-layer"] == "top": - continue - elif zlayer not in range(-5,6): - continue - if "width" in entry["style"] or "pattern-image" in entry["style"] or (("fill-color" in entry["style"] or "fill-image" in entry["style"]) and (layer_type == "polygon") and (entry["style"].get("fill-position", "foreground")=="foreground")): - xml += xml_rule_start() - xml += x_scale - xml += xml_filter(entry["rulestring"]) - if not check_if_roads_table(entry["rulestring"]): - roads = False - if layer_type == "polygon" and (entry["style"].get("fill-position", "foreground")=="foreground"): - if "fill-color" in entry["style"]: - xml += xml_polygonsymbolizer(entry["style"].get("fill-color", "black"), relaxedFloat(entry["style"].get("fill-opacity", "1")), relaxedFloat(entry["style"].get("smooth","0"))) - if "fill-image" in entry["style"]: - xml += xml_polygonpatternsymbolizer(entry["style"].get("fill-image", "")) - if "width" in entry["style"]: - twidth = relaxedFloat(entry["style"].get("width", "1")) - - # linejoins are round, but for thin roads they're miter - tlinejoin = "round" - if twidth <= 2: - tlinejoin = "miter" - tlinejoin = entry["style"].get("linejoin", tlinejoin) - - # linecaps are round for roads, and butts for roads on non-default layer= - tlinecap = "round" - if zlayer != 0: - tlinecap = "butt" - tlinecap = entry["style"].get("linecap", tlinecap) - - xml += xml_linesymbolizer(color=entry["style"].get("color", "black"), - width=twidth, - opacity=relaxedFloat(entry["style"].get("opacity", "1")), - linecap=tlinecap, - linejoin=tlinejoin, - dashes=entry["style"].get("dashes", ""), - smooth=relaxedFloat(entry["style"].get("smooth","0")), - zoom=zoom) - if entry["style"].get("dashes", ""): - there_are_dashed_lines = True - #print "dashes!!!" - if "pattern-image" in entry["style"]: - there_are_line_patterns = True - if entry["style"]["pattern-image"] == "arrows": - xml += xml_hardcoded_arrows() - else: - if "pattern-rotate" in entry["style"] or "pattern-spacing" in entry["style"]: - fname = entry["style"]["pattern-image"] - try: - im = Image.open(icons_path + fname).convert("RGBA") - fname = "f"+fname - if "pattern-rotate" in entry["style"]: - im = im.rotate(relaxedFloat(entry["style"]["pattern-rotate"])) - fname = "r"+str(relaxedFloat(entry["style"]["pattern-rotate"]))+fname - if "pattern-scale" in entry["style"]: - sc = relaxedFloat(entry["style"]["pattern-scale"])*1. - ns = (max(int(round(im.size[0]*sc)),1), max(int(round(im.size[1]*sc)),1)) - im = im.resize(ns, Image.BILINEAR) - fname = "z"+str(sc)+fname - if "pattern-spacing" in entry["style"]: - im2 = Image.new("RGBA", (im.size[0]+int(relaxedFloat(entry["style"]["pattern-spacing"])),im.size[1])) - im2.paste(im,(0,0)) - im = im2 - fname = "s"+str(int(relaxedFloat(entry["style"]["pattern-spacing"])))+fname - if not os.path.exists(icons_path+"komap/"): - os.makedirs(icons_path+"komap/") - if not os.path.exists(icons_path+"komap/"+fname): - im.save(icons_path+"komap/"+fname, "PNG") - xml += xml_linepatternsymbolizer("komap/"+fname) - except: - print >> sys.stderr, "Error writing to ", icons_path+"komap/"+fname - else: - xml += xml_linepatternsymbolizer(entry["style"]["pattern-image"]) - sql.add(entry["sql"]) - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) - xml += xml_rule_end() - - xml += xml_style_end() - sql.discard("()") - if sql: - sql_g.update(sql) - xml_g += xml - itags_g.update(itags) - else: - xml_nosubstyle() - sql = sql_g - itags = itags_g - if sql: mfile.write(xml_g) sql = "(" + " OR ".join(sql) + ")"# and way && !bbox!" - if zlayer == 0 and full_layering: - sql = "("+ sql +') and ("layer" not in ('+ ", ".join(['\'%s\''%i for i in range(-5,6) if i != 0])+") or \"layer\" is NULL)" - elif zlayer <=5 and zlayer >= -5 and full_layering: - sql = "("+ sql +') and "layer" = \'%s\''%zlayer - oitags = itags itags = add_numerics_to_itags(itags) - if layer_type == "polygon" and there_are_line_patterns: - itags = ", ".join(itags) - oitags = '"'+ "\", \"".join(oitags) +'"' - sqlz = """SELECT %s, ST_ForceRHR(way) as way from %spolygon where (%s) and way && !bbox! and ST_IsValid(way)"""%(itags, libkomapnik.table_prefix ,sql) - mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom)) - - #### FIXME: Performance degrades painfully on large lines ST_Union. Gotta find workaround :( - #if layer_type == "polygon" and there_are_dashed_lines: - #itags = ", ".join(itags) - #oitags = '"'+ "\", \"".join(oitags) +'"' - #sqlz = """select %s, ST_LineMerge(ST_Union(way)) as way from - #(SELECT %s, ST_Boundary(way) as way from planet_osm_polygon where (%s) and way && !bbox! and ST_IsValid(way) ) tex - #group by %s - #"""%(itags,oitags,sql,oitags) - elif layer_type == "line" and there_are_dashed_lines and zoom < 10: - itags = ", ".join(itags) # FIXME: wrong when working with hstore - oitags = '"'+ "\", \"".join(oitags) +'"' - sqlz = """select %s, ST_LineMerge(ST_Union(way)) as way from (SELECT %s, ST_SnapToGrid(way, %s) as way from %sline where way && !bbox! and (%s)) as tex - group by %s - """%(itags, oitags,pixel_size_at_zoom(zoom,1.5),libkomapnik.table_prefix,sql,oitags) - mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom )) - else: - if roads: - layer_type = 'roads' - mfile.write(xml_layer("postgis", layer_type, itags, sql, zoom=zoom )) - else: + mfile.write(xml_layer("postgis", "polygon", itags, sql, zoom=zoom )) + else: xml_nolayer() - if not options.bgonly: - ## icons pass - sql_g = set() - itags_g = set() - xml_g = "" - prevtype = "" - for zindex in ta: - for layer_type, entry_types in [("point", ("node", "point")),("line",("way", "line")), ("polygon",("way","area"))]: - sql = set() - itags = set() - style_started = False - for entry in zsheet[zindex]: - if entry["type"] in entry_types: - if "icon-image" in entry["style"]: - if not prevtype: - prevtype = layer_type - if prevtype != layer_type: - if sql_g: - mfile.write(xml_g) - sql_g = "(" + " OR ".join(sql_g) + ")"# and way && !bbox!" - itags_g = add_numerics_to_itags(itags_g) - mfile.write(xml_layer("postgis", prevtype, itags_g, sql_g, zoom=zoom )) - sql_g = set() - itags_g = set() - xml_g = "" + if hshack: + xml = xml_hillshade(zoom, x_scale) + mfile.write(xml) + + index_range = range(-6,7) + full_layering = conf_full_layering + if (zoom < 9) or not conf_full_layering : + index_range = (-6,0,6) + full_layering = False + def check_if_roads_table(rulestring): + roads = set([ + "[highway] = 'secondary'", + "[highway] = 'secondary_link'", + "[highway] = 'primary'", + "[highway] = 'primary_link'", + "[highway] = 'trunk'", + "[highway] = 'trunk_link'", + "[highway] = 'motorway'", + "[highway] = 'motorway_link'", + "[boundary] = 'administrative'", + "[railway] " + ]) + for a in rulestring.split(') or ('): + for r in roads: + if r not in a: + return False + return True + for zlayer in index_range: + for layer_type, entry_types in [("line",("way", "line")),("polygon",("way","area"))]: + sql_g = set() + there_are_dashed_lines = False + itags_g = set() + xml_g = "" + roads = (layer_type == 'line') # whether to use planet_osm_roads + ## casings pass + for zindex in ta: sql = set() itags = set() - else: - xml_nolayer() - prevtype = layer_type - if not style_started: - xml = xml_style_start() - style_started = True - xml += xml_rule_start() - xml += x_scale - xml += xml_filter(entry["rulestring"]) - xml += xml_pointsymbolizer( - path=entry["style"].get("icon-image", ""), - width=entry["style"].get("icon-width", ""), - height=entry["style"].get("icon-height", ""), - opacity=relaxedFloat(entry["style"].get("opacity", "1"))) - if ("text" in entry["style"] and entry["style"].get("text-position","center")=='center'): - ttext = entry["style"]["text"].extract_tags().pop() - sql.add("(("+entry["sql"]+") and "+escape_sql_column(ttext) + " is NULL)") - itags.add(ttext) - if ttext in columnmap: - itags.update(columnmap[ttext][1]) - else: - sql.add(entry["sql"]) - - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) - xml += xml_rule_end() - if style_started: - xml += xml_style_end() - style_started = False - sql.discard("()") - if sql: - sql_g.update(sql) - xml_g += xml - itags_g.update(itags) - else: - xml_nosubstyle() - if sql_g: - mfile.write(xml_g) - sql_g = "(" + " OR ".join(sql_g) + ")"# and way && !bbox!" - itags_g = add_numerics_to_itags(itags_g) - mfile.write(xml_layer("postgis", prevtype, itags_g, sql_g, zoom=zoom )) - else: - xml_nolayer() + xml = xml_style_start() + for entry in zsheet[zindex]: + if entry["type"] in entry_types: + if "-x-kot-layer" in entry["style"]: + if zlayer != -6 and entry["style"]["-x-kot-layer"] == "bottom": + continue + if zlayer != 6 and entry["style"]["-x-kot-layer"] == "top": + continue + elif zlayer not in range(-5,6): + continue + if "casing-width" in entry["style"]: + xml += xml_rule_start() + xml += x_scale + xml += xml_filter(entry["rulestring"]) + if not check_if_roads_table(entry["rulestring"]): + roads = False + twidth = 2*float(entry["style"].get("casing-width", 1))+float(entry["style"].get("width", 0)); + tlinejoin = "round" + if twidth < 3: + tlinejoin = "miter" + xml += xml_linesymbolizer(color=entry["style"].get("casing-color", "black"), + width=twidth, + opacity=relaxedFloat(entry["style"].get("casing-opacity", entry["style"].get("opacity","1"))), + linecap=entry["style"].get("casing-linecap", entry["style"].get("linecap","butt")), + linejoin=entry["style"].get("casing-linejoin", entry["style"].get("linejoin", "round")), + dashes=entry["style"].get("casing-dashes",entry["style"].get("dashes", "")), + smooth=relaxedFloat(entry["style"].get("smooth","0")), + zoom=zoom) - ta.reverse() - for zindex in ta: - for layer_type, entry_types in [ ("polygon",("way","area")),("point", ("node", "point")),("line",("way", "line"))]: - for placement in ("center","line"): - ## text pass - collhere = set() - for entry in zsheet[zindex]: - if entry["type"] in entry_types:#, "node", "line", "point"): - if ("text" in entry["style"] or "shield-text" in entry["style"]) and entry["style"].get("text-position","center")==placement: - csb = entry["style"].get("collision-sort-by",None) - cso = entry["style"].get("collision-sort-order","desc") - collhere.add((csb,cso)) - for snap_to_street in ('true', 'false'): - for (csb, cso) in collhere: - sql = set() - itags = set() - texttags = set() - xml = xml_style_start() - for entry in zsheet[zindex]: - if entry["type"] in entry_types and csb == entry["style"].get("collision-sort-by",None) and cso == entry["style"].get("collision-sort-order","desc") and snap_to_street == entry["style"].get("-x-mapnik-snap-to-street","false"): - if "shield-text" in entry["style"] and "shield-image" in entry["style"]: - ttext = entry["style"]["shield-text"].extract_tags().pop() - texttags.add(ttext) - tface = entry["style"].get("shield-font-family","DejaVu Sans Book") - tsize = entry["style"].get("shield-font-size","10") - tcolor = entry["style"].get("shield-text-color","#000000") - toverlap= entry["style"].get("text-allow-overlap",entry["style"].get("allow-overlap","false")) - tdistance= relaxedFloat(entry["style"].get("-x-mapnik-min-distance","20")) - twrap= relaxedFloat(entry["style"].get("shield-max-width",25)) - talign= entry["style"].get("shield-text-align","center") - topacity= relaxedFloat(entry["style"].get("shield-text-opacity",entry["style"].get("opacity","1"))) - toffset= relaxedFloat(entry["style"].get("shield-text-offset","0")) - ttransform = entry["style"].get("shield-text-transform","none") - tspacing = entry["style"].get("shield-spacing","500") - xml += xml_rule_start() - xml += x_scale + sql.add(entry["sql"]) + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() - xml += xml_filter(entry["rulestring"]) - - xml += xml_shieldsymbolizer( - entry["style"].get("shield-image", ""), - "", - "", - ttext,tface,tsize,tcolor, "#000000", 0, "center", - toffset,toverlap,tdistance,twrap,talign,topacity, ttransform, "false", tspacing) - sql.add(entry["sql"]) - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) - xml += xml_rule_end() - - if "text" in entry["style"] and entry["style"].get("text-position","center")==placement: - ttext = entry["style"]["text"].extract_tags().pop() - texttags.add(ttext) - tface = entry["style"].get("font-family","DejaVu Sans Book") - tsize = entry["style"].get("font-size","10") - tcolor = entry["style"].get("text-color","#000000") - thcolor= entry["style"].get("text-halo-color","#ffffff") - thradius= relaxedFloat(entry["style"].get("text-halo-radius","0")) - tplace= entry["style"].get("text-position","center") - toffset= relaxedFloat(entry["style"].get("text-offset","0")) - toverlap= entry["style"].get("text-allow-overlap",entry["style"].get("allow-overlap","false")) - tdistance= relaxedFloat(entry["style"].get("-x-mapnik-min-distance","20")) - twrap= relaxedFloat(entry["style"].get("max-width",256)) - talign= entry["style"].get("text-align","center") - topacity= relaxedFloat(entry["style"].get("text-opacity",entry["style"].get("opacity","1"))) - tpos = entry["style"].get("text-placement","X") - ttransform = entry["style"].get("text-transform","none") - tspacing = entry["style"].get("text-spacing","4096") + xml += xml_style_end() + sql.discard("()") + if sql: + sql_g.update(sql) + xml_g += xml + itags_g.update(itags) + else: + xml_nosubstyle() - xml += xml_rule_start() - xml += x_scale - - xml += xml_filter(entry["rulestring"]) - if "icon-image" in entry["style"] and entry["style"].get("text-position","center")=='center': - xml += xml_shieldsymbolizer( - entry["style"].get("icon-image", ""), - entry["style"].get("icon-width", ""), - entry["style"].get("icon-height", ""), - ttext,tface,tsize,tcolor, thcolor, thradius, tplace, - toffset,toverlap,tdistance,twrap,talign,topacity, ttransform) - else: - xml += xml_textsymbolizer(ttext,tface,tsize,tcolor, thcolor, thradius, tplace, toffset,toverlap,tdistance,twrap,talign,topacity,tpos,ttransform,tspacing) - sql.add(entry["sql"]) - itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) - xml += xml_rule_end() - - xml += xml_style_end() - sql.discard("()") + sql = sql_g + itags = itags_g if sql: - order = "" - if csb: - if cso != "desc": - cso = "asc" - order = """ order by (CASE WHEN "%s" ~ E'^[[:digit:]]+([.][[:digit:]]+)?$' THEN to_char(CAST ("%s" AS FLOAT) ,'000000000000000.99999999999') else "%s" end) %s nulls last """%(csb,csb,csb,cso) - - mfile.write(xml) - - add_tags = set() - for t in itags: - if t in columnmap: - add_tags.update(columnmap[t][1]) - texttags.update(columnmap[t][1]) - - oitags = itags.union(add_tags) # SELECT: (tags->'mooring') as "mooring" - oitags = ", ".join([ escape_sql_column(i, asname=True) for i in oitags]) - - goitags = itags.union(add_tags) # GROUP BY: (tags->'mooring') - goitags = ", ".join([ escape_sql_column(i) for i in goitags]) - - fitags = [columnmap.get(i, (i,))[0] for i in itags] - - #fitags = add_numerics_to_itags(itags) - itags = add_numerics_to_itags(fitags) # population => {population, population__num} - neitags = add_numerics_to_itags(fitags, escape = False) # for complex polygons, no escapng needed - del fitags - - ttext = " OR ".join([escape_sql_column(i)+ " is not NULL" for i in texttags]) - - if placement == "center" and layer_type == "polygon" and snap_to_street == 'false': - sqlz = " OR ".join(sql) - itags = ", ".join(itags) - neitags = ", ".join(neitags) - if not order: - order = "order by" - else: - order += ", " - if zoom > 11 or zoom < 6: - sqlz = """select %s, way - from %s%s - where (%s) and (%s) and (way_area > %s) and way && ST_Expand(!bbox!,3000) %s way_area desc - """%(itags,libkomapnik.table_prefix,layer_type,ttext,sqlz,pixel_size_at_zoom(zoom,3)**2, order) - else: - sqlz = """select %s, way - from ( - select (ST_Dump(ST_Multi(ST_Buffer(ST_Simplify(ST_Collect(p.way),%s),%s)))).geom as way, %s - from ( - select * - from %s%s p - where (%s) and way_area > %s and p.way && ST_Expand(!bbox!,%s) and (%s)) p - group by %s) p %s ST_Area(p.way) desc - """%(neitags,pixel_size_at_zoom(zoom,9),pixel_size_at_zoom(zoom,10),oitags, - libkomapnik.table_prefix,layer_type,ttext,pixel_size_at_zoom(zoom,5)**2,max(pixel_size_at_zoom(zoom,20),3000),sqlz,goitags,order) - - mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom )) - elif layer_type == "line" and zoom < 16 and snap_to_street == 'false': - sqlz = " OR ".join(sql) - itags = ", ".join(itags) - if not order: - order = "order by" - else: - order += ", " - #itags = "\""+ itags+"\"" - sqlz = """select * from (select %s, ST_Simplify(ST_LineMerge(ST_Union(way)),%s) as way from (SELECT * from %sline where way && ST_Expand(!bbox!,%s) and (%s) and (%s)) as tex - group by %s) p - where ST_Length(p.way) > %s - %s ST_Length(p.way) desc - """%(itags,pixel_size_at_zoom(zoom,3),libkomapnik.table_prefix,max(pixel_size_at_zoom(zoom,20),3000),ttext,sqlz,goitags,pixel_size_at_zoom(zoom,4),order) - mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom )) - - - elif snap_to_street == 'true': - sqlz = " OR ".join(sql) - itags = ", ".join(itags) - - sqlz = """select %s, - - coalesce( - (select - ST_Intersection( - ST_Translate( - ST_Rotate( - ST_GeomFromEWKT('SRID=%s;LINESTRING(-50 0, 50 0)'), - -1*ST_Azimuth(ST_PointN(ST_ShortestLine(l.way, ST_PointOnSurface(ST_Buffer(h.way,0.1))),1), - ST_PointN(ST_ShortestLine(l.way, ST_PointOnSurface(ST_Buffer(h.way,0.1))),2) - ) - ), - ST_X(ST_PointOnSurface(ST_Buffer(h.way,0.1))), - ST_Y(ST_PointOnSurface(ST_Buffer(h.way,0.1))) - ), - ST_Buffer(h.way,20) - ) - as way - from %sline l - where - l.way && ST_Expand(h.way, 600) and - ST_IsValid(l.way) and - l."name" = h."addr:street" and - l.highway is not NULL and - l."name" is not NULL - order by ST_Distance(ST_PointOnSurface(ST_Buffer(h.way,0.1)), l.way) asc - limit 1 - ), - (select - ST_Intersection( - ST_Translate( - ST_Rotate( - ST_GeomFromEWKT('SRID=%s;LINESTRING(-50 0, 50 0)'), - -1*ST_Azimuth(ST_PointN(ST_ShortestLine(ST_Centroid(l.way), ST_PointOnSurface(ST_Buffer(h.way,0.1))),1), - ST_PointN(ST_ShortestLine(ST_Centroid(l.way), ST_PointOnSurface(ST_Buffer(h.way,0.1))),2) - ) - ), - ST_X(ST_PointOnSurface(ST_Buffer(h.way,0.1))), - ST_Y(ST_PointOnSurface(ST_Buffer(h.way,0.1))) - ), - ST_Buffer(h.way,20) - ) - as way - from %spolygon l - where - l.way && ST_Expand(h.way, 600) and - ST_IsValid(l.way) and - l."name" = h."addr:street" and - l.highway is not NULL and - l."name" is not NULL - order by ST_Distance(ST_PointOnSurface(ST_Buffer(h.way,0.1)), l.way) asc - limit 1 - ), - ST_Intersection( - ST_MakeLine( ST_Translate(ST_PointOnSurface(ST_Buffer(h.way,0.1)),-50,0), - ST_Translate(ST_PointOnSurface(ST_Buffer(h.way,0.1)), 50,0) - ), - ST_Buffer(h.way,20) - ) - ) as way - - from %s%s h - where (%s) and (%s) and way && ST_Expand(!bbox!,3000) %s - """%(itags, libkomapnik.db_srid, libkomapnik.table_prefix, libkomapnik.db_srid, libkomapnik.table_prefix, libkomapnik.table_prefix, layer_type, ttext,sqlz, order) - mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom )) - - - else: - sql = "(" + " OR ".join(sql) + ") %s"%(order)#and way && ST_Expand(!bbox!,%s), max(pixel_size_at_zoom(zoom,20),3000), + mfile.write(xml_g) + sql = "(" + " OR ".join(sql) + ")"# and way && !bbox!" + if zlayer == 0 and full_layering: + sql = "("+ sql +') and ("layer" not in ('+ ", ".join(['\'%s\''%i for i in range(-5,6) if i != 0])+") or \"layer\" is NULL)" + elif zlayer <=5 and zlayer >= -5 and full_layering: + sql = "("+ sql +') and "layer" = \'%s\''%zlayer + itags = add_numerics_to_itags(itags) + if roads: + layer_type = 'roads' mfile.write(xml_layer("postgis", layer_type, itags, sql, zoom=zoom )) else: - xml_nolayer() + xml_nolayer() - mfile.write(xml_end()) + for zindex in ta: + for layer_type, entry_types in [("line",("way", "line")),("polygon",("way","area"))]: + ## lines and polygons pass + sql_g = set() + there_are_dashed_lines = False + there_are_line_patterns = False + itags_g = set() + roads = (layer_type == 'line')# whether to use planet_osm_roads + xml_g = "" + + sql = set() + itags = set() + xml = xml_style_start() + for entry in zsheet[zindex]: + if entry["type"] in entry_types: + if "-x-kot-layer" in entry["style"]: + if zlayer != -6 and entry["style"]["-x-kot-layer"] == "bottom": + continue + if zlayer != 6 and entry["style"]["-x-kot-layer"] == "top": + continue + elif zlayer not in range(-5,6): + continue + if "width" in entry["style"] or "pattern-image" in entry["style"] or (("fill-color" in entry["style"] or "fill-image" in entry["style"]) and (layer_type == "polygon") and (entry["style"].get("fill-position", "foreground")=="foreground")): + xml += xml_rule_start() + xml += x_scale + xml += xml_filter(entry["rulestring"]) + if not check_if_roads_table(entry["rulestring"]): + roads = False + if layer_type == "polygon" and (entry["style"].get("fill-position", "foreground")=="foreground"): + if "fill-color" in entry["style"]: + xml += xml_polygonsymbolizer(entry["style"].get("fill-color", "black"), relaxedFloat(entry["style"].get("fill-opacity", "1")), relaxedFloat(entry["style"].get("smooth","0"))) + if "fill-image" in entry["style"]: + xml += xml_polygonpatternsymbolizer(entry["style"].get("fill-image", "")) + if "width" in entry["style"]: + twidth = relaxedFloat(entry["style"].get("width", "1")) + + # linejoins are round, but for thin roads they're miter + tlinejoin = "round" + if twidth <= 2: + tlinejoin = "miter" + tlinejoin = entry["style"].get("linejoin", tlinejoin) + + # linecaps are round for roads, and butts for roads on non-default layer= + tlinecap = "round" + if zlayer != 0: + tlinecap = "butt" + tlinecap = entry["style"].get("linecap", tlinecap) + + xml += xml_linesymbolizer(color=entry["style"].get("color", "black"), + width=twidth, + opacity=relaxedFloat(entry["style"].get("opacity", "1")), + linecap=tlinecap, + linejoin=tlinejoin, + dashes=entry["style"].get("dashes", ""), + smooth=relaxedFloat(entry["style"].get("smooth","0")), + zoom=zoom) + if entry["style"].get("dashes", ""): + there_are_dashed_lines = True + #print "dashes!!!" + if "pattern-image" in entry["style"]: + there_are_line_patterns = True + if entry["style"]["pattern-image"] == "arrows": + xml += xml_hardcoded_arrows() + else: + if "pattern-rotate" in entry["style"] or "pattern-spacing" in entry["style"]: + fname = entry["style"]["pattern-image"] + try: + im = Image.open(icons_path + fname).convert("RGBA") + fname = "f"+fname + if "pattern-rotate" in entry["style"]: + im = im.rotate(relaxedFloat(entry["style"]["pattern-rotate"])) + fname = "r"+str(relaxedFloat(entry["style"]["pattern-rotate"]))+fname + if "pattern-scale" in entry["style"]: + sc = relaxedFloat(entry["style"]["pattern-scale"])*1. + ns = (max(int(round(im.size[0]*sc)),1), max(int(round(im.size[1]*sc)),1)) + im = im.resize(ns, Image.BILINEAR) + fname = "z"+str(sc)+fname + if "pattern-spacing" in entry["style"]: + im2 = Image.new("RGBA", (im.size[0]+int(relaxedFloat(entry["style"]["pattern-spacing"])),im.size[1])) + im2.paste(im,(0,0)) + im = im2 + fname = "s"+str(int(relaxedFloat(entry["style"]["pattern-spacing"])))+fname + if not os.path.exists(icons_path+"komap/"): + os.makedirs(icons_path+"komap/") + if not os.path.exists(icons_path+"komap/"+fname): + im.save(icons_path+"komap/"+fname, "PNG") + xml += xml_linepatternsymbolizer("komap/"+fname) + except: + print >> sys.stderr, "Error writing to ", icons_path+"komap/"+fname + else: + xml += xml_linepatternsymbolizer(entry["style"]["pattern-image"]) + sql.add(entry["sql"]) + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() + + xml += xml_style_end() + sql.discard("()") + if sql: + sql_g.update(sql) + xml_g += xml + itags_g.update(itags) + else: + xml_nosubstyle() + sql = sql_g + itags = itags_g + if sql: + mfile.write(xml_g) + sql = "(" + " OR ".join(sql) + ")"# and way && !bbox!" + if zlayer == 0 and full_layering: + sql = "("+ sql +') and ("layer" not in ('+ ", ".join(['\'%s\''%i for i in range(-5,6) if i != 0])+") or \"layer\" is NULL)" + elif zlayer <=5 and zlayer >= -5 and full_layering: + sql = "("+ sql +') and "layer" = \'%s\''%zlayer + oitags = itags + itags = add_numerics_to_itags(itags) + if layer_type == "polygon" and there_are_line_patterns: + itags = ", ".join(itags) + oitags = '"'+ "\", \"".join(oitags) +'"' + sqlz = """SELECT %s, ST_ForceRHR(way) as way from %spolygon where (%s) and way && !bbox! and ST_IsValid(way)"""%(itags, libkomapnik.table_prefix ,sql) + mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom)) + + #### FIXME: Performance degrades painfully on large lines ST_Union. Gotta find workaround :( + #if layer_type == "polygon" and there_are_dashed_lines: + #itags = ", ".join(itags) + #oitags = '"'+ "\", \"".join(oitags) +'"' + #sqlz = """select %s, ST_LineMerge(ST_Union(way)) as way from + #(SELECT %s, ST_Boundary(way) as way from planet_osm_polygon where (%s) and way && !bbox! and ST_IsValid(way) ) tex + #group by %s + #"""%(itags,oitags,sql,oitags) + elif layer_type == "line" and there_are_dashed_lines and zoom < 10: + itags = ", ".join(itags) # FIXME: wrong when working with hstore + oitags = '"'+ "\", \"".join(oitags) +'"' + sqlz = """select %s, ST_LineMerge(ST_Union(way)) as way from (SELECT %s, ST_SnapToGrid(way, %s) as way from %sline where way && !bbox! and (%s)) as tex + group by %s + """%(itags, oitags,pixel_size_at_zoom(zoom,1.5),libkomapnik.table_prefix,sql,oitags) + mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom )) + else: + if roads: + layer_type = 'roads' + mfile.write(xml_layer("postgis", layer_type, itags, sql, zoom=zoom )) + else: + xml_nolayer() + + if not options.bgonly: + ## icons pass + sql_g = set() + itags_g = set() + xml_g = "" + prevtype = "" + for zindex in ta: + for layer_type, entry_types in [("point", ("node", "point")),("line",("way", "line")), ("polygon",("way","area"))]: + sql = set() + itags = set() + style_started = False + for entry in zsheet[zindex]: + if entry["type"] in entry_types: + if "icon-image" in entry["style"]: + if not prevtype: + prevtype = layer_type + if prevtype != layer_type: + if sql_g: + mfile.write(xml_g) + sql_g = "(" + " OR ".join(sql_g) + ")"# and way && !bbox!" + itags_g = add_numerics_to_itags(itags_g) + mfile.write(xml_layer("postgis", prevtype, itags_g, sql_g, zoom=zoom )) + sql_g = set() + itags_g = set() + xml_g = "" + sql = set() + itags = set() + else: + xml_nolayer() + prevtype = layer_type + if not style_started: + xml = xml_style_start() + style_started = True + xml += xml_rule_start() + xml += x_scale + xml += xml_filter(entry["rulestring"]) + xml += xml_pointsymbolizer( + path=entry["style"].get("icon-image", ""), + width=entry["style"].get("icon-width", ""), + height=entry["style"].get("icon-height", ""), + opacity=relaxedFloat(entry["style"].get("opacity", "1"))) + if ("text" in entry["style"] and entry["style"].get("text-position","center")=='center'): + ttext = entry["style"]["text"].extract_tags().pop() + sql.add("(("+entry["sql"]+") and "+escape_sql_column(ttext) + " is NULL)") + itags.add(ttext) + if ttext in columnmap: + itags.update(columnmap[ttext][1]) + else: + sql.add(entry["sql"]) + + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() + if style_started: + xml += xml_style_end() + style_started = False + sql.discard("()") + if sql: + sql_g.update(sql) + xml_g += xml + itags_g.update(itags) + else: + xml_nosubstyle() + if sql_g: + mfile.write(xml_g) + sql_g = "(" + " OR ".join(sql_g) + ")"# and way && !bbox!" + itags_g = add_numerics_to_itags(itags_g) + mfile.write(xml_layer("postgis", prevtype, itags_g, sql_g, zoom=zoom )) + else: + xml_nolayer() + + ta.reverse() + for zindex in ta: + for layer_type, entry_types in [ ("polygon",("way","area")),("point", ("node", "point")),("line",("way", "line"))]: + for placement in ("center","line"): + ## text pass + collhere = set() + for entry in zsheet[zindex]: + if entry["type"] in entry_types:#, "node", "line", "point"): + if ("text" in entry["style"] or "shield-text" in entry["style"]) and entry["style"].get("text-position","center")==placement: + csb = entry["style"].get("collision-sort-by",None) + cso = entry["style"].get("collision-sort-order","desc") + collhere.add((csb,cso)) + for snap_to_street in ('true', 'false'): + for (csb, cso) in collhere: + sql = set() + itags = set() + texttags = set() + xml = xml_style_start() + for entry in zsheet[zindex]: + if entry["type"] in entry_types and csb == entry["style"].get("collision-sort-by",None) and cso == entry["style"].get("collision-sort-order","desc") and snap_to_street == entry["style"].get("-x-kot-snap-to-street","false"): + if "shield-text" in entry["style"] and "shield-image" in entry["style"]: + ttext = entry["style"]["shield-text"].extract_tags().pop() + texttags.add(ttext) + tface = entry["style"].get("shield-font-family","DejaVu Sans Book") + tsize = entry["style"].get("shield-font-size","10") + tcolor = entry["style"].get("shield-text-color","#000000") + toverlap= entry["style"].get("text-allow-overlap",entry["style"].get("allow-overlap","false")) + tdistance= relaxedFloat(entry["style"].get("-x-kot-min-distance","20")) + twrap= relaxedFloat(entry["style"].get("shield-max-width",25)) + talign= entry["style"].get("shield-text-align","center") + topacity= relaxedFloat(entry["style"].get("shield-text-opacity",entry["style"].get("opacity","1"))) + toffset= relaxedFloat(entry["style"].get("shield-text-offset","0")) + ttransform = entry["style"].get("shield-text-transform","none") + tspacing = entry["style"].get("shield-spacing","500") + xml += xml_rule_start() + xml += x_scale + + xml += xml_filter(entry["rulestring"]) + + xml += xml_shieldsymbolizer( + entry["style"].get("shield-image", ""), + "", + "", + ttext,tface,tsize,tcolor, "#000000", 0, "center", + toffset,toverlap,tdistance,twrap,talign,topacity, ttransform, "false", tspacing) + sql.add(entry["sql"]) + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() + + if "text" in entry["style"] and entry["style"].get("text-position","center")==placement: + ttext = entry["style"]["text"].extract_tags().pop() + texttags.add(ttext) + tface = entry["style"].get("font-family","DejaVu Sans Book") + tsize = entry["style"].get("font-size","10") + tcolor = entry["style"].get("text-color","#000000") + thcolor= entry["style"].get("text-halo-color","#ffffff") + thradius= relaxedFloat(entry["style"].get("text-halo-radius","0")) + tplace= entry["style"].get("text-position","center") + toffset= relaxedFloat(entry["style"].get("text-offset","0")) + toverlap= entry["style"].get("text-allow-overlap",entry["style"].get("allow-overlap","false")) + tdistance= relaxedFloat(entry["style"].get("-x-kot-min-distance","20")) + twrap= relaxedFloat(entry["style"].get("max-width",256)) + talign= entry["style"].get("text-align","center") + topacity= relaxedFloat(entry["style"].get("text-opacity",entry["style"].get("opacity","1"))) + tpos = entry["style"].get("text-placement","X") + ttransform = entry["style"].get("text-transform","none") + tspacing = entry["style"].get("text-spacing","4096") + + xml += xml_rule_start() + xml += x_scale + + xml += xml_filter(entry["rulestring"]) + if "icon-image" in entry["style"] and entry["style"].get("text-position","center")=='center': + xml += xml_shieldsymbolizer( + entry["style"].get("icon-image", ""), + entry["style"].get("icon-width", ""), + entry["style"].get("icon-height", ""), + ttext,tface,tsize,tcolor, thcolor, thradius, tplace, + toffset,toverlap,tdistance,twrap,talign,topacity, ttransform) + else: + xml += xml_textsymbolizer(ttext,tface,tsize,tcolor, thcolor, thradius, tplace, toffset,toverlap,tdistance,twrap,talign,topacity,tpos,ttransform,tspacing) + sql.add(entry["sql"]) + itags.update(entry["chooser"].get_interesting_tags(entry["type"], zoom)) + xml += xml_rule_end() + + xml += xml_style_end() + sql.discard("()") + if sql: + order = "" + if csb: + if cso != "desc": + cso = "asc" + order = """ order by (CASE WHEN "%s" ~ E'^[[:digit:]]+([.][[:digit:]]+)?$' THEN to_char(CAST ("%s" AS FLOAT) ,'000000000000000.99999999999') else "%s" end) %s nulls last """%(csb,csb,csb,cso) + + mfile.write(xml) + + add_tags = set() + for t in itags: + if t in columnmap: + add_tags.update(columnmap[t][1]) + texttags.update(columnmap[t][1]) + + oitags = itags.union(add_tags) # SELECT: (tags->'mooring') as "mooring" + oitags = ", ".join([ escape_sql_column(i, asname=True) for i in oitags]) + + goitags = itags.union(add_tags) # GROUP BY: (tags->'mooring') + goitags = ", ".join([ escape_sql_column(i) for i in goitags]) + + fitags = [columnmap.get(i, (i,))[0] for i in itags] + + #fitags = add_numerics_to_itags(itags) + itags = add_numerics_to_itags(fitags) # population => {population, population__num} + neitags = add_numerics_to_itags(fitags, escape = False) # for complex polygons, no escapng needed + del fitags + + ttext = " OR ".join([escape_sql_column(i)+ " is not NULL" for i in texttags]) + + if placement == "center" and layer_type == "polygon" and snap_to_street == 'false': + sqlz = " OR ".join(sql) + itags = ", ".join(itags) + neitags = ", ".join(neitags) + if not order: + order = "order by" + else: + order += ", " + if zoom > 11 or zoom < 6: + sqlz = """select %s, way + from %s%s + where (%s) and (%s) and (way_area > %s) and way && ST_Expand(!bbox!,3000) %s way_area desc + """%(itags,libkomapnik.table_prefix,layer_type,ttext,sqlz,pixel_size_at_zoom(zoom,3)**2, order) + else: + sqlz = """select %s, way + from ( + select (ST_Dump(ST_Multi(ST_Buffer(ST_Simplify(ST_Collect(p.way),%s),%s)))).geom as way, %s + from ( + select * + from %s%s p + where (%s) and way_area > %s and p.way && ST_Expand(!bbox!,%s) and (%s)) p + group by %s) p %s ST_Area(p.way) desc + """%(neitags,pixel_size_at_zoom(zoom,9),pixel_size_at_zoom(zoom,10),oitags, + libkomapnik.table_prefix,layer_type,ttext,pixel_size_at_zoom(zoom,5)**2,max(pixel_size_at_zoom(zoom,20),3000),sqlz,goitags,order) + + mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom )) + elif layer_type == "line" and zoom < 16 and snap_to_street == 'false': + sqlz = " OR ".join(sql) + itags = ", ".join(itags) + if not order: + order = "order by" + else: + order += ", " + #itags = "\""+ itags+"\"" + sqlz = """select * from (select %s, ST_Simplify(ST_LineMerge(ST_Union(way)),%s) as way from (SELECT * from %sline where way && ST_Expand(!bbox!,%s) and (%s) and (%s)) as tex + group by %s) p + where ST_Length(p.way) > %s + %s ST_Length(p.way) desc + """%(itags,pixel_size_at_zoom(zoom,3),libkomapnik.table_prefix,max(pixel_size_at_zoom(zoom,20),3000),ttext,sqlz,goitags,pixel_size_at_zoom(zoom,4),order) + mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom=zoom )) + + + elif snap_to_street == 'true': + sqlz = " OR ".join(sql) + itags = ", ".join(itags) + + sqlz = """select %s, + + coalesce( + (select + ST_Intersection( + ST_Translate( + ST_Rotate( + ST_GeomFromEWKT('SRID=%s;LINESTRING(-50 0, 50 0)'), + -1*ST_Azimuth(ST_PointN(ST_ShortestLine(l.way, ST_PointOnSurface(ST_Buffer(h.way,0.1))),1), + ST_PointN(ST_ShortestLine(l.way, ST_PointOnSurface(ST_Buffer(h.way,0.1))),2) + ) + ), + ST_X(ST_PointOnSurface(ST_Buffer(h.way,0.1))), + ST_Y(ST_PointOnSurface(ST_Buffer(h.way,0.1))) + ), + ST_Buffer(h.way,20) + ) + as way + from %sline l + where + l.way && ST_Expand(h.way, 600) and + ST_IsValid(l.way) and + l."name" = h."addr:street" and + l.highway is not NULL and + l."name" is not NULL + order by ST_Distance(ST_PointOnSurface(ST_Buffer(h.way,0.1)), l.way) asc + limit 1 + ), + (select + ST_Intersection( + ST_Translate( + ST_Rotate( + ST_GeomFromEWKT('SRID=%s;LINESTRING(-50 0, 50 0)'), + -1*ST_Azimuth(ST_PointN(ST_ShortestLine(ST_Centroid(l.way), ST_PointOnSurface(ST_Buffer(h.way,0.1))),1), + ST_PointN(ST_ShortestLine(ST_Centroid(l.way), ST_PointOnSurface(ST_Buffer(h.way,0.1))),2) + ) + ), + ST_X(ST_PointOnSurface(ST_Buffer(h.way,0.1))), + ST_Y(ST_PointOnSurface(ST_Buffer(h.way,0.1))) + ), + ST_Buffer(h.way,20) + ) + as way + from %spolygon l + where + l.way && ST_Expand(h.way, 600) and + ST_IsValid(l.way) and + l."name" = h."addr:street" and + l.highway is not NULL and + l."name" is not NULL + order by ST_Distance(ST_PointOnSurface(ST_Buffer(h.way,0.1)), l.way) asc + limit 1 + ), + ST_Intersection( + ST_MakeLine( ST_Translate(ST_PointOnSurface(ST_Buffer(h.way,0.1)),-50,0), + ST_Translate(ST_PointOnSurface(ST_Buffer(h.way,0.1)), 50,0) + ), + ST_Buffer(h.way,20) + ) + ) as way + + from %s%s h + where (%s) and (%s) and way && ST_Expand(!bbox!,3000) %s + """%(itags, libkomapnik.db_srid, libkomapnik.table_prefix, libkomapnik.db_srid, libkomapnik.table_prefix, libkomapnik.table_prefix, layer_type, ttext,sqlz, order) + mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz, zoom )) + + + else: + sql = "(" + " OR ".join(sql) + ") %s"%(order)#and way && ST_Expand(!bbox!,%s), max(pixel_size_at_zoom(zoom,20),3000), + mfile.write(xml_layer("postgis", layer_type, itags, sql, zoom=zoom )) + else: + xml_nolayer() + + mfile.write(xml_end()) diff --git a/src/libkojs.py b/src/libkojs.py new file mode 100644 index 0000000..b14845c --- /dev/null +++ b/src/libkojs.py @@ -0,0 +1,57 @@ +def komap_js(mfile, style): + subjs = {"canvas": ("canvas",),"way": ("Polygon","LineString"), "line":("Polygon","LineString"), "area": ("Polygon",), "node": ("Point",), "*":("Point","Polygon","LineString"), "":("Point","Polygon","LineString"), } + mfile.write("function restyle (prop, zoom, type){") + mfile.write("style = new Object;") + mfile.write('style["default"] = new Object;') + for chooser in style.choosers: + condition = "" + subclass = "default" + for i in chooser.ruleChains: + if condition: + condition += "||" + rule = " zoom >= %s && zoom <= %s"%(i.minZoom, i.maxZoom) + for z in i.conditions: + t = z.type + params = z.params + if params[0] == "::class": + subclass = params[1][2:] + continue + if rule: + rule += " && " + if t == 'eq': + rule += 'prop["%s"] == "%s"'%(params[0], params[1]) + if t == 'ne': + rule += 'prop["%s"] != "%s"'%(params[0], params[1]) + if t == 'regex': + rule += 'prop["%s"].match(RegExp("%s"))'%(params[0], params[1]) + if t == 'true': + rule += 'prop["%s"] == "yes"'%(params[0]) + if t == 'untrue': + rule += 'prop["%s"] != "yes"'%(params[0]) + if t == 'set': + rule += '"%s" in prop'%(params[0]) + if t == 'unset': + rule += '!("%s"in prop)'%(params[0]) + if t == '<': + rule += 'prop["%s"] < %s'%(params[0], params[1]) + if t == '<=': + rule += 'prop["%s"] <= %s'%(params[0], params[1]) + if t == '>': + rule += 'prop["%s"] > %s'%(params[0], params[1]) + if t == '>=': + rule += 'prop["%s"] >= %s'%(params[0], params[1]) + if rule: + rule = "&&" + rule + condition += "(("+"||".join(['type == "%s"'%z for z in subjs[i.subject]])+") "+ rule + ")" + styles = "" + if subclass != "default": + styles = 'if(!("%s" in style)){style["%s"] = new Object;}'%(subclass,subclass) + for k, v in chooser.styles[0].iteritems(): + if type(v) == str: + try: + v = str(float(v)) + styles += 'style["'+subclass+'"]["'+k+'"] = '+v + ';' + except: + styles += 'style["'+subclass+'"]["'+k+'"] = "' + v + '";' + mfile.write("if(%s) {%s};\n"%(condition,styles)) + mfile.write("return style;}")