From a0e55c1c2f256aac90bb602b1d8dd8010f987e1f Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 7 Oct 2016 12:12:00 +0200 Subject: JS: manage routing Conflicts: chimere/route.py --- chimere/models.py | 3 - chimere/route.py | 9 +- chimere/static/chimere/img/icon_from.png | Bin 0 -> 177 bytes chimere/static/chimere/img/icon_to.png | Bin 0 -> 177 bytes chimere/static/chimere/img/routing_from.png | Bin 0 -> 647 bytes chimere/static/chimere/img/routing_step.png | Bin 0 -> 577 bytes chimere/static/chimere/img/routing_to.png | Bin 0 -> 639 bytes chimere/static/chimere/js/jquery.chimere.js | 484 ++++++++++++++++++---------- chimere/views.py | 6 +- 9 files changed, 325 insertions(+), 177 deletions(-) create mode 100644 chimere/static/chimere/img/icon_from.png create mode 100644 chimere/static/chimere/img/icon_to.png create mode 100644 chimere/static/chimere/img/routing_from.png create mode 100644 chimere/static/chimere/img/routing_step.png create mode 100644 chimere/static/chimere/img/routing_to.png diff --git a/chimere/models.py b/chimere/models.py index 9bf645d..057e808 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -604,9 +604,6 @@ class GeographicItem(models.Model): def _get_geom_item_fk_name(self): geom_attr = self.geom_attr - if self.geom_attr == 'route': - # # TODO v3 - backport routes - geom_attr = 'point' return GEOM_TO_GEOM_ITEM[geom_attr].lower() def getProperty(self, propertymodel, safe=None): diff --git a/chimere/route.py b/chimere/route.py index 31cf4f0..3c37a08 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -26,6 +26,7 @@ import os import re import shutil import tempfile +import json from BeautifulSoup import BeautifulSoup from subprocess import Popen, PIPE from django.contrib.gis.gdal import DataSource @@ -94,8 +95,14 @@ class RoutinoRouter(Router): break multilines = trk_layer.get_geoms() res = [] + jsonencoder = json.JSONEncoder() + jsondecoder = json.JSONDecoder() for multiline in multilines: - res += [geom.geojson for geom in multiline] + res += [ + jsonencoder.encode( + {"type": "Feature", + "geometry": jsondecoder.decode(geom.geojson)}) + for geom in multiline] desc = [] # only keeping interessant lines of the desc for line in open(tmp_dir + 'shortest.html').readlines(): diff --git a/chimere/static/chimere/img/icon_from.png b/chimere/static/chimere/img/icon_from.png new file mode 100644 index 0000000..3623e50 Binary files /dev/null and b/chimere/static/chimere/img/icon_from.png differ diff --git a/chimere/static/chimere/img/icon_to.png b/chimere/static/chimere/img/icon_to.png new file mode 100644 index 0000000..6a2bab2 Binary files /dev/null and b/chimere/static/chimere/img/icon_to.png differ diff --git a/chimere/static/chimere/img/routing_from.png b/chimere/static/chimere/img/routing_from.png new file mode 100644 index 0000000..22641ca Binary files /dev/null and b/chimere/static/chimere/img/routing_from.png differ diff --git a/chimere/static/chimere/img/routing_step.png b/chimere/static/chimere/img/routing_step.png new file mode 100644 index 0000000..04d8004 Binary files /dev/null and b/chimere/static/chimere/img/routing_step.png differ diff --git a/chimere/static/chimere/img/routing_to.png b/chimere/static/chimere/img/routing_to.png new file mode 100644 index 0000000..15386a0 Binary files /dev/null and b/chimere/static/chimere/img/routing_to.png differ diff --git a/chimere/static/chimere/js/jquery.chimere.js b/chimere/static/chimere/js/jquery.chimere.js index 0ffb14f..ef7c3d0 100644 --- a/chimere/static/chimere/js/jquery.chimere.js +++ b/chimere/static/chimere/js/jquery.chimere.js @@ -19,6 +19,9 @@ See the file COPYING for details. var extra_url; var labels = { + 'routing_from': "From", + 'routing_to': "To", + 'routing_add_step': "Add step", 'center_map': "Center map here", 'zoom_in': "Zoom in", 'zoom_out': "Zoom out" @@ -27,6 +30,9 @@ var labels = { if (typeof language != 'undefined'){ if (language == 'fr'){ labels = { + 'routing_from': "En partir", + 'routing_to': "Y aller", + 'routing_add_step': "Ajouter une étape", 'center_map': "Centrer la carte ici", 'zoom_in': "Zoom avant", 'zoom_out': "Zoom arrière" @@ -160,6 +166,10 @@ function transform(obj) { return obj.transform(EPSG_DISPLAY_PROJECTION, EPSG_PROJECTION); } +function transformCoordToLonLat(coord) { + return ol.proj.transform(coord, EPSG_PROJECTION, EPSG_DISPLAY_PROJECTION); +} + /* * Little hasattr helper */ @@ -247,9 +257,9 @@ function transform(obj) { marker_hover_id:'marker_hover', marker_hover_content_id:'marker_hover_content', marker_hover_offset: null, - icon_start: null, - icon_step: null, - icon_end: null, + icon_start_style: null, + icon_step_style: null, + icon_end_style: null, mobile: false, input_id: 'id_point', animation_duration: 250 @@ -375,11 +385,27 @@ function transform(obj) { }); // manage context menu - - var contextmenu = new ContextMenu({ - width: 170, - default_items: false, - items: [ + var contextmenu_items = []; + if (settings.routing){ + contextmenu_items = [ + { + text: labels['routing_from'], + callback: methods.routingFrom, + icon: STATIC_URL + 'chimere/img/icon_from.png' + }, + { + text: labels['routing_add_step'], + callback: methods.routingAddStep, + icon: STATIC_URL + 'chimere/img/icon_add_step.png' + }, + { + text: labels['routing_to'], + callback: methods.routingTo, + icon: STATIC_URL + 'chimere/img/icon_to.png' + }, + '-']; + } + contextmenu_items = contextmenu_items.concat([ { text: labels['center_map'], callback: methods.mapCenter, @@ -396,7 +422,12 @@ function transform(obj) { classname: 'ol-ctx-menu-zoom-out ol-ctx-menu-icon', callback: methods.zoomOut } - ] + ]); + + var contextmenu = new ContextMenu({ + width: 170, + default_items: false, + items: contextmenu_items }); settings.map.addControl(contextmenu); @@ -481,21 +512,6 @@ function transform(obj) { $('#map_menu_center').bind("click", methods.mapCenter); */ /* OL3-deprecated routing - // manage the routing - if (settings.routing){ - settings.routing_start = null; - settings.routing_steps = new Array(); - settings.routing_end = null; - $('#map_menu_from').bind("click", methods.routingFrom); - $('#map_menu_step').bind("click", methods.routingAddStep); - $('#map_menu_to').bind("click", methods.routingTo); - $('#map_menu_clear').bind("click", methods.routingClear); - settings.layerRoute = new OpenLayers.Layer.Vector("Route Layer"); - settings.map.addLayer(settings.layerRoute); - settings.layerRouteMarker = new OpenLayers.Layer.Markers( - 'Route markers'); - settings.map.addLayer(settings.layerRouteMarker); - } */ settings.layerSwitcher = new LayerSwitcher({ @@ -547,6 +563,23 @@ function transform(obj) { settings.popup = new ol.Overlay(popup_options); settings.map.addOverlay(settings.popup); + // manage the routing + if (settings.routing){ + settings.routing_start = null; + settings.routing_steps = new Array(); + settings.routing_end = null; + settings.routingFeatures = new ol.Collection(); + + settings.sourceRoutingFeatures = new ol.source.Vector({ + features: settings.routingFeatures + }); + + settings.layerRoutingFeatures = new ol.layer.Vector({ + source: settings.sourceRoutingFeatures + }); + settings.map.addLayer(settings.layerRoutingFeatures); + } + // display marker on click settings.map.on('click', function(evt) { var feature = settings.map.forEachFeatureAtPixel( @@ -1087,11 +1120,11 @@ function transform(obj) { if (geom.getType() == 'Point'){ settings.popup.setPosition(geom.getCoordinates()); } else if (geom.getType() == 'Polygon'){ - settings.popup.setPosition(geom.getInteriorPoint().getCoordinates()); + settings.popup.setPosition(geom.getInteriorPoint().getCoordinates()); } else if (geom.getType() == 'LineString'){ - settings.popup.setPosition(geom.getCoordinateAt(0.5)); + settings.popup.setPosition(geom.getCoordinateAt(0.5)); } else if (geom.getType() == 'MultipleLineString'){ - settings.popup.setPosition(geom.getLineString(0).getCoordinatesAt(0.5)); + settings.popup.setPosition(geom.getLineString(0).getCoordinatesAt(0.5)); } } settings.popup.setOffset([offset_x, offset_y]); @@ -1582,6 +1615,30 @@ function transform(obj) { settings.modify_activated = false; } }, + _getIconStyle: function(properties){ + for (var i in settings.iconStyles){ + if (i == properties.icon_path){ + return settings.iconStyles[i]; + } + } + if (!iconStyle){ + var icon_url = MEDIA_URL + properties.icon_path; + var size = [properties.icon_width, properties.icon_height]; + var anchor = [properties.icon_offset_x, + properties.icon_offset_y]; + var iconStyle = new ol.style.Style({ + image: new ol.style.Icon({ + anchor: anchor, + anchorXUnits: 'pixels', + anchorYUnits: 'pixels', + src: icon_url, + size: size + }) + }); + settings.iconStyles[properties.icon_path] = iconStyle; + return iconStyle; + } + }, /* * Put a marker on the map */ @@ -1603,28 +1660,7 @@ function transform(obj) { popup_offset_y: mark.properties.icon_popup_offset_y }); - var iconStyle; - for (var i in settings.iconStyles){ - if (i == mark.properties.icon_path){ - iconStyle = settings.iconStyles[i]; - } - } - if (!iconStyle){ - var icon_url = MEDIA_URL + mark.properties.icon_path; - var size = [mark.properties.icon_width, mark.properties.icon_height]; - var anchor = [mark.properties.icon_offset_x, - mark.properties.icon_offset_y]; - iconStyle = new ol.style.Style({ - image: new ol.style.Icon({ - anchor: anchor, - anchorXUnits: 'pixels', - anchorYUnits: 'pixels', - src: icon_url, - size: size - }) - }); - settings.iconStyles[mark.properties.icon_path] = iconStyle; - } + var iconStyle = methods._getIconStyle(mark.properties, MEDIA_URL); iconFeature.setStyle(iconStyle); iconFeature.setId(mark.properties.key); @@ -1967,31 +2003,46 @@ function transform(obj) { }, redrawRoutingIcons: function(){ - settings.layerRouteMarker.clearMarkers(); - settings.layerRouteMarker.addMarker(settings.routing_start); - settings.layerRouteMarker.addMarker(settings.routing_end); + settings.routingFeatures.clear(); + settings.routingFeatures.push(settings.routing_start); + settings.routingFeatures.push(settings.routing_end); for (var k=0;k 0){ uri += '_'; } - uri += step.lon + '_' + step.lat; + uri += step[0] + '_' + step[1]; } - settings.permalink.updateLink(); + // TODO ol3 + // settings.permalink.updateLink(); $.ajax({url: uri, dataType: "json", success: function (data) { - settings.layerRoute.removeAllFeatures(); methods.redrawRoutingIcons(); methods.hideMessage(); if (!data.features.length){ @@ -2272,10 +2355,35 @@ function transform(obj) { settings.current_routes_features = []; for (var i = 0; i < data.features.length; i++) { var feat = data.features[i]; - if(feat.type == 'LineString'){ + if(feat.geometry.type == 'LineString'){ settings.current_routes_features.push( - methods.putRoute(feat)); + methods.putRouting(feat)); } else { + var point = new ol.geom.Point([ + feat.geometry.coordinates[0], + feat.geometry.coordinates[1] + ]); + point.transform(EPSG_DISPLAY_PROJECTION, + EPSG_PROJECTION); + var feature = new ol.Feature({ + geometry: point + }); + + feature.setStyle( + new ol.style.Style({ + image: new ol.style.Circle({ + fill:new ol.style.Fill( + {color: 'rgba(200, 0, 0, 0.9)'}), + stroke: new ol.style.Stroke({ + color: 'rgba(255, 255, 255, 0.5)', + width: 4}), + radius: 6 + }) + }) + ); + + settings.routingFeatures.push(feature); + /* var lonlat = new OpenLayers.LonLat( feat.geometry.coordinates[0], feat.geometry.coordinates[1]); @@ -2293,12 +2401,25 @@ function transform(obj) { -icon_height)) ); settings.layerRouteMarker.addMarker(marker); + */ } } if (data.message) methods.displayMessage(data.message); - settings.map.zoomToExtent( - settings.layerRoute.getDataExtent()); - settings.map.zoomOut(); + var v = settings.map.getView(); + // animation + var pan = ol.animation.pan( + {duration: settings.animation_duration, + source: v.getCenter()}) + var zoom = ol.animation.zoom( + {duration: settings.animation_duration, + resolution: v.getResolution()}) + settings.map.beforeRender(pan, zoom); + options = {}; + if ($("#panel").is(":visible")){ + options = {"padding": [0, 0, 0, $("#panel").width()]}; + } + v.fit(settings.sourceRoutingFeatures.getExtent(), + settings.map.getSize(), options); $('#id_transport_it').find('span' ).removeClass('selected'); $('#id_transport_it_'+data.properties.transport @@ -2317,21 +2438,25 @@ function transform(obj) { methods.updateRoutingInput(); } // Added for mobile - START // - //iOS + // iOS methods.connectWebViewJavascriptBridge( function(bridge) { - if(!bridge){ - bridge.init(function(message, responseCallback) { - if (responseCallback) { - responseCallback("Right back atcha"); - } - }); - } - bridge.send('routeCalculated:'+data.properties.total); - bridge.send('routeCalculatedDetail:'+data.properties.description); - }); - //android - window.JSInterface.routeCalculated(data.properties.total, data.properties.description); + if(!bridge){ + bridge.init( + function(message, responseCallback) { + if (responseCallback) { + responseCallback("Right back atcha"); + } + }); + } + bridge.send('routeCalculated:'+data.properties.total); + bridge.send('routeCalculatedDetail:'+data.properties.description); + } + ); + // Android + if (typeof window.JSInterface != 'undefined') + window.JSInterface.routeCalculated( + data.properties.total, data.properties.description); // Added for mobile - START // }, error: function (jqXHR, textStatus, errorThrown) { @@ -2339,7 +2464,6 @@ function transform(obj) { methods.hideMessage(); console.log(errorThrown); console.log(textStatus); - settings.layerRoute.removeAllFeatures(); methods.displayMessage(routing_fail_message); } }); @@ -2348,7 +2472,25 @@ function transform(obj) { /* Put a route on the map */ - putRoute: function(polyline) { + putRouting: function(polyline) { + var feat = new ol.format.GeoJSON().readFeature(polyline); + feat.setGeometry(transform(feat.getGeometry())); + feat.setStyle([ + new ol.style.Style({ + stroke: new ol.style.Stroke({ + width: 5, + color: 'rgba(203, 194, 185, 0.8)' + })}), + new ol.style.Style({ + stroke: new ol.style.Stroke({ + width: 5, color: 'rgba(100, 100, 100, 1)', + lineDash: [.9, 10] + })}) + ]); + settings.routingFeatures.push(feat); + return feat; + + /* var point_array = new Array(); for (i=0; i