示例#1
0
文件: libkomwm.py 项目: rokuz/kothic
def komap_mapswithme(options):

    ddir = os.path.dirname(options.outfile)

    classificator = {}
    class_order = []
    class_tree = {}

    # Build classificator tree from mapcss-mapping.csv file
    types_file = open(os.path.join(ddir, 'types.txt'), "w")

    colors_file_name = os.path.join(ddir, 'colors.txt')
    colors = set()
    if os.path.exists(colors_file_name):
        colors_in_file = open(colors_file_name, "r")
        for colorLine in colors_in_file:
            colors.add(int(colorLine))
        colors_in_file.close()

    patterns = []
    def addPattern(dashes):
        if dashes and dashes not in patterns:
            patterns.append(dashes)

    patterns_file_name = os.path.join(ddir, 'patterns.txt')
    if os.path.exists(patterns_file_name):
        patterns_in_file = open(patterns_file_name, "r")
        for patternsLine in patterns_in_file:
            addPattern([float(x) for x in patternsLine.split()])
        patterns_in_file.close()

    for row in csv.reader(open(os.path.join(ddir, 'mapcss-mapping.csv')), delimiter=';'):
        cl = row[0].replace("|", "-")
        pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
        kv = {}
        for i in pairs:
            if len(i) == 1:
                if i[0]:
                    if i[0][0] == "!":
                        kv[i[0][1:].strip('?')] = "no"
                    else:
                        kv[i[0].strip('?')] = "yes"
            else:
                kv[i[0]] = i[1]
        classificator[cl] = kv
        if row[2] != "x":
            class_order.append(cl)
            print >> types_file, row[0]
        else:
            # compatibility mode
            if row[6]:
                print >> types_file, row[6]
            else:
                print >> types_file, "mapswithme"
        class_tree[cl] = row[0]
    class_order.sort()
    types_file.close()

    # Get all mapcss static tags which are used in mapcss-mapping.csv
    mapcss_static_tags = set()
    for v in classificator.values():
        for t in v.keys():
            mapcss_static_tags.add(t)

    # Get all mapcss dynamic tags from mapcss-dynamic.txt
    mapcss_dynamic_tags = set([line.rstrip() for line in open(os.path.join(ddir, 'mapcss-dynamic.txt'))])

    # Parse style mapcss
    style = MapCSS(options.minzoom, options.maxzoom + 1)
    style.parse(filename = options.filename, static_tags = mapcss_static_tags, dynamic_tags = mapcss_dynamic_tags)

    # Build optimization tree - class/type -> StyleChoosers
    for cl in class_order:
        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
        cltags = classificator[cl]
        style.build_choosers_tree(clname, "line", cltags)
        style.build_choosers_tree(clname, "area", cltags)
        style.build_choosers_tree(clname, "node", cltags)
    style.restore_choosers_order("line")
    style.restore_choosers_order("area")
    style.restore_choosers_order("node")

    visibility = {}

    bgpos = 0

    dr_linecaps = {'none': BUTTCAP, 'butt': BUTTCAP, 'round': ROUNDCAP}
    dr_linejoins = {'none': NOJOIN, 'bevel': BEVELJOIN, 'round': ROUNDJOIN}

    # Build drules tree

    drules = ContainerProto()

    for cl in class_order:

        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]

        cltags = classificator[cl]
        cltags["name"] = "name"
        cltags["addr:housenumber"] = "addr:housenumber"
        cltags["addr:housename"] = "addr:housename"
        cltags["ref"] = "ref"
        cltags["int_name"] = "int_name"
        cltags["addr:flats"] = "addr:flats"

        dr_cont = ClassifElementProto()
        dr_cont.name = cl

        visstring = ["0"] * (options.maxzoom - options.minzoom + 1)

        for zoom in xrange(options.minzoom, options.maxzoom + 1):

            runtime_conditions_arr = []

            # Get runtime conditions which are used for class 'cl' on zoom 'zoom'
            if "area" not in cltags:
                runtime_conditions_arr.extend( style.get_runtime_rules(clname, "line", cltags, zoom) )
            runtime_conditions_arr.extend( style.get_runtime_rules(clname, "area", cltags, zoom) )
            if "area" not in cltags:
                runtime_conditions_arr.extend( style.get_runtime_rules(clname, "node", cltags, zoom) )

            # If there is no any runtime conditions, do not filter style by runtime conditions
            if len(runtime_conditions_arr) == 0:
                runtime_conditions_arr.append(None)

            for runtime_conditions in runtime_conditions_arr:

                has_icons_for_areas = False
                zstyle = {}

                # Get style for class 'cl' on zoom 'zoom' with corresponding runtime conditions
                if "area" not in cltags:
                    linestyle = style.get_style_dict(clname, "line", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
                    zstyle = linestyle
                areastyle = style.get_style_dict(clname, "area", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
                for st in areastyle.values():
                    if "icon-image" in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons_for_areas = True
                        break
                zstyle = areastyle
                if "area" not in cltags:
                    nodestyle = style.get_style_dict(clname, "node", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
                    zstyle = nodestyle

                zstyle = zstyle.values()

                if len(zstyle) == 0:
                    continue

                has_lines = False
                has_icons = False
                has_fills = False
                for st in zstyle:
                    st = dict([(k, v) for k, v in st.iteritems() if str(v).strip(" 0.")])
                    if 'width' in st or 'pattern-image' in st:
                        has_lines = True
                    if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons = True
                    if 'fill-color' in st:
                        has_fills = True

                has_text = None
                txfmt = []
                for st in zstyle:
                    if st.get('text') and not st.get('text') in txfmt:
                        txfmt.append(st.get('text'))
                        if has_text is None:
                            has_text = []
                        has_text.append(st)

                if (not has_lines) and (not has_text) and (not has_fills) and (not has_icons):
                    continue

                visstring[zoom] = "1"

                dr_element = DrawElementProto()
                dr_element.scale = zoom

                if runtime_conditions:
                    for rc in runtime_conditions:
                        dr_element.apply_if.append(str(rc))

                for st in zstyle:
                    if st.get('-x-kot-layer') == 'top':
                        st['z-index'] = float(st.get('z-index', 0)) + 15001.
                    elif st.get('-x-kot-layer') == 'bottom':
                        st['z-index'] = float(st.get('z-index', 0)) - 15001.

                    if st.get('casing-width') not in (None, 0):  # and (st.get('width') or st.get('fill-color')):
                        if st.get('casing-linecap', 'butt') == 'butt':
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                            dr_line.color = mwm_encode_color(colors, st, "casing")
                            dr_line.priority = min(int(st.get('z-index', 0) + 999), 20000)
                            dashes = st.get('casing-dashes', st.get('dashes', []))
                            dr_line.dashdot.dd.extend(dashes)
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                            dr_element.lines.extend([dr_line])

                        # Let's try without this additional line style overhead. Needed only for casing in road endings.
                        # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt':
                        #     dr_line = LineRuleProto()
                        #     dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                        #     dr_line.color = mwm_encode_color(colors, st, "casing")
                        #     dr_line.priority = -15000
                        #     dashes = st.get('casing-dashes', st.get('dashes', []))
                        #     dr_line.dashdot.dd.extend(dashes)
                        #     dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP)
                        #     dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                        #     dr_element.lines.extend([dr_line])

                    if has_lines:
                        if st.get('width'):
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE)
                            dr_line.color = mwm_encode_color(colors, st)
                            for i in st.get('dashes', []):
                                dr_line.dashdot.dd.extend([max(float(i), 1) * WIDTH_SCALE])
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('linejoin', 'round'), ROUNDJOIN)
                            dr_line.priority = min((int(st.get('z-index', 0)) + 1000), 20000)
                            dr_element.lines.extend([dr_line])
                        if st.get('pattern-image'):
                            dr_line = LineRuleProto()
                            dr_line.width = 0
                            dr_line.color = 0
                            icon = mwm_encode_image(st, prefix='pattern')
                            dr_line.pathsym.name = icon[0]
                            dr_line.pathsym.step = float(st.get('pattern-spacing', 0)) - 16
                            dr_line.pathsym.offset = st.get('pattern-offset', 0)
                            dr_line.priority = int(st.get('z-index', 0)) + 1000
                            dr_element.lines.extend([dr_line])
                        if st.get('shield-font-size'):
                            dr_element.shield.height = int(st.get('shield-font-size', 10))
                            dr_element.shield.color = mwm_encode_color(colors, st, "shield-text")
                            if st.get('shield-text-halo-radius', 0) != 0:
                                dr_element.shield.stroke_color = mwm_encode_color(colors, st, "shield-text-halo", "white")
                            dr_element.shield.priority = min(19100, (16000 + int(st.get('z-index', 0))))

                    if has_icons:
                        if st.get('icon-image'):
                            if not has_icons_for_areas:
                                dr_element.symbol.apply_for_type = 1
                            icon = mwm_encode_image(st)
                            dr_element.symbol.name = icon[0]
                            dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0))))
                            has_icons = False
                        if st.get('symbol-shape'):
                            dr_element.circle.radius = float(st.get('symbol-size'))
                            dr_element.circle.color = mwm_encode_color(colors, st, 'symbol-fill')
                            dr_element.circle.priority = min(19000, (14000 + int(st.get('z-index', 0))))
                            has_icons = False

                    if has_text and st.get('text'):
                        has_text = has_text[:2]
                        has_text.reverse()
                        dr_text = dr_element.path_text
                        base_z = 15000
                        if st.get('text-position', 'center') == 'line':
                            dr_text = dr_element.path_text
                            base_z = 16000
                        else:
                            dr_text = dr_element.caption
                        for sp in has_text[:]:
                            dr_cur_subtext = dr_text.primary
                            if len(has_text) == 2:
                                dr_cur_subtext = dr_text.secondary
                            dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0]))
                            dr_cur_subtext.color = mwm_encode_color(colors, sp, "text")
                            if st.get('text-halo-radius', 0) != 0:
                                dr_cur_subtext.stroke_color = mwm_encode_color(colors, sp, "text-halo", "white")
                            if 'text-offset' in sp or 'text-offset-y' in sp:
                                dr_cur_subtext.offset_y = int(sp.get('text-offset-y', sp.get('text-offset', 0)))
                            if 'text-offset-x' in sp:
                                dr_cur_subtext.offset_x = int(sp.get('text-offset-x', 0))
                            if 'text' in sp and sp.get('text') != 'name':
                                dr_cur_subtext.text = sp.get('text')
                            has_text.pop()
                        dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0))))
                        has_text = None

                    if has_fills:
                        if ('fill-color' in st) and (float(st.get('fill-opacity', 1)) > 0):
                            dr_element.area.color = mwm_encode_color(colors, st, "fill")
                            if st.get('fill-position', 'foreground') == 'background':
                                if 'z-index' not in st:
                                    bgpos -= 1
                                    dr_element.area.priority = bgpos - 16000
                                else:
                                    zzz = int(st.get('z-index', 0))
                                    if zzz > 0:
                                        dr_element.area.priority = zzz - 16000
                                    else:
                                        dr_element.area.priority = zzz - 16700
                            else:
                                dr_element.area.priority = (int(st.get('z-index', 0)) + 1 + 1000)
                            has_fills = False

                dr_cont.element.extend([dr_element])

        if dr_cont.element:
            drules.cont.extend([dr_cont])

        visibility["world|" + class_tree[cl] + "|"] = "".join(visstring)

    # Write drules_proto.bin and drules_proto.txt files

    drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
    drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
    drules_bin.write(drules.SerializeToString())
    drules_txt.write(unicode(drules))
    drules_bin.close()
    drules_txt.close()

    # Write classificator.txt and visibility.txt files

    visnodes = set()
    for k, v in visibility.iteritems():
        vis = k.split("|")
        for i in range(1, len(vis) - 1):
            visnodes.add("|".join(vis[0:i]) + "|")
    viskeys = list(set(visibility.keys() + list(visnodes)))

    def cmprepl(a, b):
        if a == b:
            return 0
        a = a.replace("|", "-")
        b = b.replace("|", "-")
        if a > b:
            return 1
        return -1
    viskeys.sort(cmprepl)

    visibility_file = open(os.path.join(ddir, 'visibility.txt'), "w")
    classificator_file = open(os.path.join(ddir, 'classificator.txt'), "w")

    oldoffset = ""
    for k in viskeys:
        offset = "    " * (k.count("|") - 1)
        for i in range(len(oldoffset) / 4, len(offset) / 4, -1):
            print >> visibility_file, "    " * i + "{}"
            print >> classificator_file, "    " * i + "{}"
        oldoffset = offset
        end = "-"
        if k in visnodes:
            end = "+"
        print >> visibility_file, offset + k.split("|")[-2] + "  " + visibility.get(k, "0" * (options.maxzoom + 1)) + "  " + end
        print >> classificator_file, offset + k.split("|")[-2] + "  " + end
    for i in range(len(offset) / 4, 0, -1):
        print >> visibility_file, "    " * i + "{}"
        print >> classificator_file, "    " * i + "{}"

    visibility_file.close()
    classificator_file.close()

    colors_file = open(colors_file_name, "w")
    for c in sorted(colors):
        colors_file.write("%d\n" % (c))
    colors_file.close()

    patterns_file = open(patterns_file_name, "w")
    for p in patterns:
        patterns_file.write("%s\n" % (' '.join(str(elem) for elem in p)))
    patterns_file.close()
