widths = [12, 13, 14, 15, 16, 16, 16, 16]; opas = [0.8, 0.6, 0.5, 0.5, 0.4]; mwidths = [1, 1, 1, 1.5, 2, 3, 5, 6, 6, 4, 3, 2]; function $(id) { return document.getElementById(id); } function marker(stat, z) { if (z > 15) { return L.circle( [stat.lat, stat.lon], { color: 'black', fillColor: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378', radius: mwidths[23 - z], fillOpacity : 1, weight : 1, id : stat.id } ); } else { return L.polyline( [[stat.lat, stat.lon], [stat.lat, stat.lon]], { color: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378', weight: widths[15 - z], opacity: opas[15 - z], id : stat.id } ); } } function poly(group, z) { if (group.new) return L.polygon(group.poly, {color: "blue", smoothFactor : 0.4, fillOpacity:0.2}) return L.polygon(group.poly, {color: '#85f385', smoothFactor : 1, fillOpacity:0.2}) } function sugArr(sug, z) { return [ L.polyline(sug.arrow, {id : sug.id, color: 'black', smoothFactor : 1, weight: 2, opacity:0.5}), L.polyline(sug.arrow, {id : sug.id, color: 'blue', smoothFactor : 1, weight: 1, opacity:0.5}) ] ; } function renderStat(stat, ll) { var attrrows = {}; var content = document.createElement('div'); content.setAttribute("id", "nav") var attrTbl = document.createElement('table'); attrTbl.setAttribute("id", "attr-tbl") var suggD = document.createElement('table'); suggD.setAttribute("id", "sugg") if (stat.attrs.name) { content.innerHTML = "Node " + stat.osmid + " (\"" + stat.attrs.name + "\")"; } else { content.innerHTML = "Node " + stat.osmid + ""; } content.appendChild(attrTbl); content.appendChild(suggD); var tbody = document.createElement('tbody'); attrTbl.appendChild(tbody); for (var key in stat.attrs) { var row = document.createElement('tr'); var col1 = document.createElement('td'); var col2 = document.createElement('td'); tbody.appendChild(row); row.appendChild(col1); row.appendChild(col2); col1.innerHTML = "" + key + ""; for (var i = 0; i < stat.attrs[key].length; i++) col2.innerHTML += "" + stat.attrs[key][i] + ""+ "
"; attrrows[key] = row; } for (var i = 0; i < stat.attrerrs.length; i++) { var err = stat.attrerrs[i]; var row = attrrows[err.attr[0]]; row.className = "err-" + Math.round(err.conf * 10); var info = document.createElement('div'); if (err.other_osmid != stat.osmid) { info.innerHTML = "Does not match node " + err.other_osmid + ""; } else { info.innerHTML = "Does not match '" + err.other_attr[0] + "' = '" + err.other_attr[1]; } info.className = 'attr-err-info'; row.childNodes[1].appendChild(info); } if (stat.suggestions.length) { suggD.innerHTML = "Suggestions"; } for (var i = 0; i < stat.suggestions.length; i++) { var sugg = stat.suggestions[i]; var suggDiv = document.createElement('div'); if (sugg.type == 1) { suggDiv.innerHTML = "• Move node into a new relation"; } else if (sugg.type == 2) { suggDiv.innerHTML = "• Move node into existing relation " + sugg.target_osm_rel_id + "."; } else if (sugg.type == 3) { suggDiv.innerHTML = "• Move node from existing relation " + sugg.orig_osm_rel_id + " into new relation (internal id=" + sugg.target_gid + ")"; } else if (sugg.type == 4) { suggDiv.innerHTML = "• Move node from existing relation " + sugg.orig_osm_rel_id + " into existing relation " + sugg.target_osm_rel_id + "."; } else if (sugg.type == 5) { suggDiv.innerHTML = "• Move node out of existing relation " + sugg.orig_osm_rel_id + "!"; } suggD.appendChild(suggDiv); } if (map.getZoom() < 18) { map.setView(ll, 18, {animate: true}); } L.popup({opacity: 0.8}) .setLatLng(ll) .setContent(content) .openOn(map); } function openStat(id, ll) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var content = JSON.parse(this.responseText); renderStat(content, ll); } }; xmlhttp.open("GET", "http://localhost:9090/stat?id=" + id, true); xmlhttp.send(); } function groupHl(id) { if (!document.groupIdx[id]) return; document.groupIdx[id].setStyle({ 'weight': 6, 'fillOpacity':0.5 }); } function groupUnHl(id) { if (!document.groupIdx[id]) return; document.groupIdx[id].setStyle({ 'weight': 3, 'fillOpacity':0.2 }); } function nodeHl(id) { if (!document.nodeIdx[id]) return; document.nodeIdx[id].setStyle({ 'weight': 5, 'color' : "#eecc00" }); } function nodeUnHl(id) { if (!document.nodeIdx[id]) return; document.nodeIdx[id].setStyle({ 'weight': 1, 'color' : "black" }); } var map = L.map('map', { renderer: L.canvas() }).setView([47.9965, 7.8469], 13); L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', { maxZoom: 23, attribution: '© OpenStreetMap, © CARTO', id: 'mapbox.streets' }).addTo(map); var layer = L.featureGroup().addTo(map); var labelLayer = L.featureGroup().addTo(map); map.on("moveend", function () { render(); }); function render() { var xmlhttp = new XMLHttpRequest(); if (map.getZoom() < 11) { xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var content = JSON.parse(this.responseText); layer.clearLayers(); labelLayer.clearLayers(); var blur = 21 - map.getZoom(); var rad = 21 - map.getZoom(); blur = Math.max(5, Math.min(9, blur)); rad = Math.min(10, rad); layer.addLayer(L.heatLayer(content.ok, {gradient: {0: '#cbf7cb', 0.5: '#78f378', 1: '#29c329'}, minOpacity: 1, blur: blur, radius: rad, maxZoom: 15})); layer.addLayer(L.heatLayer(content.sugg, {gradient: {0: '#7f7fbd', 0.5: '#4444b3', 1: '#0606c1'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15})); layer.addLayer(L.heatLayer(content.err, {gradient: {0: '#f39191', 0.5: '#ff5656', 1: '#ff0000'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15})); } }; xmlhttp.open("GET", "http://localhost:9090/heatmap?bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true); xmlhttp.send(); } else { xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var content = JSON.parse(this.responseText); layer.clearLayers(); labelLayer.clearLayers(); document.groupIdx = {}; document.nodeIdx = {}; var stations = []; var labels = []; for (var i = 0; i < content.stats.length; i++) { stat = content.stats[i]; var ndMarker = marker(stat, map.getZoom()); stations.push(ndMarker); document.nodeIdx[stat.id] = ndMarker; } var groups = []; for (var i = 0; i < content.groups.length; i++) { group = content.groups[i]; var groupPoly = poly(group, map.getZoom()); groups.push(groupPoly); document.groupIdx[group.id] = groupPoly; } var suggs = []; for (var i = 0; i < content.suggestions.length; i++) { sugg = content.suggestions[i]; var a = sugArr(sugg, map.getZoom()); suggs.push(a[0]); suggs.push(a[1]); } if (map.getZoom() > 15) { labelLayer.addLayer(L.featureGroup(labels)); layer.addLayer(L.featureGroup(groups).on('click', function(a) { console.log(a.layer.options);})); layer.addLayer(L.featureGroup(suggs).on('click', function(a) { openStat(a.layer.options.id, a.layer.getBounds().getCenter());})); } layer.addLayer(L.featureGroup(stations).on('click', function(a) { openStat(a.layer.options.id, a.layer.getBounds().getCenter());})); } }; xmlhttp.open("GET", "http://localhost:9090/map?bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true); xmlhttp.send(); } } render();