fix Umap marker Icon rendering to work with both .fr and .de servers

pull/106/head
Hartmut Holzgraefe 2023-11-23 11:32:01 +00:00
rodzic 1c4e28fcb6
commit ac4e730a5a
2 zmienionych plików z 88 dodań i 51 usunięć

Wyświetl plik

@ -37,6 +37,8 @@ import copy
from colour import Color
from jsonpath_ng import parse
from pprint import pformat
import validators
import glob
LOG = logging.getLogger('ocitysmap')
@ -79,7 +81,7 @@ def get_default_properties(json, umap_defaults, create_copy=True):
for path in ['$.properties.*', '$.properties._storage.*', '$._storage.*', '$.properties._storage_options.*', '$._storage_options.*', '$.properties._umap_options.*', '$._umap_options.*']:
for key,value in flattened(json, path).items():
if key in ['opacity', 'fillOpacity', 'weight', 'dashArray', 'iconClass', 'iconUrl']:
if key in ['name', 'opacity', 'fillOpacity', 'weight', 'dashArray', 'iconClass', 'iconUrl']:
if value == True:
value = 'yes'
umap_defaults[key] = value
@ -89,6 +91,13 @@ def get_default_properties(json, umap_defaults, create_copy=True):
if create_copy:
return umap_defaults
def _find_icon(basedir, basename):
for match in glob.glob("%s/%s*" % (basedir, basename)):
if os.path.isfile(match):
return match
return None
class UmapProcessor:
def __init__(self, umap_file):
fp = codecs.open(umap_file, 'r', 'utf-8-sig')
@ -131,7 +140,6 @@ class UmapProcessor:
except:
return None
class UmapStylesheet(Stylesheet):
def __init__(self, umap_file, tmpdir):
super().__init__()
@ -164,11 +172,16 @@ class UmapStylesheet(Stylesheet):
self.path = style_filename
def umap_preprocess(self, umap_file, tmpdir):
icon_dir = os.path.realpath(
maki_icon_dir = os.path.realpath(
os.path.join(
os.path.dirname(__file__),
'../../templates/umap/maki/icons'))
osmic_icon_dir = os.path.realpath(
os.path.join(
os.path.dirname(__file__),
'../../templates/umap/osmic'))
umap_defaults = {
'color' :'#0000ff',
'opacity' : 0.5,
@ -180,7 +193,8 @@ class UmapStylesheet(Stylesheet):
'stroke' : 'yes',
'name' : '',
'iconClass' : 'Square',
'iconUrl' : icon_dir + '/circle-15.svg',
'iconUrl' : maki_icon_dir + '/circle-15.svg',
'iconFill' : "white",
}
marker_offsets = {
@ -225,28 +239,21 @@ class UmapStylesheet(Stylesheet):
# now go over the actual geometry features in that layer
for feature in layer['features']:
try:
# feature properties override previous defaults
new_props = get_default_properties(feature, layer_defaults)
# POINT features require special handling as they actually
# usually represent a marker
if feature['geometry']['type'] == 'Point':
iconClass = layer_defaults['iconClass']
iconUrl = layer_defaults['iconUrl']
iconClass = new_props['iconClass']
iconUrl = new_props['iconUrl']
# if icon class is one of those used by Umap:
if iconClass in ['Square', 'Drop', 'Default']:
# check whether one of the default UMAP icons is used
# by known URL pattern, or external
m = re.match(r'/uploads/pictogram/(.*)-24(.*)\.png', iconUrl)
if m:
# known UMAP icon URL -> replace with local files on our server
new_props['iconUrl'] = icon_dir + '/' + m.group(1) + "-15.svg"
if m.group(2) == '':
new_props['iconFill'] = 'black'
else:
new_props['iconFill'] = 'white'
else:
if validators.url(iconUrl):
# external URL: use cached if present already,
# otherwise download it and cache for later re-use
if iconUrl in icon_cache:
@ -262,10 +269,30 @@ class UmapStylesheet(Stylesheet):
iconPath = os.path.realpath(iconFile.name)
except Exception as Argument:
LOG.exception("Could not get icon from URL %s" % iconUrl)
iconPath = icon_dir + '/circle-15.svg'
iconPath = maki_icon_dir + '/circle-15.svg'
new_props['iconUrl'] = iconPath
icon_cache[iconUrl] = iconPath
elif m := re.match(r'/uploads/pictogram/(.*)-24(.*)\.png', iconUrl):
# known UMAP icon URL -> replace with local files on our server
# there are different naming conventions
# the .fr server has basename-24.png for black maki icons
# and basename-24_1.png for white ones
# the .de server has basename-24_???????.png for black osmic icons
if m.group(2) == '':
new_props['iconUrl'] = maki_icon_dir + '/' + m.group(1) + "-15.svg"
new_props['iconFill'] = 'white'
elif m.group(2) == '_1':
new_props['iconUrl'] = maki_icon_dir + '/' + m.group(1) + "-15.svg"
new_props['iconFill'] = 'white'
else:
icon_path = _find_icon(osmic_icon_dir + "/*", m.group(1))
if icon_path is None:
icon_path = maki_icon_dir + '/circle-15.svg'
new_props['iconUrl'] = icon_path
new_props['iconFill'] = 'black'
elif len(iconUrl) < 10:
new_props['iconLabel'] = iconUrl
try:
new_props['offset'] = marker_offsets[iconClass]
@ -279,6 +306,8 @@ class UmapStylesheet(Stylesheet):
'properties' : new_props,
'geometry' : feature['geometry']
})
except Exception as Argument:
LOG.warning("Exception: %s" % Argument)
new_umap = {
'type' : 'FeatureCollection',

Wyświetl plik

@ -25,14 +25,22 @@
<Style name="point">
<Rule>
<!-- the marker outline -->
<Filter>[mapnik::geometry_type]=point</Filter>
<MarkersSymbolizer file="${basedir}/markers/[iconClass].svg" allow-overlap="true" transform='translate(0,[offset])' fill='[color]'/>
</Rule>
<Rule>
<!-- the marker symbol if given -->
<Filter>(not ([iconUrl] = null or [iconUrl] = '')) and ([mapnik::geometry_type]=point)</Filter>
<MarkersSymbolizer base="root" file="[iconUrl]" allow-overlap="true" transform='translate(0,-23)' fill='[iconFill]' width='20'/>
</Rule>
<Rule>
<!-- the in-marker text instead of an icon if given -->
<Filter>(not ([iconLabel] = null or [iconLabel] = '')) and ([mapnik::geometry_type]=point)</Filter>
<TextSymbolizer face-name="DejaVu Sans Book" size="10" placement="point" allow-overlap="true" dy="[offset]" fill="white" horizontal_alignment='middle' vertical_alignement='middle'>[iconLabel]</TextSymbolizer>
</Rule>
<Rule>
<!-- marker label under the actual marker -->
<Filter>(not ([name] = null or [name] = '')) and ([mapnik::geometry_type]=point)</Filter>
<TextSymbolizer face-name="DejaVu Sans Book" size="10" placement="point" allow-overlap="true" dy="10" halo-fill="white" halo-radius="1" fill="[color]">[name]</TextSymbolizer>
</Rule>