Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/web/www/routino/visualiser.leaflet.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2067 - (hide annotations) (download) (as text)
Thu Aug 13 18:26:27 2020 UTC (4 years, 7 months ago) by amb
File MIME type: application/javascript
File size: 28592 byte(s)
Allow multiple map libraries to be used with the web pages and select
between them with a URL argument.

1 amb 1491 //
2     // Routino data visualiser web page Javascript
3     //
4     // Part of the Routino routing software.
5     //
6 amb 2040 // This file Copyright 2008-2014, 2019, 2020 Andrew M. Bishop
7 amb 1491 //
8     // This program is free software: you can redistribute it and/or modify
9     // it under the terms of the GNU Affero General Public License as published by
10     // the Free Software Foundation, either version 3 of the License, or
11     // (at your option) any later version.
12     //
13     // This program is distributed in the hope that it will be useful,
14     // but WITHOUT ANY WARRANTY; without even the implied warranty of
15     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     // GNU Affero General Public License for more details.
17     //
18     // You should have received a copy of the GNU Affero General Public License
19     // along with this program. If not, see <http://www.gnu.org/licenses/>.
20     //
21    
22    
23     //
24     // Data types
25     //
26    
27     var data_types=[
28     "junctions",
29     "super",
30 amb 1560 "waytype",
31 amb 1491 "highway",
32     "transport",
33     "barrier",
34     "turns",
35     "speed",
36     "weight",
37     "height",
38     "width",
39     "length",
40     "property",
41     "errorlogs"
42     ];
43    
44    
45     ////////////////////////////////////////////////////////////////////////////////
46     /////////////////////////////// Initialisation /////////////////////////////////
47     ////////////////////////////////////////////////////////////////////////////////
48    
49     // Process the URL query string and extract the arguments
50    
51     var legal={"^lon" : "^[-0-9.]+$",
52     "^lat" : "^[-0-9.]+$",
53     "^zoom" : "^[0-9]+$"};
54    
55     var args={};
56    
57     if(location.search.length>1)
58     {
59     var query,queries;
60    
61     query=location.search.replace(/^\?/,"");
62     query=query.replace(/;/g,"&");
63     queries=query.split("&");
64    
65     for(var i=0;i<queries.length;i++)
66     {
67     queries[i].match(/^([^=]+)(=(.*))?$/);
68    
69     var k=RegExp.$1;
70     var v=decodeURIComponent(RegExp.$3);
71    
72     for(var l in legal)
73     {
74     if(k.match(RegExp(l)) && v.match(RegExp(legal[l])))
75     args[k]=v;
76     }
77     }
78     }
79    
80    
81     ////////////////////////////////////////////////////////////////////////////////
82     ///////////////////////////////// Map handling /////////////////////////////////
83     ////////////////////////////////////////////////////////////////////////////////
84    
85     var map;
86     var layerMap=[], layerHighlights, layerVectors, layerBoxes;
87     var box;
88    
89     //
90     // Initialise the 'map' object
91     //
92    
93     function map_init() // called from visualiser.html
94     {
95     // Create the map (Map URLs and limits are in mapprops.js)
96    
97     map = L.map("map",
98     {
99     attributionControl: false,
100     zoomControl: false,
101    
102     minZoom: mapprops.zoomout,
103     maxZoom: mapprops.zoomin,
104    
105     maxBounds: L.latLngBounds(L.latLng(mapprops.southedge,mapprops.westedge),L.latLng(mapprops.northedge,mapprops.eastedge))
106     });
107    
108     // Add map tile layers
109    
110     var baselayers={};
111    
112     for(var l=0; l<mapprops.mapdata.length; l++)
113     {
114     var urls=mapprops.mapdata[l].tiles.url.replace(/\${/g,"{");
115    
116     if(mapprops.mapdata[l].tiles.subdomains===undefined)
117     layerMap[l] = L.tileLayer(urls);
118     else
119     layerMap[l] = L.tileLayer(urls, {subdomains: mapprops.mapdata[l].tiles.subdomains});
120    
121     baselayers[mapprops.mapdata[l].label]=layerMap[l];
122    
123     if(l===0)
124     map.addLayer(layerMap[l]);
125     }
126    
127     // Add the controls
128    
129     map.addControl(L.control.zoom());
130     map.addControl(L.control.scale());
131     map.addControl(L.control.layers(baselayers));
132    
133     // Update the attribution if the layer changes
134    
135     function change_attribution_event(event)
136     {
137     for(var l=0; l<mapprops.mapdata.length; l++)
138     if(layerMap[l] == event.layer)
139     change_attribution(l);
140     }
141    
142     map.on("baselayerchange",change_attribution_event);
143    
144     function change_attribution(l)
145     {
146     var data_url =mapprops.mapdata[l].attribution.data_url;
147     var data_text=mapprops.mapdata[l].attribution.data_text;
148     var tile_url =mapprops.mapdata[l].attribution.tile_url;
149     var tile_text=mapprops.mapdata[l].attribution.tile_text;
150    
151     document.getElementById("attribution_data").innerHTML="<a href=\"" + data_url + "\" target=\"data_attribution\">" + data_text + "</a>";
152     document.getElementById("attribution_tile").innerHTML="<a href=\"" + tile_url + "\" target=\"tile_attribution\">" + tile_text + "</a>";
153     }
154    
155     change_attribution(0);
156    
157     // Add two vectors layers (one for highlights that display behind the vectors)
158    
159     layerVectors = L.layerGroup();
160     map.addLayer(layerVectors);
161    
162     layerHighlights = L.layerGroup();
163     map.addLayer(layerHighlights);
164    
165     // Handle popup
166    
167     createPopup();
168    
169     // Add a boxes layer
170    
171     layerBoxes = L.rectangle(map.options.maxBounds,{stroke: false, color: "#f00", weight: 1, opacity: 1.0,
172     fill: false});
173    
174     map.addLayer(layerBoxes);
175    
176     box=false;
177    
178     // Move the map
179    
180     map.on("moveend", updateURLs);
181    
182     var lon =args["lon"];
183     var lat =args["lat"];
184     var zoom=args["zoom"];
185    
186 amb 1493 if(lon !== undefined && lat !== undefined && zoom !== undefined)
187 amb 1491 {
188     if(lon<mapprops.westedge) lon=mapprops.westedge;
189     if(lon>mapprops.eastedge) lon=mapprops.eastedge;
190    
191     if(lat<mapprops.southedge) lat=mapprops.southedge;
192     if(lat>mapprops.northedge) lat=mapprops.northedge;
193    
194     if(zoom<mapprops.zoomout) zoom=mapprops.zoomout;
195     if(zoom>mapprops.zoomin) zoom=mapprops.zoomin;
196    
197 amb 2040 map.setView(L.latLng(Number(lat),Number(lon)),zoom);
198 amb 1491 }
199     else
200     map.fitBounds(map.options.maxBounds);
201    
202     // Unhide editing URL if variable set
203    
204 amb 1493 if(mapprops.editurl !== undefined && mapprops.editurl !== "")
205 amb 1491 {
206     var edit_url=document.getElementById("edit_url");
207    
208     edit_url.style.display="";
209     edit_url.href=mapprops.editurl;
210     }
211    
212     updateURLs();
213     }
214    
215    
216     //
217     // Format a number in printf("%.5f") format.
218     //
219    
220     function format5f(number)
221     {
222     var newnumber=Math.floor(number*100000+0.5);
223     var delta=0;
224    
225     if(newnumber>=0 && newnumber<100000) delta= 100000;
226     if(newnumber<0 && newnumber>-100000) delta=-100000;
227    
228     var string=String(newnumber+delta);
229    
230     var intpart =string.substring(0,string.length-5);
231     var fracpart=string.substring(string.length-5,string.length);
232    
233     if(delta>0) intpart="0";
234     if(delta<0) intpart="-0";
235    
236     return(intpart + "." + fracpart);
237     }
238    
239    
240     //
241     // Build a set of URL arguments for the map location
242     //
243    
244     function buildMapArguments()
245     {
246     var lonlat = map.getCenter();
247    
248     var zoom = map.getZoom();
249    
250     return "lat=" + format5f(lonlat.lat) + ";lon=" + format5f(lonlat.lng) + ";zoom=" + zoom;
251     }
252    
253    
254     //
255     // Update the URLs
256     //
257    
258     function updateURLs()
259     {
260     var mapargs=buildMapArguments();
261 amb 2067 var libargs=";library=" + mapprops.library;
262 amb 1491
263 amb 2067 if(!mapprops.libraries)
264     libargs="";
265    
266 amb 1491 var links=document.getElementsByTagName("a");
267    
268     for(var i=0; i<links.length; i++)
269     {
270     var element=links[i];
271    
272     if(element.id == "permalink_url")
273 amb 2067 element.href=location.pathname + "?" + mapargs + libargs;
274 amb 1491
275     if(element.id == "router_url")
276 amb 2052 if(location.pathname.match(/visualiser\.html\.([a-zA-Z-]+)$/))
277 amb 2067 element.href="router.html" + "." + RegExp.$1 + "?" + mapargs + libargs;
278 amb 2052 else
279 amb 2067 element.href="router.html" + "?" + mapargs + libargs;
280 amb 1491
281     if(element.id == "edit_url")
282     element.href=mapprops.editurl + "?" + mapargs;
283    
284     if(element.id.match(/^lang_([a-zA-Z-]+)_url$/))
285 amb 2067 element.href="visualiser.html" + "." + RegExp.$1 + "?" + mapargs + libargs;
286 amb 1491 }
287     }
288    
289    
290     ////////////////////////////////////////////////////////////////////////////////
291     ///////////////////////// Popup and selection handling /////////////////////////
292     ////////////////////////////////////////////////////////////////////////////////
293    
294     var popup=null;
295    
296     //
297     // Create a popup - independent of map because want it fixed on screen not fixed on map.
298     //
299    
300     function createPopup()
301     {
302     popup=document.createElement("div");
303    
304     popup.className = "popup";
305    
306     popup.innerHTML = "<span></span>";
307    
308     popup.style.display = "none";
309    
310     popup.style.position = "fixed";
311     popup.style.top = "-4000px";
312     popup.style.left = "-4000px";
313     popup.style.zIndex = "100";
314    
315     popup.style.padding = "5px";
316    
317     popup.style.opacity=0.85;
318     popup.style.backgroundColor="#C0C0C0";
319     popup.style.border="4px solid #404040";
320    
321     document.body.appendChild(popup);
322     }
323    
324    
325     //
326     // Draw a popup - independent of map because want it fixed on screen not fixed on map.
327     //
328    
329     function drawPopup(html)
330     {
331 amb 1493 if(html===null)
332 amb 1491 {
333     popup.style.display="none";
334     return;
335     }
336    
337     if(popup.style.display=="none")
338     {
339     var map_div=document.getElementById("map");
340    
341     popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px";
342     popup.style.top = map_div.offsetTop +30 + "px";
343 amb 1499 popup.style.width =map_div.clientWidth-120 + "px";
344 amb 1491
345     popup.style.display="";
346     }
347    
348 amb 1499 var close="<span style='float: right; cursor: pointer;' onclick='drawPopup(null)'>X</span>";
349    
350     popup.innerHTML=close+html;
351 amb 1491 }
352    
353    
354     //
355     // Select a circleMarker feature
356     //
357    
358     function selectCircleMarkerFeature(feature,dump,event)
359     {
360     if(dump)
361     ajaxGET("visualiser.cgi?dump=" + dump, runDumpSuccess);
362    
363     layerHighlights.clearLayers();
364    
365     var highlight = L.circleMarker(feature.getLatLng(),{radius: 2*feature.getRadius(), fill: true, fillColor: "#F0F000", fillOpacity: 1.0,
366     stroke: false});
367    
368     layerHighlights.addLayer(highlight);
369    
370     highlight.bringToBack();
371     }
372    
373    
374     //
375     // Select a Polyline feature
376     //
377    
378     function selectPolylineFeature(feature,dump,event)
379     {
380     if(dump)
381     ajaxGET("visualiser.cgi?dump=" + dump, runDumpSuccess);
382    
383     layerHighlights.clearLayers();
384    
385     var highlight = L.polyline(feature.getLatLngs(),{weight: 8, stroke: true, color: "#F0F000", opacity: 1.0,
386     fill: false});
387    
388     layerHighlights.addLayer(highlight);
389    
390     highlight.bringToBack();
391     }
392    
393    
394     //
395     // Select a Polygon feature
396     //
397    
398     function selectPolygonFeature(feature,dump,event)
399     {
400     if(dump)
401     ajaxGET("visualiser.cgi?dump=" + dump, runDumpSuccess);
402    
403     layerHighlights.clearLayers();
404    
405     var highlight = L.polygon(feature.getLatLngs(),{weight: 8, stroke: true, color: "#F0F000", opacity: 1.0,
406     fill: false});
407    
408     layerHighlights.addLayer(highlight);
409    
410     highlight.bringToBack();
411     }
412    
413    
414     //
415     // Un-select a feature
416     //
417    
418     function unselectFeature(feature)
419     {
420     layerHighlights.clearLayers();
421    
422     drawPopup(null);
423     }
424    
425    
426     //
427     // Display the dump data
428     //
429    
430     function runDumpSuccess(response)
431     {
432     var string=response.responseText;
433    
434 amb 2041 if(mapprops.browseurl !== undefined && mapprops.browseurl !== "")
435 amb 1491 {
436     var types=["node", "way", "relation"];
437     var Types=["Node", "Way", "Relation"];
438    
439     for(var t in types)
440     {
441     var Type=Types[t];
442     var type=types[t];
443    
444     var regexp=RegExp(Type + " [0-9]+");
445    
446     var match;
447    
448 amb 1493 while((match=string.match(regexp)) !== null)
449 amb 1491 {
450     match=String(match);
451    
452     var id=match.slice(1+type.length,match.length);
453    
454     string=string.replace(regexp,Type + " <a href='" + mapprops.browseurl + "/" + type + "/" + id + "' target='" + type + id + "'>" + id + "</a>");
455     }
456     }
457     }
458    
459     drawPopup(string.split("\n").join("<br>"));
460     }
461    
462    
463     ////////////////////////////////////////////////////////////////////////////////
464     /////////////////////////////// Server handling ////////////////////////////////
465     ////////////////////////////////////////////////////////////////////////////////
466    
467     //
468     // Define an AJAX request object
469     //
470    
471     function ajaxGET(url,success,failure,state)
472     {
473     var ajaxRequest=new XMLHttpRequest();
474    
475     function ajaxGOT(options) {
476     if(this.readyState==4)
477     if(this.status==200)
478     { if(typeof(options.success)=="function") options.success(this,options.state); }
479     else
480     { if(typeof(options.failure)=="function") options.failure(this,options.state); }
481     }
482    
483     ajaxRequest.onreadystatechange = function(){ ajaxGOT.call(ajaxRequest,{success: success, failure: failure, state: state}); };
484     ajaxRequest.open("GET", url, true);
485     ajaxRequest.send(null);
486     }
487    
488    
489     //
490     // Display the status
491     //
492    
493     function displayStatus(type,subtype,content)
494     {
495     var child=document.getElementById("result_status").firstChild;
496    
497     do
498     {
499 amb 1493 if(child.id !== undefined)
500 amb 1491 child.style.display="none";
501    
502     child=child.nextSibling;
503     }
504 amb 1496 while(child !== null);
505 amb 1491
506     var chosen_status=document.getElementById("result_status_" + type);
507    
508     chosen_status.style.display="";
509    
510 amb 1496 if(subtype !== undefined)
511 amb 1491 {
512     var format_status=document.getElementById("result_status_" + subtype).innerHTML;
513    
514     chosen_status.innerHTML=format_status.replace("#",String(content));
515     }
516     }
517    
518    
519     //
520     // Display data statistics
521     //
522    
523     function displayStatistics()
524     {
525     // Use AJAX to get the statistics
526    
527     ajaxGET("statistics.cgi", runStatisticsSuccess);
528     }
529    
530    
531     //
532     // Success in running data statistics generation.
533     //
534    
535     function runStatisticsSuccess(response)
536     {
537     document.getElementById("statistics_data").innerHTML="<pre>" + response.responseText + "</pre>";
538     document.getElementById("statistics_link").style.display="none";
539     }
540    
541    
542     //
543     // Get the requested data
544     //
545    
546     function displayData(datatype) // called from visualiser.html
547     {
548     for(var data in data_types)
549     hideshow_hide(data_types[data]);
550    
551 amb 1493 if(datatype !== "")
552 amb 1491 hideshow_show(datatype);
553    
554     // Delete the old data
555    
556     unselectFeature();
557    
558     layerVectors.clearLayers();
559     layerHighlights.clearLayers();
560    
561     layerBoxes.setStyle({stroke:false});
562     box=false;
563    
564     // Print the status
565    
566     displayStatus("no_data");
567    
568     // Return if just here to clear the data
569    
570 amb 1493 if(datatype === "")
571 amb 1491 return;
572    
573     // Get the new data
574    
575     var mapbounds=map.getBounds();
576    
577     var url="visualiser.cgi";
578    
579     url=url + "?lonmin=" + format5f(mapbounds.getWest());
580     url=url + ";latmin=" + format5f(mapbounds.getSouth());
581     url=url + ";lonmax=" + format5f(mapbounds.getEast());
582     url=url + ";latmax=" + format5f(mapbounds.getNorth());
583     url=url + ";data=" + datatype;
584    
585     // Use AJAX to get the data
586    
587     switch(datatype)
588     {
589     case "junctions":
590     ajaxGET(url, runJunctionsSuccess, runFailure);
591     break;
592     case "super":
593     ajaxGET(url, runSuperSuccess, runFailure);
594     break;
595 amb 1560 case "waytype":
596     var waytype;
597     var waytypes=document.forms["waytypes"].elements["waytype"];
598     for(var h in waytypes)
599     if(waytypes[h].checked)
600     waytype=waytypes[h].value;
601     url+="-" + waytype;
602     ajaxGET(url, runWaytypeSuccess, runFailure);
603 amb 1491 break;
604     case "highway":
605     var highway;
606     var highways=document.forms["highways"].elements["highway"];
607     for(var h in highways)
608     if(highways[h].checked)
609     highway=highways[h].value;
610     url+="-" + highway;
611     ajaxGET(url, runHighwaySuccess, runFailure);
612     break;
613     case "transport":
614     var transport;
615     var transports=document.forms["transports"].elements["transport"];
616     for(var t in transports)
617     if(transports[t].checked)
618     transport=transports[t].value;
619     url+="-" + transport;
620     ajaxGET(url, runTransportSuccess, runFailure);
621     break;
622     case "barrier":
623     var transport;
624     var transports=document.forms["barriers"].elements["barrier"];
625     for(var t in transports)
626     if(transports[t].checked)
627     transport=transports[t].value;
628     url+="-" + transport;
629     ajaxGET(url, runBarrierSuccess, runFailure);
630     break;
631     case "turns":
632     ajaxGET(url, runTurnsSuccess, runFailure);
633     break;
634     case "speed":
635     case "weight":
636     case "height":
637     case "width":
638     case "length":
639     ajaxGET(url, runLimitSuccess, runFailure);
640     break;
641     case "property":
642     var property;
643     var properties=document.forms["properties"].elements["property"];
644     for(var p in properties)
645     if(properties[p].checked)
646     property=properties[p].value;
647     url+="-" + property;
648     ajaxGET(url, runPropertySuccess, runFailure);
649     break;
650     case "errorlogs":
651     ajaxGET(url, runErrorlogSuccess, runFailure);
652     break;
653     }
654     }
655    
656    
657     //
658 amb 2006 // Add a bounding box
659     //
660    
661     function addBox(words)
662     {
663 amb 2040 var lat1=Number(words[0]);
664     var lon1=Number(words[1]);
665     var lat2=Number(words[2]);
666     var lon2=Number(words[3]);
667 amb 2006
668     var bounds = L.latLngBounds(L.latLng(lat1,lon1),L.latLng(lat2,lon2));
669    
670     layerBoxes.setBounds(bounds);
671    
672     layerBoxes.setStyle({stroke: true});
673     box=true;
674     }
675    
676    
677     //
678 amb 1491 // Success in getting the junctions.
679     //
680    
681     function runJunctionsSuccess(response)
682     {
683     var lines=response.responseText.split("\n");
684    
685     var junction_colours={
686     0: "#FFFFFF",
687     1: "#FF0000",
688     2: "#FFFF00",
689     3: "#00FF00",
690     4: "#8B4513",
691     5: "#00BFFF",
692     6: "#FF69B4",
693     7: "#000000",
694     8: "#000000",
695     9: "#000000"
696     };
697    
698     for(var line=0;line<lines.length;line++)
699     {
700     var words=lines[line].split(" ");
701    
702 amb 1493 if(line === 0)
703 amb 2006 addBox(words);
704 amb 1493 else if(words[0] !== "")
705 amb 1491 {
706     var dump=words[0];
707 amb 2040 var lat=Number(words[1]);
708     var lon=Number(words[2]);
709 amb 1491 var count=words[3];
710    
711     var lonlat = L.latLng(lat,lon);
712    
713     var feature = L.circleMarker(lonlat,{radius: 2, fill: true, fillColor: junction_colours[count], fillOpacity: 1.0,
714     stroke: false});
715    
716     feature.on("click", (function(f,d) { return function(evt) { selectCircleMarkerFeature(f,d,evt); }; }(feature,dump)));
717    
718     layerVectors.addLayer(feature);
719     }
720     }
721    
722     displayStatus("data","junctions",lines.length-2);
723     }
724    
725    
726     //
727     // Success in getting the super-node and super-segments
728     //
729    
730     function runSuperSuccess(response)
731     {
732     var lines=response.responseText.split("\n");
733    
734     var nodelonlat;
735    
736     for(var line=0;line<lines.length;line++)
737     {
738     var words=lines[line].split(" ");
739    
740 amb 1493 if(line === 0)
741 amb 2006 addBox(words);
742 amb 1493 else if(words[0] !== "")
743 amb 1491 {
744     var dump=words[0];
745 amb 2040 var lat=Number(words[1]);
746     var lon=Number(words[2]);
747 amb 1491
748     var lonlat = L.latLng(lat,lon);
749    
750     if(dump.charAt(0) == "n")
751     {
752     nodelonlat=lonlat;
753    
754     var feature = L.circleMarker(lonlat,{radius: 4, fill: true, fillColor: "#FF0000", fillOpacity: 1.0,
755     stroke: false});
756    
757     feature.on("click", (function(f,d) { return function(evt) { selectCircleMarkerFeature(f,d,evt); }; }(feature,dump)));
758    
759     layerVectors.addLayer(feature);
760     }
761     else
762     {
763     var feature = L.polyline([nodelonlat,lonlat],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
764     fill: false});
765    
766     feature.on("click", (function(f,d) { return function(evt) { selectPolylineFeature(f,d,evt); }; }(feature,dump)));
767    
768     layerVectors.addLayer(feature);
769     }
770     }
771     }
772    
773     displayStatus("data","super",lines.length-2);
774     }
775    
776    
777     //
778 amb 1560 // Success in getting the waytype data
779 amb 1491 //
780    
781 amb 1560 function runWaytypeSuccess(response)
782 amb 1491 {
783     var hex={0: "00", 1: "11", 2: "22", 3: "33", 4: "44", 5: "55", 6: "66", 7: "77",
784     8: "88", 9: "99", 10: "AA", 11: "BB", 12: "CC", 13: "DD", 14: "EE", 15: "FF"};
785    
786     var lines=response.responseText.split("\n");
787    
788     for(var line=0;line<lines.length;line++)
789     {
790     var words=lines[line].split(" ");
791    
792 amb 1493 if(line === 0)
793 amb 2006 addBox(words);
794 amb 1493 else if(words[0] !== "")
795 amb 1491 {
796     var dump=words[0];
797 amb 2040 var lat1=Number(words[1]);
798     var lon1=Number(words[2]);
799     var lat2=Number(words[3]);
800     var lon2=Number(words[4]);
801 amb 1491
802     var lonlat1 = L.latLng(lat1,lon1);
803     var lonlat2 = L.latLng(lat2,lon2);
804    
805     var point1 = map.options.crs.latLngToPoint(lonlat1,15);
806     var point2 = map.options.crs.latLngToPoint(lonlat2,15);
807    
808     var dy = point2.y-point1.y;
809     var dx = point2.x-point1.x;
810     var dist = Math.sqrt(dx*dx+dy*dy)/2;
811     var ang = Math.atan2(-dy,dx);
812    
813     var point3 = L.point(point1.x-dy/dist,point1.y+dx/dist);
814     var point4 = L.point(point1.x+dy/dist,point1.y-dx/dist);
815    
816     var lonlat3 = map.options.crs.pointToLatLng(point3,15);
817     var lonlat4 = map.options.crs.pointToLatLng(point4,15);
818    
819     var r=Math.round(7.5+7.9*Math.cos(ang));
820     var g=Math.round(7.5+7.9*Math.cos(ang+2.0943951));
821     var b=Math.round(7.5+7.9*Math.cos(ang-2.0943951));
822     var colour = "#" + hex[r] + hex[g] + hex[b];
823    
824     var feature = L.polygon([lonlat2,lonlat3,lonlat4],{weight: 2, stroke: true, color: colour, opacity: 1.0,
825     fill: false});
826    
827     feature.on("click", (function(f,d) { return function(evt) { selectPolygonFeature(f,d,evt); }; }(feature,dump)));
828    
829     layerVectors.addLayer(feature);
830     }
831     }
832    
833 amb 1560 displayStatus("data","waytype",lines.length-2);
834 amb 1491 }
835    
836    
837     //
838     // Success in getting the highway data
839     //
840    
841     function runHighwaySuccess(response)
842     {
843     var lines=response.responseText.split("\n");
844    
845     for(var line=0;line<lines.length;line++)
846     {
847     var words=lines[line].split(" ");
848    
849 amb 1493 if(line === 0)
850 amb 2006 addBox(words);
851 amb 1493 else if(words[0] !== "")
852 amb 1491 {
853     var dump=words[0];
854 amb 2040 var lat1=Number(words[1]);
855     var lon1=Number(words[2]);
856     var lat2=Number(words[3]);
857     var lon2=Number(words[4]);
858 amb 1491
859     var lonlat1 = L.latLng(lat1,lon1);
860     var lonlat2 = L.latLng(lat2,lon2);
861    
862     var feature = L.polyline([lonlat1,lonlat2],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
863     fill: false});
864    
865     feature.on("click", (function(f,d) { return function(evt) { selectPolylineFeature(f,d,evt); }; }(feature,dump)));
866    
867     layerVectors.addLayer(feature);
868     }
869     }
870    
871     displayStatus("data","highway",lines.length-2);
872     }
873    
874    
875     //
876     // Success in getting the transport data
877     //
878    
879     function runTransportSuccess(response)
880     {
881     var lines=response.responseText.split("\n");
882    
883     for(var line=0;line<lines.length;line++)
884     {
885     var words=lines[line].split(" ");
886    
887 amb 1493 if(line === 0)
888 amb 2006 addBox(words);
889 amb 1493 else if(words[0] !== "")
890 amb 1491 {
891     var dump=words[0];
892 amb 2040 var lat1=Number(words[1]);
893     var lon1=Number(words[2]);
894     var lat2=Number(words[3]);
895     var lon2=Number(words[4]);
896 amb 1491
897     var lonlat1 = L.latLng(lat1,lon1);
898     var lonlat2 = L.latLng(lat2,lon2);
899    
900     var feature = L.polyline([lonlat1,lonlat2],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
901     fill: false});
902    
903     feature.on("click", (function(f,d) { return function(evt) { selectPolylineFeature(f,d,evt); }; }(feature,dump)));
904    
905     layerVectors.addLayer(feature);
906     }
907     }
908    
909     displayStatus("data","transport",lines.length-2);
910     }
911    
912    
913     //
914     // Success in getting the barrier data
915     //
916    
917     function runBarrierSuccess(response)
918     {
919     var lines=response.responseText.split("\n");
920    
921     for(var line=0;line<lines.length;line++)
922     {
923     var words=lines[line].split(" ");
924    
925 amb 1493 if(line === 0)
926 amb 2006 addBox(words);
927 amb 1493 else if(words[0] !== "")
928 amb 1491 {
929     var dump=words[0];
930 amb 2040 var lat=Number(words[1]);
931     var lon=Number(words[2]);
932 amb 1491
933     var lonlat = L.latLng(lat,lon);
934    
935     var feature = L.circleMarker(lonlat,{radius: 2, fill: true, fillColor: "#FF0000", fillOpacity: 1.0,
936     stroke: false});
937    
938     feature.on("click", (function(f,d) { return function(evt) { selectCircleMarkerFeature(f,d,evt); }; }(feature,dump)));
939    
940     layerVectors.addLayer(feature);
941     }
942     }
943    
944     displayStatus("data","barrier",lines.length-2);
945     }
946    
947    
948     //
949     // Success in getting the turn restrictions data
950     //
951    
952     function runTurnsSuccess(response)
953     {
954     var lines=response.responseText.split("\n");
955    
956     for(var line=0;line<lines.length;line++)
957     {
958     var words=lines[line].split(" ");
959    
960 amb 1493 if(line === 0)
961 amb 2006 addBox(words);
962 amb 1493 else if(words[0] !== "")
963 amb 1491 {
964     var dump=words[0];
965 amb 2040 var lat1=Number(words[1]);
966     var lon1=Number(words[2]);
967     var lat2=Number(words[3]);
968     var lon2=Number(words[4]);
969     var lat3=Number(words[5]);
970     var lon3=Number(words[6]);
971 amb 1491
972     var lonlat1 = L.latLng(lat1,lon1);
973     var lonlat2 = L.latLng(lat2,lon2);
974     var lonlat3 = L.latLng(lat3,lon3);
975    
976     var feature = L.polygon([lonlat1,lonlat2,lonlat3],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
977     fill: false});
978    
979     feature.on("click", (function(f,d) { return function(evt) { selectPolygonFeature(f,d,evt); }; }(feature,dump)));
980    
981     layerVectors.addLayer(feature);
982     }
983     }
984    
985     displayStatus("data","turns",lines.length-2);
986     }
987    
988    
989     //
990     // Success in getting the speed/weight/height/width/length limits
991     //
992    
993     function runLimitSuccess(response)
994     {
995     var lines=response.responseText.split("\n");
996    
997     var nodelonlat;
998    
999     for(var line=0;line<lines.length;line++)
1000     {
1001     var words=lines[line].split(" ");
1002    
1003 amb 1493 if(line === 0)
1004 amb 2006 addBox(words);
1005 amb 1493 else if(words[0] !== "")
1006 amb 1491 {
1007     var dump=words[0];
1008 amb 2040 var lat=Number(words[1]);
1009     var lon=Number(words[2]);
1010 amb 1491 var number=words[3];
1011    
1012     var lonlat = L.latLng(lat,lon);
1013    
1014 amb 1493 if(number === undefined)
1015 amb 1491 {
1016     nodelonlat=lonlat;
1017    
1018     var feature = L.circleMarker(lonlat,{radius: 3, fill: true, fillColor: "#FF0000", fillOpacity: 1.0,
1019     stroke: false});
1020    
1021     feature.on("click", (function(f,d) { return function(evt) { selectCircleMarkerFeature(f,d,evt); }; }(feature,dump)));
1022    
1023     layerVectors.addLayer(feature);
1024     }
1025     else
1026     {
1027     var lonlat = L.latLng(lat,lon);
1028    
1029     var feature = L.polyline([nodelonlat,lonlat],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
1030     fill: false});
1031    
1032     feature.on("click", (function(f,d) { return function(evt) { selectPolylineFeature(f,d,evt); }; }(feature,dump)));
1033    
1034     layerVectors.addLayer(feature);
1035    
1036     var point1 = map.options.crs.latLngToPoint(nodelonlat,15);
1037     var point2 = map.options.crs.latLngToPoint(lonlat ,15);
1038    
1039     var dy = point2.y-point1.y;
1040     var dx = point2.x-point1.x;
1041     var dist = Math.sqrt(dx*dx+dy*dy)/24;
1042    
1043     var point = L.point(point1.x+dx/dist,point1.y+dy/dist);
1044    
1045     feature=L.marker(map.options.crs.pointToLatLng(point,15), {clickable: false,
1046     icon: L.icon({iconUrl: "icons/limit-" + number + ".png",
1047     iconSize: L.point(19,19),
1048     iconAnchor: L.point(9,10)})});
1049    
1050     layerVectors.addLayer(feature);
1051     }
1052     }
1053     }
1054    
1055     displayStatus("data","limit",lines.length-2);
1056     }
1057    
1058    
1059     //
1060     // Success in getting the property data
1061     //
1062    
1063     function runPropertySuccess(response)
1064     {
1065     var lines=response.responseText.split("\n");
1066    
1067     for(var line=0;line<lines.length;line++)
1068     {
1069     var words=lines[line].split(" ");
1070    
1071 amb 1493 if(line === 0)
1072 amb 2006 addBox(words);
1073 amb 1493 else if(words[0] !== "")
1074 amb 1491 {
1075     var dump=words[0];
1076 amb 2040 var lat1=Number(words[1]);
1077     var lon1=Number(words[2]);
1078     var lat2=Number(words[3]);
1079     var lon2=Number(words[4]);
1080 amb 1491
1081     var lonlat1 = L.latLng(lat1,lon1);
1082     var lonlat2 = L.latLng(lat2,lon2);
1083    
1084     var feature = L.polyline([lonlat1,lonlat2],{weight: 2, stroke: true, color: "#FF0000", opacity: 1.0,
1085     fill: false});
1086    
1087     feature.on("click", (function(f,d) { return function(evt) { selectPolylineFeature(f,d,evt); }; }(feature,dump)));
1088    
1089     layerVectors.addLayer(feature);
1090     }
1091     }
1092    
1093     displayStatus("data","property",lines.length-2);
1094     }
1095    
1096    
1097     //
1098     // Success in getting the error log data
1099     //
1100    
1101     function runErrorlogSuccess(response)
1102     {
1103     var lines=response.responseText.split("\n");
1104    
1105     for(var line=0;line<lines.length;line++)
1106     {
1107     var words=lines[line].split(" ");
1108    
1109 amb 1493 if(line === 0)
1110 amb 2006 addBox(words);
1111 amb 1493 else if(words[0] !== "")
1112 amb 1491 {
1113     var dump=words[0];
1114 amb 2040 var lat=Number(words[1]);
1115     var lon=Number(words[2]);
1116 amb 1491
1117     var lonlat = L.latLng(lat,lon);
1118    
1119     var feature = L.circleMarker(lonlat,{radius: 3, fill: true, fillColor: "#FF0000", fillOpacity: 1.0,
1120     stroke: false});
1121    
1122     feature.on("click", (function(f,d) { return function(evt) { selectCircleMarkerFeature(f,d,evt); }; }(feature,dump)));
1123    
1124     layerVectors.addLayer(feature);
1125     }
1126     }
1127    
1128     displayStatus("data","errorlogs",lines.length-2);
1129     }
1130    
1131    
1132     //
1133     // Failure in getting data.
1134     //
1135    
1136     function runFailure(response)
1137     {
1138     displayStatus("failed");
1139     }