script.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. widths = [12, 13, 14, 15, 16, 16, 16, 16];
  2. opas = [0.8, 0.6, 0.5, 0.5, 0.4];
  3. mwidths = [1, 1, 1, 1.5, 2, 3, 5, 6, 6, 4, 3, 2];
  4. function $(id) { return document.getElementById(id); }
  5. function marker(stat, z) {
  6. if (z > 15) {
  7. return L.circle(
  8. [stat.lat, stat.lon],
  9. {
  10. color: 'black',
  11. fillColor: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378',
  12. radius: mwidths[23 - z],
  13. fillOpacity : 1,
  14. weight : 1,
  15. id : stat.id
  16. }
  17. );
  18. } else {
  19. return L.polyline(
  20. [[stat.lat, stat.lon], [stat.lat, stat.lon]],
  21. {
  22. color: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378',
  23. weight: widths[15 - z],
  24. opacity: opas[15 - z],
  25. id : stat.id
  26. }
  27. );
  28. }
  29. }
  30. function poly(group, z) {
  31. if (group.new) return L.polygon(group.poly, {color: "blue", smoothFactor : 0.4})
  32. return L.polygon(group.poly, {color: '#85f385', smoothFactor : 1})
  33. }
  34. function sugArr(sug, z) {
  35. return [
  36. L.polyline(sug.arrow, {id : sug.id, color: 'black', smoothFactor : 1, weight: 2, opacity:0.5}),
  37. L.polyline(sug.arrow, {id : sug.id, color: 'blue', smoothFactor : 1, weight: 1, opacity:0.5})
  38. ]
  39. ;
  40. }
  41. function renderStat(stat, ll) {
  42. var attrrows = {};
  43. var content = document.createElement('div');
  44. content.setAttribute("id", "nav")
  45. var attrTbl = document.createElement('table');
  46. attrTbl.setAttribute("id", "attr-tbl")
  47. var suggD = document.createElement('table');
  48. suggD.setAttribute("id", "sugg")
  49. if (stat.attrs.name) {
  50. content.innerHTML = "OSM node <a target='_blank' href='https://www.openstreetmap.org/node/" + stat.osmid + "'>" + stat.osmid + "</a><br>(<b>" + stat.attrs.name + "</b>)";
  51. } else {
  52. content.innerHTML = "OSM node <a target='_blank' href='https://www.openstreetmap.org/node/" + stat.osmid + "'>" + stat.osmid + "</a>";
  53. }
  54. content.appendChild(attrTbl);
  55. content.appendChild(suggD);
  56. var tbody = document.createElement('tbody');
  57. attrTbl.appendChild(tbody);
  58. for (var key in stat.attrs) {
  59. var row = document.createElement('tr');
  60. var col1 = document.createElement('td');
  61. var col2 = document.createElement('td');
  62. tbody.appendChild(row);
  63. row.appendChild(col1);
  64. row.appendChild(col2);
  65. col1.innerHTML = "<a href=\"https://wiki.openstreetmap.org/wiki/Key:" + key + "\" target=\"_blank\">" + key + "</a>";
  66. for (var i = 0; i < stat.attrs[key].length; i++) col2.innerHTML += "<span class='attrval'>" + stat.attrs[key][i] + "</span>"+ "<br>";
  67. attrrows[key] = row;
  68. }
  69. for (var i = 0; i < stat.attrerrs.length; i++) {
  70. var err = stat.attrerrs[i];
  71. var row = attrrows[err.attr[0]];
  72. row.className = "err-" + Math.round(err.conf * 10);
  73. var info = document.createElement('div');
  74. if (err.other_osmid != stat.osmid) {
  75. info.innerHTML = "Does not match node <a target=\"_blank\" href=\"https://www.openstreetmap.org/node/" + err.other_osmid + "\">" + err.other_osmid + "</a>";
  76. } else {
  77. info.innerHTML = "Does not match '" + err.other_attr[0] + "' = '" + err.other_attr[1];
  78. }
  79. info.className = 'attr-err-info';
  80. row.childNodes[1].appendChild(info);
  81. }
  82. if (stat.suggestions.length) {
  83. suggD.innerHTML = "<span class='sugtit'>Suggestions</span>";
  84. }
  85. for (var i = 0; i < stat.suggestions.length; i++) {
  86. var sugg = stat.suggestions[i];
  87. var suggDiv = document.createElement('div');
  88. if (sugg.type == 1) {
  89. suggDiv.innerHTML = "&bull; Move node into a new relation (internal id=" + sugg.target_gid + ")";
  90. } else if (sugg.type == 2) {
  91. suggDiv.innerHTML = "&bull; Move node into existing relation <a href=\"https://www.openstreetmap.org/relation/" + sugg.target_osm_rel_id + "\" target=\"_blank\">" + sugg.target_osm_rel_id + "</a>.";
  92. } else if (sugg.type == 3) {
  93. suggDiv.innerHTML = "&bull; Move node from existing relation <a href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a> into new relation (internal id=" + sugg.target_gid + ")";
  94. } else if (sugg.type == 4) {
  95. suggDiv.innerHTML = "&bull; Move node from existing relation <a href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a> into existing relation <a href=\"https://www.openstreetmap.org/relation/" + sugg.target_osm_rel_id + "\" target=\"_blank\">" + sugg.target_osm_rel_id + "</a>.";
  96. } else if (sugg.type == 5) {
  97. suggDiv.innerHTML = "&bull; Move node out of existing relation <a href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a>!";
  98. }
  99. suggD.appendChild(suggDiv);
  100. }
  101. if (map.getZoom() < 18) {
  102. map.setView(ll, 18);
  103. }
  104. L.popup({opacity: 0.8})
  105. .setLatLng(ll)
  106. .setContent(content)
  107. .openOn(map);
  108. }
  109. function openStat(id, ll) {
  110. var xmlhttp = new XMLHttpRequest();
  111. xmlhttp.onreadystatechange = function() {
  112. if (this.readyState == 4 && this.status == 200) {
  113. var content = JSON.parse(this.responseText);
  114. renderStat(content, ll);
  115. }
  116. };
  117. xmlhttp.open("GET", "http://localhost:9090/stat?id=" + id, true);
  118. xmlhttp.send();
  119. }
  120. var map = L.map('map', {
  121. renderer: L.canvas()
  122. }).setView([47.9965, 7.8469], 13);
  123. L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
  124. maxZoom: 23,
  125. attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attribution">CARTO</a>',
  126. id: 'mapbox.streets'
  127. }).addTo(map);
  128. var layer = L.featureGroup().addTo(map);
  129. var labelLayer = L.featureGroup().addTo(map);
  130. map.on("zoomend", function () {
  131. render();
  132. });
  133. function render() {
  134. var xmlhttp = new XMLHttpRequest();
  135. if (map.getZoom() < 11) {
  136. xmlhttp.onreadystatechange = function() {
  137. if (this.readyState == 4 && this.status == 200) {
  138. var content = JSON.parse(this.responseText);
  139. layer.clearLayers();
  140. labelLayer.clearLayers();
  141. var blur = 21 - map.getZoom();
  142. var rad = 21 - map.getZoom();
  143. blur = Math.max(5, Math.min(9, blur));
  144. rad = Math.min(10, rad);
  145. layer.addLayer(L.heatLayer(content.ok, {gradient: {0: '#cbf7cb', 0.5: '#78f378', 1: '#29c329'}, minOpacity: 1, blur: blur, radius: rad, maxZoom: 15}));
  146. layer.addLayer(L.heatLayer(content.sugg, {gradient: {0: '#7f7fbd', 0.5: '#4444b3', 1: '#0606c1'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15}));
  147. layer.addLayer(L.heatLayer(content.err, {gradient: {0: '#f39191', 0.5: '#ff5656', 1: '#ff0000'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15}));
  148. }
  149. };
  150. 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);
  151. xmlhttp.send();
  152. } else {
  153. xmlhttp.onreadystatechange = function() {
  154. if (this.readyState == 4 && this.status == 200) {
  155. var content = JSON.parse(this.responseText);
  156. layer.clearLayers();
  157. labelLayer.clearLayers();
  158. var stations = [];
  159. var labels = [];
  160. for (var i = 0; i < content.stats.length; i++) {
  161. stat = content.stats[i];
  162. stations.push(marker(stat, map.getZoom()));
  163. }
  164. var groups = [];
  165. for (var i = 0; i < content.groups.length; i++) {
  166. group = content.groups[i];
  167. groups.push(poly(group, map.getZoom()));
  168. }
  169. var suggs = [];
  170. for (var i = 0; i < content.suggestions.length; i++) {
  171. sugg = content.suggestions[i];
  172. var a = sugArr(sugg, map.getZoom());
  173. suggs.push(a[0]);
  174. suggs.push(a[1]);
  175. }
  176. if (map.getZoom() > 15) {
  177. labelLayer.addLayer(L.featureGroup(labels));
  178. layer.addLayer(L.featureGroup(groups).on('click', function(a) { console.log(a);}));
  179. layer.addLayer(L.featureGroup(suggs).on('click', function(a) { openStat(a.layer.options.id, a.layer.getBounds().getCenter());}));
  180. }
  181. layer.addLayer(L.featureGroup(stations).on('click', function(a) {
  182. openStat(a.layer.options.id, a.layer.getBounds().getCenter());}));
  183. }
  184. };
  185. 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);
  186. xmlhttp.send();
  187. }
  188. }
  189. render();