示例#2
0
def komap_mapswithme(options):
    ddir = os.path.dirname(options.outfile)

    classificator = {}
    class_order = []
    class_tree = {}

    colors_file_name = os.path.join(ddir, 'colors.txt')
    colors = set()
    if os.path.exists(colors_file_name):
        colors_in_file = open(colors_file_name, "r")
        for colorLine in colors_in_file:
            colors.add(int(colorLine))
        colors_in_file.close()

    patterns = []

    def addPattern(dashes):
        if dashes and dashes not in patterns:
            patterns.append(dashes)

    patterns_file_name = os.path.join(ddir, 'patterns.txt')
    if os.path.exists(patterns_file_name):
        patterns_in_file = open(patterns_file_name, "r")
        for patternsLine in patterns_in_file:
            addPattern([float(x) for x in patternsLine.split()])
        patterns_in_file.close()

    # Build classificator tree from mapcss-mapping.csv file
    types_file = open(os.path.join(ddir, 'types.txt'), "w")

    cnt = 1
    for row in csv.reader(open(os.path.join(ddir, 'mapcss-mapping.csv')),
                          delimiter=';'):
        while int(row[5]) > cnt:
            print >> types_file, "mapswithme"
            cnt += 1
        cnt += 1
        cl = row[0].replace("|", "-")
        pairs = [
            i.strip(']').split("=") for i in row[1].split(',')[0].split('[')
        ]
        kv = {}
        for i in pairs:
            if len(i) == 1:
                if i[0]:
                    if i[0][0] == "!":
                        kv[i[0][1:].strip('?')] = "no"
                    else:
                        kv[i[0].strip('?')] = "yes"
            else:
                kv[i[0]] = i[1]
        classificator[cl] = kv
        if row[2] != "x":
            class_order.append(cl)
            print >> types_file, row[0]
        else:
            # compatibility mode
            if row[6]:
                print >> types_file, row[6]
            else:
                print >> types_file, "mapswithme"
        class_tree[cl] = row[0]
    class_order.sort()
    types_file.close()

    # Get all mapcss static tags which are used in mapcss-mapping.csv
    mapcss_static_tags = set()
    for v in classificator.values():
        for t in v.keys():
            mapcss_static_tags.add(t)

    # Get all mapcss dynamic tags from mapcss-dynamic.txt
    mapcss_dynamic_tags = set([
        line.rstrip()
        for line in open(os.path.join(ddir, 'mapcss-dynamic.txt'))
    ])

    # Parse style mapcss
    style = MapCSS(options.minzoom, options.maxzoom + 1)
    style.parse(filename=options.filename,
                static_tags=mapcss_static_tags,
                dynamic_tags=mapcss_dynamic_tags)

    # Build optimization tree - class/type -> StyleChoosers
    for cl in class_order:
        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
        cltags = classificator[cl]
        style.build_choosers_tree(clname, "line", cltags)
        style.build_choosers_tree(clname, "area", cltags)
        style.build_choosers_tree(clname, "node", cltags)
    style.restore_choosers_order("line")
    style.restore_choosers_order("area")
    style.restore_choosers_order("node")

    visibility = {}

    bgpos = 0

    dr_linecaps = {'none': BUTTCAP, 'butt': BUTTCAP, 'round': ROUNDCAP}
    dr_linejoins = {'none': NOJOIN, 'bevel': BEVELJOIN, 'round': ROUNDJOIN}

    # Build drules tree

    drules = ContainerProto()

    for cl in class_order:

        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]

        cltags = classificator[cl]
        cltags["name"] = "name"
        cltags["addr:housenumber"] = "addr:housenumber"
        cltags["addr:housename"] = "addr:housename"
        cltags["ref"] = "ref"
        cltags["int_name"] = "int_name"
        cltags["addr:flats"] = "addr:flats"

        dr_cont = ClassifElementProto()
        dr_cont.name = cl

        visstring = ["0"] * (options.maxzoom - options.minzoom + 1)

        for zoom in xrange(options.minzoom, options.maxzoom + 1):

            runtime_conditions_arr = []

            # Get runtime conditions which are used for class 'cl' on zoom 'zoom'
            if "area" not in cltags:
                runtime_conditions_arr.extend(
                    style.get_runtime_rules(clname, "line", cltags, zoom))
            runtime_conditions_arr.extend(
                style.get_runtime_rules(clname, "area", cltags, zoom))
            if "area" not in cltags:
                runtime_conditions_arr.extend(
                    style.get_runtime_rules(clname, "node", cltags, zoom))

            # If there is no any runtime conditions, do not filter style by runtime conditions
            if len(runtime_conditions_arr) == 0:
                runtime_conditions_arr.append(None)

            for runtime_conditions in runtime_conditions_arr:

                has_icons_for_areas = False
                zstyle = {}

                # Get style for class 'cl' on zoom 'zoom' with corresponding runtime conditions
                if "area" not in cltags:
                    linestyle = style.get_style_dict(
                        clname,
                        "line",
                        cltags,
                        zoom,
                        olddict=zstyle,
                        filter_by_runtime_conditions=runtime_conditions)
                    zstyle = linestyle
                areastyle = style.get_style_dict(
                    clname,
                    "area",
                    cltags,
                    zoom,
                    olddict=zstyle,
                    filter_by_runtime_conditions=runtime_conditions)
                for st in areastyle.values():
                    if "icon-image" in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons_for_areas = True
                        break
                zstyle = areastyle
                if "area" not in cltags:
                    nodestyle = style.get_style_dict(
                        clname,
                        "node",
                        cltags,
                        zoom,
                        olddict=zstyle,
                        filter_by_runtime_conditions=runtime_conditions)
                    zstyle = nodestyle

                zstyle = zstyle.values()

                if len(zstyle) == 0:
                    continue

                has_lines = False
                has_icons = False
                has_fills = False
                for st in zstyle:
                    st = dict([(k, v) for k, v in st.iteritems()
                               if str(v).strip(" 0.")])
                    if 'width' in st or 'pattern-image' in st:
                        has_lines = True
                    if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons = True
                    if 'fill-color' in st:
                        has_fills = True

                has_text = None
                txfmt = []
                for st in zstyle:
                    if st.get('text') and st.get(
                            'text') != 'none' and not st.get('text') in txfmt:
                        txfmt.append(st.get('text'))
                        if has_text is None:
                            has_text = []
                        has_text.append(st)

                if (not has_lines) and (not has_text) and (not has_fills) and (
                        not has_icons):
                    continue

                visstring[zoom] = "1"

                dr_element = DrawElementProto()
                dr_element.scale = zoom

                if runtime_conditions:
                    for rc in runtime_conditions:
                        dr_element.apply_if.append(str(rc))

                for st in zstyle:
                    if st.get('-x-kot-layer') == 'top':
                        st['z-index'] = float(st.get('z-index', 0)) + 15001.
                    elif st.get('-x-kot-layer') == 'bottom':
                        st['z-index'] = float(st.get('z-index', 0)) - 15001.

                    if st.get('casing-width') not in (
                            None, 0
                    ):  # and (st.get('width') or st.get('fill-color')):
                        if st.get('casing-linecap', 'butt') == 'butt':
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE
                                             ) + (st.get('casing-width') *
                                                  WIDTH_SCALE * 2)
                            dr_line.color = mwm_encode_color(
                                colors, st, "casing")
                            if '-x-me-casing-line-priority' in st:
                                dr_line.priority = int(
                                    st.get('-x-me-casing-line-priority'))
                            else:
                                dr_line.priority = min(
                                    int(st.get('z-index', 0) + 999), 20000)
                            dashes = st.get('casing-dashes',
                                            st.get('dashes', []))
                            dr_line.dashdot.dd.extend(dashes)
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(
                                st.get('casing-linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(
                                st.get('casing-linejoin', 'round'), ROUNDJOIN)
                            dr_element.lines.extend([dr_line])

                        # Let's try without this additional line style overhead. Needed only for casing in road endings.
                        # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt':
                        #     dr_line = LineRuleProto()
                        #     dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                        #     dr_line.color = mwm_encode_color(colors, st, "casing")
                        #     dr_line.priority = -15000
                        #     dashes = st.get('casing-dashes', st.get('dashes', []))
                        #     dr_line.dashdot.dd.extend(dashes)
                        #     dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP)
                        #     dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                        #     dr_element.lines.extend([dr_line])

                    if has_lines:
                        if st.get('width'):
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE)
                            dr_line.color = mwm_encode_color(colors, st)
                            for i in st.get('dashes', []):
                                dr_line.dashdot.dd.extend(
                                    [max(float(i), 1) * WIDTH_SCALE])
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(
                                st.get('linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(
                                st.get('linejoin', 'round'), ROUNDJOIN)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(
                                    st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = min(
                                    (int(st.get('z-index', 0)) + 1000), 20000)
                            dr_element.lines.extend([dr_line])
                        if st.get('pattern-image'):
                            dr_line = LineRuleProto()
                            dr_line.width = 0
                            dr_line.color = 0
                            icon = mwm_encode_image(st, prefix='pattern')
                            dr_line.pathsym.name = icon[0]
                            dr_line.pathsym.step = float(
                                st.get('pattern-spacing', 0)) - 16
                            dr_line.pathsym.offset = st.get(
                                'pattern-offset', 0)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(
                                    st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = int(st.get('z-index',
                                                              0)) + 1000
                            dr_element.lines.extend([dr_line])
                        if st.get('shield-font-size'):
                            dr_element.shield.height = int(
                                st.get('shield-font-size', 10))
                            dr_element.shield.color = mwm_encode_color(
                                colors, st, "shield-text")
                            if st.get('shield-text-halo-radius', 0) != 0:
                                dr_element.shield.stroke_color = mwm_encode_color(
                                    colors, st, "shield-text-halo", "white")
                            if '-x-me-shield-priority' in st:
                                dr_element.shield.priority = int(
                                    st.get('-x-me-shield-priority'))
                            else:
                                dr_element.shield.priority = min(
                                    19100, (16000 + int(st.get('z-index', 0))))
                            if st.get('shield-min-distance', 0) != 0:
                                dr_element.shield.min_distance = int(
                                    st.get('shield-min-distance', 0))

                    if has_icons:
                        if st.get('icon-image'):
                            if not has_icons_for_areas:
                                dr_element.symbol.apply_for_type = 1
                            icon = mwm_encode_image(st)
                            dr_element.symbol.name = icon[0]
                            if '-x-me-icon-priority' in st:
                                dr_element.symbol.priority = int(
                                    st.get('-x-me-icon-priority'))
                            else:
                                dr_element.symbol.priority = min(
                                    19100, (16000 + int(st.get('z-index', 0))))
                            if 'icon-min-distance' in st:
                                dr_element.symbol.min_distance = int(
                                    st.get('icon-min-distance', 0))
                            has_icons = False
                        if st.get('symbol-shape'):
                            dr_element.circle.radius = float(
                                st.get('symbol-size'))
                            dr_element.circle.color = mwm_encode_color(
                                colors, st, 'symbol-fill')
                            if '-x-me-symbol-priority' in st:
                                dr_element.circle.priority = int(
                                    st.get('-x-me-symbol-priority'))
                            else:
                                dr_element.circle.priority = min(
                                    19000, (14000 + int(st.get('z-index', 0))))
                            has_icons = False

                    if has_text and st.get(
                            'text') and st.get('text') != 'none':
                        has_text = has_text[:2]
                        has_text.reverse()
                        dr_text = dr_element.path_text
                        base_z = 15000
                        if st.get('text-position', 'center') == 'line':
                            dr_text = dr_element.path_text
                            base_z = 16000
                        else:
                            dr_text = dr_element.caption
                        for sp in has_text[:]:
                            dr_cur_subtext = dr_text.primary
                            if len(has_text) == 2:
                                dr_cur_subtext = dr_text.secondary
                            dr_cur_subtext.height = int(
                                float(sp.get('font-size', "10").split(",")[0]))
                            dr_cur_subtext.color = mwm_encode_color(
                                colors, sp, "text")
                            if st.get('text-halo-radius', 0) != 0:
                                dr_cur_subtext.stroke_color = mwm_encode_color(
                                    colors, sp, "text-halo", "white")
                            if 'text-offset' in sp or 'text-offset-y' in sp:
                                dr_cur_subtext.offset_y = int(
                                    sp.get('text-offset-y',
                                           sp.get('text-offset', 0)))
                            if 'text-offset-x' in sp:
                                dr_cur_subtext.offset_x = int(
                                    sp.get('text-offset-x', 0))
                            if 'text' in sp and sp.get('text') != 'name':
                                dr_cur_subtext.text = sp.get('text')
                            if 'text-optional' in sp:
                                is_valid, value = to_boolean(
                                    sp.get('text-optional', ''))
                                if is_valid:
                                    dr_cur_subtext.is_optional = value
                            has_text.pop()
                        if '-x-me-text-priority' in st:
                            dr_text.priority = int(
                                st.get('-x-me-text-priority'))
                        else:
                            dr_text.priority = min(
                                19000, (base_z + int(st.get('z-index', 0))))
                        has_text = None

                    if has_fills:
                        if ('fill-color' in st) and (float(
                                st.get('fill-opacity', 1)) > 0):
                            dr_element.area.color = mwm_encode_color(
                                colors, st, "fill")
                            priority = 0
                            if st.get('fill-position',
                                      'foreground') == 'background':
                                if 'z-index' not in st:
                                    bgpos -= 1
                                    priority = bgpos - 16000
                                else:
                                    zzz = int(st.get('z-index', 0))
                                    if zzz > 0:
                                        priority = zzz - 16000
                                    else:
                                        priority = zzz - 16700
                            else:
                                priority = (int(st.get('z-index', 0)) + 1 +
                                            1000)
                            if '-x-me-area-priority' in st:
                                dr_element.area.priority = int(
                                    st.get('-x-me-area-priority'))
                            else:
                                dr_element.area.priority = priority
                            has_fills = False

                dr_cont.element.extend([dr_element])

        if dr_cont.element:
            drules.cont.extend([dr_cont])

        visibility["world|" + class_tree[cl] + "|"] = "".join(visstring)

    # Write drules_proto.bin and drules_proto.txt files

    drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
    drules_bin.write(drules.SerializeToString())
    drules_bin.close()

    if options.txt:
        drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
        drules_txt.write(unicode(drules))
        drules_txt.close()

    # Write classificator.txt and visibility.txt files

    visnodes = set()
    for k, v in visibility.iteritems():
        vis = k.split("|")
        for i in range(1, len(vis) - 1):
            visnodes.add("|".join(vis[0:i]) + "|")
    viskeys = list(set(visibility.keys() + list(visnodes)))

    def cmprepl(a, b):
        if a == b:
            return 0
        a = a.replace("|", "-")
        b = b.replace("|", "-")
        if a > b:
            return 1
        return -1

    viskeys.sort(cmprepl)

    visibility_file = open(os.path.join(ddir, 'visibility.txt'), "w")
    classificator_file = open(os.path.join(ddir, 'classificator.txt'), "w")

    oldoffset = ""
    for k in viskeys:
        offset = "    " * (k.count("|") - 1)
        for i in range(len(oldoffset) / 4, len(offset) / 4, -1):
            print >> visibility_file, "    " * i + "{}"
            print >> classificator_file, "    " * i + "{}"
        oldoffset = offset
        end = "-"
        if k in visnodes:
            end = "+"
        print >> visibility_file, offset + k.split(
            "|")[-2] + "  " + visibility.get(
                k, "0" * (options.maxzoom + 1)) + "  " + end
        print >> classificator_file, offset + k.split("|")[-2] + "  " + end
    for i in range(len(offset) / 4, 0, -1):
        print >> visibility_file, "    " * i + "{}"
        print >> classificator_file, "    " * i + "{}"

    visibility_file.close()
    classificator_file.close()

    colors_file = open(colors_file_name, "w")
    for c in sorted(colors):
        colors_file.write("%d\n" % (c))
    colors_file.close()

    patterns_file = open(patterns_file_name, "w")
    for p in patterns:
        patterns_file.write("%s\n" % (' '.join(str(elem) for elem in p)))
    patterns_file.close()
示例#3
0
def komap_mapswithme(options):
    if options.data and os.path.isdir(options.data):
        ddir = options.data
    else:
        ddir = os.path.dirname(options.outfile)

    classificator = {}
    class_order = []
    class_tree = {}

    colors_file_name = os.path.join(ddir, 'colors.txt')
    colors = set()
    if os.path.exists(colors_file_name):
        colors_in_file = open(colors_file_name, "r")
        for colorLine in colors_in_file:
            colors.add(int(colorLine))
        colors_in_file.close()

    patterns = []
    def addPattern(dashes):
        if dashes and dashes not in patterns:
            patterns.append(dashes)

    patterns_file_name = os.path.join(ddir, 'patterns.txt')
    if os.path.exists(patterns_file_name):
        patterns_in_file = open(patterns_file_name, "r")
        for patternsLine in patterns_in_file:
            addPattern([float(x) for x in patternsLine.split()])
        patterns_in_file.close()

    # Build classificator tree from mapcss-mapping.csv file
    types_file = open(os.path.join(ddir, 'types.txt'), "w")

    # Mapcss-mapping format
    #
    # A CSV table mapping tags to types. Some types can be deemed obsolete, either completely or replaced with a different type.
    #
    # Example row: highway|bus_stop;[highway=bus_stop];;name;int_name;22; (mind the last semicolon!)
    # It contains:
    # - type name: "highway|bus_stop" ('|' is converted to '-' internally)
    # - mapcss selector for tags: "[highway=bus_stop]" (you can group selectors and use e.g. [oneway?])
    # - "x" for an obsolete type or an empty cell otherwise
    # - primary title tag (usually "name")
    # - secondary title tag (usually "int_name")
    # - type id, sequential starting from 1
    # - replacement type for an obsolete tag, if exists
    #
    # A shorter format for above example: highway|bus_stop;22;
    # It leaves only columns 1, 6 and 7. For obsolete types with no replacement put "x" into the last column.
    # Obviously it works only for simple types that are produced from tags replacing '=' with '|'.
    #
    # An example of type with replacement:
    # highway|unsurfaced|disused;[highway=unsurfaced][disused?];x;name;int_name;838;highway|unclassified

    cnt = 1
    unique_types_check = set()
    for row in csv.reader(open(os.path.join(ddir, 'mapcss-mapping.csv')), delimiter=';'):
        if len(row) <= 1:
            # Allow for empty lines and comments that do not contain ';' symbol
            continue
        if len(row) == 3:
            # Short format: type name, type id, x / replacement type name
            tag = row[0].replace('|', '=')
            obsolete = len(row[2].strip()) > 0
            row = (row[0], '[{0}]'.format(tag), 'x' if obsolete else '', 'name', 'int_name', row[1], row[2] if row[2] != 'x' else '')
        if len(row) != 7:
            raise Exception('Expecting 3 or 7 columns in mapcss-mapping: {0}'.format(';'.join(row)))

        if int(row[5]) < cnt:
            raise Exception('Wrong type id: {0}'.format(';'.join(row)))
        while int(row[5]) > cnt:
            print("mapswithme", file=types_file)
            cnt += 1
        cnt += 1

        cl = row[0].replace("|", "-")
        if cl in unique_types_check and row[2] != 'x':
            raise Exception('Duplicate type: {0}'.format(row[0]))
        pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
        kv = OrderedDict()
        for i in pairs:
            if len(i) == 1:
                if i[0]:
                    if i[0][0] == "!":
                        kv[i[0][1:].strip('?')] = "no"
                    else:
                        kv[i[0].strip('?')] = "yes"
            else:
                kv[i[0]] = i[1]
        if row[2] != "x":
            classificator[cl] = kv
            class_order.append(cl)
            unique_types_check.add(cl)
            # Mark original type to distinguish it among replacing types.
            print("*" + row[0], file=types_file)
        else:
            # compatibility mode
            if row[6]:
                print(row[6], file=types_file)
            else:
                print("mapswithme", file=types_file)
        class_tree[cl] = row[0]
    class_order.sort()
    types_file.close()

    # Get all mapcss static tags which are used in mapcss-mapping.csv
    # This is a dict with main_tag flags (True = appears first in types)
    mapcss_static_tags = {}
    for v in list(classificator.values()):
        for i, t in enumerate(v.keys()):
            mapcss_static_tags[t] = mapcss_static_tags.get(t, True) and i == 0

    # Get all mapcss dynamic tags from mapcss-dynamic.txt
    mapcss_dynamic_tags = set([line.rstrip() for line in open(os.path.join(ddir, 'mapcss-dynamic.txt'))])

    # Parse style mapcss
    global style
    style = MapCSS(options.minzoom, options.maxzoom + 1)
    style.parse(filename=options.filename, static_tags=mapcss_static_tags,
                dynamic_tags=mapcss_dynamic_tags)

    # Build optimization tree - class/type -> StyleChoosers
    for cl in class_order:
        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
        cltags = classificator[cl]
        style.build_choosers_tree(clname, "line", cltags)
        style.build_choosers_tree(clname, "area", cltags)
        style.build_choosers_tree(clname, "node", cltags)
    style.restore_choosers_order("line")
    style.restore_choosers_order("area")
    style.restore_choosers_order("node")

    # Get colors section from style
    style_colors = {}
    raw_style_colors = style.get_colors()
    if raw_style_colors is not None:
        unique_style_colors = set()
        for k in list(raw_style_colors.keys()):
            unique_style_colors.add(k[:k.rindex('-')])
        for k in unique_style_colors:
            style_colors[k] = mwm_encode_color(colors, raw_style_colors, k)

    visibility = {}

    bgpos = 0

    dr_linecaps = {'none': BUTTCAP, 'butt': BUTTCAP, 'round': ROUNDCAP}
    dr_linejoins = {'none': NOJOIN, 'bevel': BEVELJOIN, 'round': ROUNDJOIN}

    # Build drules tree

    drules = ContainerProto()
    dr_cont = None
    if MULTIPROCESSING:
        pool = Pool()
        imapfunc = pool.imap
    else:
        imapfunc = itertools.imap

    if style_colors:
        for k, v in style_colors.items():
            color_proto = ColorElementProto()
            color_proto.name = k
            color_proto.color = v
            color_proto.x = 0
            color_proto.y = 0
            drules.colors.value.extend([color_proto])

    all_draw_elements = set()

    for results in imapfunc(query_style, ((cl, classificator[cl], options.minzoom, options.maxzoom) for cl in class_order)):
        for result in results:
                cl, zoom, has_icons_for_areas, runtime_conditions, zstyle = result

                if dr_cont is not None and dr_cont.name != cl:
                    if dr_cont.element:
                        drules.cont.extend([dr_cont])
                    visibility["world|" + class_tree[dr_cont.name] + "|"] = "".join(visstring)
                    dr_cont = None

                if dr_cont is None:
                    dr_cont = ClassifElementProto()
                    dr_cont.name = cl

                    visstring = ["0"] * (options.maxzoom - options.minzoom + 1)

                if len(zstyle) == 0:
                    continue

                has_lines = False
                has_icons = False
                has_fills = False
                for st in zstyle:
                    st = dict([(k, v) for k, v in st.items() if str(v).strip(" 0.")])
                    if 'width' in st or 'pattern-image' in st:
                        has_lines = True
                    if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons = True
                    if 'fill-color' in st:
                        has_fills = True

                has_text = None
                txfmt = []
                for st in zstyle:
                    if st.get('text') and st.get('text') != 'none' and not st.get('text') in txfmt:
                        txfmt.append(st.get('text'))
                        if has_text is None:
                            has_text = []
                        has_text.append(st)

                if (not has_lines) and (not has_text) and (not has_fills) and (not has_icons):
                    continue

                visstring[zoom] = "1"

                dr_element = DrawElementProto()
                dr_element.scale = zoom

                if runtime_conditions:
                    for rc in runtime_conditions:
                        dr_element.apply_if.append(str(rc))

                for st in zstyle:
                    if st.get('-x-kot-layer') == 'top':
                        st['z-index'] = float(st.get('z-index', 0)) + 15001.
                    elif st.get('-x-kot-layer') == 'bottom':
                        st['z-index'] = float(st.get('z-index', 0)) - 15001.

                    if st.get('casing-width') not in (None, 0):  # and (st.get('width') or st.get('fill-color')):
                        if has_lines and st.get('casing-linecap', 'butt') == 'butt':
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                            dr_line.color = mwm_encode_color(colors, st, "casing")
                            if '-x-me-casing-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-casing-line-priority'))
                            else:
                                dr_line.priority = min(int(st.get('z-index', 0) + 999), 20000)
                            dashes = st.get('casing-dashes', st.get('dashes', []))
                            dr_line.dashdot.dd.extend(dashes)
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                            dr_element.lines.extend([dr_line])

                        if has_fills and 'fill-color' in st and float(st.get('fill-opacity', 1)) > 0:
                            dr_element.area.border.color = mwm_encode_color(colors, st, "casing")
                            dr_element.area.border.width = st.get('casing-width', 0) * WIDTH_SCALE
                            
                        # Let's try without this additional line style overhead. Needed only for casing in road endings.
                        # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt':
                        #     dr_line = LineRuleProto()
                        #     dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                        #     dr_line.color = mwm_encode_color(colors, st, "casing")
                        #     dr_line.priority = -15000
                        #     dashes = st.get('casing-dashes', st.get('dashes', []))
                        #     dr_line.dashdot.dd.extend(dashes)
                        #     dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP)
                        #     dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                        #     dr_element.lines.extend([dr_line])

                    if has_lines:
                        if st.get('width'):
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE)
                            dr_line.color = mwm_encode_color(colors, st)
                            for i in st.get('dashes', []):
                                dr_line.dashdot.dd.extend([max(float(i), 1) * WIDTH_SCALE])
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('linejoin', 'round'), ROUNDJOIN)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = min((int(st.get('z-index', 0)) + 1000), 20000)
                            dr_element.lines.extend([dr_line])
                        if st.get('pattern-image'):
                            dr_line = LineRuleProto()
                            dr_line.width = 0
                            dr_line.color = 0
                            icon = mwm_encode_image(st, prefix='pattern')
                            dr_line.pathsym.name = icon[0]
                            dr_line.pathsym.step = float(st.get('pattern-spacing', 0)) - 16
                            dr_line.pathsym.offset = st.get('pattern-offset', 0)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = int(st.get('z-index', 0)) + 1000
                            dr_element.lines.extend([dr_line])
                        if st.get('shield-font-size'):
                            dr_element.shield.height = int(st.get('shield-font-size', 10))
                            dr_element.shield.text_color = mwm_encode_color(colors, st, "shield-text")
                            if st.get('shield-text-halo-radius', 0) != 0:
                                dr_element.shield.text_stroke_color = mwm_encode_color(colors, st, "shield-text-halo", "white")
                            dr_element.shield.color = mwm_encode_color(colors, st, "shield")
                            if st.get('shield-outline-radius', 0) != 0:
                                dr_element.shield.stroke_color = mwm_encode_color(colors, st, "shield-outline", "white")
                            if '-x-me-shield-priority' in st:
                                dr_element.shield.priority = int(st.get('-x-me-shield-priority'))
                            else:
                                dr_element.shield.priority = min(19100, (16000 + int(st.get('z-index', 0))))
                            if st.get('shield-min-distance', 0) != 0:
                                dr_element.shield.min_distance = int(st.get('shield-min-distance', 0))

                    if has_icons:
                        if st.get('icon-image'):
                            if not has_icons_for_areas:
                                dr_element.symbol.apply_for_type = 1
                            icon = mwm_encode_image(st)
                            dr_element.symbol.name = icon[0]
                            if '-x-me-icon-priority' in st:
                                dr_element.symbol.priority = int(st.get('-x-me-icon-priority'))
                            else:
                                dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0))))
                            if 'icon-min-distance' in st:
                                dr_element.symbol.min_distance = int(st.get('icon-min-distance', 0))
                            has_icons = False
                        if st.get('symbol-shape'):
                            dr_element.circle.radius = float(st.get('symbol-size'))
                            dr_element.circle.color = mwm_encode_color(colors, st, 'symbol-fill')
                            if '-x-me-symbol-priority' in st:
                                dr_element.circle.priority = int(st.get('-x-me-symbol-priority'))
                            else:
                                dr_element.circle.priority = min(19000, (14000 + int(st.get('z-index', 0))))
                            has_icons = False

                    if has_text and st.get('text') and st.get('text') != 'none':
                        has_text = has_text[:2]
                        has_text.reverse()
                        dr_text = dr_element.path_text
                        base_z = 15000
                        if st.get('text-position', 'center') == 'line':
                            dr_text = dr_element.path_text
                            base_z = 16000
                        else:
                            dr_text = dr_element.caption
                        for sp in has_text[:]:
                            dr_cur_subtext = dr_text.primary
                            if len(has_text) == 2:
                                dr_cur_subtext = dr_text.secondary
                            dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0]))
                            dr_cur_subtext.color = mwm_encode_color(colors, sp, "text")
                            if st.get('text-halo-radius', 0) != 0:
                                dr_cur_subtext.stroke_color = mwm_encode_color(colors, sp, "text-halo", "white")
                            if 'text-offset' in sp or 'text-offset-y' in sp:
                                dr_cur_subtext.offset_y = int(sp.get('text-offset-y', sp.get('text-offset', 0)))
                            if 'text-offset-x' in sp:
                                dr_cur_subtext.offset_x = int(sp.get('text-offset-x', 0))
                            if 'text' in sp and sp.get('text') != 'name':
                                dr_cur_subtext.text = sp.get('text')
                            if 'text-optional' in sp:
                                is_valid, value = to_boolean(sp.get('text-optional', ''))
                                if is_valid:
                                    dr_cur_subtext.is_optional = value
                                else:
                                    dr_cur_subtext.is_optional = True
                            has_text.pop()
                        if '-x-me-text-priority' in st:
                            dr_text.priority = int(st.get('-x-me-text-priority'))
                        else:
                            dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0))))
                        has_text = None

                    if has_fills:
                        if ('fill-color' in st) and (float(st.get('fill-opacity', 1)) > 0):
                            dr_element.area.color = mwm_encode_color(colors, st, "fill")
                            priority = 0
                            if st.get('fill-position', 'foreground') == 'background':
                                if 'z-index' not in st:
                                    bgpos -= 1
                                    priority = bgpos - 16000
                                else:
                                    zzz = int(st.get('z-index', 0))
                                    if zzz > 0:
                                        priority = zzz - 16000
                                    else:
                                        priority = zzz - 16700
                            else:
                                priority = (int(st.get('z-index', 0)) + 1 + 1000)
                            if '-x-me-area-priority' in st:
                                dr_element.area.priority = int(st.get('-x-me-area-priority'))
                            else:
                                dr_element.area.priority = priority
                            has_fills = False

                str_dr_element = dr_cont.name + "/" + str(dr_element)
                if str_dr_element not in all_draw_elements:
                    all_draw_elements.add(str_dr_element)
                    dr_cont.element.extend([dr_element])

    if dr_cont is not None:
        if dr_cont.element:
            drules.cont.extend([dr_cont])

        visibility["world|" + class_tree[cl] + "|"] = "".join(visstring)

    # Write drules_proto.bin and drules_proto.txt files

    drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
    drules_bin.write(drules.SerializeToString())
    drules_bin.close()

    if options.txt:
        drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
        drules_txt.write(str(drules).encode())
        drules_txt.close()

    # Write classificator.txt and visibility.txt files

    visnodes = set()
    for k, v in visibility.items():
        vis = k.split("|")
        for i in range(1, len(vis) - 1):
            visnodes.add("|".join(vis[0:i]) + "|")
    viskeys = list(set(list(visibility.keys()) + list(visnodes)))

    def cmprepl(a, b):
        if a == b:
            return 0
        a = a.replace("|", "-")
        b = b.replace("|", "-")
        if a > b:
            return 1
        return -1
    viskeys.sort(key=functools.cmp_to_key(cmprepl))

    visibility_file = open(os.path.join(ddir, 'visibility.txt'), "w")
    classificator_file = open(os.path.join(ddir, 'classificator.txt'), "w")

    oldoffset = ""
    for k in viskeys:
        offset = "    " * (k.count("|") - 1)
        for i in range(int(len(oldoffset) / 4), int(len(offset) / 4), -1):
            print("    " * i + "{}", file=visibility_file)
            print("    " * i + "{}", file=classificator_file)
        oldoffset = offset
        end = "-"
        if k in visnodes:
            end = "+"
        print(offset + k.split("|")[-2] + "  " + visibility.get(k, "0" * (options.maxzoom + 1)) + "  " + end, file=visibility_file)
        print(offset + k.split("|")[-2] + "  " + end, file=classificator_file)
    for i in range(int(len(offset) / 4), 0, -1):
        print("    " * i + "{}", file=visibility_file)
        print("    " * i + "{}", file=classificator_file)

    visibility_file.close()
    classificator_file.close()

    colors_file = open(colors_file_name, "w")
    for c in sorted(colors):
        colors_file.write("%d\n" % (c))
    colors_file.close()

    patterns_file = open(patterns_file_name, "w")
    for p in patterns:
        patterns_file.write("%s\n" % (' '.join(str(elem) for elem in p)))
    patterns_file.close()
