diff --git a/README.md b/README.md index 5dce2e12c..2dc09ed0d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Setup ----- The frontend should work directly as provided. Several settings - including the URL for the routing server and the geocoder server - can be specified in `OSRM.config.js`. -Different tile servers can be specified in `OSRM.main.js`. +Different tile servers can be specified in `OSRM.Map.js`. Note that the URL shortener used for generating route links only works with URLs pointing to the official Project-OSRM website. diff --git a/WebContent/L.Bugfixes.js b/WebContent/L.Bugfixes.js new file mode 100644 index 000000000..e1979df15 --- /dev/null +++ b/WebContent/L.Bugfixes.js @@ -0,0 +1,80 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// Leaflet bugfixes +// [assorted bugfixes to Leaflet functions we use] + + +// return closest point on segment or distance to that point +L.LineUtil._sqClosestPointOnSegment = function (p, p1, p2, sqDist) { + var x = p1.x, + y = p1.y, + dx = p2.x - x, + dy = p2.y - y, + dot = dx * dx + dy * dy, + t; + + if (dot > 0) { + t = ((p.x - x) * dx + (p.y - y) * dy) / dot; + + if (t > 1) { + x = p2.x; + y = p2.y; + } else if (t > 0) { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + // DS_CHANGE: modified return values + if(sqDist) + return dx*dx + dy*dy; + else { + var p = new L.Point(x,y); + p._sqDist = dx*dx + dy*dy; + return p; + } +}; + + +// makes requestAnimFrame respect the immediate paramter -> prevents drag events after dragend events +// (alternatively: add if(!this.dragging ) return to L.Draggable._updatePosition, but must be done in leaflet.js!) +// [TODO: In Leaflet 0.4 use L.Util.cancelAnimFrame(this._animRequest) in L.Draggable._onUp() instead, also has to be done in leaflet.js!] +L.Util.requestAnimFrame = (function () { + function timeoutDefer(callback) { + window.setTimeout(callback, 1000 / 60); + } + + var requestFn = window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + timeoutDefer; + + return function (callback, context, immediate, contextEl) { + callback = context ? L.Util.bind(callback, context) : callback; + if (immediate ) { // DS_CHANGE: removed additional condition requestFn === timeoutDefer + callback(); + } else { + requestFn(callback, contextEl); + } + }; +}()); diff --git a/WebContent/L.MouseMarker.js b/WebContent/L.MouseMarker.js index 87eaed1a7..b19d96861 100644 --- a/WebContent/L.MouseMarker.js +++ b/WebContent/L.MouseMarker.js @@ -16,8 +16,7 @@ or see http://www.gnu.org/licenses/agpl.txt. */ // Leaflet extension: MouseMarker -// [marker class that propagates modifier and button presses] -// [currently deactivated: propagation mousemove events] +// [marker class that propagates modifier and button presses in mouse click events and allows for changing icons] // extended marker class @@ -25,21 +24,33 @@ L.MouseMarker = L.Marker.extend({ initialize: function (latlng, options) { L.Marker.prototype.initialize.apply(this, arguments); }, - -// _initInteraction: function (){ -// L.Marker.prototype._initInteraction.apply(this, arguments); -// if (this.options.clickable) -// L.DomEvent.addListener(this._icon, 'mousemove', this._fireMouseEvent, this); -// }, - -// _fireMouseEvent: function (e) { -// this.fire(e.type, { -// latlng: this._map.mouseEventToLatLng(e), -// layerPoint: this._map.mouseEventToLayerPoint(e) -// }); -// L.DomEvent.stopPropagation(e); -// }, + switchIcon: function( icon ) { + this.options.icon = icon; + + if (this._map) { + this._changeIcon(); + this._reset(); + } + }, + + _changeIcon: function () { + var options = this.options; + + if (this._icon) { + this._icon = options.icon.switchIcon( this._icon ); + this._icon.title = options.title; + } + + var panes = this._map._panes; + + if (this._shadow) + panes.shadowPane.removeChild(this._shadow); + this._shadow = options.icon.createShadow(); + if (this._shadow) + panes.shadowPane.appendChild(this._shadow); + }, + _onMouseClick: function (e) { L.DomEvent.stopPropagation(e); if (this.dragging && this.dragging.moved()) { return; } diff --git a/WebContent/L.SwitchableIcon.js b/WebContent/L.SwitchableIcon.js new file mode 100644 index 000000000..8a93d863e --- /dev/null +++ b/WebContent/L.SwitchableIcon.js @@ -0,0 +1,115 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// Leaflet extension: SwitchableIcon +// [will be an extension of L.Icon in Leaflet 0.4, for now it is a copy with added functionality] + + +// icon class with functions to simply switch the icon images +L.SwitchableIcon = L.Class.extend({ + options: { + /* + iconUrl: (String) (required) + iconSize: (Point) (can be set through CSS) + iconAnchor: (Point) (centered by default if size is specified, can be set in CSS with negative margins) + popupAnchor: (Point) (if not specified, popup opens in the anchor point) + shadowUrl: (Point) (no shadow by default) + shadowSize: (Point) + */ + className: '' + }, + + initialize: function (options) { + L.Util.setOptions(this, options); + }, + + createIcon: function () { + return this._createIcon('icon'); + }, + + createShadow: function () { + return this.options.shadowUrl ? this._createIcon('shadow') : null; + }, + + _createIcon: function (name) { + var img = this._createImg(this.options[name + 'Url']); + this._setIconStyles(img, name); + return img; + }, + + _setIconStyles: function (img, name) { + var options = this.options, + size = options[name + 'Size'], + anchor = options.iconAnchor; + + if (!anchor && size) { + anchor = size.divideBy(2, true); + } + + if (name === 'shadow' && anchor && options.shadowOffset) { + anchor._add(options.shadowOffset); + } + + img.className = 'leaflet-marker-' + name + ' ' + options.className; + + if (anchor) { + img.style.marginLeft = (-anchor.x) + 'px'; + img.style.marginTop = (-anchor.y) + 'px'; + } + + if (size) { + img.style.width = size.x + 'px'; + img.style.height = size.y + 'px'; + } + }, + + _createImg: function (src) { + var el; + if (!L.Browser.ie6) { + el = document.createElement('img'); + el.src = src; + } else { + el = document.createElement('div'); + el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '")'; + } + return el; + }, + + // new functions start here + switchIcon: function (el) { + return this._switchIcon('icon', el); + }, + + switchShadow: function (el) { + return this.options.shadowUrl ? this._switchIcon('shadow', el) : null; + }, + + _switchIcon: function (name, el) { + var img = this._switchImg(this.options[name + 'Url'], el); + this._setIconStyles(img, name); + return img; + }, + + _switchImg: function (src, el) { + if (!L.Browser.ie6) { + el.src = src; + } else { + el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '")'; + } + return el; + } +}); diff --git a/WebContent/OSRM.GUI.js b/WebContent/OSRM.GUI.js index e2096f664..b1ede611b 100644 --- a/WebContent/OSRM.GUI.js +++ b/WebContent/OSRM.GUI.js @@ -20,10 +20,34 @@ or see http://www.gnu.org/licenses/agpl.txt. OSRM.GUI = { + +// defaults +visible: null, +width: null, -// default state -visible: true, -width: 410, +// init GUI +init: function() { + OSRM.GUI.visible = true; + OSRM.GUI.width = document.getElementById("main-wrapper").clientWidth; + + // translate + document.getElementById("open-josm").innerHTML = OSRM.loc("OPEN_JOSM"); + document.getElementById("open-osmbugs").innerHTML = OSRM.loc("OPEN_OSMBUGS"); + document.getElementById("gui-reset").innerHTML = OSRM.loc("GUI_RESET"); + document.getElementById("gui-reverse").innerHTML = OSRM.loc("GUI_REVERSE"); + document.getElementById("gui-option-highlight-nonames-label").innerHTML = OSRM.loc("GUI_HIGHLIGHT_UNNAMED_ROADS"); + document.getElementById("options-toggle").innerHTML = OSRM.loc("GUI_OPTIONS"); + document.getElementById("gui-search-source").innerHTML = OSRM.loc("GUI_SEARCH"); + document.getElementById("gui-search-target").innerHTML = OSRM.loc("GUI_SEARCH"); + document.getElementById("gui-search-source-label").innerHTML = OSRM.loc("GUI_START")+":"; + document.getElementById("gui-search-target-label").innerHTML = OSRM.loc("GUI_END")+":"; + document.getElementById("input-source-name").title = OSRM.loc("GUI_START_TOOLTIP"); + document.getElementById("input-target-name").title = OSRM.loc("GUI_END_TOOLTIP"); + document.getElementById("legal-notice").innerHTML = OSRM.loc("GUI_LEGAL_NOTICE"); + + document.getElementById('input-source-name').value = OSRM.DEFAULTS.ONLOAD_SOURCE; + document.getElementById('input-target-name').value = OSRM.DEFAULTS.ONLOAD_TARGET; +}, // show/hide main-gui toggleMain: function() { diff --git a/WebContent/OSRM.Geocoder.js b/WebContent/OSRM.Geocoder.js index fef263524..6896d702c 100644 --- a/WebContent/OSRM.Geocoder.js +++ b/WebContent/OSRM.Geocoder.js @@ -60,7 +60,7 @@ _onclickResult: function(marker_id, lat, lon) { OSRM.G.markers.route[index].show(); OSRM.G.markers.route[index].centerView(); - getRoute(OSRM.C.FULL_DESCRIPTION); + OSRM.Routing.getRoute(); }, diff --git a/WebContent/OSRM.JSONP.js b/WebContent/OSRM.JSONP.js index 1c9bcc8ff..bdd611401 100644 --- a/WebContent/OSRM.JSONP.js +++ b/WebContent/OSRM.JSONP.js @@ -66,8 +66,8 @@ OSRM.JSONP = { OSRM.JSONP.fences[id] = undefined; // clean fence } - OSRM.JSONP.sum[id] += new Number( new Date() - OSRM.JSONP.durations[id] ); - OSRM.debug.log("[jsonp] response handling: "+id+" "+ (OSRM.JSONP.sum[id]/OSRM.JSONP.counter[id]).toFixed(2) ); +// OSRM.JSONP.sum[id] += new Number( new Date() - OSRM.JSONP.durations[id] ); +// OSRM.debug.log("[jsonp] response handling: "+id+" "+ (OSRM.JSONP.sum[id]/OSRM.JSONP.counter[id]).toFixed(2) ); }; // clean DOM (unfortunately, script elements cannot be reused by all browsers) @@ -85,12 +85,11 @@ OSRM.JSONP = { // start timeout timer OSRM.JSONP.timers[id] = setTimeout(OSRM.JSONP.timeouts[id], timeout); - // statistics - if(!OSRM.JSONP.durations) { OSRM.JSONP.durations = {}; OSRM.JSONP.counter = {}; OSRM.JSONP.sum = {}; } - if(OSRM.JSONP.counter[id]) OSRM.JSONP.counter[id]++; else {OSRM.JSONP.counter[id] = 1;OSRM.JSONP.sum[id] = 0;} - OSRM.JSONP.durations[id] = new Date(); - -// OSRM.debug.log("[jsonp] init: "+id); +// if(!OSRM.JSONP.durations) { OSRM.JSONP.durations = {}; OSRM.JSONP.counter = {}; OSRM.JSONP.sum = {}; } +// if(OSRM.JSONP.counter[id]) OSRM.JSONP.counter[id]++; else {OSRM.JSONP.counter[id] = 1;OSRM.JSONP.sum[id] = 0;} +// OSRM.JSONP.durations[id] = new Date(); +// OSRM.debug.log("[jsonp] init: "+id); + return true; }, @@ -101,4 +100,4 @@ OSRM.JSONP = { OSRM.JSONP.timeouts = {}; OSRM.JSONP.timers = {}; } -}; \ No newline at end of file +}; diff --git a/WebContent/OSRM.Localization.js b/WebContent/OSRM.Localization.js index 110d16bbb..ffe7ec9ec 100644 --- a/WebContent/OSRM.Localization.js +++ b/WebContent/OSRM.Localization.js @@ -39,12 +39,14 @@ OSRM.loc = OSRM.Localization.translate; // German language support OSRM.Localization["de"] = { //gui +"OPEN_JOSM": "JOSM", +"OPEN_OSMBUGS": "OSM Bugs", "GUI_START": "Start", "GUI_END": "Ziel", "GUI_RESET": "Reset", "GUI_SEARCH": "Zeigen", "GUI_REVERSE": "Umdrehen", -"GUI_OPTIONS": "Optionen", +"GUI_OPTIONS": "Kartenwerkzeuge", "GUI_HIGHLIGHT_UNNAMED_ROADS": "Unbenannte Straßen hervorheben", "GUI_START_TOOLTIP": "Startposition eingeben", "GUI_END_TOOLTIP": "Zielposition eingeben", @@ -80,12 +82,14 @@ OSRM.Localization["de"] = { // English language support OSRM.Localization["en"] = { //gui +"OPEN_JOSM": "JOSM", +"OPEN_OSMBUGS": "OSM Bugs", "GUI_START": "Start", "GUI_END": "End", "GUI_RESET": "  Reset  ", "GUI_SEARCH": "  Show  ", "GUI_REVERSE": "Reverse", -"GUI_OPTIONS": "Options", +"GUI_OPTIONS": "Mapping Tools", "GUI_HIGHLIGHT_UNNAMED_ROADS": "Highlight unnamed streets", "GUI_START_TOOLTIP": "Enter start", "GUI_END_TOOLTIP": "Enter destination", diff --git a/WebContent/OSRM.Map.js b/WebContent/OSRM.Map.js new file mode 100644 index 000000000..1031f3f0a --- /dev/null +++ b/WebContent/OSRM.Map.js @@ -0,0 +1,151 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM map handling +// [initialization, event handling, centering relative to UI] + +// will hold the map object +OSRM.GLOBALS.map = null; + + +// map view/model +// [extending Leaflet L.Map with setView/fitBounds methods that respect UI visibility] +OSRM.MapView = L.Map.extend({ + setViewUI: function(position, zoom) { + if( OSRM.GUI.visible == true ) { + var point = OSRM.G.map.project( position, zoom); + point.x-=OSRM.GUI.width/2; + position = OSRM.G.map.unproject(point,zoom); + } + this.setView( position, zoom); + }, + fitBoundsUI: function(bounds) { + var southwest = bounds.getSouthWest(); + var northeast = bounds.getNorthEast(); + var zoom = OSRM.G.map.getBoundsZoom(bounds); + var sw_point = OSRM.G.map.project( southwest, zoom); + if( OSRM.GUI.visible == true ) + sw_point.x-=OSRM.GUI.width/2; + else + sw_point.x-=10; + sw_point.y+=10; + var ne_point = OSRM.G.map.project( northeast, zoom); + ne_point.y-=10; + sw_point.x+=10; + bounds.extend( OSRM.G.map.unproject(sw_point,zoom) ); + bounds.extend( OSRM.G.map.unproject(ne_point,zoom) ); + this.fitBounds( bounds ); + }, + getCenterUI: function(unbounded) { + var viewHalf = this.getSize(); + if( OSRM.GUI.visible == true ) + viewHalf.x += OSRM.GUI.width; + var centerPoint = this._getTopLeftPoint().add(viewHalf.divideBy(2)); + + return this.unproject(centerPoint, this._zoom, unbounded); + } +}); + + +// map controller +// [map initialization, event handling] +OSRM.Map = { + +// map initialization +init: function() { + // check if GUI is initialized! + if(OSRM.GUI.visible == null) + OSRM.GUI.init(); + + // setup tile servers + var osmorgURL = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + osmorgAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 Mapnik', + osmorgOptions = {maxZoom: 18, attribution: osmorgAttribution}; + + var osmdeURL = 'http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', + osmdeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 Mapnik', + osmdeOptions = {maxZoom: 18, attribution: osmdeAttribution}; + + var mapquestURL = 'http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', + mapquestAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 MapQuest', + mapquestOptions = {maxZoom: 18, attribution: mapquestAttribution, subdomains: '1234'}; + + var cloudmadeURL = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', + cloudmadeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade', + cloudmadeOptions = {maxZoom: 18, attribution: cloudmadeAttribution}; + + var osmorg = new L.TileLayer(osmorgURL, osmorgOptions), + osmde = new L.TileLayer(osmdeURL, osmdeOptions), + mapquest = new L.TileLayer(mapquestURL, mapquestOptions), + cloudmade = new L.TileLayer(cloudmadeURL, cloudmadeOptions); + + // setup map + OSRM.G.map = new OSRM.MapView('map', { + center: new L.LatLng(51.505, -0.09), + zoom: 13, + zoomAnimation: false, // false: removes animations and hiding of routes during zoom + fadeAnimation: false, + layers: [osmorg] + }); + + // add tileservers + var baseMaps = { + "osm.org": osmorg, + "osm.de": osmde, + "MapQuest": mapquest, + "CloudMade": cloudmade + }; + + var overlayMaps = {}; + var layersControl = new L.Control.Layers(baseMaps, overlayMaps); + OSRM.G.map.addControl(layersControl); + + // move zoom markers + getElementsByClassName(document,'leaflet-control-zoom')[0].style.left=(OSRM.GUI.width+10)+"px"; + getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px"; + + // initial map position and zoom + var position = new L.LatLng( OSRM.DEFAULTS.ONLOAD_LATITUDE, OSRM.DEFAULTS.ONLOAD_LONGITUDE); + OSRM.G.map.setViewUI( position, OSRM.DEFAULTS.ZOOM_LEVEL); + + // map events + OSRM.G.map.on('zoomend', OSRM.Map.zoomed ); + OSRM.G.map.on('click', OSRM.Map.click ); + OSRM.G.map.on('contextmenu', OSRM.Map.contextmenu ); + OSRM.G.map.on('mousemove', OSRM.Map.mousemove ); +}, + +// map event handlers +zoomed: function(e) { OSRM.Routing.getRoute(); }, +contextmenu: function(e) {;}, +mousemove: function(e) { OSRM.Via.drawDragMarker(e); }, +click: function(e) { + if( !OSRM.G.markers.hasSource() ) { + var index = OSRM.G.markers.setSource( e.latlng ); + OSRM.Geocoder.updateAddress( OSRM.C.SOURCE_LABEL, OSRM.C.DO_FALLBACK_TO_LAT_LNG ); + OSRM.G.markers.route[index].show(); + OSRM.G.markers.route[index].centerView( OSRM.G.map.getZoom() ); + OSRM.Routing.getRoute(); + } else if( !OSRM.G.markers.hasTarget() ) { + var index = OSRM.G.markers.setTarget( e.latlng ); + OSRM.Geocoder.updateAddress( OSRM.C.TARGET_LABEL, OSRM.C.DO_FALLBACK_TO_LAT_LNG ); + OSRM.G.markers.route[index].show(); + OSRM.G.markers.route[index].centerView( OSRM.G.map.getZoom() ); + OSRM.Routing.getRoute(); + } +} +}; \ No newline at end of file diff --git a/WebContent/OSRM.Markers.js b/WebContent/OSRM.Markers.js index 801b2359e..bc8ff1bd8 100644 --- a/WebContent/OSRM.Markers.js +++ b/WebContent/OSRM.Markers.js @@ -59,16 +59,7 @@ isShown: function() { centerView: function(zoom) { if( zoom == undefined ) zoom = OSRM.DEFAULTS.ZOOM_LEVEL; - - var position; - if( OSRM.GUI.visible == true ) { - var point = OSRM.G.map.project( this.position, zoom); - point.x-=OSRM.GUI.width/2; - position = OSRM.G.map.unproject(point,zoom); - } else { - position = this.position; - } - OSRM.G.map.setView( position, zoom); + OSRM.G.map.setViewUI( this.position, zoom ); }, toString: function() { return "OSRM.Marker: \""+this.label+"\", "+this.position+")"; @@ -76,26 +67,9 @@ toString: function() { }); -// highlight marker class (cannot be dragged) -OSRM.HighlightMarker = function( label, style, position) { - OSRM.HighlightMarker.prototype.base.constructor.apply( this, arguments ); - this.label = label ? label : "highlight_marker"; - - this.marker.on( 'click', this.onClick ); -}; -OSRM.inheritFrom( OSRM.HighlightMarker, OSRM.Marker ); -OSRM.extend( OSRM.HighlightMarker, { -toString: function() { - return "OSRM.HighlightMarker: \""+this.label+"\", "+this.position+")"; -}, -onClick: function(e) { - this.parent.hide(); -} -}); - - // route marker class (draggable, invokes route drawing routines) OSRM.RouteMarker = function ( label, style, position ) { + style.baseicon = style.icon; OSRM.RouteMarker.prototype.base.constructor.apply( this, arguments ); this.label = label ? label : "route_marker"; @@ -114,32 +88,37 @@ onClick: function(e) { } } - getRoute(OSRM.C.FULL_DESCRIPTION); + OSRM.Routing.getRoute(); OSRM.G.markers.highlight.hide(); }, onDrag: function(e) { this.parent.setPosition( e.target.getLatLng() ); - getRoute(OSRM.C.NO_DESCRIPTION); + if(OSRM.G.markers.route.length>1) + OSRM.Routing.getDragRoute(); OSRM.Geocoder.updateLocation( this.parent.label ); }, onDragStart: function(e) { OSRM.G.dragging = true; + this.switchIcon(this.options.dragicon); // store id of dragged marker for( var i=0; i this.route.length-2 ) return -1; - this.route.splice(id+1,0, new OSRM.RouteMarker(OSRM.C.VIA_LABEL, {draggable:true,icon:OSRM.icons['marker-via']}, position)); + this.route.splice(id+1,0, new OSRM.RouteMarker(OSRM.C.VIA_LABEL, {draggable:true,icon:OSRM.G.icons['marker-via'],dragicon:OSRM.G.icons['marker-via-drag']}, position)); return id+1; }, removeMarker: function(id) { @@ -205,13 +218,15 @@ removeMarker: function(id) { this.removeVias(); document.getElementById('input-source-name').value = ""; document.getElementById('information-box').innerHTML = ""; - document.getElementById('information-box-headline').innerHTML = ""; + document.getElementById('information-box-headline').innerHTML = ""; + document.getElementById('delete-source-marker').style.visibility = "hidden"; } else if( id == this.route.length-1 && this.route[ this.route.length-1 ].label == OSRM.C.TARGET_LABEL ) { this.removeVias(); id = this.route.length-1; document.getElementById('input-target-name').value = ""; document.getElementById('information-box').innerHTML = ""; - document.getElementById('information-box-headline').innerHTML = ""; + document.getElementById('information-box-headline').innerHTML = ""; + document.getElementById('delete-target-marker').style.visibility = "hidden"; } this.route[id].hide(); diff --git a/WebContent/OSRM.Route.js b/WebContent/OSRM.Route.js index 19810636c..54a1097e8 100644 --- a/WebContent/OSRM.Route.js +++ b/WebContent/OSRM.Route.js @@ -27,8 +27,6 @@ OSRM.SimpleRoute = function (label, style) { if(style) this.route.setStyle( style ); this.shown = false; - - this.route.on('click', this.onClick); }; OSRM.extend( OSRM.SimpleRoute,{ show: function() { @@ -56,26 +54,7 @@ setStyle: function(style) { }, centerView: function() { var bounds = new L.LatLngBounds( this.getPositions() ); - - var southwest = bounds.getSouthWest(); - var northeast = bounds.getNorthEast(); - var zoom = OSRM.G.map.getBoundsZoom(bounds); - var sw_point = OSRM.G.map.project( southwest, zoom); - if( OSRM.GUI.visible == true ) - sw_point.x-=OSRM.GUI.width/2; - else - sw_point.x-=10; - sw_point.y+=10; - var ne_point = OSRM.G.map.project( northeast, zoom); - ne_point.y-=10; - sw_point.x+=10; - bounds.extend( OSRM.G.map.unproject(sw_point,zoom) ); - bounds.extend( OSRM.G.map.unproject(ne_point,zoom) ); - OSRM.G.map.fitBounds( bounds ); -}, -onClick: function(e) { - if(OSRM.G.route.isRoute()) - OSRM.Via.findViaPosition( e.latlng ); + OSRM.g.map.fitBoundsUI( bounds ); }, toString: function() { return "OSRM.Route("+ this.label + ", " + this.route.getLatLngs().length + " points)"; diff --git a/WebContent/OSRM.Via.js b/WebContent/OSRM.Via.js index d072b9797..0b307de7d 100644 --- a/WebContent/OSRM.Via.js +++ b/WebContent/OSRM.Via.js @@ -44,7 +44,7 @@ _findNearestRouteSegment: function( new_via ) { // find the correct index among all via nodes to insert the new via node, and insert it -findViaPosition: function( new_via_position ) { +findViaIndex: function( new_via_position ) { // find route segment that is closest to click position (marked by last index) var nearest_index = OSRM.Via._findNearestRouteSegment( new_via_position ); @@ -60,12 +60,62 @@ findViaPosition: function( new_via_position ) { } // add via node - var index = OSRM.G.markers.setVia(new_via_index, new_via_position); - OSRM.G.markers.route[index].show(); - - getRoute(OSRM.C.FULL_DESCRIPTION); - return new_via_index; +}, + + +//function that draws a drag marker +dragTimer: new Date(), + +drawDragMarker: function(event) { + if( OSRM.G.route.isShown() == false) + return; + if( OSRM.G.dragging == true ) + return; + + // throttle computation + if( (new Date() - OSRM.Via.dragTimer) < 25 ) + return; + OSRM.Via.dragTimer = new Date(); + + // get distance to route + var minpoint = OSRM.G.route._current_route.route.closestLayerPoint( event.layerPoint ); + var min_dist = minpoint._sqDist; + + // get distance to markers + var mouse = event.latlng; + for(var i=0, size=OSRM.G.markers.route.length; i used to add member values and functions +// extend prototypes of a class -> used to add member values and functions OSRM.extend = function( target_class, properties ) { for( property in properties ) { target_class.prototype[property] = properties[property]; diff --git a/WebContent/OSRM.debug.js b/WebContent/OSRM.debug.js index 6da0d2691..1f363b041 100644 --- a/WebContent/OSRM.debug.js +++ b/WebContent/OSRM.debug.js @@ -21,7 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt. OSRM.debug = {}; -//working functions +// access functions OSRM.debug.log = function(text) { OSRM.debug.content.innerHTML += text + "
"; OSRM.debug.content.scrollTop = OSRM.debug.content.scrollHeight; @@ -63,4 +63,4 @@ OSRM.debug.init = function() { if(document.addEventListener) // FF, CH document.addEventListener("DOMContentLoaded", OSRM.debug.init, false); else // IE - OSRM.debug.init(); \ No newline at end of file + OSRM.debug.init(); diff --git a/WebContent/images/drag.pdf b/WebContent/images/drag.pdf new file mode 100644 index 000000000..9b2ec783e Binary files /dev/null and b/WebContent/images/drag.pdf differ diff --git a/WebContent/images/marker-drag.png b/WebContent/images/marker-drag.png new file mode 100644 index 000000000..9832ead70 Binary files /dev/null and b/WebContent/images/marker-drag.png differ diff --git a/WebContent/images/marker-highlight-drag.png b/WebContent/images/marker-highlight-drag.png new file mode 100644 index 000000000..70e558b99 Binary files /dev/null and b/WebContent/images/marker-highlight-drag.png differ diff --git a/WebContent/images/marker-source-drag.png b/WebContent/images/marker-source-drag.png new file mode 100644 index 000000000..cc72f6fca Binary files /dev/null and b/WebContent/images/marker-source-drag.png differ diff --git a/WebContent/images/marker-target-drag.png b/WebContent/images/marker-target-drag.png new file mode 100644 index 000000000..c3c6f7c08 Binary files /dev/null and b/WebContent/images/marker-target-drag.png differ diff --git a/WebContent/images/marker-via-drag.png b/WebContent/images/marker-via-drag.png new file mode 100644 index 000000000..e1b10039f Binary files /dev/null and b/WebContent/images/marker-via-drag.png differ diff --git a/WebContent/main.css b/WebContent/main.css index 062bb3f9d..31c9ec175 100644 --- a/WebContent/main.css +++ b/WebContent/main.css @@ -148,8 +148,21 @@ html, body, #map { .main-options { + position:relative; font-size:10px; } +.main-options-left-box +{ + position:absolute; + left:5px; + top:0px; +} +.main-options-right-box +{ + position:absolute; + right:5px; + top:5px; +} #options-toggle { cursor:pointer; @@ -333,4 +346,25 @@ html, body, #map { { background-color:#F4F4F4; color:#FF0000; +} + + +.delete-marker +{ + cursor:pointer; + position:absolute; + right:5px; + top:3px; + width:16px; + height:16px; + background-image:url("images/cancel.png"); + visibility:hidden; +} +.delete-marker:hover +{ + background-image:url("images/cancel_hover.png"); +} +.delete-marker:active +{ + background-image:url("images/cancel_active.png"); } \ No newline at end of file diff --git a/WebContent/main.html b/WebContent/main.html index 02933f485..5d6787d60 100644 --- a/WebContent/main.html +++ b/WebContent/main.html @@ -39,32 +39,38 @@ or see http://www.gnu.org/licenses/agpl.txt. + + - + + - - - - + + + + + + + + - - - - + + + - +
@@ -88,14 +94,18 @@ or see http://www.gnu.org/licenses/agpl.txt. - - + + - - + +
Start:Zeigen
+ +
Zeigen
Ende:Zeigen
+ +
Zeigen
@@ -103,17 +113,22 @@ or see http://www.gnu.org/licenses/agpl.txt.
- - + +
Reset Umdrehen Reset Umdrehen
-
-
Options
-
- Unbenannte Straßen hervorheben -
+ Kartenwerkzeuge +
+ + Unbenannte Straßen hervorheben + + + JOSM + OSM Bugs + +
diff --git a/WebContent/main.js b/WebContent/main.js index dd97ca4eb..76471caa7 100644 --- a/WebContent/main.js +++ b/WebContent/main.js @@ -16,34 +16,38 @@ or see http://www.gnu.org/licenses/agpl.txt. */ // OSRM initialization -// [initialization of maps, local strings, image prefetching] +// [initialization, image prefetching] // will hold the Leaflet map object OSRM.GLOBALS.map = null; // onload initialization routine -function init() { - prefetchImages(); - prefetchIcons(); +OSRM.init = function() { + OSRM.prefetchImages(); + OSRM.prefetchIcons(); - initLocale(); - initGUI(); - initMap(); - initRouting(); - - // check if the URL contains some GET parameter, e.g. for the route - checkURL(); -} + OSRM.GUI.init(); + OSRM.Map.init(); + OSRM.Routing.init(); + + // check if the URL contains some GET parameter, e.g. for showing a route + OSRM.checkURL(); +}; // prefetch images -OSRM.images = Array(); -function prefetchImages() { +OSRM.GLOBALS.images = Array(); +OSRM.prefetchImages = function() { var images = [ 'images/marker-source.png', 'images/marker-target.png', 'images/marker-via.png', 'images/marker-highlight.png', + 'images/marker-source-drag.png', + 'images/marker-target-drag.png', + 'images/marker-via-drag.png', + 'images/marker-highlight-drag.png', + 'images/marker-drag.png', 'images/cancel.png', 'images/cancel_active.png', 'images/cancel_hover.png', @@ -53,143 +57,42 @@ function prefetchImages() { ]; for(var i=0; i"; -} -function timeoutRoute() { - showNoRouteGeometry(); - OSRM.G.route.hideUnnamedRoute(); - showNoRouteDescription(); - document.getElementById('information-box').innerHTML = "

