Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/web/www/routino/router.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (show annotations) (download) (as text)
Wed Dec 29 10:25:14 2010 UTC (14 years, 2 months ago) by amb
File MIME type: application/javascript
File size: 42101 byte(s)
Added the uncontrolled (not auto-generated) files from routino-1.4.

1 //
2 // Routino router web page Javascript
3 //
4 // Part of the Routino routing software.
5 //
6 // This file Copyright 2008-2010 Andrew M. Bishop
7 //
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 /////////////////////////// Routino default profile ////////////////////////////
24 ////////////////////////////////////////////////////////////////////////////////
25
26 var routino={ // contains all default Routino options (generated using "--help-profile-js").
27
28 // Default transport type
29 transport: 'motorcar',
30
31 // Transport types
32 transports: {foot: 1, horse: 2, wheelchair: 3, bicycle: 4, moped: 5, motorbike: 6, motorcar: 7, goods: 8, hgv: 9, psv: 10},
33
34 // Highway types
35 highways: {motorway: 1, trunk: 2, primary: 3, secondary: 4, tertiary: 5, unclassified: 6, residential: 7, service: 8, track: 9, cycleway: 10, path: 11, steps: 12},
36
37 // Property types
38 properties: {paved: 1, multilane: 2, bridge: 3, tunnel: 4},
39
40 // Restriction types
41 restrictions: {oneway: 1, weight: 2, height: 3, width: 4, length: 5},
42
43 // Allowed highways
44 profile_highway: {
45 motorway: {foot: 0, horse: 0, wheelchair: 0, bicycle: 0, moped: 0, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100},
46 trunk: {foot: 40, horse: 25, wheelchair: 40, bicycle: 30, moped: 90, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100},
47 primary: {foot: 50, horse: 50, wheelchair: 50, bicycle: 70, moped: 100, motorbike: 90, motorcar: 90, goods: 90, hgv: 90, psv: 90},
48 secondary: {foot: 60, horse: 50, wheelchair: 60, bicycle: 80, moped: 90, motorbike: 80, motorcar: 80, goods: 80, hgv: 80, psv: 80},
49 tertiary: {foot: 70, horse: 75, wheelchair: 70, bicycle: 90, moped: 80, motorbike: 70, motorcar: 70, goods: 70, hgv: 70, psv: 70},
50 unclassified: {foot: 80, horse: 75, wheelchair: 80, bicycle: 90, moped: 70, motorbike: 60, motorcar: 60, goods: 60, hgv: 60, psv: 60},
51 residential: {foot: 90, horse: 75, wheelchair: 90, bicycle: 90, moped: 60, motorbike: 50, motorcar: 50, goods: 50, hgv: 50, psv: 50},
52 service: {foot: 90, horse: 75, wheelchair: 90, bicycle: 90, moped: 80, motorbike: 80, motorcar: 80, goods: 80, hgv: 80, psv: 80},
53 track: {foot: 95, horse: 100, wheelchair: 95, bicycle: 90, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0},
54 cycleway: {foot: 95, horse: 90, wheelchair: 95, bicycle: 100, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0},
55 path: {foot: 100, horse: 100, wheelchair: 100, bicycle: 90, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0},
56 steps: {foot: 80, horse: 0, wheelchair: 0, bicycle: 0, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0}
57 },
58
59 // Speed limits
60 profile_speed: {
61 motorway: {foot: 0, horse: 0, wheelchair: 0, bicycle: 0, moped: 48, motorbike: 112, motorcar: 112, goods: 96, hgv: 89, psv: 89},
62 trunk: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 96, motorcar: 96, goods: 96, hgv: 80, psv: 80},
63 primary: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 96, motorcar: 96, goods: 96, hgv: 80, psv: 80},
64 secondary: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 88, motorcar: 88, goods: 88, hgv: 80, psv: 80},
65 tertiary: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 80, motorcar: 80, goods: 80, hgv: 80, psv: 80},
66 unclassified: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 64, motorcar: 64, goods: 64, hgv: 64, psv: 64},
67 residential: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 48, motorbike: 48, motorcar: 48, goods: 48, hgv: 48, psv: 48},
68 service: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 32, motorbike: 32, motorcar: 32, goods: 32, hgv: 32, psv: 32},
69 track: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 16, motorbike: 16, motorcar: 16, goods: 16, hgv: 16, psv: 16},
70 cycleway: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0},
71 path: {foot: 4, horse: 8, wheelchair: 4, bicycle: 20, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0},
72 steps: {foot: 4, horse: 0, wheelchair: 4, bicycle: 0, moped: 0, motorbike: 0, motorcar: 0, goods: 0, hgv: 0, psv: 0}
73 },
74
75 // Highway properties
76 profile_property: {
77 paved: {foot: 50, horse: 20, wheelchair: 90, bicycle: 50, moped: 100, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100},
78 multilane: {foot: 25, horse: 25, wheelchair: 25, bicycle: 25, moped: 25, motorbike: 75, motorcar: 75, goods: 75, hgv: 75, psv: 75},
79 bridge: {foot: 50, horse: 50, wheelchair: 50, bicycle: 50, moped: 50, motorbike: 50, motorcar: 50, goods: 50, hgv: 50, psv: 50},
80 tunnel: {foot: 50, horse: 50, wheelchair: 50, bicycle: 50, moped: 50, motorbike: 50, motorcar: 50, goods: 50, hgv: 50, psv: 50}
81 },
82
83 // Restrictions
84 profile_restrictions: {
85 oneway: {foot: 0, horse: 1, wheelchair: 0, bicycle: 1, moped: 1, motorbike: 1, motorcar: 1, goods: 1, hgv: 1, psv: 1},
86 weight: {foot: 0.0, horse: 0.0, wheelchair: 0.0, bicycle: 0.0, moped: 0.0, motorbike: 0.0, motorcar: 0.0, goods: 5.0, hgv: 10.0, psv: 15.0},
87 height: {foot: 0.0, horse: 0.0, wheelchair: 0.0, bicycle: 0.0, moped: 0.0, motorbike: 0.0, motorcar: 0.0, goods: 2.5, hgv: 3.0, psv: 3.0},
88 width: {foot: 0.0, horse: 0.0, wheelchair: 0.0, bicycle: 0.0, moped: 0.0, motorbike: 0.0, motorcar: 0.0, goods: 2.0, hgv: 2.5, psv: 2.5},
89 length: {foot: 0.0, horse: 0.0, wheelchair: 0.0, bicycle: 0.0, moped: 0.0, motorbike: 0.0, motorcar: 0.0, goods: 5.0, hgv: 6.0, psv: 6.0}
90 }
91
92 }; // end of routino variable
93
94 // Make a deep copy of the routino profile.
95
96 var routino_default={};
97 for(var l1 in routino)
98 if(typeof(routino[l1])!='object')
99 routino_default[l1]=routino[l1];
100 else
101 {
102 routino_default[l1]={};
103 for(var l2 in routino[l1])
104 if(typeof(routino[l1][l2])!='object')
105 routino_default[l1][l2]=Number(routino[l1][l2]);
106 else
107 {
108 routino_default[l1][l2]={};
109 for(var l3 in routino[l1][l2])
110 routino_default[l1][l2][l3]=Number(routino[l1][l2][l3]);
111 }
112 }
113
114
115 ////////////////////////////////////////////////////////////////////////////////
116 //////////////////////////////// Form handling /////////////////////////////////
117 ////////////////////////////////////////////////////////////////////////////////
118
119 //
120 // Form initialisation - fill in the uninitialised parts
121 //
122
123 function form_init()
124 {
125 // Update the routino variable with the URL settings (from the HTML).
126
127 for(var lang=0;lang< document.forms["form"].elements["language"].length;lang++)
128 if(document.forms["form"].elements["language"][lang].checked)
129 formSetLanguage(document.forms["form"].elements["language"][lang].value);
130
131 var transport=null;
132
133 for(var key in routino.transports)
134 if(document.forms["form"].elements["transport"][routino.transports[key]-1].checked)
135 transport=key;
136
137 if(transport==null)
138 formSetTransport(routino.transport);
139 else
140 {
141 routino.transport=transport;
142
143 for(var key in routino.profile_highway)
144 {
145 if(document.forms["form"].elements["highway-" + key].value=="")
146 document.forms["form"].elements["highway-" + key].value=routino.profile_highway[key][routino.transport];
147 else
148 formSetHighway(key);
149 }
150
151 for(var key in routino.profile_speed)
152 {
153 if(document.forms["form"].elements["speed-" + key].value=="")
154 document.forms["form"].elements["speed-" + key].value=routino.profile_speed[key][routino.transport];
155 else
156 formSetSpeed(key);
157 }
158
159 for(var key in routino.profile_property)
160 {
161 if(document.forms["form"].elements["property-" + key].value=="")
162 document.forms["form"].elements["property-" + key].value=routino.profile_property[key][routino.transport];
163 else
164 formSetProperty(key);
165 }
166
167 for(var key in routino.restrictions)
168 {
169 if(key=="oneway")
170 formSetRestriction(key);
171 else
172 {
173 if(document.forms["form"].elements["restrict-" + key].value=="")
174 document.forms["form"].elements["restrict-" + key].value=routino.profile_restrictions[key][routino.transport];
175 else
176 formSetRestriction(key);
177 }
178 }
179 }
180
181 // Delete the extra empty waypoints
182
183 var filled=0;
184
185 for(var marker=nmarkers;marker>=1;marker--)
186 {
187 var lon=document.forms["form"].elements["lon" + marker].value;
188 var lat=document.forms["form"].elements["lat" + marker].value;
189
190 if(lon != "" && lat != "")
191 {
192 filled++;
193 markerAddMap(marker);
194 }
195 else if(filled==0)
196 markerRemove(marker);
197 }
198
199 // Get the home location cookie and compare to each waypoint
200
201 var cookies=document.cookie.split('; ');
202
203 for(var cookie=0;cookie<cookies.length;cookie++)
204 if(cookies[cookie].substr(0,"Routino-home".length)=="Routino-home")
205 {
206 var data=cookies[cookie].split(/[=:;]/);
207
208 if(data[1]=="lon") homelon=Number(data[2]);
209 if(data[3]=="lat") homelat=Number(data[4]);
210 }
211
212 if(homelon!=null && homelat!=null)
213 {
214 for(var marker=nmarkers;marker>=1;marker--)
215 {
216 var lon=document.forms["form"].elements["lon" + marker].value;
217 var lat=document.forms["form"].elements["lat" + marker].value;
218
219 if(lon==homelon && lat==homelat)
220 updateIcon(marker);
221 }
222
223 // If the first location is empty and the cookie is set then fill it.
224
225 if(document.forms["form"].elements["lon1"].value=="" && document.forms["form"].elements["lat1"].value=="")
226 {
227 document.forms["form"].elements["lon1"].value=homelon;
228 document.forms["form"].elements["lat1"].value=homelat;
229
230 markerAddMap(1);
231 }
232 }
233
234 updateCustomURL();
235 }
236
237
238 //
239 // Change of language in the form
240 //
241
242 function formSetLanguage(type)
243 {
244 routino.language=type;
245
246 updateCustomURL();
247 }
248
249
250 //
251 // Change of transport in the form
252 //
253
254 function formSetTransport(type)
255 {
256 routino.transport=type;
257
258 for(var key in routino.transports)
259 document.forms["form"].elements["transport"][routino.transports[key]-1].checked=(key==routino.transport);
260
261 for(var key in routino.profile_highway)
262 document.forms["form"].elements["highway-" + key].value=routino.profile_highway[key][routino.transport];
263
264 for(var key in routino.profile_speed)
265 document.forms["form"].elements["speed-" + key].value=routino.profile_speed[key][routino.transport];
266
267 for(var key in routino.profile_property)
268 document.forms["form"].elements["property-" + key].value=routino.profile_property[key][routino.transport];
269
270 for(var key in routino.restrictions)
271 {
272 if(key=="oneway")
273 document.forms["form"].elements["restrict-" + key].checked=routino.profile_restrictions[key][routino.transport];
274 else
275 document.forms["form"].elements["restrict-" + key].value=routino.profile_restrictions[key][routino.transport];
276 }
277
278 paramschanged=true;
279
280 updateCustomURL();
281 }
282
283
284 //
285 // Change of highway in the form
286 //
287
288 function formSetHighway(type)
289 {
290 routino.profile_highway[type][routino.transport]=document.forms["form"].elements["highway-" + type].value;
291
292 paramschanged=true;
293
294 updateCustomURL();
295 }
296
297
298 //
299 // Change of Speed in the form
300 //
301
302 function formSetSpeed(type)
303 {
304 routino.profile_speed[type][routino.transport]=document.forms["form"].elements["speed-" + type].value;
305
306 paramschanged=true;
307
308 updateCustomURL();
309 }
310
311
312 //
313 // Change of Property in the form
314 //
315
316 function formSetProperty(type)
317 {
318 routino.profile_property[type][routino.transport]=document.forms["form"].elements["property-" + type].value;
319
320 paramschanged=true;
321
322 updateCustomURL();
323 }
324
325
326 //
327 // Change of oneway rule in the form
328 //
329
330 function formSetRestriction(type)
331 {
332 if(type=="oneway")
333 routino.profile_restrictions[type][routino.transport]=document.forms["form"].elements["restrict-" + type].checked;
334 else
335 routino.profile_restrictions[type][routino.transport]=document.forms["form"].elements["restrict-" + type].value;
336
337 paramschanged=true;
338
339 updateCustomURL();
340 }
341
342
343 //
344 // Set the feature coordinates from the form when the form changes.
345 //
346
347 function formSetCoords(marker)
348 {
349 var lonlat=map.getCenter().clone();
350
351 lonlat.transform(map.getProjectionObject(),epsg4326);
352
353 var lon=document.forms["form"].elements["lon" + marker].value;
354 var lat=document.forms["form"].elements["lat" + marker].value;
355
356 if(lon!="")
357 {
358 if(lon<-180) lon=-180;
359 if(lon>+180) lon=+180;
360 lonlat.lon=lon;
361 }
362
363 if(lat!="")
364 {
365 if(lat<-90 ) lat=-90 ;
366 if(lat>+90 ) lat=+90 ;
367 lonlat.lat=lat;
368 }
369
370 var point = lonlat.clone();
371
372 point.transform(epsg4326,map.getProjectionObject());
373
374 markers[marker].move(point);
375
376 markersmoved=true;
377
378 coordsSetForm(marker);
379 }
380
381
382 //
383 // Set the feature coordinates in the form.
384 //
385
386 function coordsSetForm(marker)
387 {
388 var lonlat = new OpenLayers.LonLat(markers[marker].geometry.x, markers[marker].geometry.y);
389 lonlat.transform(map.getProjectionObject(),epsg4326);
390
391 var lon=format5f(lonlat.lon);
392 var lat=format5f(lonlat.lat);
393
394 document.forms["form"].elements["lon" + marker].value=lon;
395 document.forms["form"].elements["lat" + marker].value=lat;
396
397 updateIcon(marker);
398
399 updateCustomURL();
400 }
401
402
403 //
404 // Format a number in printf("%.5f") format.
405 //
406
407 function format5f(number)
408 {
409 var newnumber=Math.floor(number*100000+0.5);
410 var delta=0;
411
412 if(newnumber>=0 && newnumber<100000) delta= 100000;
413 if(newnumber<0 && newnumber>-100000) delta=-100000;
414
415 var string=String(newnumber+delta);
416
417 var intpart =string.substring(0,string.length-5);
418 var fracpart=string.substring(string.length-5,string.length);
419
420 if(delta>0) intpart="0";
421 if(delta<0) intpart="-0";
422
423 return(intpart + "." + fracpart);
424 }
425
426
427 //
428 // Build a set of URL arguments
429 //
430
431 function buildURLArguments(all)
432 {
433 var url="?";
434
435 url=url + "transport=" + routino.transport;
436
437 for(var marker=1;marker<=vismarkers;marker++)
438 if(markers[marker].style.display == "" || all)
439 {
440 url=url + ";lon" + marker + "=" + document.forms["form"].elements["lon" + marker].value;
441 url=url + ";lat" + marker + "=" + document.forms["form"].elements["lat" + marker].value;
442 }
443
444 for(var key in routino.profile_highway)
445 if(routino.profile_highway[key][routino.transport]!=routino_default.profile_highway[key][routino.transport])
446 url=url + ";highway-" + key + "=" + routino.profile_highway[key][routino.transport];
447
448 for(var key in routino.profile_speed)
449 if(routino.profile_speed[key][routino.transport]!=routino_default.profile_speed[key][routino.transport])
450 url=url + ";speed-" + key + "=" + routino.profile_speed[key][routino.transport];
451
452 for(var key in routino.profile_property)
453 if(routino.profile_property[key][routino.transport]!=routino_default.profile_property[key][routino.transport])
454 url=url + ";property-" + key + "=" + routino.profile_property[key][routino.transport];
455
456 for(var key in routino.restrictions)
457 if(routino.profile_restrictions[key][routino.transport]!=routino_default.profile_restrictions[key][routino.transport])
458 url=url + ";" + key + "=" + routino.profile_restrictions[key][routino.transport];
459
460 if(routino.language)
461 url=url + ";language=" + routino.language;
462
463 return(url);
464 }
465
466
467 //
468 // Update custom URL
469 //
470
471 function updateCustomURL()
472 {
473 var visualiser_url=document.getElementById("visualiser_url");
474 var link_url =document.getElementById("link_url");
475 var edit_url =document.getElementById("edit_url");
476
477 visualiser_url.href="customvisualiser.cgi?" + map_args;
478 link_url.href="customrouter.cgi" + buildURLArguments(1) + ";" + map_args;
479 edit_url.href="http://www.openstreetmap.org/edit?" + map_args;
480 }
481
482
483 //
484 // Block the use of the return key to submit the form
485 //
486
487 function block_return_key()
488 {
489 var form=document.getElementById("form");
490
491 if(form.addEventListener)
492 form.addEventListener('keyup', discardReturnKey, false);
493 else if(form.attachEvent)
494 form.attachEvent('keyup', discardReturnKey); // Internet Explorer
495 }
496
497 //
498 // Function to discard the return key if pressed
499 //
500
501 function discardReturnKey(ev)
502 {
503 if(ev.keyCode==13)
504 return(false);
505
506 return(true);
507 }
508
509
510 ////////////////////////////////////////////////////////////////////////////////
511 ///////////////////////////////// Map handling /////////////////////////////////
512 ////////////////////////////////////////////////////////////////////////////////
513
514 var map;
515 var layerMapOSM, layerVectors, layerGPX;
516 var epsg4326, epsg900913;
517 var map_args;
518
519 //
520 // Initialise the 'map' object
521 //
522
523 function map_init(lat,lon,zoom)
524 {
525 // Default configuration:
526 // UK coordinate range
527 // West -11.0, South 49.5, East 2.0, North 61.0
528 // Zoom level 4 to 15
529
530 // EDIT THIS below to change the visible map limits
531
532 var westedge = -11.0; // Minimum longitude (degrees)
533 var eastedge = 2.0; // Maximum longitude (degrees)
534 var southedge = 49.5; // Minimum latitude (degrees)
535 var northedge = 61.0; // Maximum latitude (degrees)
536 var zoomout = 4; // Minimum zoom
537 var zoomin = 15; // Maximum zoom
538
539 // EDIT THIS above to change the visible map limits
540
541 //
542 // Create the map
543 //
544
545 epsg4326=new OpenLayers.Projection("EPSG:4326");
546 epsg900913=new OpenLayers.Projection("EPSG:900913");
547
548 map = new OpenLayers.Map ("map",
549 {
550 controls:[
551 new OpenLayers.Control.Navigation(),
552 new OpenLayers.Control.PanZoomBar(),
553 new OpenLayers.Control.ScaleLine(),
554 new OpenLayers.Control.LayerSwitcher()
555 ],
556
557 projection: epsg900913,
558 displayProjection: epsg4326,
559
560 minZoomLevel: zoomout,
561 numZoomLevels: zoomin-zoomout+1,
562 maxResolution: 156543.0339 / Math.pow(2,zoomout),
563
564 maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
565 restrictedExtent: new OpenLayers.Bounds(westedge,southedge,eastedge,northedge).transform(epsg4326,epsg900913),
566
567 units: "m"
568 });
569
570 map.events.register("moveend", map, mapMoved);
571
572 // Add a map tile layer (OpenStreetMap tiles, direct access)
573
574 layerMapOSM = new OpenLayers.Layer.TMS("Original OSM map",
575 "http://tile.openstreetmap.org/",
576 {
577 emptyUrl: "http://openstreetmap.org/openlayers/img/404.png",
578 type: 'png',
579 getURL: limitedUrl,
580 displayOutsideMaxExtent: true,
581 buffer: 1
582 });
583 map.addLayer(layerMapOSM);
584
585 // Get a URL for the tile; limited to map restricted extent.
586
587 function limitedUrl(bounds)
588 {
589 var z = map.getZoom() + map.minZoomLevel;
590
591 if (z>=7 && (bounds.right < map.restrictedExtent.left ||
592 bounds.left > map.restrictedExtent.right ||
593 bounds.top < map.restrictedExtent.bottom ||
594 bounds.bottom > map.restrictedExtent.top))
595 return this.emptyUrl;
596
597 var res = map.getResolution();
598 var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
599 var limit = Math.pow(2, z);
600
601 if (y < 0 || y >= limit)
602 return this.emptyUrl;
603
604 var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
605
606 x = ((x % limit) + limit) % limit;
607 return this.url + z + "/" + x + "/" + y + "." + this.type;
608 }
609
610 // Define a GPX layer but don't add it yet
611
612 layerGPX={shortest: null, quickest: null};
613
614 gpx_style={shortest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#00FF00"}),
615 quickest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#0000FF"})};
616
617 // Add a vectors layer
618
619 layerVectors = new OpenLayers.Layer.Vector("Markers");
620 map.addLayer(layerVectors);
621
622 // A set of markers
623
624 nmarkers=99;
625 vismarkers=0;
626 markers={};
627 markersmoved=false;
628 paramschanged=false;
629
630 for(var marker=1;marker<=nmarkers;marker++)
631 {
632 if(document.forms["form"].elements["lon" + marker] != undefined)
633 {
634 markers[marker] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
635 new OpenLayers.Style({},{externalGraphic: 'icons/marker-' + marker + '-red.png',
636 fillColor: "white",
637 graphicYOffset: -25,
638 graphicWidth: 21,
639 graphicHeight: 25,
640 display: "none"}));
641
642 layerVectors.addFeatures([markers[marker]]);
643 }
644 else
645 {
646 nmarkers=marker-1;
647 vismarkers=marker-1;
648 break;
649 }
650 }
651
652 // A function to drag the markers
653
654 var drag = new OpenLayers.Control.DragFeature(layerVectors,
655 {onDrag: dragMove,
656 onComplete: dragComplete });
657 map.addControl(drag);
658 drag.activate();
659
660 // Markers to highlight a selected point
661
662 for(var highlight in highlights)
663 {
664 highlights[highlight] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
665 new OpenLayers.Style({},{strokeColor: route_dark_colours[highlight],
666 fillColor: "white",
667 pointRadius: 10,
668 strokeWidth: 4,
669 fillOpacity: 0,
670 display: "none"}));
671
672 layerVectors.addFeatures([highlights[highlight]]);
673 }
674
675 // A popup for routing results
676
677 for(var popup in popups)
678 popups[popup] = createPopup(popup);
679
680 // Set the map centre to the limited range specified
681
682 map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true));
683 map.maxResolution = map.getResolution();
684
685 // Move the map
686
687 if(lon != 'lon' && lat != 'lat' && zoom != 'zoom')
688 {
689 var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,map.getProjectionObject());
690
691 map.moveTo(lonlat,zoom-map.minZoomLevel);
692 }
693 }
694
695
696 //
697 // Map has moved
698 //
699
700 function mapMoved()
701 {
702 var centre = map.getCenter().clone();
703
704 var lonlat = centre.transform(map.getProjectionObject(),epsg4326);
705
706 var zoom = this.getZoom() + map.minZoomLevel;
707
708 map_args="lat=" + lonlat.lat + ";lon=" + lonlat.lon + ";zoom=" + zoom;
709
710 updateCustomURL();
711 }
712
713
714 //
715 // OpenLayers.Control.DragFeature callback for a drag occuring.
716 //
717
718 function dragMove(feature,pixel)
719 {
720 for(var marker in markers)
721 if(feature==markers[marker])
722 {
723 markersmoved=true;
724
725 coordsSetForm(marker);
726 }
727 }
728
729
730 //
731 // OpenLayers.Control.DragFeature callback for completing a drag.
732 //
733
734 function dragComplete(feature,pixel)
735 {
736 for(var marker in markers)
737 if(feature==markers[marker])
738 {
739 markersmoved=true;
740
741 coordsSetForm(marker);
742 }
743 }
744
745
746 ////////////////////////////////////////////////////////////////////////////////
747 /////////////////////////////// Marker handling ////////////////////////////////
748 ////////////////////////////////////////////////////////////////////////////////
749
750 var nmarkers, vismarkers, markers, markersmoved, paramschanged;
751 var homelat=null, homelon=null;
752
753
754 //
755 // Toggle a marker on the map.
756 //
757
758 function markerToggleMap(marker)
759 {
760 if(markers[marker].style.display == "")
761 markerRemoveMap(marker);
762 else
763 markerAddMap(marker);
764 }
765
766
767 //
768 // Show a marker on the map.
769 //
770
771 function markerAddMap(marker)
772 {
773 markers[marker].style.display = "";
774
775 formSetCoords(marker);
776
777 updateIcon(marker);
778
779 markersmoved=true;
780 }
781
782
783 //
784 // Remove a marker from the map.
785 //
786
787 function markerRemoveMap(marker)
788 {
789 markers[marker].style.display = "none";
790
791 updateIcon(marker);
792
793 markersmoved=true;
794 }
795
796
797 //
798 // Centre the marker on the map
799 //
800
801 function markerCentre(marker)
802 {
803 document.forms["form"].elements["lon" + marker].value="";
804 document.forms["form"].elements["lat" + marker].value="";
805
806 formSetCoords(marker);
807
808 markersmoved=true;
809 }
810
811
812 //
813 // Clear the current marker.
814 //
815
816 function markerRemove(marker)
817 {
818 for(var marker2=marker;marker2<vismarkers;marker2++)
819 {
820 document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2+1)].value;
821 document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2+1)].value;
822
823 if(markers[marker2+1].style.display=="")
824 markerAddMap(marker2);
825 else
826 markerRemoveMap(marker2);
827 }
828
829 markerRemoveMap(vismarkers);
830
831 var marker_tr=document.getElementById("point" + vismarkers);
832
833 marker_tr.style.display="none";
834
835 vismarkers--;
836
837 if(vismarkers==1)
838 markerAddAfter(1);
839
840 updateCustomURL();
841 }
842
843
844 //
845 // Add a marker before the current one.
846 //
847
848 function markerAddBefore(marker)
849 {
850 if(vismarkers==nmarkers || marker==1)
851 return false;
852
853 vismarkers++;
854
855 var marker_tr=document.getElementById("point" + vismarkers);
856
857 marker_tr.style.display="";
858
859 for(var marker2=vismarkers;marker2>marker;marker2--)
860 {
861 document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2-1)].value;
862 document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2-1)].value;
863
864 if(markers[marker2-1].style.display=="")
865 markerAddMap(marker2);
866 else
867 markerRemoveMap(marker2);
868 }
869
870 document.forms["form"].elements["lon" + marker].value="";
871 document.forms["form"].elements["lat" + marker].value="";
872 markers[marker].style.display="none";
873
874 markerRemoveMap(marker);
875
876 updateCustomURL();
877 }
878
879
880 //
881 // Add a marker after the current one.
882 //
883
884 function markerAddAfter(marker)
885 {
886 if(vismarkers==nmarkers)
887 return false;
888
889 vismarkers++;
890
891 var marker_tr=document.getElementById("point" + vismarkers);
892
893 marker_tr.style.display="";
894
895 for(var marker2=vismarkers;marker2>(marker+1);marker2--)
896 {
897 document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2-1)].value;
898 document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2-1)].value;
899
900 if(markers[marker2-1].style.display=="")
901 markerAddMap(marker2);
902 else
903 markerRemoveMap(marker2);
904 }
905
906 document.forms["form"].elements["lon" + (marker+1)].value="";
907 document.forms["form"].elements["lat" + (marker+1)].value="";
908 markers[marker+1].style.display="none";
909
910 markerRemoveMap(marker+1);
911
912 updateCustomURL();
913 }
914
915
916 //
917 // Set this marker as the home location.
918 //
919
920 function markerHome(marker)
921 {
922 if(markerHomeCookie(marker))
923 for(marker=1;marker<=nmarkers;marker++)
924 updateIcon(marker);
925 }
926
927
928 //
929 // Update an icon to set colours and home or normal marker.
930 //
931
932 function updateIcon(marker)
933 {
934 var lon=document.forms["form"].elements["lon" + marker].value;
935 var lat=document.forms["form"].elements["lat" + marker].value;
936
937 if(lon==homelon && lat==homelat)
938 {
939 if(markers[marker].style.display=="")
940 document.images["waypoint" + marker].src="icons/marker-home-red.png";
941 else
942 document.images["waypoint" + marker].src="icons/marker-home-grey.png";
943
944 markers[marker].style.externalGraphic="icons/marker-home-red.png";
945 }
946 else
947 {
948 if(markers[marker].style.display=="")
949 document.images["waypoint" + marker].src="icons/marker-" + marker + "-red.png";
950 else
951 document.images["waypoint" + marker].src="icons/marker-" + marker + "-grey.png";
952
953 markers[marker].style.externalGraphic="icons/marker-" + marker + "-red.png";
954 }
955
956 layerVectors.drawFeature(markers[marker]);
957 }
958
959
960 //
961 // Set or clear the home marker icon
962 //
963
964 function markerHomeCookie(marker)
965 {
966 var lon=document.forms["form"].elements["lon" + marker].value;
967 var lat=document.forms["form"].elements["lat" + marker].value;
968
969 if(lon=="" || lat=="")
970 return(false);
971
972 var cookie;
973 var date = new Date();
974
975 if((homelat==null && homelon==null) ||
976 (homelat!=lat && homelon!=lon))
977 {
978 cookie="Routino-home=lon:" + lon + ":lat:" + lat;
979
980 date.setUTCFullYear(date.getUTCFullYear()+5);
981
982 homelat=lat;
983 homelon=lon;
984 }
985 else
986 {
987 cookie="Routino-home=unset";
988
989 date.setUTCFullYear(date.getUTCFullYear()-1);
990
991 homelat=null;
992 homelon=null;
993 }
994
995 document.cookie=cookie + ";expires=" + date.toGMTString();
996
997 return(true);
998 }
999
1000
1001 //
1002 // Move this marker up.
1003 //
1004
1005 function markerMoveUp(marker)
1006 {
1007 if(marker==1)
1008 return false;
1009
1010 markerSwap(marker,marker-1);
1011 }
1012
1013
1014 //
1015 // Move this marker down.
1016 //
1017
1018 function markerMoveDown(marker)
1019 {
1020 if(marker==vismarkers)
1021 return false;
1022
1023 markerSwap(marker,marker+1);
1024 }
1025
1026
1027 //
1028 // Swap a pair of markers.
1029 //
1030
1031 function markerSwap(marker1,marker2)
1032 {
1033 var lon=document.forms["form"].elements["lon" + marker1].value;
1034 var lat=document.forms["form"].elements["lat" + marker1].value;
1035 var display=markers[marker1].style.display;
1036
1037 document.forms["form"].elements["lon" + marker1].value=document.forms["form"].elements["lon" + marker2].value;
1038 document.forms["form"].elements["lat" + marker1].value=document.forms["form"].elements["lat" + marker2].value;
1039 if(markers[marker2].style.display=="")
1040 markerAddMap(marker1);
1041 else
1042 markerRemoveMap(marker1);
1043
1044 document.forms["form"].elements["lon" + marker2].value=lon;
1045 document.forms["form"].elements["lat" + marker2].value=lat;
1046 if(display=="")
1047 markerAddMap(marker2);
1048 else
1049 markerRemoveMap(marker2);
1050
1051 updateCustomURL();
1052 }
1053
1054
1055 //
1056 // Reverse the markers.
1057 //
1058
1059 function markersReverse()
1060 {
1061 for(var marker=1;marker<=vismarkers/2;marker++)
1062 markerSwap(marker,vismarkers+1-marker);
1063
1064 updateCustomURL();
1065 }
1066
1067
1068 ////////////////////////////////////////////////////////////////////////////////
1069 //////////////////////////// Route results handling ////////////////////////////
1070 ////////////////////////////////////////////////////////////////////////////////
1071
1072 var route_light_colours={shortest: "#60C060", quickest: "#6060C0"};
1073 var route_dark_colours ={shortest: "#408040", quickest: "#404080"};
1074
1075 var highlights={shortest: null, quickest: null};
1076 var popups={shortest: null, quickest: null};
1077 var routepoints={shortest: {}, quickest: {}};
1078 var gpx_style={shortest: null, quickest: null};
1079
1080 //
1081 // Zoom to a specific item in the route
1082 //
1083
1084 function zoomTo(type,line)
1085 {
1086 var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat).transform(epsg4326,map.getProjectionObject());
1087
1088 map.moveTo(lonlat,map.numZoomLevels-2);
1089 }
1090
1091
1092 //
1093 // Highlight a specific item in the route
1094 //
1095
1096 function highlight(type,line)
1097 {
1098 if(line==-1)
1099 {
1100 highlights[type].style.display = "none";
1101
1102 drawPopup(popups[type],null);
1103 }
1104 else
1105 {
1106 // Marker
1107
1108 var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat).transform(epsg4326,map.getProjectionObject());
1109
1110 highlights[type].move(lonlat);
1111
1112 if(highlights[type].style.display = "none")
1113 highlights[type].style.display = "";
1114
1115 // Popup
1116
1117 drawPopup(popups[type],"<table>" + routepoints[type][line].html + "</table>");
1118 }
1119
1120 layerVectors.drawFeature(highlights[type]);
1121 }
1122
1123
1124 //
1125 // Create a popup - not using OpenLayers because want it fixed on screen not fixed on map.
1126 //
1127
1128 function createPopup(type)
1129 {
1130 var popup=document.createElement('div');
1131
1132 popup.className = "popup";
1133
1134 popup.innerHTML = "<span></span>";
1135
1136 popup.style.display = "none";
1137
1138 popup.style.position = "fixed";
1139 popup.style.top = "-4000px";
1140 popup.style.left = "-4000px";
1141 popup.style.zIndex = "100";
1142
1143 popup.style.padding = "5px";
1144
1145 popup.style.opacity=0.85;
1146 popup.style.backgroundColor=route_light_colours[type];
1147 popup.style.border="4px solid " + route_dark_colours[type];
1148
1149 document.body.appendChild(popup);
1150
1151 return(popup);
1152 }
1153
1154
1155 //
1156 // Draw a popup - not using OpenLayers because want it fixed on screen not fixed on map.
1157 //
1158
1159 function drawPopup(popup,html)
1160 {
1161 if(html==null)
1162 {
1163 popup.style.display="none";
1164 return;
1165 }
1166
1167 if(popup.style.display=="none")
1168 {
1169 var map_div=document.getElementById("map");
1170
1171 popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px";
1172 popup.style.top = map_div.offsetTop +30 + "px";
1173 popup.style.width =map_div.clientWidth-100 + "px";
1174
1175 popup.style.display="";
1176 }
1177
1178 popup.innerHTML=html;
1179 }
1180
1181
1182 //
1183 // Remove a GPX trace
1184 //
1185
1186 function removeGPXTrace(type)
1187 {
1188 map.removeLayer(layerGPX[type]);
1189 layerGPX[type].destroy();
1190 layerGPX[type]=null;
1191
1192 displayStatus(type,"no_info");
1193
1194 var div_links=document.getElementById(type + "_links");
1195 div_links.style.display = "none";
1196
1197 var div_route=document.getElementById(type + "_route");
1198 div_route.innerHTML = "";
1199
1200 hideshow_hide(type);
1201 }
1202
1203
1204 ////////////////////////////////////////////////////////////////////////////////
1205 /////////////////////////////// Server handling ////////////////////////////////
1206 ////////////////////////////////////////////////////////////////////////////////
1207
1208 //
1209 // Display data statistics
1210 //
1211
1212 function displayStatistics()
1213 {
1214 // Use AJAX to get the statistics
1215
1216 OpenLayers.loadURL("statistics.cgi",null,null,runStatisticsSuccess);
1217 }
1218
1219
1220 //
1221 // Success in running data statistics generation.
1222 //
1223
1224 function runStatisticsSuccess(response)
1225 {
1226 var statistics_data=document.getElementById("statistics_data");
1227 var statistics_link=document.getElementById("statistics_link");
1228
1229 statistics_data.innerHTML="<pre>" + response.responseText + "</pre>";
1230
1231 statistics_link.style.display="none";
1232 }
1233
1234
1235 //
1236 // Submit form - perform the routing
1237 //
1238
1239 function findRoute(type)
1240 {
1241 tab_select("results");
1242
1243 hideshow_hide('help_options');
1244 hideshow_hide('shortest');
1245 hideshow_hide('quickest');
1246
1247 displayStatus("result","running");
1248
1249 var url="router.cgi" + buildURLArguments(0) + ";type=" + type;
1250
1251 // Destroy the existing layer(s)
1252
1253 if(markersmoved || paramschanged)
1254 {
1255 if(layerGPX.shortest!=null)
1256 removeGPXTrace("shortest");
1257 if(layerGPX.quickest!=null)
1258 removeGPXTrace("quickest");
1259 markersmoved=false;
1260 paramschanged=false;
1261 }
1262 else if(layerGPX[type]!=null)
1263 removeGPXTrace(type);
1264
1265 // Use AJAX to run the router
1266
1267 routing_type=type;
1268
1269 OpenLayers.loadURL(url,null,null,runRouterSuccess,runRouterFailure);
1270 }
1271
1272
1273 //
1274 // Success in running router.
1275 //
1276
1277 function runRouterSuccess(response)
1278 {
1279 var lines=response.responseText.split('\n');
1280
1281 var uuid=lines[0];
1282 var cpuinfo=lines[1];
1283 var distinfo=lines[2];
1284 var message=lines[3];
1285
1286 // Update the status message
1287
1288 if(message!="")
1289 {
1290 displayStatus("result","error");
1291 hideshow_show('help_route');
1292 return;
1293 }
1294 else
1295 {
1296 displayStatus("result","complete");
1297 hideshow_hide('help_route');
1298 }
1299
1300 // Update the routing result message
1301
1302 displayStatus(routing_type,"info",distinfo.bold());
1303
1304 var link;
1305
1306 link=document.getElementById(routing_type + "_html");
1307 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
1308 link=document.getElementById(routing_type + "_gpx_track");
1309 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1310 link=document.getElementById(routing_type + "_gpx_route");
1311 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";
1312 link=document.getElementById(routing_type + "_text_all");
1313 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";
1314 link=document.getElementById(routing_type + "_text");
1315 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";
1316
1317 var div_links=document.getElementById(routing_type + "_links");
1318 div_links.style.display = "";
1319
1320 // Add a GPX layer
1321
1322 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1323
1324 layerGPX[routing_type] = new OpenLayers.Layer.GML("GPX (" + routing_type + ")", url,
1325 {
1326 format: OpenLayers.Format.GPX,
1327 style: gpx_style[routing_type],
1328 projection: map.displayProjection
1329 });
1330
1331 map.addLayer(layerGPX[routing_type]);
1332
1333 hideshow_show(routing_type);
1334
1335 displayResult(routing_type,uuid);
1336 }
1337
1338
1339 //
1340 // Failure in running router.
1341 //
1342
1343 function runRouterFailure(response)
1344 {
1345 displayStatus("result","failed");
1346 }
1347
1348
1349 //
1350 // Display the status
1351 //
1352
1353 function displayStatus(type,subtype,content)
1354 {
1355 var div_status=document.getElementById(type + "_status");
1356
1357 var child=div_status.firstChild;
1358
1359 do
1360 {
1361 if(child.id != undefined)
1362 child.style.display="none";
1363
1364 child=child.nextSibling;
1365 }
1366 while(child != undefined);
1367
1368 var span_status=document.getElementById(type + "_status_" + subtype);
1369
1370 span_status.style.display="";
1371
1372 if(content != null)
1373 span_status.innerHTML=content;
1374 }
1375
1376
1377 //
1378 // Display the route
1379 //
1380
1381 function displayResult(type,uuid)
1382 {
1383 routing_type = type;
1384
1385 // Add the route
1386
1387 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
1388
1389 // Use AJAX to get the route
1390
1391 OpenLayers.loadURL(url,null,null,getRouteSuccess,getRouteFailure);
1392 }
1393
1394
1395 //
1396 // Success in getting route.
1397 //
1398
1399 function getRouteSuccess(response)
1400 {
1401 var lines=response.responseText.split('\n');
1402 var div_route=document.getElementById(routing_type + "_route");
1403
1404 routepoints[routing_type]=[];
1405
1406 var points=routepoints[routing_type];
1407
1408 var table=0;
1409 var point=0;
1410 var total_table,total_word;
1411
1412 for(var line=0;line<lines.length;line++)
1413 {
1414 var thisline=lines[line];
1415
1416 if(table==0)
1417 {
1418 if(thisline.match('<table>'))
1419 table=1;
1420 else
1421 continue;
1422 }
1423
1424 if(thisline.match('</table>'))
1425 break;
1426
1427 if(thisline.match('<tr class=\'([a-z])\'>'))
1428 {
1429 var rowtype=RegExp.$1;
1430
1431 if(rowtype=='c')
1432 {
1433 thisline.match('<td class=\'r\'> *([-0-9.]+) *([-0-9.]+)');
1434 points[point]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), html: "", highway: "", distance: "", total: ""};
1435
1436 point++;
1437 }
1438 else if(rowtype=='n')
1439 {
1440 points[point-1].html += thisline;
1441 }
1442 else if(rowtype=='s')
1443 {
1444 thisline.match('<span class=\'h\'>([^<]+)</span>');
1445 points[point-1].highway = RegExp.$1;
1446
1447 thisline.match('<span class=\'d\'>([^<]+)</span>');
1448 points[point-1].distance = RegExp.$1;
1449
1450 thisline.match('(<span class=\'j\'>[^<]+</span>)');
1451 points[point-1].total = RegExp.$1;
1452
1453 thisline.match('^(.*).<span class=\'j\'>');
1454
1455 points[point-1].html += RegExp.$1;
1456 }
1457 else if(rowtype=='t')
1458 {
1459 points[point-1].html += thisline;
1460
1461 thisline.match('^(.*<td class=\'r\'>)');
1462 total_table = RegExp.$1;
1463
1464 thisline.match('<td class=\'l\'>([^<]+)<');
1465 total_word = RegExp.$1;
1466
1467 thisline.match('<span class=\'j\'>([^<]+)</span>');
1468 points[point-1].total = RegExp.$1;
1469 }
1470 }
1471 }
1472
1473 var result="<table onmouseout='highlight(\"" + routing_type + "\",-1)'>";
1474
1475 for(var p=0;p<point-1;p++)
1476 {
1477 points[p].html += total_table + points[p].total;
1478
1479 result=result + "<tr onclick='zoomTo(\"" + routing_type + "\"," + p + ")'" +
1480 " onmouseover='highlight(\"" + routing_type + "\"," + p + ")'>" +
1481 "<td class='distance' title='" + points[p].distance + "'>#" + (p+1) +
1482 "<td class='highway'>" + points[p].highway;
1483 }
1484
1485 result=result + "<tr onclick='zoomTo(\"" + routing_type + "\"," + p + ")'" +
1486 " onmouseover='highlight(\"" + routing_type + "\"," + p + ")'>" +
1487 "<td colspan='2'>" + total_word + " " + points[p].total;
1488
1489 result=result + "</table>";
1490
1491 div_route.innerHTML=result;
1492 }
1493
1494
1495 //
1496 // Failure in getting route.
1497 //
1498
1499 function getRouteFailure(response)
1500 {
1501 var div_route=document.getElementById(routing_type + "_route");
1502 div_route.innerHTML = "";
1503 }