示例#4
0
文件: libkomwm.py 项目: mapsme/kothic
def komap_mapswithme(options):
    ddir = os.path.dirname(options.outfile)

    classificator = {}
    class_order = []
    class_tree = {}

    colors_file_name = os.path.join(ddir, 'colors.txt')
    colors = set()
    if os.path.exists(colors_file_name):
        colors_in_file = open(colors_file_name, "r")
        for colorLine in colors_in_file:
            colors.add(int(colorLine))
        colors_in_file.close()

    patterns = []
    def addPattern(dashes):
        if dashes and dashes not in patterns:
            patterns.append(dashes)

    patterns_file_name = os.path.join(ddir, 'patterns.txt')
    if os.path.exists(patterns_file_name):
        patterns_in_file = open(patterns_file_name, "r")
        for patternsLine in patterns_in_file:
            addPattern([float(x) for x in patternsLine.split()])
        patterns_in_file.close()

    # Build classificator tree from mapcss-mapping.csv file
    types_file = open(os.path.join(ddir, 'types.txt'), "w")

    # Mapcss-mapping format
    #
    # A CSV table mapping tags to types. Some types can be deemed obsolete, either completely or replaced with a different type.
    #
    # Example row: highway|bus_stop;[highway=bus_stop];;name;int_name;22; (mind the last semicolon!)
    # It contains:
    # - type name: "highway|bus_stop" ('|' is converted to '-' internally)
    # - mapcss selector for tags: "[highway=bus_stop]" (you can group selectors and use e.g. [oneway?])
    # - "x" for an obsolete type or an empty cell otherwise
    # - primary title tag (usually "name")
    # - secondary title tag (usually "int_name")
    # - type id, sequential starting from 1
    # - replacement type for an obsolete tag, if exists
    #
    # A shorter format for above example: highway|bus_stop;22;
    # It leaves only columns 1, 6 and 7. For obsolete types with no replacement put "x" into the last column.
    # Obviously it works only for simple types that are produced from tags replacing '=' with '|'.
    #
    # An example of type with replacement:
    # highway|unsurfaced|disused;[highway=unsurfaced][disused?];x;name;int_name;838;highway|unclassified

    cnt = 1
    unique_types_check = set()
    for row in csv.reader(open(os.path.join(ddir, 'mapcss-mapping.csv')), delimiter=';'):
        if len(row) <= 1:
            # Allow for empty lines and comments that do not contain ';' symbol
            continue
        if len(row) == 3:
            # Short format: type name, type id, x / replacement type name
            tag = row[0].replace('|', '=')
            obsolete = len(row[2].strip()) > 0
            row = (row[0], '[{0}]'.format(tag), 'x' if obsolete else '', 'name', 'int_name', row[1], row[2] if row[2] != 'x' else '')
        if len(row) != 7:
            raise Exception('Expecting 3 or 7 columns in mapcss-mapping: {0}'.format(';'.join(row)))

        if int(row[5]) < cnt:
            raise Exception('Wrong type id: {0}'.format(';'.join(row)))
        while int(row[5]) > cnt:
            print >> types_file, "mapswithme"
            cnt += 1
        cnt += 1

        cl = row[0].replace("|", "-")
        if cl in unique_types_check and row[2] != 'x':
            raise Exception('Duplicate type: {0}'.format(row[0]))
        pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
        kv = {}
        for i in pairs:
            if len(i) == 1:
                if i[0]:
                    if i[0][0] == "!":
                        kv[i[0][1:].strip('?')] = "no"
                    else:
                        kv[i[0].strip('?')] = "yes"
            else:
                kv[i[0]] = i[1]
        classificator[cl] = kv
        if row[2] != "x":
            class_order.append(cl)
            unique_types_check.add(cl)
            print >> types_file, row[0]
        else:
            # compatibility mode
            if row[6]:
                print >> types_file, row[6]
            else:
                print >> types_file, "mapswithme"
        class_tree[cl] = row[0]
    class_order.sort()
    types_file.close()

    # Get all mapcss static tags which are used in mapcss-mapping.csv
    mapcss_static_tags = set()
    for v in classificator.values():
        for t in v.keys():
            mapcss_static_tags.add(t)

    # Get all mapcss dynamic tags from mapcss-dynamic.txt
    mapcss_dynamic_tags = set([line.rstrip() for line in open(os.path.join(ddir, 'mapcss-dynamic.txt'))])

    # Parse style mapcss
    global style
    style = MapCSS(options.minzoom, options.maxzoom + 1)
    style.parse(filename = options.filename, static_tags = mapcss_static_tags, dynamic_tags = mapcss_dynamic_tags)

    # Build optimization tree - class/type -> StyleChoosers
    for cl in class_order:
        clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
        cltags = classificator[cl]
        style.build_choosers_tree(clname, "line", cltags)
        style.build_choosers_tree(clname, "area", cltags)
        style.build_choosers_tree(clname, "node", cltags)
    style.restore_choosers_order("line")
    style.restore_choosers_order("area")
    style.restore_choosers_order("node")

    visibility = {}

    bgpos = 0

    dr_linecaps = {'none': BUTTCAP, 'butt': BUTTCAP, 'round': ROUNDCAP}
    dr_linejoins = {'none': NOJOIN, 'bevel': BEVELJOIN, 'round': ROUNDJOIN}

    # Build drules tree

    drules = ContainerProto()
    dr_cont = None
    if MULTIPROCESSING:
        pool = Pool()
        imapfunc = pool.imap
    else:
        imapfunc = itertools.imap

    for results in imapfunc(query_style, ((cl, classificator[cl], options.minzoom, options.maxzoom) for cl in class_order)):
        for result in results:
                cl, zoom, has_icons_for_areas, runtime_conditions, zstyle = result

                if dr_cont is not None and dr_cont.name != cl:
                    if dr_cont.element:
                        drules.cont.extend([dr_cont])
                    visibility["world|" + class_tree[dr_cont.name] + "|"] = "".join(visstring)
                    dr_cont = None

                if dr_cont is None:
                    dr_cont = ClassifElementProto()
                    dr_cont.name = cl

                    visstring = ["0"] * (options.maxzoom - options.minzoom + 1)

                if len(zstyle) == 0:
                    continue

                has_lines = False
                has_icons = False
                has_fills = False
                for st in zstyle:
                    st = dict([(k, v) for k, v in st.iteritems() if str(v).strip(" 0.")])
                    if 'width' in st or 'pattern-image' in st:
                        has_lines = True
                    if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
                        has_icons = True
                    if 'fill-color' in st:
                        has_fills = True

                has_text = None
                txfmt = []
                for st in zstyle:
                    if st.get('text') and st.get('text') != 'none' and not st.get('text') in txfmt:
                        txfmt.append(st.get('text'))
                        if has_text is None:
                            has_text = []
                        has_text.append(st)

                if (not has_lines) and (not has_text) and (not has_fills) and (not has_icons):
                    continue

                visstring[zoom] = "1"

                dr_element = DrawElementProto()
                dr_element.scale = zoom

                if runtime_conditions:
                    for rc in runtime_conditions:
                        dr_element.apply_if.append(str(rc))

                for st in zstyle:
                    if st.get('-x-kot-layer') == 'top':
                        st['z-index'] = float(st.get('z-index', 0)) + 15001.
                    elif st.get('-x-kot-layer') == 'bottom':
                        st['z-index'] = float(st.get('z-index', 0)) - 15001.

                    if st.get('casing-width') not in (None, 0):  # and (st.get('width') or st.get('fill-color')):
                        if st.get('casing-linecap', 'butt') == 'butt':
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                            dr_line.color = mwm_encode_color(colors, st, "casing")
                            if '-x-me-casing-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-casing-line-priority'))
                            else:
                                dr_line.priority = min(int(st.get('z-index', 0) + 999), 20000)
                            dashes = st.get('casing-dashes', st.get('dashes', []))
                            dr_line.dashdot.dd.extend(dashes)
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                            dr_element.lines.extend([dr_line])

                        # Let's try without this additional line style overhead. Needed only for casing in road endings.
                        # if st.get('casing-linecap', st.get('linecap', 'round')) != 'butt':
                        #     dr_line = LineRuleProto()
                        #     dr_line.width = (st.get('width', 0) * WIDTH_SCALE) + (st.get('casing-width') * WIDTH_SCALE * 2)
                        #     dr_line.color = mwm_encode_color(colors, st, "casing")
                        #     dr_line.priority = -15000
                        #     dashes = st.get('casing-dashes', st.get('dashes', []))
                        #     dr_line.dashdot.dd.extend(dashes)
                        #     dr_line.cap = dr_linecaps.get(st.get('casing-linecap', 'round'), ROUNDCAP)
                        #     dr_line.join = dr_linejoins.get(st.get('casing-linejoin', 'round'), ROUNDJOIN)
                        #     dr_element.lines.extend([dr_line])

                    if has_lines:
                        if st.get('width'):
                            dr_line = LineRuleProto()
                            dr_line.width = (st.get('width', 0) * WIDTH_SCALE)
                            dr_line.color = mwm_encode_color(colors, st)
                            for i in st.get('dashes', []):
                                dr_line.dashdot.dd.extend([max(float(i), 1) * WIDTH_SCALE])
                            addPattern(dr_line.dashdot.dd)
                            dr_line.cap = dr_linecaps.get(st.get('linecap', 'butt'), BUTTCAP)
                            dr_line.join = dr_linejoins.get(st.get('linejoin', 'round'), ROUNDJOIN)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = min((int(st.get('z-index', 0)) + 1000), 20000)
                            dr_element.lines.extend([dr_line])
                        if st.get('pattern-image'):
                            dr_line = LineRuleProto()
                            dr_line.width = 0
                            dr_line.color = 0
                            icon = mwm_encode_image(st, prefix='pattern')
                            dr_line.pathsym.name = icon[0]
                            dr_line.pathsym.step = float(st.get('pattern-spacing', 0)) - 16
                            dr_line.pathsym.offset = st.get('pattern-offset', 0)
                            if '-x-me-line-priority' in st:
                                dr_line.priority = int(st.get('-x-me-line-priority'))
                            else:
                                dr_line.priority = int(st.get('z-index', 0)) + 1000
                            dr_element.lines.extend([dr_line])
                        if st.get('shield-font-size'):
                            dr_element.shield.height = int(st.get('shield-font-size', 10))
                            dr_element.shield.color = mwm_encode_color(colors, st, "shield-text")
                            if st.get('shield-text-halo-radius', 0) != 0:
                                dr_element.shield.stroke_color = mwm_encode_color(colors, st, "shield-text-halo", "white")
                            if '-x-me-shield-priority' in st:
                                dr_element.shield.priority = int(st.get('-x-me-shield-priority'))
                            else:
                                dr_element.shield.priority = min(19100, (16000 + int(st.get('z-index', 0))))
                            if st.get('shield-min-distance', 0) != 0:
                                dr_element.shield.min_distance = int(st.get('shield-min-distance', 0))

                    if has_icons:
                        if st.get('icon-image'):
                            if not has_icons_for_areas:
                                dr_element.symbol.apply_for_type = 1
                            icon = mwm_encode_image(st)
                            dr_element.symbol.name = icon[0]
                            if '-x-me-icon-priority' in st:
                                dr_element.symbol.priority = int(st.get('-x-me-icon-priority'))
                            else:
                                dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0))))
                            if 'icon-min-distance' in st:
                                dr_element.symbol.min_distance = int(st.get('icon-min-distance', 0))
                            has_icons = False
                        if st.get('symbol-shape'):
                            dr_element.circle.radius = float(st.get('symbol-size'))
                            dr_element.circle.color = mwm_encode_color(colors, st, 'symbol-fill')
                            if '-x-me-symbol-priority' in st:
                                dr_element.circle.priority = int(st.get('-x-me-symbol-priority'))
                            else:
                                dr_element.circle.priority = min(19000, (14000 + int(st.get('z-index', 0))))
                            has_icons = False

                    if has_text and st.get('text') and st.get('text') != 'none':
                        has_text = has_text[:2]
                        has_text.reverse()
                        dr_text = dr_element.path_text
                        base_z = 15000
                        if st.get('text-position', 'center') == 'line':
                            dr_text = dr_element.path_text
                            base_z = 16000
                        else:
                            dr_text = dr_element.caption
                        for sp in has_text[:]:
                            dr_cur_subtext = dr_text.primary
                            if len(has_text) == 2:
                                dr_cur_subtext = dr_text.secondary
                            dr_cur_subtext.height = int(float(sp.get('font-size', "10").split(",")[0]))
                            dr_cur_subtext.color = mwm_encode_color(colors, sp, "text")
                            if st.get('text-halo-radius', 0) != 0:
                                dr_cur_subtext.stroke_color = mwm_encode_color(colors, sp, "text-halo", "white")
                            if 'text-offset' in sp or 'text-offset-y' in sp:
                                dr_cur_subtext.offset_y = int(sp.get('text-offset-y', sp.get('text-offset', 0)))
                            if 'text-offset-x' in sp:
                                dr_cur_subtext.offset_x = int(sp.get('text-offset-x', 0))
                            if 'text' in sp and sp.get('text') != 'name':
                                dr_cur_subtext.text = sp.get('text')
                            if 'text-optional' in sp:
                                is_valid, value = to_boolean(sp.get('text-optional', ''))
                                if is_valid:
                                    dr_cur_subtext.is_optional = value
                            has_text.pop()
                        if '-x-me-text-priority' in st:
                            dr_text.priority = int(st.get('-x-me-text-priority'))
                        else:
                            dr_text.priority = min(19000, (base_z + int(st.get('z-index', 0))))
                        has_text = None

                    if has_fills:
                        if ('fill-color' in st) and (float(st.get('fill-opacity', 1)) > 0):
                            dr_element.area.color = mwm_encode_color(colors, st, "fill")
                            priority = 0
                            if st.get('fill-position', 'foreground') == 'background':
                                if 'z-index' not in st:
                                    bgpos -= 1
                                    priority = bgpos - 16000
                                else:
                                    zzz = int(st.get('z-index', 0))
                                    if zzz > 0:
                                        priority = zzz - 16000
                                    else:
                                        priority = zzz - 16700
                            else:
                                priority = (int(st.get('z-index', 0)) + 1 + 1000)
                            if '-x-me-area-priority' in st:
                                dr_element.area.priority = int(st.get('-x-me-area-priority'))
                            else:
                                dr_element.area.priority = priority
                            has_fills = False

                dr_cont.element.extend([dr_element])

    if dr_cont is not None:
        if dr_cont.element:
            drules.cont.extend([dr_cont])

        visibility["world|" + class_tree[cl] + "|"] = "".join(visstring)

    # Write drules_proto.bin and drules_proto.txt files

    drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
    drules_bin.write(drules.SerializeToString())
    drules_bin.close()

    if options.txt:
        drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
        drules_txt.write(unicode(drules))
        drules_txt.close()

    # Write classificator.txt and visibility.txt files

    visnodes = set()
    for k, v in visibility.iteritems():
        vis = k.split("|")
        for i in range(1, len(vis) - 1):
            visnodes.add("|".join(vis[0:i]) + "|")
    viskeys = list(set(visibility.keys() + list(visnodes)))

    def cmprepl(a, b):
        if a == b:
            return 0
        a = a.replace("|", "-")
        b = b.replace("|", "-")
        if a > b:
            return 1
        return -1
    viskeys.sort(cmprepl)

    visibility_file = open(os.path.join(ddir, 'visibility.txt'), "w")
    classificator_file = open(os.path.join(ddir, 'classificator.txt'), "w")

    oldoffset = ""
    for k in viskeys:
        offset = "    " * (k.count("|") - 1)
        for i in range(len(oldoffset) / 4, len(offset) / 4, -1):
            print >> visibility_file, "    " * i + "{}"
            print >> classificator_file, "    " * i + "{}"
        oldoffset = offset
        end = "-"
        if k in visnodes:
            end = "+"
        print >> visibility_file, offset + k.split("|")[-2] + "  " + visibility.get(k, "0" * (options.maxzoom + 1)) + "  " + end
        print >> classificator_file, offset + k.split("|")[-2] + "  " + end
    for i in range(len(offset) / 4, 0, -1):
        print >> visibility_file, "    " * i + "{}"
        print >> classificator_file, "    " * i + "{}"

    visibility_file.close()
    classificator_file.close()

    colors_file = open(colors_file_name, "w")
    for c in sorted(colors):
        colors_file.write("%d\n" % (c))
    colors_file.close()

    patterns_file = open(patterns_file_name, "w")
    for p in patterns:
        patterns_file.write("%s\n" % (' '.join(str(elem) for elem in p)))
    patterns_file.close()