"+OSRM.loc("TIMED_OUT")+".

"; -} -function showRouteSimple(response) { - if(!response) - return; - - if( !OSRM.G.dragging ) // prevent simple routing when no longer dragging - return; - - if( response.status == 207) { - showNoRouteGeometry(); - showNoRouteDescription(); - document.getElementById('information-box').innerHTML = "

"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".

"; - } else { - showRouteGeometry(response); - showRouteDescriptionSimple(response); - } - updateHints(response); - -// // TODO: hack to process final drag event, if it was fenced, but we are still dragging (alternative approach) -// if(OSRM.G.pending) { -// clearTimeout(OSRM.G.pendingTimer); -// OSRM.G.pendingTimer = setTimeout(timeoutDrag,100); -// } -} -function showRoute(response) { - if(!response) - return; - - if(response.status == 207) { - showNoRouteGeometry(); - OSRM.G.route.hideUnnamedRoute(); - showNoRouteDescription(); - document.getElementById('information-box').innerHTML = "

"+OSRM.loc("NO_ROUTE_FOUND")+".

"; - } else { - showRouteGeometry(response); - showRouteNonames(response); - showRouteDescription(response); - snapRoute(); - } - updateHints(response); -} - - -// show route geometry -function showNoRouteGeometry() { - var positions = []; - for(var i=0; i'+response.ShortURL+']'; -} -function showRouteLink_TimeOut(){ - document.getElementById('route-prelink').innerHTML = '['+OSRM.loc("LINK_TO_ROUTE_TIMEOUT")+']'; -} -function showRouteDescription(response) { - // compute query string - var query_string = '?rebuild=1'; - for(var i=0; i'+OSRM.loc("GET_LINK_TO_ROUTE")+']'; - - // create GPX link - var gpx_link = '['+OSRM.loc("GPX_FILE")+']'; - - // create route description - var route_desc = ""; - route_desc += ''; - - for(var i=0; i < response.route_instructions.length; i++){ - //odd or even ? - var rowstyle='results-odd'; - if(i%2==0) { rowstyle='results-even'; } - - route_desc += ''; - - route_desc += '"; - - route_desc += '"; - - route_desc += '"; - - route_desc += ""; - } - - route_desc += '
'; - route_desc += ''; - route_desc += "'; - route_desc += ''; - route_desc += response.route_instructions[i][0]; - if( i == 0 ) - route_desc += ' ' + OSRM.loc( response.route_instructions[i][6] ); - if( response.route_instructions[i][1] != "" ) { - route_desc += ' on '; - route_desc += '' + response.route_instructions[i][1] + ''; - } - //route_desc += ' for '; - route_desc += ''; - route_desc += "'; - if( i != response.route_instructions.length-1 ) - route_desc += ''+OSRM.Utils.metersToDistance(response.route_instructions[i][2])+''; - route_desc += "
'; - headline = ""; - headline += OSRM.loc("ROUTE_DESCRIPTION")+":
"; - headline += '

'; - headline += "" - + OSRM.loc("DISTANCE")+": " + OSRM.Utils.metersToDistance(response.route_summary.total_distance) - + "
" - + OSRM.loc("DURATION")+": " + OSRM.Utils.secondsToTime(response.route_summary.total_time) - + "
"; - headline += '
'; - headline += '
'+route_link+'
'+gpx_link+'
'; - - var output = ""; - output += route_desc; - - document.getElementById('information-box-headline').innerHTML = headline; - document.getElementById('information-box').innerHTML = output; -} -function showRouteDescriptionSimple(response) { - headline = OSRM.loc("ROUTE_DESCRIPTION")+":
"; - headline += "" - + OSRM.loc("DISTANCE")+": " + OSRM.Utils.metersToDistance(response.route_summary.total_distance) - + "
" - + OSRM.loc("DURATION")+": " + OSRM.Utils.secondsToTime(response.route_summary.total_time) - + "
"; - headline += '

'; - - document.getElementById('information-box-headline').innerHTML = headline; - document.getElementById('information-box').innerHTML = "

"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".

"; -} -function showNoRouteDescription() { - headline = OSRM.loc("ROUTE_DESCRIPTION")+":
"; - headline += "" - + OSRM.loc("DISTANCE")+": N/A" - + "
" - + OSRM.loc("DURATION")+": N/A" - + "
"; - headline += '

