WIP Rewrite mapcss files from pseudo-tags to OM types

Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
This commit is contained in:
Konstantin Pastbin 2023-09-19 21:46:46 +03:00
parent 2796db7ae3
commit de23971947
2 changed files with 112 additions and 46 deletions

View file

@ -461,6 +461,7 @@ def komap_mapswithme(options):
ddir = os.path.dirname(options.outfile)
classificator = {}
tags_to_cl = {}
class_order = []
class_tree = {}
@ -514,17 +515,26 @@ def komap_mapswithme(options):
raise Exception('Duplicate type: {0}'.format(row[0]))
pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
kv = OrderedDict()
match_tags = ''
for i in pairs:
if len(i) == 1:
if i[0]:
if i[0][0] == "!":
kv[i[0][1:].strip('?')] = "no"
# Skip match_tags.
else:
kv[i[0].strip('?')] = "yes"
match_tags += '[' + i[0] + ']'
else:
kv[i[0]] = i[1]
match_tags += '[' + i[0] + '=' + i[1] + ']'
if row[2] != "x":
classificator[cl] = kv
if match_tags not in tags_to_cl:
tags_to_cl[match_tags] = cl
else:
print(f'WARNING: not unique match_tags: {match_tags}={cl}, previous ={tags_to_cl[match_tags]}')
#tags_to_cl[row[1].split(',')[0]] = cl
class_order.append(cl)
unique_types_check.add(cl)
# Mark original type to distinguish it among replacing types.
@ -539,6 +549,28 @@ def komap_mapswithme(options):
class_order.sort()
types_file.close()
#pastk
#cl = 'leisure-track-area'
#print(cl, classificator[cl]) #OrderedDict([('leisure', 'track'), ('area', 'yes')])
#tags = '[leisure=track][area?]'
#print(tags, tags_to_cl[tags])
#tags = '[railway=rail][highspeed?]' #'[railway=rail][highspeed?][!service]'
#print(tags, tags_to_cl[tags])
# Manually-assisted conversions:
tags_to_cl['[place]'] = 'place'
tags_to_cl['[leisure]'] = 'leisure'
tags_to_cl['[waterway]'] = 'waterway'
tags_to_cl['[isoline]'] = 'isoline'
tags_to_cl['[sport]'] = 'sport'
tags_to_cl['[tourism]'] = 'tourism'
tags_to_cl['[craft]'] = 'craft'
tags_to_cl['[shop]'] = 'shop'
tags_to_cl['[highway]'] = 'highway'
tags_to_cl['[landuse=military][military=danger_area]'] = 'landuse-military-danger_area'
tags_to_cl['[railway=rail][bridge?]'] = 'railway-rail-bridge'
tags_to_cl['[railway=rail][tunnel?]'] = 'railway-rail-tunnel'
output = ''
for prio_range in prio_ranges.keys():
load_priorities(prio_range, options.priorities_path, unique_types_check, compress = False)
@ -560,9 +592,8 @@ def komap_mapswithme(options):
# Parse style mapcss
global style
style = MapCSS(options.minzoom, options.maxzoom)
style.parse(clamp=False, stretch=LAYER_PRIORITY_RANGE,
filename=options.filename, static_tags=mapcss_static_tags,
dynamic_tags=mapcss_dynamic_tags)
style.parse(filename=options.filename, static_tags=mapcss_static_tags,
dynamic_tags=mapcss_dynamic_tags, rewrite = True, tags_to_cl = tags_to_cl)
# Build optimization tree - class/zoom/type -> StyleChoosers
clname_cltag_unique = set()

View file

