From a3b9493c57729681e85648a825eb1db777c3059e Mon Sep 17 00:00:00 2001 From: Nikita Litvin Date: Wed, 25 Sep 2019 05:21:09 +0300 Subject: [PATCH] genPOI: support polylines and filled-in polygons Add support for polyline POIs just like in the good ol' Google Maps days. See #883. The format after this commit is: { id, x, y, z, text, color, polyline/polygon: [{ x, y, z }, ...] } Optional properties: - common ones like "icon" and "hovertext" - "strokeColor" (string), - "fill" (boolean) - "weight" (integer) Docs not included. Largely based on PR #1536 by @jsmienk. Closes #1456, closes #1536, closes #1643. --- overviewer_core/aux_files/genPOI.py | 40 ++++++++++++++++------ overviewer_core/data/js_src/util.js | 39 ++++++++++++++++----- overviewer_core/data/web_assets/regions.js | 11 +++--- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/overviewer_core/aux_files/genPOI.py b/overviewer_core/aux_files/genPOI.py index 4b01268..e996429 100755 --- a/overviewer_core/aux_files/genPOI.py +++ b/overviewer_core/aux_files/genPOI.py @@ -418,18 +418,36 @@ def create_marker_from_filter_result(poi, result): else: # ...otherwise default to display text. d['hovertext'] = result['text'] - if 'polyline' in result and hasattr(result['polyline'], '__iter__'): - d['polyline'] = [] - for point in result['polyline']: - # point.copy() would work, but this validates better - d['polyline'].append(dict(x=point['x'], y=point['y'], z=point['z'])) - if isinstance(result['color'], str): - d['strokeColor'] = result['color'] + if "icon" in result: + d["icon"] = result['icon'] + if "createInfoWindow" in result: + d["createInfoWindow"] = result['createInfoWindow'] - if "icon" in result: - d["icon"] = result['icon'] - if "createInfoWindow" in result: - d["createInfoWindow"] = result['createInfoWindow'] + # Polylines and polygons + if ('polyline' in result and hasattr(result['polyline'], '__iter__')) or \ + 'polygon' in result and hasattr(result['polygon'], '__iter__'): + # If the points form a line or closed shape + d['isLine'] = 'polyline' in result + # Collect points + d['points'] = [] + for point in (result['polyline'] if d['isLine'] else result['polygon']): + d['points'].append(dict(x=point['x'], y=point['y'], z=point['z'])) + + # Options and default values + if 'color' in result: + d['strokeColor'] = result['color'] + else: + d['strokeColor'] = 'red' + + if 'fill' in result: + d['fill'] = result['fill'] + else: + d['fill'] = not d['isLine'] # fill polygons by default + + if 'weight' in result: + d['strokeWeight'] = result['weight'] + else: + d['strokeWeight'] = 2 else: raise ValueError("Got an %s as result for POI with id %s" % (type(result).__name__, poi['id'])) diff --git a/overviewer_core/data/js_src/util.js b/overviewer_core/data/js_src/util.js index cb0e6b2..79e7fa6 100644 --- a/overviewer_core/data/js_src/util.js +++ b/overviewer_core/data/js_src/util.js @@ -378,27 +378,48 @@ overviewer.util = { console.log("this tileset has markers:", obj); obj.marker_groups = {}; + // For every group of markers for (var mkidx = 0; mkidx < markers[obj.path].length; mkidx++) { + // Create a Leaflet layer group var marker_group = new L.layerGroup(); var marker_entry = markers[obj.path][mkidx]; L.Util.setOptions(marker_group, {default_checked: marker_entry.checked}); var icon = L.divIcon({html: ``}); + // For every marker in group for (var dbidx = 0; dbidx < markersDB[marker_entry.groupName].raw.length; dbidx++) { - var db = markersDB[marker_entry.groupName].raw[dbidx]; - var latlng = overviewer.util.fromWorldToLatLng(db.x, db.y, db.z, obj); - var m_icon; - if (db.icon != undefined) { - m_icon = L.divIcon({html: ``}); + let db = markersDB[marker_entry.groupName].raw[dbidx]; + var layerObj = undefined; + + // Shape or marker? + if ('points' in db) { + // Convert all coords + plLatLng = db['points'].map(function(p) { + return overviewer.util.fromWorldToLatLng(p.x, p.y, p.z, obj); + }); + options = { + color: db['strokeColor'], + weight: db['strokeWeight'], + fill: db['fill'] + }; + layerObj = db['isLine'] ? L.polyline(plLatLng, options) : L.polygon(plLatLng, options); + // TODO: add other config options (fill color, fill opacity) } else { - m_icon = icon; + // Convert coords + let latlng = overviewer.util.fromWorldToLatLng(db.x, db.y, db.z, obj); + // Set icon and use default icon if not specified + let m_icon = L.divIcon({html: ``}); + // Create marker + layerObj = new L.marker(latlng, {icon: m_icon, title: db.hovertext}); } - let new_marker = new L.marker(latlng, {icon: m_icon, title: db.hovertext}); + // Add popup to marker if (marker_entry.createInfoWindow) { - new_marker.bindPopup(db.text); + layerObj.bindPopup(db.text); } - marker_group.addLayer(new_marker); + // Add the polyline or marker to the layer + marker_group.addLayer(layerObj); } + // Save marker group obj.marker_groups[marker_entry.displayName] = marker_group; } } diff --git a/overviewer_core/data/web_assets/regions.js b/overviewer_core/data/web_assets/regions.js index cef6ff0..21da8f2 100644 --- a/overviewer_core/data/web_assets/regions.js +++ b/overviewer_core/data/web_assets/regions.js @@ -7,11 +7,10 @@ var world = "top"; markersDB[groupName] = { "raw": [ { - "fillColor": "#00FF00", - "fillOpacity": 0.2, "strokeColor": "#FF0000", - "strokeOpacity": 1, - "polygon" : [ + "strokeWeight": 2, + "fill": true, + "polyline" : [ {"x": 347, "y": 67, "z": 95}, {"x": 347, "y": 77, "z": 95}, {"x": 347, "y": 77, "z": 105}, @@ -19,7 +18,7 @@ markersDB[groupName] = { {"x": 347, "y": 67, "z": 105} ]} ], - "name": "Regions", + "name": groupName, "created": false } @@ -31,4 +30,4 @@ markers[world].push( "displayName": displayName, "checked": true }); -*/ \ No newline at end of file +*/