'; - - document.getElementById('information-box-headline').innerHTML = headline; - document.getElementById('information-box').innerHTML = "

"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".

"; -} - - -// unnamed streets display -function showRouteNonames(response) { - // do not display unnamed streets? - if( document.getElementById('option-highlight-nonames').checked == false) { - OSRM.G.route.hideUnnamedRoute(); - return; - } - - // mark geometry positions where unnamed/named streets switch - var named = []; - for (var i = 0; i < response.route_instructions.length; i++) { - if( response.route_instructions[i][1] == '' ) - named[ response.route_instructions[i][3] ] = false; // no street name - else - named[ response.route_instructions[i][3] ] = true; // yes street name - } - - // aggregate geometry for unnamed streets - var geometry = decodeRouteGeometry(response.route_geometry, 5); - var is_named = true; - var current_positions = []; - var all_positions = []; - for( var i=0; i < geometry.length; i++) { - current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) ); - - // still named/unnamed? - if( (named[i] == is_named || named[i] == undefined) && i != geometry.length-1 ) - continue; - - // switch between named/unnamed! - if(is_named == false) - all_positions.push( current_positions ); - current_positions = []; - current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) ); - is_named = named[i]; - } - - // display unnamed streets - OSRM.G.route.showUnnamedRoute(all_positions); -} - - -//-- main function -- - -// generate server calls to query routes -function getRoute(do_description) { - - // if source or target are not set -> hide route - if( OSRM.G.markers.route.length < 2 ) { - OSRM.G.route.hideRoute(); - return; - } - - // prepare JSONP call - var type = null; - var callback = null; - var timeout = null; - - var source = OSRM.DEFAULTS.HOST_ROUTING_URL; - source += '?z=' + OSRM.G.map.getZoom() + '&output=json' + '&geomformat=cmp'; - if(OSRM.G.markers.checksum) - source += '&checksum=' + OSRM.G.markers.checksum; - for(var i=0; i= 0x20); - var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lat += dlat; - shift = 0; - result = 0; - do { - b = encoded.charCodeAt(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lng += dlng; - array.push([lat * precision, lng * precision]); - } - return array; -} - -// update hints of all markers -function updateHints(response) { - var hint_locations = response.hint_data.locations; - OSRM.G.markers.checksum = response.hint_data.checksum; - for(var i=0; i 1){ - OSRM.G.markers.route[0].label = OSRM.C.SOURCE_LABEL; - OSRM.G.markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); - - OSRM.G.markers.route[OSRM.G.markers.route.length-1].label = OSRM.C.TARGET_LABEL; - OSRM.G.markers.route[OSRM.G.markers.route.length-1].marker.setIcon( new L.Icon('images/marker-target.png') ); - } - - // recompute route - if( OSRM.G.route.isShown() ) { - getRoute(OSRM.C.FULL_DESCRIPTION); - OSRM.G.markers.highlight.hide(); - } else { - document.getElementById('information-box').innerHTML = ""; - document.getElementById('information-box-headline').innerHTML = ""; - } -} - -// click: button "show" -function showMarker(marker_id) { - if( OSRM.JSONP.fences["geocoder_source"] || OSRM.JSONP.fences["geocoder_target"] ) - return; - - if( marker_id == OSRM.C.SOURCE_LABEL && OSRM.G.markers.hasSource() ) - OSRM.G.markers.route[0].centerView(); - else if( marker_id == OSRM.C.TARGET_LABEL && OSRM.G.markers.hasTarget() ) - OSRM.G.markers.route[OSRM.G.markers.route.length-1].centerView(); -} - - -// changed: any inputbox (is called when return is pressed [after] or focus is lost [before]) -function inputChanged(marker_id) { - if( marker_id == OSRM.C.SOURCE_LABEL) - OSRM.Geocoder.call(OSRM.C.SOURCE_LABEL, document.getElementById('input-source-name').value); - else if( marker_id == OSRM.C.TARGET_LABEL) - OSRM.Geocoder.call(OSRM.C.TARGET_LABEL, document.getElementById('input-target-name').value); -} diff --git a/WebContent/routing/OSRM.Routing.js b/WebContent/routing/OSRM.Routing.js new file mode 100644 index 000000000..2796d187d --- /dev/null +++ b/WebContent/routing/OSRM.Routing.js @@ -0,0 +1,148 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM routing +// [management of routing requests and processing of responses] + +// some variables +OSRM.GLOBALS.route = null; +OSRM.GLOBALS.markers = null; + +OSRM.GLOBALS.dragging = null; +OSRM.GLOBALS.dragid = null; +OSRM.GLOBALS.pending = false; +OSRM.GLOBALS.pendingTimer = null; + + +OSRM.Routing = { + +// init routing data structures +init: function() { + OSRM.G.route = new OSRM.Route(); + OSRM.G.markers = new OSRM.Markers(); +}, + + +// -- JSONP processing -- + +// process JSONP response of routing server +timeoutRouteSimple: function() { + OSRM.RoutingGeometry.showNA(); + OSRM.RoutingDescription.showNA( OSRM.loc("TIMED_OUT") ); +}, +timeoutRoute: function() { + OSRM.RoutingGeometry.showNA(); + OSRM.RoutingNoNames.showNA(); + OSRM.RoutingDescription.showNA( OSRM.loc("TIMED_OUT") ); +}, +showRouteSimple: function(response) { + if(!response) + return; + if( !OSRM.G.dragging ) // prevent simple routing when no longer dragging + return; + + if( response.status == 207) { + OSRM.RoutingGeometry.showNA(); + OSRM.RoutingDescription.showNA( OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED") ); + } else { + OSRM.RoutingGeometry.show(response); + OSRM.RoutingDescription.showSimple(response); + } + OSRM.Routing._updateHints(response); + + if(OSRM.G.pending) + OSRM.G.pendingTimer = setTimeout(OSRM.Routing.draggingTimeout,1); +}, +showRoute: function(response) { + if(!response) + return; + + OSRM.G.via_points = response.via_points.slice(0); + if(response.status == 207) { + OSRM.RoutingGeometry.showNA(); + OSRM.RoutingNoNames.showNA(); + OSRM.RoutingDescription.showNA( OSRM.loc("NO_ROUTE_FOUND") ); + } else { + OSRM.RoutingGeometry.show(response); + OSRM.RoutingNoNames.show(response); + OSRM.RoutingDescription.show(response); + OSRM.Routing._snapRoute(); + } + OSRM.Routing._updateHints(response); +}, + + + +//-- main function -- + +//generate server calls to query routes +getRoute: function() { + + // if source or target are not set -> hide route + if( OSRM.G.markers.route.length < 2 ) { + OSRM.G.route.hideRoute(); + return; + } + + OSRM.JSONP.call(OSRM.Routing._buildCall()+'&instructions=true', OSRM.Routing.showRoute, OSRM.Routing.timeoutRoute, OSRM.DEFAULTS.JSONP_TIMEOUT, 'route'); +}, +getDragRoute: function() { + OSRM.G.pending = !OSRM.JSONP.call(OSRM.Routing._buildCall()+'&instructions=false', OSRM.Routing.showRouteSimple, OSRM.Routing.timeoutRouteSimple, OSRM.DEFAULTS.JSONP_TIMEOUT, 'dragging');; +}, +draggingTimeout: function() { + OSRM.G.markers.route[OSRM.G.dragid].hint = null; + OSRM.Routing.getDragRoute(); +}, + +_buildCall: function() { + var source = OSRM.DEFAULTS.HOST_ROUTING_URL; + source += '?z=' + OSRM.G.map.getZoom() + '&output=json&geomformat=cmp'; + if(OSRM.G.markers.checksum) + source += '&checksum=' + OSRM.G.markers.checksum; + for(var i=0,size=OSRM.G.markers.route.length; i'+response.ShortURL+']'; +// document.getElementById('route-prelink').innerHTML = '[]'; +}, +showRouteLink_TimeOut: function(){ + document.getElementById('route-prelink').innerHTML = '['+OSRM.loc("LINK_TO_ROUTE_TIMEOUT")+']'; +}, + +// handling of routing description +show: function(response) { + // compute query string + var query_string = '?rebuild=1'; + for(var i=0; i'+OSRM.loc("GET_LINK_TO_ROUTE")+']'; + + // create GPX link + var gpx_link = '['+OSRM.loc("GPX_FILE")+']'; + + // create route description + var route_desc = ""; + route_desc += ''; + + for(var i=0; i < response.route_instructions.length; i++){ + //odd or even ? + var rowstyle='results-odd'; + if(i%2==0) { rowstyle='results-even'; } + + route_desc += ''; + + route_desc += '"; + + route_desc += '"; + + route_desc += '"; + + route_desc += ""; + } + + route_desc += '
'; + route_desc += ''; + route_desc += "'; + route_desc += ''; + route_desc += response.route_instructions[i][0]; + if( i == 0 ) + route_desc += ' ' + OSRM.loc( response.route_instructions[i][6] ); + if( response.route_instructions[i][1] != "" ) { + route_desc += ' on '; + route_desc += '' + response.route_instructions[i][1] + ''; + } + //route_desc += ' for '; + route_desc += ''; + route_desc += "'; + if( i != response.route_instructions.length-1 ) + route_desc += ''+OSRM.Utils.metersToDistance(response.route_instructions[i][2])+''; + route_desc += "
'; + headline = ""; + headline += OSRM.loc("ROUTE_DESCRIPTION")+":
"; + headline += '