@ -32,8 +32,8 @@ CLASS = re.compile(r'([\.:]:?[*\w]+) \s* ', re.S | re.X)
#NOT_CLASS = re.compile(r'!([\.:]\w+) \s* ', re.S | re.X)
ZOOM = re.compile(r'\| \s* z([\d\-]+) \s* ', re.I | re.S | re.X)
GROUP = re.compile(r', \s* ', re.I | re.S | re.X)
CONDITION = re.compile(r'\[(.+?)\] \s* ', re.S | re.X)
OBJECT = re.compile(r'(\*|[\w]+) \s* ', re.S | re.X)
CONDITION = re.compile(r'\[(.+?)\] (\s*) ', re.S | re.X)
OBJECT = re.compile(r'(\*|[\w]+) (\s*) ', re.S | re.X)
DECLARATION = re.compile(r'\{(.*?)\} \s* ', re.S | re.X)
IMPORT = re.compile(r'@import\("(.+?)"\); \s* ', re.S | re.X)
VARIABLE_SET = re.compile(r'@([a-z][\w\d]*) \s* : \s* (.+?) \s* ; \s* ', re.S | re.X | re.I)
@ -211,7 +211,7 @@ class MapCSS():
raise Exception("Variable not found: " + str(format(name)))
return self.variables[name] if name in self.variables else m.group()
def parse(self, css=None, clamp=True, stretch=1000, filename=None, static_tags={}, dynamic_tags=set()):
def parse(self, css=None, filename=None, static_tags={}, dynamic_tags=set(), rewrite = False, tags_to_cl = {}):
"""
Parses MapCSS given as string
"""
@ -226,9 +226,24 @@ class MapCSS():
log = logging.getLogger('mapcss.parser')
previous = oNONE # what was the previous CSS word?
sc = StyleChooser(self.scalepair) # currently being assembled
full_condition = ''
stck = [] # filename, original, remained
stck = [] # filename, remained, original
stck.append([filename, css, css])
if rewrite:
out_file = open(stck[-1][0], 'w')
def rewrite_file(s):
if rewrite:
out_file.write(s)
def convert_to_cl(tags):
if tags in tags_to_cl:
#return tags # DEBUG To focus on non-matches only.
return '|' + tags_to_cl[tags]
# There is no OM type for this combination of tags. Have to migrate manually.
return '|' + tags + ' /*NO-TYPE-MATCH*/'
try:
while (len(stck) > 0):
css = stck[-1][1].lstrip() # remained
@ -240,28 +255,24 @@ class MapCSS():
if previous == oDECLARATION:
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)
cond = CLASS.match(css).groups()[0]
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
m = CLASS.match(css)
rewrite_file(m.group(0))
cond = m.group(1)
log.debug("class found: %s" % (cond))
css = CLASS.sub("", css, 1)
sc.addCondition(Condition('eq', ("::class", cond)))
previous = oCONDITION
## Not class - !.motorway, !.builtup, !:hover
#elif NOT_CLASS.match(css):
#if (previous == oDECLARATION):
#self.choosers.append(sc)
#sc = StyleChooser(self.scalepair)
#cond = NOT_CLASS.match(css).groups()[0]
#log.debug("not_class found: %s" % (cond))
#css = NOT_CLASS.sub("", css, 1)
#sc.addCondition(Condition('ne', ("::class", cond)))
#previous = oCONDITION
# Zoom
elif ZOOM.match(css):
if (previous != oOBJECT & previous != oCONDITION):
sc.newObject()
cond = ZOOM.match(css).groups()[0]
m = ZOOM.match(css)
rewrite_file(m.group(0))
cond = m.group(1)
log.debug("zoom found: %s" % (cond))
css = ZOOM.sub("", css, 1)
sc.addZoom(self.parseZoom(cond))
@ -269,6 +280,10 @@ class MapCSS():
# Grouping - just a comma
elif GROUP.match(css):
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file(GROUP.match(css).group(0))
css = GROUP.sub("", css, 1)
sc.newGroup()
had_main_tag = False
@ -283,12 +298,18 @@ class MapCSS():
if (previous != oOBJECT) and (previous != oZOOM) and (previous != oCONDITION):
sc.newObject()
had_main_tag = False
cond = CONDITION.match(css).groups()[0]
m = CONDITION.match(css)
cond = m.group(1)
c = parseCondition(cond)
tag = c.extract_tag()
tag_type = static_tags.get(tag, None)
if tag == "*" or tag_type is not None:
if tag_type and had_main_tag:
if rewrite:
if full_condition:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file('[' + cond + ']' + m.group(2))
if '!' in cond:
condType = 'ne'
cond = cond.replace('!', '')
@ -296,10 +317,17 @@ class MapCSS():
condType = 'eq'
sc.addRuntimeCondition(Condition(condType, ('extra_tag', cond)))
else:
if rewrite:
full_condition += '[' + cond + ']'
sc.addCondition(c)
if tag_type:
had_main_tag = True
elif tag in dynamic_tags:
if rewrite:
if full_condition:
rewrite_file(convert_to_cl(full_condition))
full_condition = ''
rewrite_file('[' + cond + ']' + m.group(2))
sc.addRuntimeCondition(c)
else:
raise Exception("Unknown tag '" + tag + "' in condition " + cond)
@ -308,10 +336,15 @@ class MapCSS():
# Object - way, node, relation
elif OBJECT.match(css):
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition) + ',\n')
full_condition = ''
if (previous == oDECLARATION):
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)
obj = OBJECT.match(css).groups()[0]
m = OBJECT.match(css)
obj = m.group(1)
rewrite_file(obj + m.group(2))
log.debug("object found: %s" % (obj))
css = OBJECT.sub("", css, 1)
sc.newObject(obj)
@ -320,9 +353,16 @@ class MapCSS():
# Declaration - {...}
elif DECLARATION.match(css):
#previous = oGROUP
if full_condition and previous == oCONDITION:
rewrite_file(convert_to_cl(full_condition) + '\n')
#rewrite_file(convert_to_cl(full_condition) + ',\n')
full_condition = ''
if previous == oDECLARATION or previous == oNONE:
raise Exception("Declaration without conditions")
decl = DECLARATION.match(css).groups()[0]
m = DECLARATION.match(css)
rewrite_file(m.group(0))
decl = m.group(1)
log.debug("declaration found: %s" % (decl))
sc.addStyles(self.subst_variables(parseDeclaration(decl)))
css = DECLARATION.sub("", css, 1)
@ -331,17 +371,23 @@ class MapCSS():
# CSS comment
elif COMMENT.match(css):
log.debug("comment found")
rewrite_file(COMMENT.match(css).group(0))
css = COMMENT.sub("", css, 1)
# @import("filename.css");
elif IMPORT.match(css):
m = IMPORT.match(css)
rewrite_file(m.group(0))
log.debug("import found")
import_filename = os.path.join(basepath, IMPORT.match(css).groups()[0])
import_filename = os.path.join(basepath, m.group(1))
try:
css = IMPORT.sub("", css, 1)
import_text = open(import_filename, "r").read()
stck[-1][1] = css # store remained part
stck.append([import_filename, import_text, import_text])
if rewrite:
out_file.close()
out_file = open(stck[-1][0], 'w')
wasBroken = True
break
except IOError as e:
@ -349,9 +395,11 @@ class MapCSS():
# Variables
elif VARIABLE_SET.match(css):
name = VARIABLE_SET.match(css).groups()[0]
m = VARIABLE_SET.match(css)
rewrite_file(m.group(0))
name = m.group(1)
log.debug("variable set found: %s" % name)
self.variables[name] = VARIABLE_SET.match(css).groups()[1]
self.variables[name] = m.group(2)
css = VARIABLE_SET.sub("", css, 1)
previous = oVARIABLE_SET
@ -367,11 +415,18 @@ class MapCSS():
if not wasBroken:
stck.pop()
if rewrite:
out_file.close()
if (len(stck) > 0):
out_file = open(stck[-1][0], 'a')
if (previous == oDECLARATION):
self.choosers.append(sc)
sc = StyleChooser(self.scalepair)
if rewrite:
out_file.close()
except Exception as e:
filename = stck[-1][0] # filename
css_orig = stck[-1][2] # original
@ -380,26 +435,6 @@ class MapCSS():
msg = str(e) + "\nFile: " + filename + "\nLine: " + str(line)
raise Exception(msg)
try:
if clamp:
"clamp z-indexes, so they're tightly following integers"
zindex = set()
for chooser in self.choosers:
for stylez in chooser.styles:
zindex.add(float(stylez.get('z-index', 0)))
zindex = list(zindex)
zindex.sort()
for chooser in self.choosers:
for stylez in chooser.styles:
if 'z-index' in stylez:
res = zindex.index(float(stylez.get('z-index', 0)))
if stretch:
stylez['z-index'] = stretch * res / len(zindex)
else:
stylez['z-index'] = res
except TypeError:
pass
for chooser in self.choosers:
for t in chooser.compatible_types:
if t not in self.choosers_by_type: