From d8c8c3d6df7ac3fd8fc802b11ebbc2ea1e382753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kom=D1=8Fpa?= Date: Sun, 28 Nov 2010 14:31:40 +0200 Subject: [PATCH] Support for > < = for numbers. Initial support for commandline arguments --- src/komap.py | 93 ++++++++++++++++++++++++++++++++++++++-------- src/libkomapnik.py | 9 ++++- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/src/komap.py b/src/komap.py index a6b7384..1f89b14 100644 --- a/src/komap.py +++ b/src/komap.py @@ -20,6 +20,7 @@ from debug import debug, Timer from mapcss import MapCSS import sys from libkomapnik import * +from optparse import OptionParser try: import psyco @@ -27,13 +28,44 @@ try: except ImportError: pass -minzoom = 0 -maxzoom = 19 + +parser = OptionParser() +parser.add_option("-s", "--stylesheet", dest="filename", + help="read MapCSS stylesheet from FILE", metavar="FILE") +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", + 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") + +(options, args) = parser.parse_args() +#print (options, args) + +minzoom = options.minzoom +maxzoom = options.maxzoom+1 +locale = options.locale + + +if options.outfile == "-": + mfile = sys.stdout +else: + mfile = open(options.outfile,"w") style = MapCSS(minzoom, maxzoom) #zoom levels -style.parse(open("styles/osmosnimki-maps.mapcss","r").read()) +style.parse(open(options.filename,"r").read()) +columnmap = {} + +if locale == "en": + columnmap["name"] = ("""(CASE WHEN "name:en" IS NOT NULL THEN "name:en" ELSE CASE WHEN "int_name" IS NOT NULL THEN "int_name" ELSE replace(replace(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') END END) AS name""",('name:en','int_name',)) +elif locale: + columnmap["name"] = ('(CASE WHEN "name:'+loacle+' IS NOT NULL THEN "name:'+locale+'" ELSE name END) AS name',('name:'+locale,)) + +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}...]...}...} @@ -54,6 +86,7 @@ for zoom in range (minzoom, maxzoom): chooser_entry["style"] = styles chooser_entry["type"] = chooser.ruleChains[0][0].subject chooser_entry["rule"] = [i.conditions for i in chooser.ruleChains[0] if i.test_zoom(zoom)] + numerics.update(chooser.get_numerics()) 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"] == "area" and "[natural] = 'coastline'" in chooser_entry["rulestring"]: @@ -65,11 +98,25 @@ for zoom in range (minzoom, maxzoom): - +sys.stderr.write(str(numerics)+"\n") #print mapniksheet -mfile = open("mapnik.xml","w") -mfile = sys.stdout +def add_numerics_to_itags(itags): + tt = set() + nitags = set() + 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"""%(i,i,i)) + kav = "" + if '"' not in i: + kav = '"' + nitags.add(kav+i+kav) + itags = nitags + itags.update(tt) + return itags + + + mfile.write(xml_start(style.get_style("canvas", {}, maxzoom)[0].get("fill-color", "#000000"))) for zoom, zsheet in mapniksheet.iteritems(): @@ -116,6 +163,7 @@ for zoom, zsheet in mapniksheet.iteritems(): if sql: mfile.write(xml) sql = " OR ".join(sql) + itags = add_numerics_to_itags(itags) mfile.write(xml_layer("postgis", "polygon", itags, sql )) else: xml_nolayer() @@ -159,6 +207,7 @@ for zoom, zsheet in mapniksheet.iteritems(): 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: sql = "("+ sql +') and "layer" = \'%s\''%zlayer + itags = add_numerics_to_itags(itags) mfile.write(xml_layer("postgis", layer_type, itags, sql )) else: xml_nolayer() @@ -206,6 +255,7 @@ for zoom, zsheet in mapniksheet.iteritems(): 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: sql = "("+ sql +') and "layer" = \'%s\''%zlayer + itags = add_numerics_to_itags(itags) mfile.write(xml_layer("postgis", layer_type, itags, sql )) else: xml_nolayer() @@ -237,10 +287,11 @@ for zoom, zsheet in mapniksheet.iteritems(): if sql: mfile.write(xml) sql = " OR ".join(sql) + itags = add_numerics_to_itags(itags) mfile.write(xml_layer("postgis", layer_type, itags, sql )) 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"): @@ -280,11 +331,24 @@ for zoom, zsheet in mapniksheet.iteritems(): sql.discard("()") if sql: 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) + + oitags = [ '"'+i+'"' for i in oitags] + oitags = ", ".join(oitags) + ttext = " OR ".join(['"'+i+ "\" is not NULL " for i in texttags]) + itags = [columnmap.get(i, (i,))[0] for i in itags] + itags = add_numerics_to_itags(itags) if placement == "center" and layer_type == "polygon": sqlz = " OR ".join(sql) - itags = "\", \"".join(itags) - itags = "\""+ itags+"\"" + itags = ", ".join(itags) + #itags = "\""+ itags+"\"" sqlz = """select %s, ST_PointOnSurface(ST_Buffer(p.way,0)) as way from planet_osm_%s p where (%s) and p.way && !bbox! and (%s) order by way_area @@ -292,12 +356,11 @@ for zoom, zsheet in mapniksheet.iteritems(): mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz )) elif layer_type == "line": sqlz = " OR ".join(sql) - itags = "\", \"".join(itags) - itags = "\""+ itags+"\"" - sqlz = """with aaa as (SELECT %s, way FROM planet_osm_line where (%s) and (%s)), - bbb as (SELECT %s, way from aaa where way && !bbox! ) - select %s, ST_LineMerge(ST_Union(way)) as way from bbb group by %s - """%(itags,sqlz,ttext,itags,itags,itags) + itags = ", ".join(itags) + #itags = "\""+ itags+"\"" + sqlz = """select %s, ST_LineMerge(ST_Union(way)) as way from (SELECT * from planet_osm_line where way && !bbox! and (%s) and (%s)) as tex + group by %s + """%(itags,ttext,sqlz,oitags) mfile.write(xml_layer("postgis-process", layer_type, itags, sqlz )) else: sql = " OR ".join(sql) diff --git a/src/libkomapnik.py b/src/libkomapnik.py index 61db3d3..aaa64ff 100644 --- a/src/libkomapnik.py +++ b/src/libkomapnik.py @@ -188,8 +188,13 @@ def xml_layer(type="postgis", geom="point", interesting_tags = "*", sql = "true" subs = "\n".join(["s%s"%i for i in substyles]) substyles = [] if type == "postgis": - interesting_tags = "\", \"".join(interesting_tags) - interesting_tags = "\""+ interesting_tags+"\"" + interesting_tags = list(interesting_tags) + if '"' not in "".join(interesting_tags): + interesting_tags = "\", \"".join(interesting_tags) + interesting_tags = "\""+ interesting_tags+"\"" + else: + interesting_tags = ", ".join(interesting_tags) + return """