diff --git a/js/map2gpx.babel.js b/js/map2gpx.babel.js index 80b94ba..5f3e010 100644 --- a/js/map2gpx.babel.js +++ b/js/map2gpx.babel.js @@ -383,6 +383,7 @@ L.Polyline.include({ var _interpolateTrackData = function _interpolateTrackData(deferred, coords, coordsLeft, depth) { + // Avoid interpolating when too long if (coords.length > 500) { return $.Deferred(function () { var _this = this; @@ -395,28 +396,43 @@ var _interpolateTrackData = function _interpolateTrackData(deferred, coords, coo var l = new L.Polyline(coords); - if (coords.length < 100) { + if (coords.length <= 4) { + // We'll not be able to interpolate (came down to too few samples); just find a straight line and use it var straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); - - if (coords.length <= 4 || l.distanceTo(straight) < 10) { - deferred.notify({ line: straight, count: coords.length - 1 }); - return $.Deferred(function () { - this.resolve({ line: straight, mode: 'straight', coordsLeft: coordsLeft }); - }); - } + deferred.notify({ line: straight, count: coords.length - 1 }); + return $.Deferred(function () { + this.resolve({ line: straight, mode: 'straight', coordsLeft: coordsLeft, count: coords.length }); + }); } return $.Deferred(function () { var _this = this; L.polyline_findAuto(coords[0], coords[coords.length - 1]).done(function (geojson) { - var d = l.distanceTo(geojson); - if (d < 10) { + var found = false; + var haversineDistance = coords[0].distanceTo(coords[coords.length - 1]); + var threshold = Math.max(10, 2 * haversineDistance / 100); + + if (l.distanceTo(geojson) < threshold) { + // Found it deferred.notify({ line: geojson, count: coords.length - 1 }); - _this.resolve({ line: geojson, mode: 'auto', coordsLeft: coordsLeft }); - } else { + _this.resolve({ line: geojson, mode: 'auto', coordsLeft: coordsLeft, count: coords.length }); + found = true; + } else if (coords.length < 100) { + // Test if straight line is better + var _straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); + if (l.distanceTo(_straight) < threshold) { + // Found it + deferred.notify({ line: _straight, count: coords.length - 1 }); + _this.resolve({ line: _straight, mode: 'straight', coordsLeft: coordsLeft, count: coords.length }); + found = true; + } + } + + if (!found) { + // Could not find; interpolate on half of the track var coords1 = coords.slice(0, Math.floor(coords.length / 2) + 1); - var coords2 = coords.slice(Math.floor(coords.length / 2)); + var coords2 = coords.slice(Math.floor(coords.length / 2)); // and concatenate rest of the track to the pending coordinates _interpolateTrackData(deferred, coords1, coords2.concat(coordsLeft.slice(1)), depth + 1).done(_this.resolve).fail(_this.reject); } @@ -439,7 +455,14 @@ L.polyline_interpolate = function (coords) { lines.push(line); if (line.coordsLeft.length > 0) { - _interpolateTrackData(_this, line.coordsLeft, [], 0).done(onDone).fail(_this.reject); + // Still some paths to interpolate. + + // Don't try to interpolate the whole line.coordsLeft thing (usually won't work), use previously path found + var sizeToInterpolate = Math.min(line.count * 3, line.coordsLeft.length); + var coords1 = line.coordsLeft.slice(0, sizeToInterpolate + 1); + var coords2 = line.coordsLeft.slice(sizeToInterpolate); + + _interpolateTrackData(_this, coords1, coords2, 0).done(onDone).fail(_this.reject); } else { _this.resolve(lines); } @@ -667,11 +690,15 @@ L.polyline_interpolate = function (coords) { $.Cache = {}; var getKey = function getKey(coords) { - return coords.lng + '/' + coords.lat; + return getKeyLatLng(coords.lat, coords.lng); + }; + + var getKeyLatLng = function getKeyLatLng(lat, lng) { + return Math.roundE8(lng) + '/' + Math.roundE8(lat); }; $.Cache.addAltitude = function (lat, lng, z) { - _altitudes[lng + '/' + lat] = z; + _altitudes[getKeyLatLng(lat, lng)] = z; }; $.Cache.getAltitude = function (coords) { @@ -684,7 +711,7 @@ L.polyline_interpolate = function (coords) { }; $.Cache.addSlope = function (lat, lng, slope) { - _slopes[lng + '/' + lat] = slope; + _slopes[getKeyLatLng(lat, lng)] = slope; }; $.Cache.getSlope = function (coords) { diff --git a/js/map2gpx.min.js b/js/map2gpx.min.js index d7fbdfb..a328141 100644 --- a/js/map2gpx.min.js +++ b/js/map2gpx.min.js @@ -1 +1 @@ -"use strict";function fetchAltitude(t){return $.Deferred(function(){var e=this,n={apiKey:keyIgn,sampling:t.length,positions:t,onSuccess:function(t){t?($.each(t.elevations,function(t,e){$.Cache.addAltitude(e.lat,e.lon,e.z)}),e.resolveWith({size:t.elevations.length})):(console.log("Impossible d'obtenir les données d'altitude: résultats invalides"),e.reject())},onFailure:function(t){console.log("Impossible d'obtenir les données d'altitude: ",t.message),e.reject()}};Gp.Services.getAltitude(n)})}function fetchSlope(t,e,n){return $.Deferred(function(){var o=this,a={tilematrix:16,tilerow:e,tilecol:t,lon:"",lat:"",x:"",y:""};$.each(n,function(t,e){t>0&&(a.lon+="|",a.lat+="|",a.x+="|",a.y+="|"),a.lon+=e.lng.toString(),a.lat+=e.lat.toString(),a.x+=e.x.toString(),a.y+=e.y.toString()}),$.getJSON("slope.php",a,function(t){t.results?($.each(t.results,function(t,e){$.Cache.addSlope(e.lat,e.lon,e.slope)}),o.resolveWith({size:t.results.length})):(console.log("Impossible d'obtenir les données de pente: résultats invalides"),o.reject())}).fail(function(t,e,n){console.log("Impossible d'obtenir les données de pente: ",e,n),o.reject()})})}!function(t){var e=function(t){var e;try{var n="__storage_test__";return(e=window[t]).setItem(n,n),e.removeItem(n),!0}catch(t){return t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&0!==e.length}}("localStorage");t.localStorage={get:function(t){return e?localStorage.getItem(t):null},getAsJSON:function(t){return e&&null!==localStorage.getItem(t)?JSON.parse(localStorage.getItem(t)):null},set:function(t,n){e&&localStorage.setItem(t,n)},setAsJSON:function(t,e){this.set(t,JSON.stringify(e))}}}(jQuery),jQuery.QueryString=function(t){for(var e={},n=0;n=0&&n0&&void 0!==arguments[0]&&arguments[0])){var i=e.indexOf(this);null!==t.localStorage.get("tutorial"+i)&&(a=parseInt(t.localStorage.get("tutorial"+i)))}return a>=0&&at}}(jQuery),Math.roundE8=function(t){return Math.round(t*Math.pow(10,8))/Math.pow(10,8)},Math.radians=function(t){return t*Math.PI/180},Math.degrees=function(t){return 180*t/Math.PI},L.LatLng.prototype.roundE8=function(){return L.latLng(Math.roundE8(this.lat),Math.roundE8(this.lng))},L.LatLng.prototype.toTilePixel=function(t,e,n,o){var a=t.latLngToPoint(this,e).floor(),i=a.divideBy(n).floor(),r=i.multiplyBy(n).subtract(o);return{tile:i,tilePixel:a.subtract(o).subtract(r)}},L.LatLng.prototype.getDestinationAlong=function(t,e){var n=Math.radians(t),o=Math.radians(this.lat),a=Math.radians(this.lng),i=Math.asin(Math.sin(o)*Math.cos(e/6378137)+Math.cos(o)*Math.sin(e/6378137)*Math.cos(n)),r=a+Math.atan2(Math.sin(n)*Math.sin(e/6378137)*Math.cos(o),Math.cos(e/6378137)-Math.sin(o)*Math.sin(i));return i=Math.degrees(i),r=Math.degrees(r),L.latLng(Math.roundE8(i),Math.roundE8(r))},L.LatLng.prototype.bearingTo=function(t){var e=Math.radians(this.lat),n=Math.radians(this.lng),o=Math.radians(t.lat),a=Math.radians(t.lng),i=Math.log(Math.tan(o/2+Math.PI/4)/Math.tan(e/2+Math.PI/4)),r=a-n;return Math.abs(r)>Math.PI&&(r=r>0?-(2*Math.PI-r):2*Math.PI+r),(Math.degrees(Math.atan2(r,i))+360)%360},L.Handler.include({setEnabled:function(t){t?this.enable():this.disable()}}),L.Control.EasyButton.include({setEnabled:function(t){t?this.enable():this.disable()}}),L.Polyline.include({getLatLngsFlatten:function(){var t=this.getLatLngs();if(t.length>0&&Array.isArray(t[0])){var e=[];return $.each(t,function(t,n){e=e.concat(n)}),e}return t}}),L.polyline_findAuto=function(t,e){return $.Deferred(function(){var n=this,o={distanceUnit:"m",endPoint:{x:e.lng,y:e.lat},exclusions:[],geometryInInstructions:!0,graph:"Pieton",routePreferences:"fastest",startPoint:{x:t.lng,y:t.lat},viaPoints:[],apiKey:keyIgn,onSuccess:function(t){if(t){var e=[];$.each(t.routeInstructions,function(t,n){$.each(n.geometry.coordinates,function(t,n){e.push(L.latLng(n[1],n[0]))})});var o=L.polyline(e);n.resolve(o)}else n.rejectWith({error:"Impossible d'obtenir la route: pas de résultats fournis"})},onFailure:function(t){n.rejectWith({error:"Impossible d'obtenir la route: "+t.message})}};Gp.Services.route(o)})},L.polyline_findStraight=function(t,e){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,o=t.roundE8(),a=e.roundE8(),i=o.distanceTo(a),r=o.bearingTo(a),s=[o],l=n;lr&&(r=u)}for(var h=0;hs&&(s=p)}return Math.max(r,s)}});var _interpolateTrackData=function t(e,n,o,a){if(n.length>500)return $.Deferred(function(){var i=n.slice(0,500),r=n.slice(499);t(e,i,r.concat(o.slice(1)),a+1).done(this.resolve).fail(this.reject)});var i=new L.Polyline(n);if(n.length<100){var r=L.polyline_findStraight(n[0],n[n.length-1]);if(n.length<=4||i.distanceTo(r)<10)return e.notify({line:r,count:n.length-1}),$.Deferred(function(){this.resolve({line:r,mode:"straight",coordsLeft:o})})}return $.Deferred(function(){var r=this;L.polyline_findAuto(n[0],n[n.length-1]).done(function(s){if(i.distanceTo(s)<10)e.notify({line:s,count:n.length-1}),r.resolve({line:s,mode:"auto",coordsLeft:o});else{var l=n.slice(0,Math.floor(n.length/2)+1),u=n.slice(Math.floor(n.length/2));t(e,l,u.concat(o.slice(1)),a+1).done(r.resolve).fail(r.reject)}}).fail(function(){var i=n.slice(0,Math.floor(n.length/2)+1),s=n.slice(Math.floor(n.length/2));t(e,i,s.concat(o.slice(1)),a+1).done(r.resolve).fail(r.reject)})})};L.polyline_interpolate=function(t){return $.Deferred(function(){var e=this,n=[];_interpolateTrackData(this,t,[],0).done(function t(o){n.push(o),o.coordsLeft.length>0?_interpolateTrackData(e,o.coordsLeft,[],0).done(t).fail(e.reject):e.resolve(n)}).fail(this.reject)})},function(t){var e=0,n=[];t.fn.clearCompute=function(){return this.each(function(){e-=t(this).queue().length,t(this).clearQueue(),t.Queue.stop()})},t.fn.startCompute=function(n){return this.each(function(){t.Queue.start(),e++,t(this).queue(n)})},t.fn.endCompute=function(n){return this.each(function(){e--,n(),t.Queue.stop()})},t.Queue={size:function(){return e},bindTo:function(t){return n.push(t)},start:function(){0==e&&t.each(n,function(){this.progress("start")})},stop:function(){0==e&&t.each(n,function(){this.progress("stop")})},notify:function(e){t.each(n,function(){this.progress("update",e)})}}}(jQuery),function(t){var e=0,n=[];t.fn.clearBlockingCompute=function(){return this.each(function(){e-=t(this).queue().length,t(this).clearQueue(),t.BlockingQueue.stop()})},t.fn.startBlockingCompute=function(n){return this.each(function(){t.BlockingQueue.start(),e++,t(this).queue(n)})},t.fn.endBlockingCompute=function(n){return this.each(function(){e--,n(),t.BlockingQueue.stop()})},t.BlockingQueue={size:function(){return e},bindTo:function(t){return n.push(t)},start:function(){0==e&&t.each(n,function(){this.start()})},stop:function(){0==e&&t.each(n,function(){this.stop()})}}}(jQuery),function(t){t.widget("map2gpx.progress",{options:{progress:0,total:0,started:!1},_create:function(){this.element.append('


- Calculs en cours...

'),this.$h2=this.element.find("h2"),this.$progress=this.element.find(".data-computing-progress"),this.$progressbar=this.element.find(".data-computing-progressbar"),this.$status=this.element.find(".data-computing-status"),this.options.started&&this.start()},_buildEventData:function(){return{started:this.options.started}},start:function(){this.options.started||(this.options.progress=0,this.options.total=0),this.options.started=!0,this.update({start:!0,total:1,status:"Calculs en cours..."}),this._trigger("statechanged",null,this._buildEventData()),this._trigger("started",null,{})},stop:function(){this.options.started=!1,this.update({end:!0,status:"Finalisation..."}),this._trigger("statechanged",null,this._buildEventData()),this._trigger("stopped",null,{})},started:function(t){if(void 0===t)return this.options.started;t?this.start():this.stop()},update:function(e){if(Array.isArray(e)){var n=this;t.each(e,function(){n._update(this)})}else this._update(e);this._display()},_update:function(e){e.start?this.options.total+=e.total:e.end?this.options.progress=this.options.total:e.count?this.options.progress+=e.count:this.options.progress++,"status"in e&&e.status&&this.$status.text(e.status),"step"in e&&e.step&&t("
"+e.step+"
").insertAfter(this.$h2).fadeOut(400,function(){t(this).remove()})},_display:function(){var e=1;this.options.total>0&&(e=this.options.progress/this.options.total),this.$progress.text(Math.round(100*e)+"%"),this.$progressbar.css("width",Math.round(100*e)+"%"),42==Math.round(100*e)&&t("
La grande question sur la vie, l'univers et le reste répondue
").insertAfter(this.$h2).fadeOut(400,function(){t(this).remove()})}})}(jQuery),function(t){var e={},n={};t.Cache={};var o=function(t){return t.lng+"/"+t.lat};t.Cache.addAltitude=function(t,n,o){e[n+"/"+t]=o},t.Cache.getAltitude=function(t){var n=o(t);return n in e?e[n]:null},t.Cache.hasAltitude=function(t){return o(t)in e},t.Cache.addSlope=function(t,e,o){n[e+"/"+t]=o},t.Cache.getSlope=function(t){var e=o(t);return e in n?n[e]:null},t.Cache.hasSlope=function(t){return o(t)in n},t.Cache.getInfos=function(t){var a=o(t);return{z:a in e?e[a]:null,slope:a in n?n[a]:null}}}(jQuery),L.Map.include({_bindViewEvents:function(){this.on("zoomend",function(){console.log("Zoomed to ",this.getZoom()),$.localStorage.set("view",[this.getCenter().lat,this.getCenter().lng,this.getZoom()])}),this.on("moveend",function(){console.log("Moved to ",this.getCenter()),$.localStorage.setAsJSON("view",[this.getCenter().lat,this.getCenter().lng,this.getZoom()])})},_setView:function(t){this.setView([t[0],t[1]],t[2])},initView:function(){var t=this;return $.Deferred(function(){var e=this,n=$.localStorage.getAsJSON("view")||[44.96777356135154,6.06822967529297,13];if(n[2]>17&&(n[2]=17),"lat"in $.QueryString&&"lng"in $.QueryString&&(n=[$.QueryString.lat,$.QueryString.lng,15]),"loc"in $.QueryString){var o={text:$.QueryString.loc,filterOptions:{type:["StreetAddress","PositionOfInterest"]},apiKey:keyIgn,onSuccess:function(o){o&&"suggestedLocations"in o&&o.suggestedLocations.length>0?(t._setView([o.suggestedLocations[0].position.y,o.suggestedLocations[0].position.x,15]),e.resolveWith(t)):(console.log("No results?"),t._setView(n),e.resolveWith(t))},onFailure:function(o){console.log(o),t._setView(n),e.resolveWith(t)}};Gp.Services.autoComplete(o)}else t._setView(n),e.resolveWith(t)}).done(this._bindViewEvents)}}),L.Layer.include({_elevations:[],_distance:0,_altMin:0,_altMax:0,_denivPos:0,_denivNeg:0,prepareForMap:function(t,e,n){this._mapToAdd=t,this._start=e,this._end=n},getStartMarker:function(){return this._start},getEndMarker:function(){return this._end},getElevations:function(){return JSON.parse(JSON.stringify(this._elevations))},getDistance:function(){return this._distance},getAltMin:function(){return this._altMin},getAltMax:function(){return this._altMax},getDenivPos:function(){return this._denivPos},getDenivNeg:function(){return this._denivNeg},computeStats:function(){var t=this;return $.Deferred(function(){var e=this,n=t._fetchAltitude().concat(t._fetchSlope()),o=n.length;e.notify({start:!0,total:o,status:"Récupération des données géographiques..."}),$.each(n,function(){this.done(function(){e.notify({step:this.size+" points récupérés"})})}),$.when.apply($,n).fail(e.reject).then(function(){t._computeStats(),e.resolve()})})},_computeStats:function(){var t=[];if($.each(this.getLatLngsFlatten(),function(e,n){var o=$.extend({},{lat:n.lat,lng:n.lng},$.Cache.getInfos(n));t.push(o)}),0==t.length)return!1;this._distance=0,this._altMin=t[0].z,this._altMax=t[0].z,this._denivPos=0,this._denivNeg=0,t[0].dist=0,t[0].slopeOnTrack=0,this._elevations=[t[0]];for(var e=0,n=1;n0&&(this._distance+=o/1e3,e++,this._elevations[e]=t[n],this._elevations[e].dist=this._distance,this._elevations[e].slopeOnTrack=Math.degrees(Math.atan((Math.round(this._elevations[e].z)-Math.round(this._elevations[e-1].z))/o)),this._elevations[e].zthis._altMax&&(this._altMax=this._elevations[e].z),this._elevations[e].z0&&e.push(fetchAltitude(t)),e},_fetchSlope:function(){var t={},e=[],n=this._map||this._mapToAdd;return $.each(this.getLatLngsFlatten(),function(e,o){if(!$.Cache.hasSlope(o)){var a=o.toTilePixel(n.options.crs,16,256,n.getPixelOrigin()),i=a.tile,r=a.tilePixel;i.x in t||(t[i.x]={}),i.y in t[i.x]||(t[i.x][i.y]=[[]]),t[i.x][i.y][t[i.x][i.y].length-1].length>50&&t[i.x][i.y].push([]),t[i.x][i.y][t[i.x][i.y].length-1].push({lat:o.lat,lng:o.lng,x:r.x,y:r.y})}}),$.each(t,function(t,n){$.each(n,function(n,o){$.each(o,function(o,a){e.push(fetchSlope(t,n,a))})})}),e},setPopupContentWith:function(t,e){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];this.setPopupContent('
  • Altitude max: '+Math.round(e.altMax)+"m
  • D+: "+Math.round(e.denivPos)+"m
  • Altitude min: "+Math.round(e.altMin)+"m
  • D-: "+Math.round(e.denivNeg)+"m
  • Distance: "+Math.round(100*e.distance)/100+"km
"+(n?'':""))}}),function(t){t.widget("map2gpx.chart",{options:{map:void 0,dataEmpty:"#data-empty",isSmallScreen:!1,showMarker:!0,plotMarkerOptions:{icon:L.AwesomeMarkers.icon({icon:"area-chart",markerColor:"cadetblue",prefix:"fa"}),draggable:!1,clickable:!1,zIndexOffset:1e3},showSlope:!0,showTerrainSlope:!0},_create:function(){var e=this;if(void 0===this.options.map)throw'"map" option cannot be undefined';if(this.$emptyElement=t(this.options.dataEmpty),!this.options.isSmallScreen){this.$chart=t('').appendTo(this.element);var n=[{label:"Altitude",data:[],fill:!1,borderColor:"rgba(12, 98, 173, 0.8)",backgroundColor:"rgba(12, 98, 173, 0.8)",lineTension:0,pointRadius:0,yAxisId:"alt"}],o=[{id:"alt",type:"linear",position:"left",beginAtZero:!1}];this.options.showSlope&&(this.slopeIdx=n.length,n.push({label:"Pente de l'itinéraire",data:[],fill:!0,pointRadius:0,yAxisID:"slope"}),o.push({id:"slope",type:"linear",position:"right"})),this.options.showTerrainSlope&&(this.slopeTerrainIdx=n.length,n.push({label:"Pente du terrain",data:[],fill:!0,pointRadius:0,yAxisID:"slope2",hidden:!0}),o.push({id:"slope2",type:"linear",position:"right",ticks:{min:0,max:45}}));var a={};this.options.showMarker&&(a={mode:"index",intersect:!1,onHover:function(t,n){return e._onHover(t,n)}}),this.chartjs=new Chart(this.$chart,{type:"line",data:{datasets:n},options:{maintainAspectRatio:!1,onClick:function(t,n){return e._onClick(t,n)},hover:a,scales:{xAxes:[{id:"distance",type:"linear",position:"bottom",ticks:{min:0}}],yAxes:o},legend:{position:"left"},tooltips:{mode:"index",intersect:!1,callbacks:{title:function(t,e){return"Distance: "+Math.floor(100*t[0].xLabel)/100+"km"},label:function(t,e){return e.datasets[t.datasetIndex].label+": "+(0==t.datasetIndex?Math.round(100*t.yLabel)/100+"m":Math.round(t.yLabel)+"°")}}},annotation:{annotations:[]}}})}},_onClick:function(t,e){if(e&&e.length>0){var n=e[0]._index,o=this.chartjs.config.data.datasets[0].data[n];o.route&&o.route.openPopup(L.latLng(o.lat,o.lng))}},_onHover:function(t,e){if("mousemove"==t.type)if(e&&e.length>0){var n=e[0]._index,o=this.chartjs.config.data.datasets[0].data[n];null==this.plotMarker?(this.plotMarker=L.marker(L.latLng(o.lat,o.lng),this.options.plotMarkerOptions),this.plotMarker.addTo(this.options.map)):(this.plotMarker.setLatLng(L.latLng(o.lat,o.lng)),this.plotMarker.update())}else this.plotMarker&&(this.options.map.removeLayer(this.plotMarker),this.plotMarker=null);else"mouseout"==t.type&&this.plotMarker&&(this.options.map.removeLayer(this.plotMarker),this.plotMarker=null)},_replotSmallScreen:function(t){t.size>0?this.element.html("
  • Altitude max: "+Math.round(t.total.altMax)+"m; D+: "+Math.round(t.total.denivPos)+"m
  • Altitude min: "+Math.round(t.total.altMin)+"m; D-: "+Math.round(t.total.denivNeg)+"m
  • Distance: "+Math.round(100*t.elevations[t.size-1].dist)/100+"km
"):this.element.empty()},_replotWideScreen:function(t){if(t.size>0){for(var e=[],n=[],o=[],a=0,i=0,r=0;r3&&ra&&(a=s),s=45&&u.addColorStop((a-45)/c,"purple"),a>=40&&u.addColorStop((a-40)/c,"red"),a>=35&&u.addColorStop((a-35)/c,"orange"),a>=30&&u.addColorStop((a-30)/c,"yellow"),u.addColorStop(a/c,"grey"),i<=-30&&u.addColorStop((a+30)/c,"yellow"),i<=-35&&u.addColorStop((a+35)/c,"orange"),i<=-40&&u.addColorStop((a+40)/c,"red"),i<=-45&&u.addColorStop((a+45)/c,"purple"),this.chartjs.config.data.datasets[this.slopeIdx].backgroundColor=u)}if(this.options.showTerrainSlope){this.chartjs.config.data.datasets[this.slopeTerrainIdx].data=o;var h=this.$chart[0].getContext("2d").createLinearGradient(0,0,0,120);h.addColorStop(0,"purple"),h.addColorStop(1-40/45,"red"),h.addColorStop(1-35/45,"orange"),h.addColorStop(1-30/45,"yellow"),h.addColorStop(1,"grey"),this.chartjs.config.data.datasets[this.slopeTerrainIdx].backgroundColor=h}this.chartjs.options.annotation={},this.chartjs.update(),this.chartjs.options.annotation={annotations:t.annotations},this.chartjs.update()}else{this.chartjs.options.scales.xAxes[0].ticks.max=1;for(var p=0;p0?this.$emptyElement.slideUp():this.$emptyElement.slideDown()}})}(jQuery),function(t){function e(e,o,a,i){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"auto";return t.Deferred(function(){var s=this;"straight"==r?n(e,o,a,i).progress(s.notify).done(s.resolve).fail(s.reject):function(t,e,n,o){return L.polyline_findAuto(e.getLatLng(),n.getLatLng())}(0,o,a).progress(s.notify).done(s.resolve).fail(function(){console.log(this.error),console.log("Trying straight line...");var r=new Drop({target:t(".awesome-marker").eq(i+1)[0],classes:"drop-theme-arrows",position:"right middle",constrainToWindow:!1,constrainToScrollParent:!1,openOn:null,content:"Impossible d'obtenir le tracé en mode automatique. Le mode ligne droite va être utilisé."});r.open(),t(r.content).on("click",function(){r.destroy()}),n(e,o,a,i).progress(s.notify).done(s.resolve).fail(s.reject)})})}function n(e,n,o,a){var i=L.polyline_findStraight(n.getLatLng(),o.getLatLng());return t.Deferred(function(){this.resolve(i)})}var o={red:"#D63E2A",orange:"#F59630",green:"#72B026",blue:"#38AADD",purple:"#D252B9",darkred:"#A23336",darkblue:"#0067A3",darkgreen:"#728224",darkpurple:"#5B396B",cadetblue:"#436978",lightred:"#FF8E7F",beige:"#FFCB92",lightgreen:"#BBF970",lightblue:"#8ADAFF",pink:"#FF91EA",white:"#FBFBFB",lightgray:"#A3A3A3",gray:"#575757",black:"#303030"},a=["blue","green","orange","purple","red","darkblue","darkpurple","lightblue","lightgreen","beige","pink","lightred"];L.Track=L.Evented.extend({options:{map:void 0},initialize:function(t){L.setOptions(this,t),this.Lmap=this.options.map.map("getMap"),this.$map=this.options.map,this.currentColor=0,this.markersLength=0},getCurrentColor:function(){return this.currentColor},nextColor:function(){return this.currentColor=(this.currentColor+1)%a.length,this.currentColor},lengthOfMarkers:function(){return this.markersLength},hasMarkers:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;return this.markersLength>=t},hasRoutes:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;return this.markersLength-1>=t},isImport:function(){return this.hasRoutes()&&"import"==this.getFirstMarker().getRouteModeFromHere()},getBounds:function(){var t=L.latLngBounds(this.getFirstMarker(0).getLatLng(),this.getLastMarker().getLatLng());return this.eachRoute(function(e,n){t.extend(n.getBounds())}),t},getFirstMarker:function(){return this.firstMarker},getLastMarker:function(){return this.lastMarker},isLoop:function(){return!!this.firstMarker&&!!this.lastMarker&&this.firstMarker.getLatLng().distanceTo(this.lastMarker.getLatLng())<10},clear:function(){this.eachMarker(function(t,e){e.remove(!1)}),this.fire("markerschanged")},eachMarker:function(t){for(var e=this.firstMarker,n=0;e;){var o=e._nextMarker;t.call(e,n,e),e=o,n++}},eachRoute:function(t){for(var e=this.firstMarker,n=0;e;){var o=e.getRouteFromHere();o&&(t.call(o,n,o),n++),e=e._nextMarker}},addMarker:function(e){var n,o=this,a=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return void 0===this.firstMarker&&(this.firstMarker=e),void 0!==this.lastMarker&&a&&(n=this.lastMarker.computeRouteTo(e,this.$map.map("getMode"))),this.lastMarker=e,this.markersLength++,e.track=this,e.addTo(this.Lmap),n||(n=t.Deferred(function(){this.resolve()})),n.done(function(){return o.fire("markerschanged")})},moveMarker:function(e){var n=this;return t.Deferred(function(){var o=this,a=[];if(e.hasRouteFromHere()){a.length;a.push(e.recomputeRouteFromHere(n.$map.map("getMode")))}if(e.hasRouteToHere()){a.length;a.push(e.recomputeRouteToHere(n.$map.map("getMode")))}t.when.apply(t,a).done(function(){n.fire("markerschanged"),o.resolve()}).fail(o.fail)})},insertMarker:function(e,n){var o=this;return t.Deferred(function(){var a=this,i=[];i.push(n.getStartMarker().computeRouteTo(e,o.$map.map("getMode"))),i.push(e.computeRouteTo(n.getEndMarker(),o.$map.map("getMode"))),o.markersLength++,e.addTo(o.Lmap),t.when.apply(t,i).done(function(){o.fire("markerschanged"),a.resolve()}).fail(a.fail)})},_initStats:function(){return{distance:0,altMin:Number.MAX_VALUE,altMax:Number.MIN_VALUE,denivPos:0,denivNeg:0}},computeStats:function(){var t=this,e=[],n=[],o=this._initStats(),a=this._initStats();if(this.eachMarker(function(i,r){if("step"==r.getType()){e.push(o.distance);for(var s=r;s&&s.hasRouteToHere()&&(s.getRouteToHere().setPopupContentWith(s._previousMarker.getColorCode(),a,"import"!=s._previousMarker.getRouteModeFromHere()),"step"!=(s=s._previousMarker).getType()););a=t._initStats()}var l=r.getRouteFromHere(),u=l?l.getElevations():[];if(u.length>0){for(var c=0;c0)for(var i=this.getLastMarker();i&&i.hasRouteToHere()&&(i.getRouteToHere().setPopupContentWith(i._previousMarker.getColorCode(),a,"import"!=i._previousMarker.getRouteModeFromHere()),"step"!=(i=i._previousMarker).getType()););return{size:n.length,elevations:n,total:o,steps:e}},exportGpx:function(e){var n=!1;try{n=!!new Blob}catch(t){}if(!n)return!1;var o='\n';o+='\n",o+=" \n",this.eachMarker(function(n,a){a.hasRouteFromHere()&&("step"==a.getType()&&(o+=" \n",o+=" \n",o+=" \n",o+=" "+e+"-"+n+"\n",o+=" \n"),t.each(a.getRouteFromHere().getLatLngsFlatten(),function(e,n){o+=' ',t.Cache.hasAltitude(n)&&(o+=""+t.Cache.getAltitude(n)+""),o+="\n"}))}),o+=" \n",o+=" \n",o+="\n";var a=new Blob([o],{type:"application/gpx+xml;charset=utf-8"});return saveAs(a,e+".gpx"),!0},exportKml:function(e){var n=!1;try{n=!!new Blob}catch(t){}if(!n)return!1;var o='\n';o+='\n",o+=" \n",o+=" "+e+"\n",o+=" \n",o+=" 1\n",o+=" \n",o+=" ",this.eachMarker(function(n,a){a.hasRouteFromHere()&&("step"==a.getType()&&(o+="\n \n",o+=" \n",o+=" \n",o+=" \n",o+=" "+e+"-"+n+"\n",o+=" \n",o+=" 1\n",o+=" \n",o+=" "),t.each(a.getRouteFromHere().getLatLngsFlatten(),function(t,e){o+=e.lng+","+e.lat+",0 "}))}),o+="\n \n",o+=" \n",o+=" \n",o+=" \n",o+="\n";var a=new Blob([o],{type:"text/plain;charset=utf-8"});return saveAs(a,e+".kml"),!0},importGpx:function(e,n){var o=this;return t.Deferred(function(){var a=this,i=new FileReader;t(o).startBlockingCompute(function(r){i.onload=function(e){var i=[];new L.GPX(e.target.result,{async:!0,onFail:function(){t(o).endBlockingCompute(r),a.rejectWith({error:"Impossible de traiter ce fichier"})},onSuccess:function(e){a.notify({step:"Fichier traité"}),a.notify({start:!0,total:i.length,status:n?"Interpolation en cours...":"Traitement en cours..."}),o.clear();var s=e.getBounds();o.Lmap.fitBounds(s,{padding:[50,50]});var l=[],u=[];t.each(i,function(e,i){if(n){var r=i.getLatLngsFlatten();a.notify({start:!0,total:r.length}),i.prepareForMap(o.Lmap,null,null),i.setStyle({weight:5,color:"#81197f",opacity:.2,snakingPause:0,snakingSpeed:1e3}),i.addTo(o.Lmap),l.push(L.polyline_interpolate(r).progress(function(t){a.notify({count:t.count,step:t.count+" points trouvés"}),t.line.prepareForMap(o.Lmap,null,null),t.line.setStyle({weight:5,color:"#81197f",opacity:.5,snakingPause:0,snakingSpeed:1e3}),t.line.addTo(o.Lmap),u.push(t.line.computeStats().progress(a.notify))}).done(function(){return i.remove()}))}else i.prepareForMap(o.Lmap,null,null),i.setStyle({weight:5,color:"#81197f",opacity:.5,snakingPause:0,snakingSpeed:1e3}),i.addTo(o.Lmap),l.push(t.Deferred(function(){this.resolve([{line:i,mode:"import"}])})),u.push(i.computeStats().progress(a.notify))}),t.when.apply(t,l).done(function(){for(var e,i=arguments,s=function(a){var r=i[a],s=r.length;t.each(r,function(a,i){var r=i.line.getLatLngsFlatten();if(void 0===e){var l=r[0];e=L.Marker.routed(l,{riseOnHover:!0,draggable:n,opacity:1,color:o.getCurrentColor(),type:"waypoint"}),n?e.add(o,!1):o.addMarker(e,!1)}var u=r[r.length-1],c=L.Marker.routed(u,{riseOnHover:!0,draggable:n,opacity:1,color:a==s-1?o.nextColor():o.getCurrentColor(),type:a==s-1?"step":"waypoint"});if(n?c.add(o,!1):o.addMarker(c,!1),i.line.prepareForMap(o.Lmap,e,c),i.line.setStyle({weight:5,color:e.getColorRgb(),opacity:.75}),i.line.bindPopup("Calculs en cours..."),n){var h=e;i.line.on("popupopen",function(e){t(".marker-add-button:visible").click(function(){L.Marker.routed(e.popup.getLatLng().roundE8(),{riseOnHover:!0,draggable:!0,opacity:.5,color:h.getColorIndex(),type:"waypoint"}).insert(i.line)})})}e.attachRouteFrom(c,i.line,i.mode),e=c})},l=0;l Marquer comme étape '),this.on("popupopen",function(){t(".marker-delete-button:visible").click(function(){e.remove()}),t(".marker-promote-button:visible").click(function(){e.closePopup(),e.setPopupContent(''),e.promoteToStep()})}),this.on("moveend",function(t){e.track.moveMarker(e)})},add:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return this.track=t,this._bindEvents(),this.track.addMarker(this,e)},insert:function(e){return this.track=t("#map").map("getTrack"),this._bindEvents(),this.track.insertMarker(this,e)},remove:function(){var e,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];"step"==this.options.type&&n&&this.demoteToWaypoint();var o=this._previousMarker,a=this._nextMarker;if(this.track._removeMarker(this),this.routeFrom&&this.deleteRouteFromHere(),o&&(o.deleteRouteFromHere(),a))if(o.getLatLng().equals(a.getLatLng()))o.attachRouteFrom(a,null,void 0),e="step"==o.options.type?a.remove(n):o.remove(n);else if(n){var i=this.track.$map.map("getMode")||this._mode||"auto";e=o.computeRouteTo(a,i)}return e||(e=t.Deferred(function(){this.resolve()})),L.Marker.prototype.remove.call(this),this.track.fire("markerschanged"),e}}),L.Marker.routed=function(t,e){return new L.Marker.Routed(t,e)}}(jQuery),function(t){t.widget("map2gpx.map",{options:{leafletOptions:{},controls:{searchEngine:{show:!0,leafletOptions:{displayAdvancedSearch:!1}},minimap:{show:!0,leafletOptions:{position:"bottomleft",zoomLevelOffset:-4}},layerSwitcher:{show:!0,leafletOptions:{collapsed:!1}},scale:{show:!0,leafletOptions:{imperial:!1,position:"bottomright"}},help:{show:!0}}},getMap:function(){return this.map},getTrack:function(){return this.track},getMode:function(){return this.mode},_buildEventData:function(){return{mode:this.mode}},_setMode:function(t){this.mode=t,this._trigger("modechanged",null,this._buildEventData())},_onCreated:function(){var e=this;this.element.on("mapmodechanged",function(t){e.map.doubleClickZoom.setEnabled(null===e.mode)}),this.map.on("dblclick",function(t){return e._addMarker.call(e,t)}),this._initializeLayers(),this.options.controls.searchEngine.show&&this._initializeSearchEngine(),this.options.controls.minimap.show&&this._initializeMinimap(),this.options.controls.layerSwitcher.show&&this._initializeLayerSwitcher(),this.options.controls.scale.show&&this._initializeScale(),this._initializeTraceButtons(),this._initializeExportButtons(),this._initializeImportButtons(),this._initializeHelpButtons(),this._trigger("created",null,{}),this._trigger("statechanged",null,this._buildEventData()),t.when.apply(t,this.layers.promises).done(function(){e._trigger("loaded",null,{})})},_initializeLayers:function(){var e=this,n=this;this.layers.photos=L.geoportalLayer.WMTS({layer:"ORTHOIMAGERY.ORTHOPHOTOS",apiKey:keyIgn}).addTo(this.map),this.layers.promises.push(t.Deferred(function(){n.layers.photos.once("load",this.resolve)})),this.layers.slopes=L.geoportalLayer.WMTS({layer:"GEOGRAPHICALGRIDSYSTEMS.SLOPES.MOUNTAIN",apiKey:keyIgn},{opacity:.25}).addTo(this.map),this.layers.maps=L.geoportalLayer.WMTS({layer:"GEOGRAPHICALGRIDSYSTEMS.MAPS",apiKey:keyIgn},{opacity:.25}).addTo(this.map),this.layers.promises.push(t.Deferred(function(){n.layers.maps.once("load",this.resolve)}));var o=void 0;this.map.on("zoomend",function(){var n=e.map.getZoom(),a=void 0,i=void 0;e.map.hasLayer(e.layers.photos)&&(e.layers.photos.options.minZoom>n||e.layers.photos.options.maxZoomn||e.layers.maps.options.maxZoomn||e.layers.slopes.options.maxZoomAttention: l'import va effacer l'itinéraire existant!"):t("#import-gpx-status").text("")}},{stateName:"computing",icon:"fa-spinner fa-pulse",title:"Importer (calcul en cours...)"}]});t("#import-gpx-button").click(function(){var e=t(this),a=t("#import-gpx-file")[0].files[0],i=t("#import-gpx-interpolate").is(":checked");void 0!=a?(e.attr("disabled","disabled"),t("body").startCompute(function(r){t.Queue.notify({start:!0,total:1,status:"Importation en cours..."}),n.track.importGpx(a,i).done(function(){e.removeAttr("disabled"),n._setMode(null)}).fail(function(){t("#import-gpx-status").text(this.error),e.removeAttr("disabled")}).progress(function(e){t.Queue.notify(e),o.isOpen()&&n.map.closePopup()}).always(function(){return t("body").endCompute(r)})})):t("#import-gpx-status").text("Veuillez sélectionner un fichier")});var i=L.easyButton({id:"btn-reset",states:[{stateName:"loaded",icon:"fa-trash",title:"Effacer l'itinéraire",onClick:function(t,n){e.track.clear()}},{stateName:"computing",icon:"fa-spinner fa-pulse",title:"Effacer l'itinéraire (calcul en cours...)"}]});L.easyBar([a,i]).addTo(this.map),this.element.on("mapcomputingchanged mapstatechanged",function(t){a.state(e.computing?"computing":"loaded"),i.state(e.computing?"computing":"loaded"),a.setEnabled(!e.computing),i.setEnabled(!e.computing&&e.track.hasMarkers())})},_initializeHelpButtons:function(){var e=this,n=L.popup().setContent(L.DomUtil.get("about")),o=L.easyButton({position:"bottomright",states:[{icon:"fa-info-circle",onClick:function(t,o){n.setLatLng(e.map.getCenter()).openOn(e.map)},title:"A propos & crédits"}]}),a=L.easyButton({position:"bottomright",states:[{icon:"fa-question-circle",onClick:function(e,n){t.Shepherd.get(0).start(!0)},title:"Aide"}]});L.easyBar([o,a],{position:"bottomright"}).addTo(this.map)},_create:function(){var t=this;this.element.uniqueId(),this.layers={},this.layers.promises=[],this.mode=null,this.map=L.map(this.element.attr("id"),this.options.leafletOptions),this.track=L.track({map:this.element}),this.track.on("markerschanged",function(){return t._trigger("statechanged",null,t._buildEventData())}),this.map.initView().done(function(){return t._onCreated()})},_addMarker:function(t){if(null!==this.mode){var e=L.Marker.routed(t.latlng.roundE8(),{riseOnHover:!0,draggable:!0,opacity:.5,color:this.track.hasMarkers()?this.track.getLastMarker().getColorIndex():this.track.getCurrentColor(),type:"waypoint"});this.track.hasMarkers()&&this.track.getLastMarker().getLatLng().equals(e.getLatLng())||e.add(this.track)}}})}(jQuery);var isSmallScreen=window.innerWidth<=800&&window.innerHeight<=600;showLoadingMessage("Observation des faucons crécerelle..."),isSmallScreen&&$("#mobile-warning").show().find("button").click(function(){$("#mobile-warning").hide()}),window.onload=function(){try{showLoadingMessage("Localisation des chamois..."),$("#data-computing").progress().on("progressstatechanged",function(e,n){n.started?$("#data-computing").fadeIn():($("#data").data("map2gpx-chart").replot(t.map("getTrack").computeStats()),$("#data-computing").fadeOut())}),$.Queue.bindTo($("#data-computing")),$.BlockingQueue.bindTo({start:function(){return $("#pending").fadeIn()},stop:function(){return $("#pending").fadeOut()}});var t=$("#map").map({controls:{minimap:{show:!isSmallScreen},layerSwitcher:{leafletOptions:{collapsed:isSmallScreen}},scale:{show:!isSmallScreen},help:{show:!isSmallScreen}},created:function(){showLoadingMessage("Suivi des renards roux..."),isSmallScreen||$.Shepherd.tour().add("welcome",{text:$("#help-welcome")[0]}).add("layers",{text:$("#help-layers")[0],attachTo:{element:$(".GPlayerName").closest(".GPwidget")[0],on:"left"}}).add("search",{text:$("#help-search")[0],attachTo:{element:$(".GPshowAdvancedToolOpen").closest(".GPwidget")[0],on:"right"}}).add("autotrace",{text:$("#help-autotrace")[0],attachTo:{element:$("#btn-autotrace")[0],on:"right"}}).add("straighttrace",{text:$("#help-straighttrace")[0],attachTo:{element:$("#btn-straighttrace")[0],on:"right"}}).start()},loaded:function(){showLoadingMessage("Alignement des satellites..."),clearInterval(interval),$("#loading").fadeOut()}}).on("mapmarkerschanged",function(e){isSmallScreen||(t.map("getTrack").hasMarkers(2)&&!$.Shepherd.has(1)&&$.Shepherd.tour().add("data",{text:$("#help-data")[0],attachTo:{element:$("#data")[0],on:"top"}}).add("closeloop",{text:$("#help-closeloop")[0],attachTo:{element:$("#btn-closeloop")[0],on:"right"}}).add("export",{text:$("#help-export")[0],attachTo:{element:$("#btn-export")[0],on:"right"}}).start(),t.map("getTrack").hasMarkers(3)&&!$.Shepherd.has(2)&&$.Shepherd.tour().add("movemarker",{text:$("#help-movemarker")[0],attachTo:{element:$(".awesome-marker").last()[0],on:"bottom"}}).add("movemarker2",{text:$("#help-movemarker2")[0],attachTo:{element:$(".awesome-marker").eq(-2)[0],on:"bottom"}}).add("steps",{text:$("#help-steps")[0],attachTo:{element:$(".awesome-marker").last()[0],on:"bottom"}}).add("steps2",{beforeShowPromise:function(){return $.Deferred(function(){var e=t.map("getTrack").getFirstMarker().getRouteFromHere(),n=e.getLatLngsFlatten(),o=n[Math.floor(n.length/2)];e.openPopup(o),this.resolve()}).promise()},text:$("#help-steps2")[0]}).start())}).on("mapstatechanged",function(e){$("#data").data("map2gpx-chart").replot(t.map("getTrack").computeStats())});$("#data").chart({map:t.map("getMap"),dataEmpty:"#data-empty",isSmallScreen:isSmallScreen})}catch(t){gotError=!0,console.log("Got exception",t),$("#loading").animate({backgroundColor:"#A23336",color:"#FFFFFF"}),$("#loading h2 i.fa").removeClass("fa-spinner fa-pulse").addClass("fa-bug"),$("#loading h2 span").html("Une erreur s'est produite: ""+t+""."),$("#loading h3").html($('
N\'hésitez pas à ouvrir un ticket sur Github ou à m\'envoyer un mail à hi@tmuguet.me.
').hide().slideDown()),clearInterval(interval)}}; \ No newline at end of file +"use strict";function fetchAltitude(t){return $.Deferred(function(){var e=this,n={apiKey:keyIgn,sampling:t.length,positions:t,onSuccess:function(t){t?($.each(t.elevations,function(t,e){$.Cache.addAltitude(e.lat,e.lon,e.z)}),e.resolveWith({size:t.elevations.length})):(console.log("Impossible d'obtenir les données d'altitude: résultats invalides"),e.reject())},onFailure:function(t){console.log("Impossible d'obtenir les données d'altitude: ",t.message),e.reject()}};Gp.Services.getAltitude(n)})}function fetchSlope(t,e,n){return $.Deferred(function(){var o=this,i={tilematrix:16,tilerow:e,tilecol:t,lon:"",lat:"",x:"",y:""};$.each(n,function(t,e){t>0&&(i.lon+="|",i.lat+="|",i.x+="|",i.y+="|"),i.lon+=e.lng.toString(),i.lat+=e.lat.toString(),i.x+=e.x.toString(),i.y+=e.y.toString()}),$.getJSON("slope.php",i,function(t){t.results?($.each(t.results,function(t,e){$.Cache.addSlope(e.lat,e.lon,e.slope)}),o.resolveWith({size:t.results.length})):(console.log("Impossible d'obtenir les données de pente: résultats invalides"),o.reject())}).fail(function(t,e,n){console.log("Impossible d'obtenir les données de pente: ",e,n),o.reject()})})}!function(t){var e=function(t){var e;try{var n="__storage_test__";return(e=window[t]).setItem(n,n),e.removeItem(n),!0}catch(t){return t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&0!==e.length}}("localStorage");t.localStorage={get:function(t){return e?localStorage.getItem(t):null},getAsJSON:function(t){return e&&null!==localStorage.getItem(t)?JSON.parse(localStorage.getItem(t)):null},set:function(t,n){e&&localStorage.setItem(t,n)},setAsJSON:function(t,e){this.set(t,JSON.stringify(e))}}}(jQuery),jQuery.QueryString=function(t){for(var e={},n=0;n=0&&n0&&void 0!==arguments[0]&&arguments[0])){var a=e.indexOf(this);null!==t.localStorage.get("tutorial"+a)&&(i=parseInt(t.localStorage.get("tutorial"+a)))}return i>=0&&it}}(jQuery),Math.roundE8=function(t){return Math.round(t*Math.pow(10,8))/Math.pow(10,8)},Math.radians=function(t){return t*Math.PI/180},Math.degrees=function(t){return 180*t/Math.PI},L.LatLng.prototype.roundE8=function(){return L.latLng(Math.roundE8(this.lat),Math.roundE8(this.lng))},L.LatLng.prototype.toTilePixel=function(t,e,n,o){var i=t.latLngToPoint(this,e).floor(),a=i.divideBy(n).floor(),r=a.multiplyBy(n).subtract(o);return{tile:a,tilePixel:i.subtract(o).subtract(r)}},L.LatLng.prototype.getDestinationAlong=function(t,e){var n=Math.radians(t),o=Math.radians(this.lat),i=Math.radians(this.lng),a=Math.asin(Math.sin(o)*Math.cos(e/6378137)+Math.cos(o)*Math.sin(e/6378137)*Math.cos(n)),r=i+Math.atan2(Math.sin(n)*Math.sin(e/6378137)*Math.cos(o),Math.cos(e/6378137)-Math.sin(o)*Math.sin(a));return a=Math.degrees(a),r=Math.degrees(r),L.latLng(Math.roundE8(a),Math.roundE8(r))},L.LatLng.prototype.bearingTo=function(t){var e=Math.radians(this.lat),n=Math.radians(this.lng),o=Math.radians(t.lat),i=Math.radians(t.lng),a=Math.log(Math.tan(o/2+Math.PI/4)/Math.tan(e/2+Math.PI/4)),r=i-n;return Math.abs(r)>Math.PI&&(r=r>0?-(2*Math.PI-r):2*Math.PI+r),(Math.degrees(Math.atan2(r,a))+360)%360},L.Handler.include({setEnabled:function(t){t?this.enable():this.disable()}}),L.Control.EasyButton.include({setEnabled:function(t){t?this.enable():this.disable()}}),L.Polyline.include({getLatLngsFlatten:function(){var t=this.getLatLngs();if(t.length>0&&Array.isArray(t[0])){var e=[];return $.each(t,function(t,n){e=e.concat(n)}),e}return t}}),L.polyline_findAuto=function(t,e){return $.Deferred(function(){var n=this,o={distanceUnit:"m",endPoint:{x:e.lng,y:e.lat},exclusions:[],geometryInInstructions:!0,graph:"Pieton",routePreferences:"fastest",startPoint:{x:t.lng,y:t.lat},viaPoints:[],apiKey:keyIgn,onSuccess:function(t){if(t){var e=[];$.each(t.routeInstructions,function(t,n){$.each(n.geometry.coordinates,function(t,n){e.push(L.latLng(n[1],n[0]))})});var o=L.polyline(e);n.resolve(o)}else n.rejectWith({error:"Impossible d'obtenir la route: pas de résultats fournis"})},onFailure:function(t){n.rejectWith({error:"Impossible d'obtenir la route: "+t.message})}};Gp.Services.route(o)})},L.polyline_findStraight=function(t,e){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,o=t.roundE8(),i=e.roundE8(),a=o.distanceTo(i),r=o.bearingTo(i),s=[o],l=n;lr&&(r=u)}for(var h=0;hs&&(s=p)}return Math.max(r,s)}});var _interpolateTrackData=function t(e,n,o,i){if(n.length>500)return $.Deferred(function(){var a=n.slice(0,500),r=n.slice(499);t(e,a,r.concat(o.slice(1)),i+1).done(this.resolve).fail(this.reject)});var a=new L.Polyline(n);if(n.length<=4){var r=L.polyline_findStraight(n[0],n[n.length-1]);return e.notify({line:r,count:n.length-1}),$.Deferred(function(){this.resolve({line:r,mode:"straight",coordsLeft:o,count:n.length})})}return $.Deferred(function(){var r=this;L.polyline_findAuto(n[0],n[n.length-1]).done(function(s){var l=!1,u=n[0].distanceTo(n[n.length-1]),c=Math.max(10,2*u/100);if(a.distanceTo(s)0){var i=Math.min(3*o.count,o.coordsLeft.length),a=o.coordsLeft.slice(0,i+1),r=o.coordsLeft.slice(i);_interpolateTrackData(e,a,r,0).done(t).fail(e.reject)}else e.resolve(n)}).fail(this.reject)})},function(t){var e=0,n=[];t.fn.clearCompute=function(){return this.each(function(){e-=t(this).queue().length,t(this).clearQueue(),t.Queue.stop()})},t.fn.startCompute=function(n){return this.each(function(){t.Queue.start(),e++,t(this).queue(n)})},t.fn.endCompute=function(n){return this.each(function(){e--,n(),t.Queue.stop()})},t.Queue={size:function(){return e},bindTo:function(t){return n.push(t)},start:function(){0==e&&t.each(n,function(){this.progress("start")})},stop:function(){0==e&&t.each(n,function(){this.progress("stop")})},notify:function(e){t.each(n,function(){this.progress("update",e)})}}}(jQuery),function(t){var e=0,n=[];t.fn.clearBlockingCompute=function(){return this.each(function(){e-=t(this).queue().length,t(this).clearQueue(),t.BlockingQueue.stop()})},t.fn.startBlockingCompute=function(n){return this.each(function(){t.BlockingQueue.start(),e++,t(this).queue(n)})},t.fn.endBlockingCompute=function(n){return this.each(function(){e--,n(),t.BlockingQueue.stop()})},t.BlockingQueue={size:function(){return e},bindTo:function(t){return n.push(t)},start:function(){0==e&&t.each(n,function(){this.start()})},stop:function(){0==e&&t.each(n,function(){this.stop()})}}}(jQuery),function(t){t.widget("map2gpx.progress",{options:{progress:0,total:0,started:!1},_create:function(){this.element.append('


- Calculs en cours...

'),this.$h2=this.element.find("h2"),this.$progress=this.element.find(".data-computing-progress"),this.$progressbar=this.element.find(".data-computing-progressbar"),this.$status=this.element.find(".data-computing-status"),this.options.started&&this.start()},_buildEventData:function(){return{started:this.options.started}},start:function(){this.options.started||(this.options.progress=0,this.options.total=0),this.options.started=!0,this.update({start:!0,total:1,status:"Calculs en cours..."}),this._trigger("statechanged",null,this._buildEventData()),this._trigger("started",null,{})},stop:function(){this.options.started=!1,this.update({end:!0,status:"Finalisation..."}),this._trigger("statechanged",null,this._buildEventData()),this._trigger("stopped",null,{})},started:function(t){if(void 0===t)return this.options.started;t?this.start():this.stop()},update:function(e){if(Array.isArray(e)){var n=this;t.each(e,function(){n._update(this)})}else this._update(e);this._display()},_update:function(e){e.start?this.options.total+=e.total:e.end?this.options.progress=this.options.total:e.count?this.options.progress+=e.count:this.options.progress++,"status"in e&&e.status&&this.$status.text(e.status),"step"in e&&e.step&&t("
"+e.step+"
").insertAfter(this.$h2).fadeOut(400,function(){t(this).remove()})},_display:function(){var e=1;this.options.total>0&&(e=this.options.progress/this.options.total),this.$progress.text(Math.round(100*e)+"%"),this.$progressbar.css("width",Math.round(100*e)+"%"),42==Math.round(100*e)&&t("
La grande question sur la vie, l'univers et le reste répondue
").insertAfter(this.$h2).fadeOut(400,function(){t(this).remove()})}})}(jQuery),function(t){var e={},n={};t.Cache={};var o=function(t){return i(t.lat,t.lng)},i=function(t,e){return Math.roundE8(e)+"/"+Math.roundE8(t)};t.Cache.addAltitude=function(t,n,o){e[i(t,n)]=o},t.Cache.getAltitude=function(t){var n=o(t);return n in e?e[n]:null},t.Cache.hasAltitude=function(t){return o(t)in e},t.Cache.addSlope=function(t,e,o){n[i(t,e)]=o},t.Cache.getSlope=function(t){var e=o(t);return e in n?n[e]:null},t.Cache.hasSlope=function(t){return o(t)in n},t.Cache.getInfos=function(t){var i=o(t);return{z:i in e?e[i]:null,slope:i in n?n[i]:null}}}(jQuery),L.Map.include({_bindViewEvents:function(){this.on("zoomend",function(){console.log("Zoomed to ",this.getZoom()),$.localStorage.set("view",[this.getCenter().lat,this.getCenter().lng,this.getZoom()])}),this.on("moveend",function(){console.log("Moved to ",this.getCenter()),$.localStorage.setAsJSON("view",[this.getCenter().lat,this.getCenter().lng,this.getZoom()])})},_setView:function(t){this.setView([t[0],t[1]],t[2])},initView:function(){var t=this;return $.Deferred(function(){var e=this,n=$.localStorage.getAsJSON("view")||[44.96777356135154,6.06822967529297,13];if(n[2]>17&&(n[2]=17),"lat"in $.QueryString&&"lng"in $.QueryString&&(n=[$.QueryString.lat,$.QueryString.lng,15]),"loc"in $.QueryString){var o={text:$.QueryString.loc,filterOptions:{type:["StreetAddress","PositionOfInterest"]},apiKey:keyIgn,onSuccess:function(o){o&&"suggestedLocations"in o&&o.suggestedLocations.length>0?(t._setView([o.suggestedLocations[0].position.y,o.suggestedLocations[0].position.x,15]),e.resolveWith(t)):(console.log("No results?"),t._setView(n),e.resolveWith(t))},onFailure:function(o){console.log(o),t._setView(n),e.resolveWith(t)}};Gp.Services.autoComplete(o)}else t._setView(n),e.resolveWith(t)}).done(this._bindViewEvents)}}),L.Layer.include({_elevations:[],_distance:0,_altMin:0,_altMax:0,_denivPos:0,_denivNeg:0,prepareForMap:function(t,e,n){this._mapToAdd=t,this._start=e,this._end=n},getStartMarker:function(){return this._start},getEndMarker:function(){return this._end},getElevations:function(){return JSON.parse(JSON.stringify(this._elevations))},getDistance:function(){return this._distance},getAltMin:function(){return this._altMin},getAltMax:function(){return this._altMax},getDenivPos:function(){return this._denivPos},getDenivNeg:function(){return this._denivNeg},computeStats:function(){var t=this;return $.Deferred(function(){var e=this,n=t._fetchAltitude().concat(t._fetchSlope()),o=n.length;e.notify({start:!0,total:o,status:"Récupération des données géographiques..."}),$.each(n,function(){this.done(function(){e.notify({step:this.size+" points récupérés"})})}),$.when.apply($,n).fail(e.reject).then(function(){t._computeStats(),e.resolve()})})},_computeStats:function(){var t=[];if($.each(this.getLatLngsFlatten(),function(e,n){var o=$.extend({},{lat:n.lat,lng:n.lng},$.Cache.getInfos(n));t.push(o)}),0==t.length)return!1;this._distance=0,this._altMin=t[0].z,this._altMax=t[0].z,this._denivPos=0,this._denivNeg=0,t[0].dist=0,t[0].slopeOnTrack=0,this._elevations=[t[0]];for(var e=0,n=1;n0&&(this._distance+=o/1e3,e++,this._elevations[e]=t[n],this._elevations[e].dist=this._distance,this._elevations[e].slopeOnTrack=Math.degrees(Math.atan((Math.round(this._elevations[e].z)-Math.round(this._elevations[e-1].z))/o)),this._elevations[e].zthis._altMax&&(this._altMax=this._elevations[e].z),this._elevations[e].z0&&e.push(fetchAltitude(t)),e},_fetchSlope:function(){var t={},e=[],n=this._map||this._mapToAdd;return $.each(this.getLatLngsFlatten(),function(e,o){if(!$.Cache.hasSlope(o)){var i=o.toTilePixel(n.options.crs,16,256,n.getPixelOrigin()),a=i.tile,r=i.tilePixel;a.x in t||(t[a.x]={}),a.y in t[a.x]||(t[a.x][a.y]=[[]]),t[a.x][a.y][t[a.x][a.y].length-1].length>50&&t[a.x][a.y].push([]),t[a.x][a.y][t[a.x][a.y].length-1].push({lat:o.lat,lng:o.lng,x:r.x,y:r.y})}}),$.each(t,function(t,n){$.each(n,function(n,o){$.each(o,function(o,i){e.push(fetchSlope(t,n,i))})})}),e},setPopupContentWith:function(t,e){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];this.setPopupContent('
  • Altitude max: '+Math.round(e.altMax)+"m
  • D+: "+Math.round(e.denivPos)+"m
  • Altitude min: "+Math.round(e.altMin)+"m
  • D-: "+Math.round(e.denivNeg)+"m
  • Distance: "+Math.round(100*e.distance)/100+"km
"+(n?'':""))}}),function(t){t.widget("map2gpx.chart",{options:{map:void 0,dataEmpty:"#data-empty",isSmallScreen:!1,showMarker:!0,plotMarkerOptions:{icon:L.AwesomeMarkers.icon({icon:"area-chart",markerColor:"cadetblue",prefix:"fa"}),draggable:!1,clickable:!1,zIndexOffset:1e3},showSlope:!0,showTerrainSlope:!0},_create:function(){var e=this;if(void 0===this.options.map)throw'"map" option cannot be undefined';if(this.$emptyElement=t(this.options.dataEmpty),!this.options.isSmallScreen){this.$chart=t('').appendTo(this.element);var n=[{label:"Altitude",data:[],fill:!1,borderColor:"rgba(12, 98, 173, 0.8)",backgroundColor:"rgba(12, 98, 173, 0.8)",lineTension:0,pointRadius:0,yAxisId:"alt"}],o=[{id:"alt",type:"linear",position:"left",beginAtZero:!1}];this.options.showSlope&&(this.slopeIdx=n.length,n.push({label:"Pente de l'itinéraire",data:[],fill:!0,pointRadius:0,yAxisID:"slope"}),o.push({id:"slope",type:"linear",position:"right"})),this.options.showTerrainSlope&&(this.slopeTerrainIdx=n.length,n.push({label:"Pente du terrain",data:[],fill:!0,pointRadius:0,yAxisID:"slope2",hidden:!0}),o.push({id:"slope2",type:"linear",position:"right",ticks:{min:0,max:45}}));var i={};this.options.showMarker&&(i={mode:"index",intersect:!1,onHover:function(t,n){return e._onHover(t,n)}}),this.chartjs=new Chart(this.$chart,{type:"line",data:{datasets:n},options:{maintainAspectRatio:!1,onClick:function(t,n){return e._onClick(t,n)},hover:i,scales:{xAxes:[{id:"distance",type:"linear",position:"bottom",ticks:{min:0}}],yAxes:o},legend:{position:"left"},tooltips:{mode:"index",intersect:!1,callbacks:{title:function(t,e){return"Distance: "+Math.floor(100*t[0].xLabel)/100+"km"},label:function(t,e){return e.datasets[t.datasetIndex].label+": "+(0==t.datasetIndex?Math.round(100*t.yLabel)/100+"m":Math.round(t.yLabel)+"°")}}},annotation:{annotations:[]}}})}},_onClick:function(t,e){if(e&&e.length>0){var n=e[0]._index,o=this.chartjs.config.data.datasets[0].data[n];o.route&&o.route.openPopup(L.latLng(o.lat,o.lng))}},_onHover:function(t,e){if("mousemove"==t.type)if(e&&e.length>0){var n=e[0]._index,o=this.chartjs.config.data.datasets[0].data[n];null==this.plotMarker?(this.plotMarker=L.marker(L.latLng(o.lat,o.lng),this.options.plotMarkerOptions),this.plotMarker.addTo(this.options.map)):(this.plotMarker.setLatLng(L.latLng(o.lat,o.lng)),this.plotMarker.update())}else this.plotMarker&&(this.options.map.removeLayer(this.plotMarker),this.plotMarker=null);else"mouseout"==t.type&&this.plotMarker&&(this.options.map.removeLayer(this.plotMarker),this.plotMarker=null)},_replotSmallScreen:function(t){t.size>0?this.element.html("
  • Altitude max: "+Math.round(t.total.altMax)+"m; D+: "+Math.round(t.total.denivPos)+"m
  • Altitude min: "+Math.round(t.total.altMin)+"m; D-: "+Math.round(t.total.denivNeg)+"m
  • Distance: "+Math.round(100*t.elevations[t.size-1].dist)/100+"km
"):this.element.empty()},_replotWideScreen:function(t){if(t.size>0){for(var e=[],n=[],o=[],i=0,a=0,r=0;r3&&ri&&(i=s),s=45&&u.addColorStop((i-45)/c,"purple"),i>=40&&u.addColorStop((i-40)/c,"red"),i>=35&&u.addColorStop((i-35)/c,"orange"),i>=30&&u.addColorStop((i-30)/c,"yellow"),u.addColorStop(i/c,"grey"),a<=-30&&u.addColorStop((i+30)/c,"yellow"),a<=-35&&u.addColorStop((i+35)/c,"orange"),a<=-40&&u.addColorStop((i+40)/c,"red"),a<=-45&&u.addColorStop((i+45)/c,"purple"),this.chartjs.config.data.datasets[this.slopeIdx].backgroundColor=u)}if(this.options.showTerrainSlope){this.chartjs.config.data.datasets[this.slopeTerrainIdx].data=o;var h=this.$chart[0].getContext("2d").createLinearGradient(0,0,0,120);h.addColorStop(0,"purple"),h.addColorStop(1-40/45,"red"),h.addColorStop(1-35/45,"orange"),h.addColorStop(1-30/45,"yellow"),h.addColorStop(1,"grey"),this.chartjs.config.data.datasets[this.slopeTerrainIdx].backgroundColor=h}this.chartjs.options.annotation={},this.chartjs.update(),this.chartjs.options.annotation={annotations:t.annotations},this.chartjs.update()}else{this.chartjs.options.scales.xAxes[0].ticks.max=1;for(var p=0;p0?this.$emptyElement.slideUp():this.$emptyElement.slideDown()}})}(jQuery),function(t){function e(e,o,i,a){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"auto";return t.Deferred(function(){var s=this;"straight"==r?n(e,o,i,a).progress(s.notify).done(s.resolve).fail(s.reject):function(t,e,n,o){return L.polyline_findAuto(e.getLatLng(),n.getLatLng())}(0,o,i).progress(s.notify).done(s.resolve).fail(function(){console.log(this.error),console.log("Trying straight line...");var r=new Drop({target:t(".awesome-marker").eq(a+1)[0],classes:"drop-theme-arrows",position:"right middle",constrainToWindow:!1,constrainToScrollParent:!1,openOn:null,content:"Impossible d'obtenir le tracé en mode automatique. Le mode ligne droite va être utilisé."});r.open(),t(r.content).on("click",function(){r.destroy()}),n(e,o,i,a).progress(s.notify).done(s.resolve).fail(s.reject)})})}function n(e,n,o,i){var a=L.polyline_findStraight(n.getLatLng(),o.getLatLng());return t.Deferred(function(){this.resolve(a)})}var o={red:"#D63E2A",orange:"#F59630",green:"#72B026",blue:"#38AADD",purple:"#D252B9",darkred:"#A23336",darkblue:"#0067A3",darkgreen:"#728224",darkpurple:"#5B396B",cadetblue:"#436978",lightred:"#FF8E7F",beige:"#FFCB92",lightgreen:"#BBF970",lightblue:"#8ADAFF",pink:"#FF91EA",white:"#FBFBFB",lightgray:"#A3A3A3",gray:"#575757",black:"#303030"},i=["blue","green","orange","purple","red","darkblue","darkpurple","lightblue","lightgreen","beige","pink","lightred"];L.Track=L.Evented.extend({options:{map:void 0},initialize:function(t){L.setOptions(this,t),this.Lmap=this.options.map.map("getMap"),this.$map=this.options.map,this.currentColor=0,this.markersLength=0},getCurrentColor:function(){return this.currentColor},nextColor:function(){return this.currentColor=(this.currentColor+1)%i.length,this.currentColor},lengthOfMarkers:function(){return this.markersLength},hasMarkers:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;return this.markersLength>=t},hasRoutes:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;return this.markersLength-1>=t},isImport:function(){return this.hasRoutes()&&"import"==this.getFirstMarker().getRouteModeFromHere()},getBounds:function(){var t=L.latLngBounds(this.getFirstMarker(0).getLatLng(),this.getLastMarker().getLatLng());return this.eachRoute(function(e,n){t.extend(n.getBounds())}),t},getFirstMarker:function(){return this.firstMarker},getLastMarker:function(){return this.lastMarker},isLoop:function(){return!!this.firstMarker&&!!this.lastMarker&&this.firstMarker.getLatLng().distanceTo(this.lastMarker.getLatLng())<10},clear:function(){this.eachMarker(function(t,e){e.remove(!1)}),this.fire("markerschanged")},eachMarker:function(t){for(var e=this.firstMarker,n=0;e;){var o=e._nextMarker;t.call(e,n,e),e=o,n++}},eachRoute:function(t){for(var e=this.firstMarker,n=0;e;){var o=e.getRouteFromHere();o&&(t.call(o,n,o),n++),e=e._nextMarker}},addMarker:function(e){var n,o=this,i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return void 0===this.firstMarker&&(this.firstMarker=e),void 0!==this.lastMarker&&i&&(n=this.lastMarker.computeRouteTo(e,this.$map.map("getMode"))),this.lastMarker=e,this.markersLength++,e.track=this,e.addTo(this.Lmap),n||(n=t.Deferred(function(){this.resolve()})),n.done(function(){return o.fire("markerschanged")})},moveMarker:function(e){var n=this;return t.Deferred(function(){var o=this,i=[];if(e.hasRouteFromHere()){i.length;i.push(e.recomputeRouteFromHere(n.$map.map("getMode")))}if(e.hasRouteToHere()){i.length;i.push(e.recomputeRouteToHere(n.$map.map("getMode")))}t.when.apply(t,i).done(function(){n.fire("markerschanged"),o.resolve()}).fail(o.fail)})},insertMarker:function(e,n){var o=this;return t.Deferred(function(){var i=this,a=[];a.push(n.getStartMarker().computeRouteTo(e,o.$map.map("getMode"))),a.push(e.computeRouteTo(n.getEndMarker(),o.$map.map("getMode"))),o.markersLength++,e.addTo(o.Lmap),t.when.apply(t,a).done(function(){o.fire("markerschanged"),i.resolve()}).fail(i.fail)})},_initStats:function(){return{distance:0,altMin:Number.MAX_VALUE,altMax:Number.MIN_VALUE,denivPos:0,denivNeg:0}},computeStats:function(){var t=this,e=[],n=[],o=this._initStats(),i=this._initStats();if(this.eachMarker(function(a,r){if("step"==r.getType()){e.push(o.distance);for(var s=r;s&&s.hasRouteToHere()&&(s.getRouteToHere().setPopupContentWith(s._previousMarker.getColorCode(),i,"import"!=s._previousMarker.getRouteModeFromHere()),"step"!=(s=s._previousMarker).getType()););i=t._initStats()}var l=r.getRouteFromHere(),u=l?l.getElevations():[];if(u.length>0){for(var c=0;c0)for(var a=this.getLastMarker();a&&a.hasRouteToHere()&&(a.getRouteToHere().setPopupContentWith(a._previousMarker.getColorCode(),i,"import"!=a._previousMarker.getRouteModeFromHere()),"step"!=(a=a._previousMarker).getType()););return{size:n.length,elevations:n,total:o,steps:e}},exportGpx:function(e){var n=!1;try{n=!!new Blob}catch(t){}if(!n)return!1;var o='\n';o+='\n",o+=" \n",this.eachMarker(function(n,i){i.hasRouteFromHere()&&("step"==i.getType()&&(o+=" \n",o+=" \n",o+=" \n",o+=" "+e+"-"+n+"\n",o+=" \n"),t.each(i.getRouteFromHere().getLatLngsFlatten(),function(e,n){o+=' ',t.Cache.hasAltitude(n)&&(o+=""+t.Cache.getAltitude(n)+""),o+="\n"}))}),o+=" \n",o+=" \n",o+="\n";var i=new Blob([o],{type:"application/gpx+xml;charset=utf-8"});return saveAs(i,e+".gpx"),!0},exportKml:function(e){var n=!1;try{n=!!new Blob}catch(t){}if(!n)return!1;var o='\n';o+='\n",o+=" \n",o+=" "+e+"\n",o+=" \n",o+=" 1\n",o+=" \n",o+=" ",this.eachMarker(function(n,i){i.hasRouteFromHere()&&("step"==i.getType()&&(o+="\n \n",o+=" \n",o+=" \n",o+=" \n",o+=" "+e+"-"+n+"\n",o+=" \n",o+=" 1\n",o+=" \n",o+=" "),t.each(i.getRouteFromHere().getLatLngsFlatten(),function(t,e){o+=e.lng+","+e.lat+",0 "}))}),o+="\n \n",o+=" \n",o+=" \n",o+=" \n",o+="\n";var i=new Blob([o],{type:"text/plain;charset=utf-8"});return saveAs(i,e+".kml"),!0},importGpx:function(e,n){var o=this;return t.Deferred(function(){var i=this,a=new FileReader;t(o).startBlockingCompute(function(r){a.onload=function(e){var a=[];new L.GPX(e.target.result,{async:!0,onFail:function(){t(o).endBlockingCompute(r),i.rejectWith({error:"Impossible de traiter ce fichier"})},onSuccess:function(e){i.notify({step:"Fichier traité"}),i.notify({start:!0,total:a.length,status:n?"Interpolation en cours...":"Traitement en cours..."}),o.clear();var s=e.getBounds();o.Lmap.fitBounds(s,{padding:[50,50]});var l=[],u=[];t.each(a,function(e,a){if(n){var r=a.getLatLngsFlatten();i.notify({start:!0,total:r.length}),a.prepareForMap(o.Lmap,null,null),a.setStyle({weight:5,color:"#81197f",opacity:.2,snakingPause:0,snakingSpeed:1e3}),a.addTo(o.Lmap),l.push(L.polyline_interpolate(r).progress(function(t){i.notify({count:t.count,step:t.count+" points trouvés"}),t.line.prepareForMap(o.Lmap,null,null),t.line.setStyle({weight:5,color:"#81197f",opacity:.5,snakingPause:0,snakingSpeed:1e3}),t.line.addTo(o.Lmap),u.push(t.line.computeStats().progress(i.notify))}).done(function(){return a.remove()}))}else a.prepareForMap(o.Lmap,null,null),a.setStyle({weight:5,color:"#81197f",opacity:.5,snakingPause:0,snakingSpeed:1e3}),a.addTo(o.Lmap),l.push(t.Deferred(function(){this.resolve([{line:a,mode:"import"}])})),u.push(a.computeStats().progress(i.notify))}),t.when.apply(t,l).done(function(){for(var e,a=arguments,s=function(i){var r=a[i],s=r.length;t.each(r,function(i,a){var r=a.line.getLatLngsFlatten();if(void 0===e){var l=r[0];e=L.Marker.routed(l,{riseOnHover:!0,draggable:n,opacity:1,color:o.getCurrentColor(),type:"waypoint"}),n?e.add(o,!1):o.addMarker(e,!1)}var u=r[r.length-1],c=L.Marker.routed(u,{riseOnHover:!0,draggable:n,opacity:1,color:i==s-1?o.nextColor():o.getCurrentColor(),type:i==s-1?"step":"waypoint"});if(n?c.add(o,!1):o.addMarker(c,!1),a.line.prepareForMap(o.Lmap,e,c),a.line.setStyle({weight:5,color:e.getColorRgb(),opacity:.75}),a.line.bindPopup("Calculs en cours..."),n){var h=e;a.line.on("popupopen",function(e){t(".marker-add-button:visible").click(function(){L.Marker.routed(e.popup.getLatLng().roundE8(),{riseOnHover:!0,draggable:!0,opacity:.5,color:h.getColorIndex(),type:"waypoint"}).insert(a.line)})})}e.attachRouteFrom(c,a.line,a.mode),e=c})},l=0;l Marquer comme étape '),this.on("popupopen",function(){t(".marker-delete-button:visible").click(function(){e.remove()}),t(".marker-promote-button:visible").click(function(){e.closePopup(),e.setPopupContent(''),e.promoteToStep()})}),this.on("moveend",function(t){e.track.moveMarker(e)})},add:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return this.track=t,this._bindEvents(),this.track.addMarker(this,e)},insert:function(e){return this.track=t("#map").map("getTrack"),this._bindEvents(),this.track.insertMarker(this,e)},remove:function(){var e,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];"step"==this.options.type&&n&&this.demoteToWaypoint();var o=this._previousMarker,i=this._nextMarker;if(this.track._removeMarker(this),this.routeFrom&&this.deleteRouteFromHere(),o&&(o.deleteRouteFromHere(),i))if(o.getLatLng().equals(i.getLatLng()))o.attachRouteFrom(i,null,void 0),e="step"==o.options.type?i.remove(n):o.remove(n);else if(n){var a=this.track.$map.map("getMode")||this._mode||"auto";e=o.computeRouteTo(i,a)}return e||(e=t.Deferred(function(){this.resolve()})),L.Marker.prototype.remove.call(this),this.track.fire("markerschanged"),e}}),L.Marker.routed=function(t,e){return new L.Marker.Routed(t,e)}}(jQuery),function(t){t.widget("map2gpx.map",{options:{leafletOptions:{},controls:{searchEngine:{show:!0,leafletOptions:{displayAdvancedSearch:!1}},minimap:{show:!0,leafletOptions:{position:"bottomleft",zoomLevelOffset:-4}},layerSwitcher:{show:!0,leafletOptions:{collapsed:!1}},scale:{show:!0,leafletOptions:{imperial:!1,position:"bottomright"}},help:{show:!0}}},getMap:function(){return this.map},getTrack:function(){return this.track},getMode:function(){return this.mode},_buildEventData:function(){return{mode:this.mode}},_setMode:function(t){this.mode=t,this._trigger("modechanged",null,this._buildEventData())},_onCreated:function(){var e=this;this.element.on("mapmodechanged",function(t){e.map.doubleClickZoom.setEnabled(null===e.mode)}),this.map.on("dblclick",function(t){return e._addMarker.call(e,t)}),this._initializeLayers(),this.options.controls.searchEngine.show&&this._initializeSearchEngine(),this.options.controls.minimap.show&&this._initializeMinimap(),this.options.controls.layerSwitcher.show&&this._initializeLayerSwitcher(),this.options.controls.scale.show&&this._initializeScale(),this._initializeTraceButtons(),this._initializeExportButtons(),this._initializeImportButtons(),this._initializeHelpButtons(),this._trigger("created",null,{}),this._trigger("statechanged",null,this._buildEventData()),t.when.apply(t,this.layers.promises).done(function(){e._trigger("loaded",null,{})})},_initializeLayers:function(){var e=this,n=this;this.layers.photos=L.geoportalLayer.WMTS({layer:"ORTHOIMAGERY.ORTHOPHOTOS",apiKey:keyIgn}).addTo(this.map),this.layers.promises.push(t.Deferred(function(){n.layers.photos.once("load",this.resolve)})),this.layers.slopes=L.geoportalLayer.WMTS({layer:"GEOGRAPHICALGRIDSYSTEMS.SLOPES.MOUNTAIN",apiKey:keyIgn},{opacity:.25}).addTo(this.map),this.layers.maps=L.geoportalLayer.WMTS({layer:"GEOGRAPHICALGRIDSYSTEMS.MAPS",apiKey:keyIgn},{opacity:.25}).addTo(this.map),this.layers.promises.push(t.Deferred(function(){n.layers.maps.once("load",this.resolve)}));var o=void 0;this.map.on("zoomend",function(){var n=e.map.getZoom(),i=void 0,a=void 0;e.map.hasLayer(e.layers.photos)&&(e.layers.photos.options.minZoom>n||e.layers.photos.options.maxZoomn||e.layers.maps.options.maxZoomn||e.layers.slopes.options.maxZoomAttention: l'import va effacer l'itinéraire existant!"):t("#import-gpx-status").text("")}},{stateName:"computing",icon:"fa-spinner fa-pulse",title:"Importer (calcul en cours...)"}]});t("#import-gpx-button").click(function(){var e=t(this),i=t("#import-gpx-file")[0].files[0],a=t("#import-gpx-interpolate").is(":checked");void 0!=i?(e.attr("disabled","disabled"),t("body").startCompute(function(r){t.Queue.notify({start:!0,total:1,status:"Importation en cours..."}),n.track.importGpx(i,a).done(function(){e.removeAttr("disabled"),n._setMode(null)}).fail(function(){t("#import-gpx-status").text(this.error),e.removeAttr("disabled")}).progress(function(e){t.Queue.notify(e),o.isOpen()&&n.map.closePopup()}).always(function(){return t("body").endCompute(r)})})):t("#import-gpx-status").text("Veuillez sélectionner un fichier")});var a=L.easyButton({id:"btn-reset",states:[{stateName:"loaded",icon:"fa-trash",title:"Effacer l'itinéraire",onClick:function(t,n){e.track.clear()}},{stateName:"computing",icon:"fa-spinner fa-pulse",title:"Effacer l'itinéraire (calcul en cours...)"}]});L.easyBar([i,a]).addTo(this.map),this.element.on("mapcomputingchanged mapstatechanged",function(t){i.state(e.computing?"computing":"loaded"),a.state(e.computing?"computing":"loaded"),i.setEnabled(!e.computing),a.setEnabled(!e.computing&&e.track.hasMarkers())})},_initializeHelpButtons:function(){var e=this,n=L.popup().setContent(L.DomUtil.get("about")),o=L.easyButton({position:"bottomright",states:[{icon:"fa-info-circle",onClick:function(t,o){n.setLatLng(e.map.getCenter()).openOn(e.map)},title:"A propos & crédits"}]}),i=L.easyButton({position:"bottomright",states:[{icon:"fa-question-circle",onClick:function(e,n){t.Shepherd.get(0).start(!0)},title:"Aide"}]});L.easyBar([o,i],{position:"bottomright"}).addTo(this.map)},_create:function(){var t=this;this.element.uniqueId(),this.layers={},this.layers.promises=[],this.mode=null,this.map=L.map(this.element.attr("id"),this.options.leafletOptions),this.track=L.track({map:this.element}),this.track.on("markerschanged",function(){return t._trigger("statechanged",null,t._buildEventData())}),this.map.initView().done(function(){return t._onCreated()})},_addMarker:function(t){if(null!==this.mode){var e=L.Marker.routed(t.latlng.roundE8(),{riseOnHover:!0,draggable:!0,opacity:.5,color:this.track.hasMarkers()?this.track.getLastMarker().getColorIndex():this.track.getCurrentColor(),type:"waypoint"});this.track.hasMarkers()&&this.track.getLastMarker().getLatLng().equals(e.getLatLng())||e.add(this.track)}}})}(jQuery);var isSmallScreen=window.innerWidth<=800&&window.innerHeight<=600;showLoadingMessage("Observation des faucons crécerelle..."),isSmallScreen&&$("#mobile-warning").show().find("button").click(function(){$("#mobile-warning").hide()}),window.onload=function(){try{showLoadingMessage("Localisation des chamois..."),$("#data-computing").progress().on("progressstatechanged",function(e,n){n.started?$("#data-computing").fadeIn():($("#data").data("map2gpx-chart").replot(t.map("getTrack").computeStats()),$("#data-computing").fadeOut())}),$.Queue.bindTo($("#data-computing")),$.BlockingQueue.bindTo({start:function(){return $("#pending").fadeIn()},stop:function(){return $("#pending").fadeOut()}});var t=$("#map").map({controls:{minimap:{show:!isSmallScreen},layerSwitcher:{leafletOptions:{collapsed:isSmallScreen}},scale:{show:!isSmallScreen},help:{show:!isSmallScreen}},created:function(){showLoadingMessage("Suivi des renards roux..."),isSmallScreen||$.Shepherd.tour().add("welcome",{text:$("#help-welcome")[0]}).add("layers",{text:$("#help-layers")[0],attachTo:{element:$(".GPlayerName").closest(".GPwidget")[0],on:"left"}}).add("search",{text:$("#help-search")[0],attachTo:{element:$(".GPshowAdvancedToolOpen").closest(".GPwidget")[0],on:"right"}}).add("autotrace",{text:$("#help-autotrace")[0],attachTo:{element:$("#btn-autotrace")[0],on:"right"}}).add("straighttrace",{text:$("#help-straighttrace")[0],attachTo:{element:$("#btn-straighttrace")[0],on:"right"}}).start()},loaded:function(){showLoadingMessage("Alignement des satellites..."),clearInterval(interval),$("#loading").fadeOut()}}).on("mapmarkerschanged",function(e){isSmallScreen||(t.map("getTrack").hasMarkers(2)&&!$.Shepherd.has(1)&&$.Shepherd.tour().add("data",{text:$("#help-data")[0],attachTo:{element:$("#data")[0],on:"top"}}).add("closeloop",{text:$("#help-closeloop")[0],attachTo:{element:$("#btn-closeloop")[0],on:"right"}}).add("export",{text:$("#help-export")[0],attachTo:{element:$("#btn-export")[0],on:"right"}}).start(),t.map("getTrack").hasMarkers(3)&&!$.Shepherd.has(2)&&$.Shepherd.tour().add("movemarker",{text:$("#help-movemarker")[0],attachTo:{element:$(".awesome-marker").last()[0],on:"bottom"}}).add("movemarker2",{text:$("#help-movemarker2")[0],attachTo:{element:$(".awesome-marker").eq(-2)[0],on:"bottom"}}).add("steps",{text:$("#help-steps")[0],attachTo:{element:$(".awesome-marker").last()[0],on:"bottom"}}).add("steps2",{beforeShowPromise:function(){return $.Deferred(function(){var e=t.map("getTrack").getFirstMarker().getRouteFromHere(),n=e.getLatLngsFlatten(),o=n[Math.floor(n.length/2)];e.openPopup(o),this.resolve()}).promise()},text:$("#help-steps2")[0]}).start())}).on("mapstatechanged",function(e){$("#data").data("map2gpx-chart").replot(t.map("getTrack").computeStats())});$("#data").chart({map:t.map("getMap"),dataEmpty:"#data-empty",isSmallScreen:isSmallScreen})}catch(t){gotError=!0,console.log("Got exception",t),$("#loading").animate({backgroundColor:"#A23336",color:"#FFFFFF"}),$("#loading h2 i.fa").removeClass("fa-spinner fa-pulse").addClass("fa-bug"),$("#loading h2 span").html("Une erreur s'est produite: ""+t+""."),$("#loading h3").html($('
N\'hésitez pas à ouvrir un ticket sur Github ou à m\'envoyer un mail à hi@tmuguet.me.
').hide().slideDown()),clearInterval(interval)}}; \ No newline at end of file diff --git a/js/map2gpx.src.js b/js/map2gpx.src.js index d695dfd..ec5e816 100644 --- a/js/map2gpx.src.js +++ b/js/map2gpx.src.js @@ -406,6 +406,7 @@ L.Polyline.include({ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { + // Avoid interpolating when too long if (coords.length > 500) { return $.Deferred(function () { const _this = this; @@ -420,13 +421,11 @@ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { const l = new L.Polyline(coords); - if (coords.length < 100) { + if (coords.length <= 4) { + // We'll not be able to interpolate (came down to too few samples); just find a straight line and use it const straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); - - if (coords.length <= 4 || l.distanceTo(straight) < 10) { - deferred.notify({ line: straight, count: coords.length - 1 }); - return $.Deferred(function () { this.resolve({ line: straight, mode: 'straight', coordsLeft }); }); - } + deferred.notify({ line: straight, count: coords.length - 1 }); + return $.Deferred(function () { this.resolve({ line: straight, mode: 'straight', coordsLeft, count: coords.length }); }); } return $.Deferred(function () { @@ -434,13 +433,30 @@ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { L.polyline_findAuto(coords[0], coords[coords.length - 1]) .done(function (geojson) { - const d = l.distanceTo(geojson); - if (d < 10) { + var found = false; + const haversineDistance = coords[0].distanceTo(coords[coords.length - 1]); + const threshold = Math.max(10, 2 * haversineDistance / 100); + + if (l.distanceTo(geojson) < threshold) { + // Found it deferred.notify({ line: geojson, count: coords.length - 1 }); - _this.resolve({ line: geojson, mode: 'auto', coordsLeft }); - } else { + _this.resolve({ line: geojson, mode: 'auto', coordsLeft, count: coords.length }); + found = true; + } else if (coords.length < 100) { + // Test if straight line is better + const straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); + if (l.distanceTo(straight) < threshold) { + // Found it + deferred.notify({ line: straight, count: coords.length - 1 }); + _this.resolve({ line: straight, mode: 'straight', coordsLeft, count: coords.length }); + found = true; + } + } + + if (!found) { + // Could not find; interpolate on half of the track const coords1 = coords.slice(0, Math.floor(coords.length / 2) + 1); - const coords2 = coords.slice(Math.floor(coords.length / 2)); + const coords2 = coords.slice(Math.floor(coords.length / 2)); // and concatenate rest of the track to the pending coordinates _interpolateTrackData(deferred, coords1, coords2.concat(coordsLeft.slice(1)), depth + 1) .done(_this.resolve) @@ -468,7 +484,14 @@ L.polyline_interpolate = function (coords) { lines.push(line); if (line.coordsLeft.length > 0) { - _interpolateTrackData(_this, line.coordsLeft, [], 0) + // Still some paths to interpolate. + + // Don't try to interpolate the whole line.coordsLeft thing (usually won't work), use previously path found + const sizeToInterpolate = Math.min(line.count * 3, line.coordsLeft.length); + const coords1 = line.coordsLeft.slice(0, sizeToInterpolate + 1); + const coords2 = line.coordsLeft.slice(sizeToInterpolate); + + _interpolateTrackData(_this, coords1, coords2, 0) .done(onDone) .fail(_this.reject); } else { @@ -700,11 +723,15 @@ L.polyline_interpolate = function (coords) { $.Cache = {}; const getKey = function (coords) { - return coords.lng + '/' + coords.lat; + return getKeyLatLng(coords.lat, coords.lng); + }; + + const getKeyLatLng = function (lat, lng) { + return Math.roundE8(lng) + '/' + Math.roundE8(lat); }; $.Cache.addAltitude = function (lat, lng, z) { - _altitudes[lng + '/' + lat] = z; + _altitudes[getKeyLatLng(lat, lng)] = z; }; $.Cache.getAltitude = function (coords) { @@ -717,7 +744,7 @@ L.polyline_interpolate = function (coords) { }; $.Cache.addSlope = function (lat, lng, slope) { - _slopes[lng + '/' + lat] = slope; + _slopes[getKeyLatLng(lat, lng)] = slope; }; $.Cache.getSlope = function (coords) { diff --git a/package-lock.json b/package-lock.json index 7235dae..405c9fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "map2gpx", - "version": "1.3.1", + "version": "1.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1cd0833..d9f5b48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "map2gpx", - "version": "1.3.1", + "version": "1.3.2", "description": "map2gpx is a web application that lets you trace paths on maps (for hiking for instance) and export them to GPX or KML formats.\\n", "main": "n/a", "private": true, diff --git a/src/js/L.Polyline.interpolate.js b/src/js/L.Polyline.interpolate.js index 51746eb..0c85580 100644 --- a/src/js/L.Polyline.interpolate.js +++ b/src/js/L.Polyline.interpolate.js @@ -1,6 +1,7 @@ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { + // Avoid interpolating when too long if (coords.length > 500) { return $.Deferred(function () { const _this = this; @@ -15,13 +16,11 @@ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { const l = new L.Polyline(coords); - if (coords.length < 100) { + if (coords.length <= 4) { + // We'll not be able to interpolate (came down to too few samples); just find a straight line and use it const straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); - - if (coords.length <= 4 || l.distanceTo(straight) < 10) { - deferred.notify({ line: straight, count: coords.length - 1 }); - return $.Deferred(function () { this.resolve({ line: straight, mode: 'straight', coordsLeft }); }); - } + deferred.notify({ line: straight, count: coords.length - 1 }); + return $.Deferred(function () { this.resolve({ line: straight, mode: 'straight', coordsLeft, count: coords.length }); }); } return $.Deferred(function () { @@ -29,13 +28,30 @@ const _interpolateTrackData = function (deferred, coords, coordsLeft, depth) { L.polyline_findAuto(coords[0], coords[coords.length - 1]) .done(function (geojson) { - const d = l.distanceTo(geojson); - if (d < 10) { + var found = false; + const haversineDistance = coords[0].distanceTo(coords[coords.length - 1]); + const threshold = Math.max(10, 2 * haversineDistance / 100); + + if (l.distanceTo(geojson) < threshold) { + // Found it deferred.notify({ line: geojson, count: coords.length - 1 }); - _this.resolve({ line: geojson, mode: 'auto', coordsLeft }); - } else { + _this.resolve({ line: geojson, mode: 'auto', coordsLeft, count: coords.length }); + found = true; + } else if (coords.length < 100) { + // Test if straight line is better + const straight = L.polyline_findStraight(coords[0], coords[coords.length - 1]); + if (l.distanceTo(straight) < threshold) { + // Found it + deferred.notify({ line: straight, count: coords.length - 1 }); + _this.resolve({ line: straight, mode: 'straight', coordsLeft, count: coords.length }); + found = true; + } + } + + if (!found) { + // Could not find; interpolate on half of the track const coords1 = coords.slice(0, Math.floor(coords.length / 2) + 1); - const coords2 = coords.slice(Math.floor(coords.length / 2)); + const coords2 = coords.slice(Math.floor(coords.length / 2)); // and concatenate rest of the track to the pending coordinates _interpolateTrackData(deferred, coords1, coords2.concat(coordsLeft.slice(1)), depth + 1) .done(_this.resolve) @@ -63,7 +79,14 @@ L.polyline_interpolate = function (coords) { lines.push(line); if (line.coordsLeft.length > 0) { - _interpolateTrackData(_this, line.coordsLeft, [], 0) + // Still some paths to interpolate. + + // Don't try to interpolate the whole line.coordsLeft thing (usually won't work), use previously path found + const sizeToInterpolate = Math.min(line.count * 3, line.coordsLeft.length); + const coords1 = line.coordsLeft.slice(0, sizeToInterpolate + 1); + const coords2 = line.coordsLeft.slice(sizeToInterpolate); + + _interpolateTrackData(_this, coords1, coords2, 0) .done(onDone) .fail(_this.reject); } else { diff --git a/src/js/cache.js b/src/js/cache.js index 956774d..c6c911a 100644 --- a/src/js/cache.js +++ b/src/js/cache.js @@ -5,11 +5,15 @@ $.Cache = {}; const getKey = function (coords) { - return coords.lng + '/' + coords.lat; + return getKeyLatLng(coords.lat, coords.lng); + }; + + const getKeyLatLng = function (lat, lng) { + return Math.roundE8(lng) + '/' + Math.roundE8(lat); }; $.Cache.addAltitude = function (lat, lng, z) { - _altitudes[lng + '/' + lat] = z; + _altitudes[getKeyLatLng(lat, lng)] = z; }; $.Cache.getAltitude = function (coords) { @@ -22,7 +26,7 @@ }; $.Cache.addSlope = function (lat, lng, slope) { - _slopes[lng + '/' + lat] = slope; + _slopes[getKeyLatLng(lat, lng)] = slope; }; $.Cache.getSlope = function (coords) {