'; + headline += "" + + OSRM.loc("DISTANCE")+": " + OSRM.Utils.metersToDistance(response.route_summary.total_distance) + + "
" + + OSRM.loc("DURATION")+": " + OSRM.Utils.secondsToTime(response.route_summary.total_time) + + "
"; + headline += '
'; + headline += '
'+route_link+'
'+gpx_link+'
'; + + var output = ""; + output += route_desc; + + document.getElementById('information-box-headline').innerHTML = headline; + document.getElementById('information-box').innerHTML = output; +}, + +// simple description +showSimple: function(response) { + headline = OSRM.loc("ROUTE_DESCRIPTION")+":
"; + headline += "" + + OSRM.loc("DISTANCE")+": " + OSRM.Utils.metersToDistance(response.route_summary.total_distance) + + "
" + + OSRM.loc("DURATION")+": " + OSRM.Utils.secondsToTime(response.route_summary.total_time) + + "
"; + headline += '

'; + + document.getElementById('information-box-headline').innerHTML = headline; + document.getElementById('information-box').innerHTML = "

"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".

"; +}, + +// no description +showNA: function( display_text ) { + headline = OSRM.loc("ROUTE_DESCRIPTION")+":
"; + headline += "" + + OSRM.loc("DISTANCE")+": N/A" + + "
" + + OSRM.loc("DURATION")+": N/A" + + "
"; + headline += '

