Retour à la documentation
/**
* @class spw.widgets.SpwMeasure
*/
define(["dojo/_base/declare","spw/api/SpwBaseTemplatedWidget", "dojo/text!./templates/SpwMeasure.html",
"dojo/dom-class", "spw/api/SpwDrawToolbar", "dojo/_base/lang",
"esri/graphic", "dojo/dom-construct","spw/api/SpwBaseWidget", "esri/tasks/Geoprocessor",
"esri/tasks/LinearUnit", "esri/units", "esri/geometry/geodesicUtils", "esri/tasks/FeatureSet",
"dojo/on", "dojo/Deferred", "esri/request", "dojo/_base/array", "dojo/_base/Color",
"esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"dojo/i18n!./nls/SpwMeasure", "spw/api/MessageManager", "dojo/dom-style", "dojo/aspect",
"dojo/window", "dojo/topic", "dojo/touch", "spw/api/GeometryUtils", "spw/api/ProjectionManager"
/* when esri 3.14 -> "esri/dijit/ElevationProfile"*/],
function(declare, SpwBaseTemplatedWidget, tmpl, domClass, Draw,
lang, graphic, domConstruct, SpwBaseWidget,
Geoprocessor, LinearUnit, Units, geodesicUtils, FeatureSet,
on, Deferred, esriRequest, array, Color, SimpleMarkerSymbol,
SimpleLineSymbol, labels, MessageManager, domStyle, aspect, win,
topic, touch, GeometryUtils, ProjectionManager
/* when esri 3.14 -> ElevationProfile */){
var SpwMeasure = declare("spw.widgets.SpwMeasure", [SpwBaseTemplatedWidget], /** @lends spw.widgets.SpwMeasure.prototype */{
templateString: tmpl,
labels: labels,
allowSelectGraph: true,
/**
* Nombre d'échantillons
* @type Number
*/
sampling: 50,
/**
* Informations sur la tâche du service
* @type Object
*/
taskInfo: null,
/**
* Objet permettant d'attaquer le service et de récupérer les informations
* @type Geoprocessor
*/
profileService: null,
/**
* Couleur de base du graphique
* @type String
*/
graphColor: "#4f8fa5",
_tooltip: null,
_tooltipHandlers: 4,
popupWidth: null,
popupHeight: null,
"widgetTitle": "Mesurer",
"position": "panel-light",
"iconClass": "mesureIcon",
"height": "auto",
"right": "15px",
"top": "85px",
"profileServiceUrl": "//geoservices.wallonie.be/arcgis/rest/services/GEOTRAITEMENT/Profil/GPServer/Profil",//"http://elevation.arcgis.com/arcgis/rest/services/Tools/ElevationSync/GPServer/Profil",
/**
* @constructs
* @param config
*/
constructor: function (config) {
},
postCreate: function() {
this.inherited(arguments);
this.spwViewer.get('spwMap').on(this.spwViewer.get('spwMap').events.MapDestroyed, lang.hitch(this, function() {
this.drawTb = null;
this.deactivateAll();
if (this.AltimetriePopup && this.AltimetriePopup) {
this.AltimetriePopup.onDeactivate();
}
}));
if (this.allowSelectGraph !== true) {
domStyle.set(this._selectGraphText, 'display', 'none');
}
this.own(
on(this.selectGraphButton, 'change', lang.hitch(this, this.selectGraphOnMap)),
on(this.DistanceButton, touch.press, lang.hitch(this, this.activateDistanceClick)),
on(this.SurfaceButton, touch.press, lang.hitch(this, this.activateSurfaceClick)),
on(this.enlargeImgNode, touch.press, lang.hitch(this, this.enlargeGraphClick)),
on(this.AltimetrieButton, touch.press, lang.hitch(this, this.activateAltimetrieClick))
);
},
selectingOnMap: false,
oldTooltip: null,
selectHandlers: null,
selectGraphOnMap: function() {
if (this.drawTb == null) {
return;
}
this.selectingOnMap = this.selectGraphButton.get('checked');
array.forEach(this.selectHandlers, function(s) {
s.remove();
});
this.selectHandlers = [];
if (this.selectingOnMap) {
this.drawTb.deactivate();
if (this._tooltip) {
this.oldTooltip = this._tooltip.innerHTML;
this._tooltip.innerHTML = 'Cliquez sur un itinéraire';
}
var mss = this.spwViewer.get('spwMap').getMapServices({
isBaseMap: false
});
this.selectHandlers.push(on(this.spwViewer.get('spwMap'), this.spwViewer.get('spwMap').events.MapServiceAdded, lang.hitch(this, function(ms) {
if (ms.layer && ms.layer.graphics) {
this.selectHandlers.push(ms.layer.on('click', lang.hitch(this, this.onGraphicsClicked)));
}
})));
array.forEach(mss, lang.hitch(this, function(ms) {
if (ms.layer && ms.layer.graphics) {
this.selectHandlers.push(ms.layer.on('click', lang.hitch(this, this.onGraphicsClicked)));
}
}));
}
else {
this.drawTb.activate(Draw.POLYLINE);
if (this._tooltip && this.oldTooltip) {
this._tooltip.innerHTML = this.oldTooltip;
}
}
},
onGraphicsClicked: function(evt) {
if (!this.selectingOnMap) {
return;
}
var graph = evt.graphic;
if (graph && graph.geometry && graph.geometry.type === 'polyline') {
this.showAltimetrie({geometry: graph.geometry});
}
},
activateDistanceClick: function(){
this.deactivateAll();
this.activateTool('Distance');
this.activateDrawLine(lang.hitch(this, function(evt){
if (evt.geometry == null) {
return;
}
this.showGeometry(evt.geometry);
var m = GeometryUtils.geometryLength(evt.geometry, 'meters');
var tmp = (Math.round(m * 10) / 10);
this.DistanceMeters.innerHTML = tmp.toString().replace('.', ',');
this.DistanceKilometers.innerHTML = (Math.round(tmp * 10) / 10000).toString().replace('.', ',');
}), 'Cliquez pour commencer la mesure');
},
activateSurfaceClick: function(){
this.deactivateAll();
this.activateTool('Surface');
this.activateDrawPolygon(lang.hitch(this, function(evt, type){
if (evt.geometry == null) {
return;
}
if (type !== 'move' && evt.geometry.isSelfIntersecting()) {
MessageManager.getInstance().notifyError('Impossible de calculer la surface car le polygone s\'intersecte lui-même.');
this.removeGeometry();
return;
}
this.showGeometry(evt.geometry);
var m = GeometryUtils.area(evt.geometry, 'square-meters');//geometryEngine.planarArea(evt.geometry, 'square-meters');
this.SurfaceMeters.innerHTML = (Math.round(m * 10) / 10).toString().replace('.', ',');
this.SurfaceKilometers.innerHTML = (Math.round(m * 10) / 10000000).toString().replace('.', ',');
this.SurfaceHectares.innerHTML = (Math.round(m * 10) / 100000).toString().replace('.', ',');
this.SurfaceAres.innerHTML = (Math.round(m * 10) / 1000).toString().replace('.', ',');
var p = GeometryUtils.geometryLength(evt.geometry, 'meters');
this.PerimetreMeters.innerHTML = (Math.round(p * 10) / 10).toString().replace('.', ',');
this.PerimetreKilometers.innerHTML = (Math.round(p * 10) / 10000).toString().replace('.', ',');
}), 'Cliquez pour commencer la mesure');
},
activateAltimetrieClick: function(){
this.deactivateAll();
this.activateTool('Altimetrie');
if (this.showAltimetrie == null) {
this.showAltimetrie = lang.hitch(this, function(evt){
domStyle.set(this.graphResult, 'display', '');
this.showGeometry(evt.geometry);
this.createAltimetrieGraph();
this.currGraphAltimetrie.showLoading();
if (this.AltimetriePopup) {
this.AltimetriePopup.showLoading();
}
/* when esri 1.14 ->
this.emit('update-chart', {geometry: evt.geometry});
*/
// on affiche le profil
this._getProfile(evt.geometry).then(lang.hitch(this, function (elevationInfo) {
this.elevationInfo = elevationInfo;
this.emit("update-chart", elevationInfo);
}), lang.hitch(this, function (error) {
MessageManager.getInstance().notifyError(lang.replace("{message}\n\n{details.0}", error));
console.error(error);
}));
});
}
this.activateDrawLine(this.showAltimetrie, 'Cliquez pour commencer la mesure', ['click']);
},
/**
* initialisation du service
*/
_initProfileService: function () {
// promesse retournée
var deferred = new Deferred();
if (this.profileService) {
deferred.resolve(this.profileService);
return deferred;
}
if (this.profileServiceUrl) {
// s'il on souhaite tester que le service est up et obtenir ses informations //
/*esriRequest({
url: this.profileServiceUrl,
content: {
f: "json"
},
callbackParamName: "callback"
}).then(lang.hitch(this, function (taskInfo) {
// détails de la tâche
this.taskInfo = taskInfo;
// création de l'objet permettant d'attaquer le service
this.profileService = new Geoprocessor(this.profileServiceUrl);
this.profileService.setOutSpatialReference(this.spwViewer.get('spwMap').get('esriMap').spatialReference);
deferred.resolve();
}), lang.hitch(this, function (error) {
deferred.reject(error);
}));*/
// création de l'objet permettant d'attaquer le service
this.profileService = new Geoprocessor(this.profileServiceUrl);
deferred.resolve(this.profileService);
} else {
deferred.reject(new Error('invalid url'));
}
return deferred.promise;
},
_getProfile: function (polyline) {
var deferred = new Deferred();
// on récupère la longueur en mètres
var lengthMeters = GeometryUtils.geometryLength(polyline, 'meters');
// var roundedLength = (Math.round(m * 10) / 10);
// on détermine la distance d'échantillonnage
var samplingDistance = (lengthMeters / this.sampling);
//var samplingDistance = this.samplingDistance;
// crée une feature qui sera transmise au service
var wkidFromMap = this.spwViewer.get('spwMap').esriMap.spatialReference.wkid;
var inputProfileGraphic = new graphic(ProjectionManager.getInstance().transform(wkidFromMap || 31370, 3857, polyline), null, {
OID: 1
});
var inputLineFeatures = new FeatureSet();
inputLineFeatures.features = [inputProfileGraphic];
// on a besoin de l'OID
inputLineFeatures.fields = [{
"name": "OID",
"type": "esriFieldTypeObjectID",
"alias": "OID"
}];
// on s'assure que le service a été initialisée
this._initProfileService().then(lang.hitch(this, function(profileService) {
profileService.setProcessSpatialReference(polyline.spatialReference ? polyline.spatialReference : this.spwViewer.get('spwMap').esriMap.spatialReference);
profileService.setOutSpatialReference(polyline.spatialReference ? polyline.spatialReference : this.spwViewer.get('spwMap').esriMap.spatialReference);
// on exécute la requête
profileService.execute({
"InputLineFeatures": inputLineFeatures,
"ProfileIDField": "OID",
"DEMResolution": "1m",
"MaximumSampleDistance": 1,
"MaximumSampleDistanceUnits": "Meters",
"returnZ": true,
"returnM": true
}).then(lang.hitch(this, function (results) {
if (results.length > 0) {
var profileOutput = results[0].value;
if (profileOutput.features.length > 0) {
// on récupère le profile
var profileFeature = profileOutput.features[0];
// récupérer la distance totale
this.altiDistance = Math.round(profileFeature.attributes.ProfileLength);
var altis = [], points = [];
//this.reorderPaths(profileFeature);
array.forEach(profileFeature.geometry.paths, lang.hitch(this, function(path){
points = points.concat(array.map(path, function(i){
return {
x:i[0], y:i[1], a:i[2]
};
}));
}));
//var pts = simplify(points, 0.5, true);
altis = simplify(points, window.tolerance || 0.5, true);
altis = array.map(altis, function(i){return Math.round(i.a * 100) / 100;});
this.altiMax = Math.max.apply(Math, altis);
this.altiMax = Math.round(this.altiMax);
this.altiMin = Math.min.apply(Math, altis);
this.altiMin = Math.round(this.altiMin);
var cur=null, next=null;
this.cneg = 0;
this.cpos = 0;
var tab = {};
array.forEach(altis, lang.hitch(this, function(a, idx){
cur = a;
if(altis.length > idx + 1) {
next = altis[idx + 1];
if(cur > next){
this.cneg += (cur - next);
} else if(cur < next){
this.cpos += (next - cur);
}
}
}));
this.cneg = Math.round(this.cneg * 100) / 100;
this.cpos = Math.round(this.cpos * 100) / 100;
this.cabs = (Math.round((this.cpos - this.cneg) * 100) / 100);
// this.altiDistNode.innerHTML = this.altiDistance;
// this.altiMaxNode.innerHTML = this.altiMax;
// this.altiMinNode.innerHTML = this.altiMin;
// this.cabsNode.innerHTML = this.cabs;
// this.cposNode.innerHTML = this.cpos;
// this.cnegNode.innerHTML = this.cneg;
// puis la géométrie
var profileGeometry = profileFeature.geometry;
var allElevations = [];
var allDistances = [];
if (profileGeometry.paths.length > 0) {
// chemins de la polyline
array.forEach(profileGeometry.paths, lang.hitch(this, function (profilePoints, pathIndex) {
// informations sur l'altitude
array.forEach(profilePoints, lang.hitch(this, function (coords, pointIndex) {
var elevationInfo = {
x: ((coords.length > 3) ? coords[3] : (pointIndex * samplingDistance)),
y: ((coords.length > 2) ? coords[2] : 0.0),
pathIdx: pathIndex,
pointIdx: pointIndex
};
allElevations.push(elevationInfo);
allDistances.push(elevationInfo.x);
}));
}));
// on résoud la promesse
deferred.resolve({
geometry: profileGeometry,
elevations: allElevations,
distances: allDistances,
samplingDistance: samplingDistance
});
} else {
deferred.reject(new Error(this.labels.UnableToProcessResults));
}
} else {
deferred.reject(new Error(this.labels.UnableToProcessResults));
}
} else {
deferred.reject(new Error(this.labels.UnableToProcessResults));
}
}), deferred.reject);
}));
return deferred.promise;
},
// reorderPaths: function(profileFeature) {
// var arr=[profileFeature.geometry.paths[0]];
// profileFeature.geometry.paths.forEach((p,idx) => {
// //if(idx === 0) return;
// var first = {x: Math.round(p[0][0]), y: Math.round(p[0][1])}; var last = {x: Math.round(p[p.length-1][0]), y: Math.round(p[p.length-1][1])};
// profileFeature.geometry.paths.forEach((p2, idx2) => {
// var first2 = {x: Math.round(p2[0][0]), y: Math.round(p2[0][1])}; var last2 = {x: Math.round(p2[p2.length-1][0]), y: Math.round(p2[p2.length-1][1])};
// if(first.x === last2.x && first.y === last2.y){
// //console.log("path " + idx + " is after path " +idx2);
// var eleIdx = arr.indexOf(profileFeature.geometry.paths[idx]);
// if(eleIdx > -1){
// arr.splice(eleIdx+1, 0, profileFeature.geometry.paths[idx2]);
// }
// } else if(first2.x === last.x && first2.y === last.y){
// //console.log("path " + idx + " is before path " +idx2);
// var eleIdx = arr.indexOf(profileFeature.geometry.paths[idx]);
// if(eleIdx > -1){
// arr.splice(eleIdx, 0, profileFeature.geometry.paths[idx2]);
// }
// }
// });
// });
// profileFeature.geometry.paths = arr;
// },
deactivateAll: function(){
if (this._tooltip) {
domConstruct.destroy(this._tooltip);
this._tooltip = null;
for (var i = 1; i <= this._tooltipHandlers; ++i) {
if (this['_tooltipHandler' + i]) {
this['_tooltipHandler' + i].remove();
}
}
}
if (this.selectGraphButton) {
this.selectGraphButton.set('checked', false);
this.selectGraphOnMap();
}
this.resetAll();
this.deactivateTool('Distance');
this.deactivateTool('Surface');
this.deactivateTool('Altimetrie');
},
activateTool: function(tool){
domClass.add(this[tool + 'Button'], "activated");
domClass.add(this['measure' + tool + 'Content'], "activated");
},
deactivateTool: function(tool){
if (this[tool + 'Button'] == null) {
return;
}
domClass.remove(this[tool + 'Button'], "activated");
domClass.remove(this['measure' + tool + 'Content'], "activated");
this.selectGraphButton.set('checked', false);
this.selectGraphOnMap();
if(this.drawTb){
this.drawTb.deactivate();
}
if(this.drawEndHdl){
this.drawEndHdl.remove();
this.drawEndHdl = null;
}
if (this.drawMoveHdl) {
this.drawMoveHdl.remove();
this.drawMoveHdl = null;
}
},
resetAll: function(){
this.elevationInfo = null;
if (this.DistanceMeters) { // peut être undefined si MapDestroyed
this.DistanceMeters.innerHTML = "";
this.DistanceKilometers.innerHTML = "";
this.SurfaceMeters.innerHTML = "";
this.SurfaceKilometers.innerHTML = "";
this.SurfaceHectares.innerHTML = "";
this.SurfaceAres.innerHTML = "";
this.PerimetreMeters.innerHTML = "";
this.PerimetreKilometers.innerHTML = "";
}
if (this.currGraphAltimetrie && (this.currGraphAltimetrie.chartLocationGraphic.nbGraph === 1 || !this.activated)) {
this.currGraphAltimetrie.onDeactivate();
this.currGraphAltimetrie.destroy();
this.currGraphAltimetrie = null;
domStyle.set(this.graphResult, 'display', 'none');
}
if (this.currGeom && (this.AltimetriePopup == null || !this.AltimetriePopup.activated)) {
this.spwViewer.get('spwMap').removeFeature(this.currGeom);
this.currGeom = null;
}
},
resetAfter: function() {
if (this.AltimetriePopup){
this.AltimetriePopup.destroy();
this.AltimetriePopup = null;
}
if (this.currGeom) {
this.spwViewer.get('spwMap').removeFeature(this.currGeom);
this.currGeom = null;
}
},
onActivate: function() {
this.inherited(arguments);
this.own(
this._graphicsClickedHandler = on(this.spwViewer.get('spwMap'), this.spwViewer.get('spwMap').events.GraphicsClicked, lang.hitch(this, this.onGraphicsClicked))
);
},
onDeactivate: function(){
this.inherited(arguments);
this.deactivateAll();
if (this._graphicsClickedHandler) {
this._graphicsClickedHandler.remove();
this._graphicsClickedHandler = null;
}
},
showTooltip: function(msg, draw) {
if (this._tooltip == null) {
this._tooltip = domConstruct.create('div', {
'class': 'tooltipMeasureV3',
innerHTML: msg
}, this.spwViewer.get('spwMap').esriMap.container);
var drawing = false;
this.own(
this._tooltipHandler1 = on(this.spwViewer.get('spwMap'), this.spwViewer.get('spwMap').events.MapMouseMove, lang.hitch(this, function(evt) {
domStyle.set(this._tooltip, {
'top': (evt.screenPoint.y + 15) + 'px',
'left': (evt.screenPoint.x + 15) + 'px'
});
})),
this._tooltipHandler2 = on(this.spwViewer.get('spwMap'), this.spwViewer.get('spwMap').events.MapClicked, lang.hitch(this, function() {
if (this.selectingOnMap) {
return;
}
if (!drawing) {
drawing = true;
if (this._tooltip) {
this._tooltip.innerHTML = 'Cliquez pour continuer ou double-cliquez pour terminer';
}
}
})),
this._tooltipHandler3 = on(draw, 'draw-end', lang.hitch(this, function() {
drawing = false;
if (this._tooltip) {
this._tooltip.innerHTML = msg;
}
})),
this._tooltipHandler4 = aspect.after(draw, '_clear', lang.hitch(this, function(def) {
drawing = false;
if (this._tooltip) {
this._tooltip.innerHTML = msg;
}
}))
);
}
else {
domStyle.set(this._tooltip, 'display', '');
if (this._tooltip) {
this._tooltip.innerHTML = msg;
}
}
},
activateDrawLine: function(fct, msg, opts) {
opts = opts || ['click', 'move'];
if(!this.drawTb){
this.drawTb = new Draw(this.spwViewer.get('spwMap').get('esriMap'), {
showTooltips: false
});
}
this.showTooltip(msg, this.drawTb);
if(this.drawEndHdl){
this.drawEndHdl.remove();
this.drawEndHdl = null;
}
if (this.drawMoveHdl) {
this.drawMoveHdl.remove();
this.drawMoveHdl = null;
}
if (opts.indexOf('click') > -1) {
this.drawEndHdl = this.drawTb.on('draw-end', lang.hitch(this, function(evt){
if(fct) {
fct(evt);
}
}));
}
if (opts.indexOf('move') > -1) {
this.drawMoveHdl = this.drawTb.on('mouse-move', lang.hitch(this, function(evt) {
fct && fct(evt, 'move');
}));
}
this.drawTb.activate(Draw.POLYLINE);
},
activateDrawPolygon: function(fct, msg, opts) {
opts = opts || ['click', 'move'];
if(!this.drawTb){
this.drawTb = new Draw(this.spwViewer.get('spwMap').get('esriMap'), {
showTooltips: false
});
}
this.showTooltip(msg, this.drawTb);
if(this.drawEndHdl){
this.drawEndHdl.remove();
this.drawEndHdl = null;
}
if (this.drawMoveHdl) {
this.drawMoveHdl.remove();
this.drawMoveHdl = null;
}
if (opts.indexOf('click') > -1) {
this.drawEndHdl = this.drawTb.on('draw-end', lang.hitch(this, function(evt){
if(fct) {
fct(evt);
}
}));
}
if (opts.indexOf('move') > -1) {
this.drawMoveHdl = this.drawTb.on('mouse-move', lang.hitch(this, function(evt) {
fct && fct(evt, 'move');
}));
}
this.drawTb.activate(Draw.POLYGON);
},
createAltimetrieGraph: function() {
if (!this.currGraphAltimetrie) {
this.currGraphAltimetrie = new graphAltimetrie({
spwViewer: this.spwViewer,
measureWidget: this,
graphColor: this.graphColor
}, domConstruct.create("div", { style: "height: 250px; position: relative;" }, this.AltimetrieGraphDiv));
this.currGraphAltimetrie.onActivate(true);
}
},
enlargeGraphClick: function(){
if(this.AltimetriePopup) {
this.AltimetriePopup.onDeactivate();
this.AltimetriePopup.destroy();
}
this.AltimetriePopup = new graphAltimetrie({
position: (this.spwViewer.mobile ? "bottom" : "panel-light"),
width: this._vwToPixels(this.popupWidth || '70vw'), // car 70vw ne permet pas au graphique de se redimensionner correctement
height: this.popupHeight || "260px",
bottom: "20px",
right: "130px",
widgetTitle: "Profil altimétrique",
activated: !this.spwViewer.mobile,
spwViewer: this.spwViewer,
measureWidget: this,
resizable: true,
inPopup: true,
graphColor: this.graphColor,
showMeasureInfo: true
});
if (this.spwViewer.mobile) {
this.AltimetriePopup.onActivate(); // si on ne le fait pas à cet endroit, ça ne s'affiche pas
}
},
_vwToPixels: function(vw) {
if (vw.indexOf('vw') < 0) {
return vw;
}
return (win.getBox().w * (parseInt(vw) / 100)) + 'px';
},
removeGeometry: function() {
if(this.currGeom){
this.spwViewer.get('spwMap').removeFeature(this.currGeom);
this.currGeom = null;
}
},
showGeometry: function(geometry) {
this.removeGeometry();
this.currGeom = new graphic(geometry);
this.spwViewer.get('spwMap').showFeature(this.currGeom);
}
});
var graphAltimetrie = declare("spw.widgets.SpwMeasureGraph", [SpwBaseWidget], {
measureWidget: null,
spwViewer: null,
inPopup: false,
profileChart: null,
profilePolyline: null,
elevationData: null,
distances: null,
/**
* graphic croix rouge -> partagé entre les différents graphiques
* @type {Object}
*/
chartLocationGraphic: {
graphic: null,
nbGraph: 0
},
plotName: 'default',
seriesName: 'elevation-data',
currentChartDistance: null,
showMeasureInfo: false,
postCreate: function(){
this.inherited(arguments);
this._createGraph();
if(this.showMeasureInfo){
var distance = domConstruct.create("span",{ innerHTML: "Distance: ", style: "text-shadow: -1px 0px"});
var distanceVal = domConstruct.create("span",{ innerHTML: this.measureWidget.altiDistance + " m", style: "padding-right: 30px"});
var altMin = domConstruct.create("span",{ innerHTML: "Altitude min: ", style: "text-shadow: -1px 0px"});
var altMinVal = domConstruct.create("span",{ innerHTML: this.measureWidget.altiMin + " m", style: "padding-right: 30px"});
var altMax = domConstruct.create("span",{ innerHTML: "Altitude max: ", style: "text-shadow: -1px 0px"});
var altMaxVal = domConstruct.create("span",{ innerHTML: this.measureWidget.altiMax + " m", style: "padding-right: 30px"});
var cumPos = domConstruct.create("span",{ innerHTML: "Cumulée +: " , style: "text-shadow: -1px 0px"});
var cumPosVal = domConstruct.create("span",{ innerHTML: this.measureWidget.cpos+ " m", style: "padding-right: 30px"});
var cumNeg = domConstruct.create("span",{ innerHTML: "Cumulée -: ", style: "text-shadow: -1px 0px"});
var cumNegVal = domConstruct.create("span",{ innerHTML: + this.measureWidget.cneg+ " m", style: "padding-right: 30px"});
var container = domConstruct.create("div", {style: "width: 100%; text-align: center"});
container.appendChild(distance);
container.appendChild(distanceVal);
container.appendChild(altMin);
container.appendChild(altMinVal);
container.appendChild(altMax);
container.appendChild(altMaxVal);
container.appendChild(cumPos);
container.appendChild(cumPosVal);
container.appendChild(cumNeg);
container.appendChild(cumNegVal);
this.domNode.appendChild(container);
}
},
destroy: function() {
this._removeChartLocation();
this.inherited(arguments);
},
resize: function() {
this.inherited(arguments);
if (!this.inPopup) {
return;
}
if (this.profileChart) {
var w = null;
var h = null;
if (arguments[0] == null) {
w = parseFloat(this.width) * 1;
h = parseFloat(this.height) * 0.8;
}
else {
if (arguments[0].w) {
w = arguments[0].w * 1;
}
if (arguments[0].h) {
h = arguments[0].h * 0.95; // pour éviter la scrollbar tout le temps
}
}
this.profileChart.resize({w: w, h: h});
}
},
onActivate: function(ignoreSuperClass) {
if (ignoreSuperClass !== true) {
this.inherited(arguments);
}
this.chartLocationGraphic.nbGraph += 1;
},
onDeactivate: function() {
this.inherited(arguments);
this.chartLocationGraphic.nbGraph -= 1;
this._removeChartLocation();
if (this.inPopup && !this.measureWidget.activated) {
this.measureWidget.resetAfter();
}
},
_removeChartLocation: function() {
if (this.chartLocationGraphic.graphic && this.spwViewer && this.chartLocationGraphic.nbGraph === 0) {
this.spwViewer.get('spwMap').removeFeature(this.chartLocationGraphic.graphic);
this.chartLocationGraphic.graphic = null;
}
},
_displayChartLocation: function (chartObjectX) {
var indexOfCurrentDistance = this.distances.indexOf(chartObjectX);
this.currentChartDistance = 0;
if(indexOfCurrentDistance > -1){
this.currentChartDistance = this.distances[indexOfCurrentDistance];
}
if (this.spwViewer && this.elevationData && this.profilePolyline) {
if (this.chartLocationGraphic.graphic == null) {
// créatin du graphic (croix rouge)
var clr = Color.fromHex(this.graphColor).toRgb();
clr.push(128); // alpha à 255 et pas 0-1...
var chartLocationSymbol = new SimpleMarkerSymbol({
"color": clr,
"size": 8,
"type": "esriSMS",
"style": "esriSMSCircle",
"outline": {
"color": [0, 0, 0, 255],
"width": 1,
"type": "esriSLS",
"style": "esriSLSSolid"
}
});
/*var couleur = Color.fromHex(this.graphColor);
var outline = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color(Color.named.black), 3);
var chartLocationSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.CIRCLE, 13, outline, couleur);*/
this.chartLocationGraphic.graphic = new graphic(null, chartLocationSymbol);
this.spwViewer.get('spwMap').showFeature(this.chartLocationGraphic.graphic);
}
// mise à jour de la position de la croix
var distanceIndex = (this.distances) ? array.indexOf(this.distances, chartObjectX) : -1;
if (distanceIndex > -1) {
var elevData = this.elevationData[distanceIndex];
this.chartLocationGraphic.graphic.setGeometry(this.profilePolyline.getPoint(elevData.pathIdx, elevData.pointIdx));
} else {
this.chartLocationGraphic.graphic.setGeometry(null);
}
topic.publish('measure/refreshCross', {
'sender': this,
'position': chartObjectX
});
}
},
_updateChart: function(elevationInfo) {
/* when esri 3.14 ->
epWidget.set("profileGeometry", elevationInfo.geometry);
*/
this._removeChartLocation();
var elevationDataSeriesName = this.seriesName;
this.profilePolyline = elevationInfo.geometry;
this.elevationData = this._convertElevationsInfoArray(elevationInfo.elevations);
this.distances = this._convertDistancesArray(elevationInfo.distances);
//this.samplingDistance.distance = this._convertDistancesArray([elevationInfo.samplingDistance.distance])[0];
// calculs des y min et max
var yMinSource = this._getArrayMin(this.elevationData);
var yMaxSource = this._getArrayMax(this.elevationData);
var yRange = (yMaxSource - yMinSource);
yMin = yMinSource - (yRange * 0.05);
yMax = yMaxSource + (yRange * 0.05);
// mise à jour du graphique
this.profileChart.getAxis("y").opt.min = yMin;
this.profileChart.getAxis("y").opt.max = yMax;
// on indique que le chart doit être regénéré
this.profileChart.dirty = true;
this.profileChart.updateSeries(elevationDataSeriesName, this.elevationData);
// qu'on regénère
this.profileChart.render();
this.hideLoading();
},
/** récupère le max d'un tableau */
_getArrayMax: function (dataArray) {
var values = array.map(dataArray, function (item) {
return item.y;
});
return Math.max.apply(Math, values);
},
/** récupère le min d'un tableau */
_getArrayMin: function (dataArray) {
var values = array.map(dataArray, function (item) {
return item.y;
});
return Math.min.apply(Math, values);
},
/** récupère le x et le y des informations retournées par le service */
_convertElevationsInfoArray: function (elevationArray) {
return array.map(elevationArray, lang.hitch(this, function (item) {
return lang.mixin(item, {
x: item.x,
y: item.y
});
}));
},
/** récupère les distances */
_convertDistancesArray: function (distancesArray) {
return array.map(distancesArray, lang.hitch(this, function (distance) {
return distance;
}));
},
_createGraph: function() {
/* when esri 3.14 ->
var profileParams = {
chartOptions: {
title: 'Profil altimétrique',
chartTitleFontSize: 14,
axisTitleFontSize: 11,
axisLabelFontSize: 9,
indicatorFontColor: '#eee',
indicatorFillColor: '#666',
titleFontColor: '#eee',
axisFontColor: '#ccc',
axisMajorTickColor: '#333',
skyTopColor: "#B0E0E6",
skyBottomColor: "#4682B4",
waterLineColor: "#eee",
waterTopColor: "#ADD8E6",
waterBottomColor: "#0000FF",
elevationLineColor: "#D2B48C",
elevationTopColor: "#8B4513",
elevationBottomColor: "#CD853F"
},
map: this.spwViewer.get('spwMap').get('esriMap'),
profileTaskUrl: 'https://elevation.arcgis.com/arcgis/rest/services/Tools/ElevationSync/GPServer',
scalebarUnits: Units.METERS
};
this.profileChart = new ElevationProfile(profileParams, this.domNode);
this.profileChart.startup();
*/
require(["dojox/charting/Chart", "dojox/charting/axis2d/Default", "dojox/charting/plot2d/Areas",
"dojox/charting/themes/PlotKit/blue", "dojox/charting/action2d/MouseZoomAndPan",
"dojox/charting/action2d/MouseIndicator", "dojox/charting/Theme"],
lang.hitch(this, function(Chart, Default, Areas, PlotKitBlue, MouseZoomAndPan, MouseIndicator, Theme) {
PlotKitBlue.next = function(elementType, mixin, doPost){
var theme = Theme.prototype.next.apply(this, arguments);
if(elementType == "line"){
theme.marker.outline = {width: 2, color: "#fff"};
theme.series.stroke.width = 3.5;
theme.marker.stroke.width = 2;
}else if(elementType == "candlestick"){
theme.series.stroke.width = 1;
}/*else if(theme.series.stroke.color && (theme.series.stroke.color.toString() ==
new Color(this.colors[(this._current-1) % this.colors.length]).toString())){
// if the user did not override the stroke, let's force blank
theme.series.stroke.color = "#fff";
}*/
return theme;
};
if(this.showMeasureInfo){
this.profileChart = new Chart(domConstruct.create('div', {}, domConstruct.create('div', { style: 'position: absolute; top: 55px; bottom: 1px; left: 0; right: 0;'}, this.domNode)));
} else {
this.profileChart = new Chart(this.domNode);
}
this.profileChart.addPlot(this.plotName, {
type: Areas,
markers: false,
tension: "X",
dirty: true
});
this.profileChart.addAxis("x", {
title: 'Distance (m)',
titleOrientation: 'away',
titleFontColor: 'rgb(153, 153, 153)',
titleFont: "Lato"
});
this.profileChart.addAxis("y", {
title: 'Altitude (m)',
vertical: true,
titleFontColor: 'rgb(153, 153, 153)',
titleFont: "Lato"
});
this.profileChart.addSeries(this.seriesName, []);
new MouseZoomAndPan(this.profileChart, this.plotName, { axis: "x" });
PlotKitBlue.chart.fill = "#fff";
PlotKitBlue.plotarea.fill = "#fff";
var baseColor = Color.fromHex(this.graphColor).toRgba();
baseColor[3] = 0.6;
PlotKitBlue.series.fill = Color.fromArray(baseColor).toString();
PlotKitBlue.colors = Theme.defineColors({
base: this.graphColor,
generator: "monochromatic"
});
this.profileChart.setTheme(PlotKitBlue);
this.mouseIndicator = new MouseIndicator(this.profileChart, this.plotName, {
series: this.seriesName,
font: "normal normal bold 8pt Tahoma",
mouseOver: true,
fillFunc: function(v){
return "#4f8fa5";//v.y >= 0 ? "green" : "red";
},
/*markerStroke: {
color: "black",
width: 3
},*/
//markerSymbol: "m -6 -6, l 12 12, m 0 -12, l -12 12",
labelFunc: lang.hitch(this, function(v) {
this._displayChartLocation(v.x);
var factor = Math.pow(10, 1);
var truncValue = Math.round(this.currentChartDistance * factor) / factor;
return ('Alt: '+Math.round(v.y * 100)/100) + ' m; Dist: ' + truncValue + " m";
})
});
this.profileChart.render();
this.own(
on(this.measureWidget, 'update-chart', lang.hitch(this, this._updateChart))
);
if (this.measureWidget.elevationInfo) {
this._updateChart(this.measureWidget.elevationInfo);
}
this.resize();
topic.subscribe('measure/refreshCross', lang.hitch(this, function(obj) {
if (obj.sender === this) {
return;
}
// mettre à jour la valeur sur le graphique...comment ?
}));
})
);
}
});
return SpwMeasure;
});
/*
(c) 2017, Vladimir Agafonkin
Simplify.js, a high-performance JS polyline simplification library
mourner.github.io/simplify-js
*/
(function () { 'use strict';
//to suit your point format, run search/replace for '.x' and '.y';
//for 3D version, see 3d branch (configurability would draw significant performance overhead)
//square distance between 2 points
function getSqDist(p1, p2) {
var dx = p1.x - p2.x,
dy = p1.y - p2.y;
return dx * dx + dy * dy;
}
//square distance from a point to a segment
function getSqSegDist(p, p1, p2) {
var x = p1.x,
y = p1.y,
dx = p2.x - x,
dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
//rest of the code doesn't care about point format
//basic distance-based simplification
function simplifyRadialDist(points, sqTolerance) {
var prevPoint = points[0],
newPoints = [prevPoint],
point;
for (var i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point) newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
var maxSqDist = sqTolerance,
index;
for (var i = first + 1; i < last; i++) {
var sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
//simplification using Ramer-Douglas-Peucker algorithm
function simplifyDouglasPeucker(points, sqTolerance) {
var last = points.length - 1;
var simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
//both algorithms combined for awesome performance
function simplify(points, tolerance, highestQuality) {
if (points.length <= 2) return points;
var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
//export as AMD module / Node module / browser or worker variable
window.simplify = simplify;
})();