'; + + document.getElementById('information-box-headline').innerHTML = headline; + document.getElementById('information-box').innerHTML = "

"+display_text+".

"; +}, + +// map driving instructions to icons +// [TODO: language-safe implementation] +getDirectionIcon: function(name) { + var directions = { + "Turn left":"turn-left.png", + "Turn right":"turn-right.png", + "U-Turn":"u-turn.png", + "Head":"continue.png", + "Continue":"continue.png", + "Turn slight left":"slight-left.png", + "Turn slight right":"slight-right.png", + "Turn sharp left":"sharp-left.png", + "Turn sharp right":"sharp-right.png", + "Enter roundabout and leave at first exit":"round-about.png", + "Enter roundabout and leave at second exit":"round-about.png", + "Enter roundabout and leave at third exit":"round-about.png", + "Enter roundabout and leave at fourth exit":"round-about.png", + "Enter roundabout and leave at fifth exit":"round-about.png", + "Enter roundabout and leave at sixth exit":"round-about.png", + "Enter roundabout and leave at seventh exit":"round-about.png", + "Enter roundabout and leave at eighth exit":"round-about.png", + "Enter roundabout and leave at nineth exit":"round-about.png", + "Enter roundabout and leave at tenth exit":"round-about.png", + "Enter roundabout and leave at one of the too many exit":"round-about.png", + "You have reached your destination":"target.png" + }; + + if( directions[name] ) + return directions[name]; + else + return "default.png"; +} + +}; \ No newline at end of file diff --git a/WebContent/routing/OSRM.RoutingGUI.js b/WebContent/routing/OSRM.RoutingGUI.js new file mode 100644 index 000000000..da0f20289 --- /dev/null +++ b/WebContent/routing/OSRM.RoutingGUI.js @@ -0,0 +1,129 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM routing +// [handles GUI events] + + +OSRM.RoutingGUI = { + +// click: button "reset" +resetRouting: function() { + document.getElementById('input-source-name').value = ""; + document.getElementById('input-target-name').value = ""; + + OSRM.G.route.hideAll(); + OSRM.G.markers.removeAll(); + OSRM.G.markers.highlight.hide(); + + document.getElementById('information-box').innerHTML = ""; + document.getElementById('information-box-headline').innerHTML = ""; + + OSRM.JSONP.reset(); +}, + +// click: button "reverse" +reverseRouting: function() { + // invert input boxes + var tmp = document.getElementById("input-source-name").value; + document.getElementById("input-source-name").value = document.getElementById("input-target-name").value; + document.getElementById("input-target-name").value = tmp; + + // invert route + OSRM.G.markers.route.reverse(); + if(OSRM.G.markers.route.length == 1) { + if(OSRM.G.markers.route[0].label == OSRM.C.TARGET_LABEL) { + OSRM.G.markers.route[0].label = OSRM.C.SOURCE_LABEL; + OSRM.G.markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); + } else if(OSRM.G.markers.route[0].label == OSRM.C.SOURCE_LABEL) { + OSRM.G.markers.route[0].label = OSRM.C.TARGET_LABEL; + OSRM.G.markers.route[0].marker.setIcon( new L.Icon('images/marker-target.png') ); + } + } else if(OSRM.G.markers.route.length > 1){ + OSRM.G.markers.route[0].label = OSRM.C.SOURCE_LABEL; + OSRM.G.markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); + + OSRM.G.markers.route[OSRM.G.markers.route.length-1].label = OSRM.C.TARGET_LABEL; + OSRM.G.markers.route[OSRM.G.markers.route.length-1].marker.setIcon( new L.Icon('images/marker-target.png') ); + } + + // recompute route + if( OSRM.G.route.isShown() ) { + OSRM.Routing.getRoute(); + OSRM.G.markers.highlight.hide(); + } else { + document.getElementById('information-box').innerHTML = ""; + document.getElementById('information-box-headline').innerHTML = ""; + } +}, + +// click: button "show" +showMarker: function(marker_id) { + if( OSRM.JSONP.fences["geocoder_source"] || OSRM.JSONP.fences["geocoder_target"] ) + return; + + if( marker_id == OSRM.C.SOURCE_LABEL && OSRM.G.markers.hasSource() ) + OSRM.G.markers.route[0].centerView(); + else if( marker_id == OSRM.C.TARGET_LABEL && OSRM.G.markers.hasTarget() ) + OSRM.G.markers.route[OSRM.G.markers.route.length-1].centerView(); +}, + + +// changed: any inputbox (is called when return is pressed [after] or focus is lost [before]) +inputChanged: function(marker_id) { + if( marker_id == OSRM.C.SOURCE_LABEL) + OSRM.Geocoder.call(OSRM.C.SOURCE_LABEL, document.getElementById('input-source-name').value); + else if( marker_id == OSRM.C.TARGET_LABEL) + OSRM.Geocoder.call(OSRM.C.TARGET_LABEL, document.getElementById('input-target-name').value); +}, + +// click: button "open JOSM" +openJOSM: function() { + var x = OSRM.G.map.getCenterUI(); + var ydelta = 0.01; + var xdelta = ydelta * 2; + var p = [ 'left=' + (x.lng - xdelta), 'bottom=' + (x.lat - ydelta), 'right=' + (x.lng + xdelta), 'top=' + (x.lat + ydelta)]; + var url = 'http://localhost:8111/load_and_zoom?' + p.join('&'); + + var frame = L.DomUtil.create('iframe', null, document.body); + frame.style.width = frame.style.height = "0px"; + frame.src = url; + frame.onload = function(e) { document.body.removeChild(frame); }; +}, + +//click: button "open OSM Bugs" +openOSMBugs: function() { + var position = OSRM.G.map.getCenterUI(); + window.open( "http://osmbugs.org/?lat="+position.lat.toFixed(6)+"&lon="+position.lng.toFixed(6)+"&zoom="+OSRM.G.map.getZoom() ); +}, + +//click: button "delete marker" +deleteMarker: function(marker_id) { + var id = null; + if(marker_id == 'source' && OSRM.G.markers.hasSource() ) + id = 0; + else if(marker_id == 'target' && OSRM.G.markers.hasTarget() ) + id = OSRM.G.markers.route.length-1; + if( id == null) + return; + + OSRM.G.markers.removeMarker( id ); + OSRM.Routing.getRoute(); + OSRM.G.markers.highlight.hide(); +} + +}; \ No newline at end of file diff --git a/WebContent/routing/OSRM.RoutingGeometry.js b/WebContent/routing/OSRM.RoutingGeometry.js new file mode 100644 index 000000000..adfdca2e1 --- /dev/null +++ b/WebContent/routing/OSRM.RoutingGeometry.js @@ -0,0 +1,71 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM routing geometry +// [renders routing geometry] + + +OSRM.RoutingGeometry = { + +// show route geometry - if there is a route +show: function(response) { + var geometry = OSRM.RoutingGeometry._decode(response.route_geometry, 5); + + var positions = []; + for( var i=0, size=geometry.length; i < size; i++) + positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) ); + + OSRM.G.route.showRoute(positions, OSRM.Route.ROUTE); +}, + +//show route geometry - if there is no route +showNA: function() { + var positions = []; + for(var i=0, size=OSRM.G.markers.route.length; i= 0x20); + var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lat += dlat; + shift = 0; + result = 0; + do { + b = encoded.charCodeAt(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lng += dlng; + array.push([lat * precision, lng * precision]); + } + return array; +} + +}; \ No newline at end of file diff --git a/WebContent/routing/OSRM.RoutingNoNames.js b/WebContent/routing/OSRM.RoutingNoNames.js new file mode 100644 index 000000000..1d67dac0b --- /dev/null +++ b/WebContent/routing/OSRM.RoutingNoNames.js @@ -0,0 +1,68 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM routing +// [renders route segments that are unnamed streets] + + +OSRM.RoutingNoNames = { + +// displays route segments that are unnamed streets +show: function(response) { + // do not display unnamed streets? + if( document.getElementById('option-highlight-nonames').checked == false) { + OSRM.G.route.hideUnnamedRoute(); + return; + } + + // mark geometry positions where unnamed/named streets switch + var named = []; + for (var i = 0; i < response.route_instructions.length; i++) { + if( response.route_instructions[i][1] == '' ) + named[ response.route_instructions[i][3] ] = false; // no street name + else + named[ response.route_instructions[i][3] ] = true; // yes street name + } + + // aggregate geometry for unnamed streets + var geometry = OSRM.RoutingGeometry._decode(response.route_geometry, 5); + var is_named = true; + var current_positions = []; + var all_positions = []; + for( var i=0; i < geometry.length; i++) { + current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) ); + + // still named/unnamed? + if( (named[i] == is_named || named[i] == undefined) && i != geometry.length-1 ) + continue; + + // switch between named/unnamed! + if(is_named == false) + all_positions.push( current_positions ); + current_positions = []; + current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) ); + is_named = named[i]; + } + + // display unnamed streets + OSRM.G.route.showUnnamedRoute(all_positions); +}, + +showNA: function() { + OSRM.G.route.hideUnnamedRoute(); +} +}; \ No newline at end of file