/**
* Constructor del servei Service Routing
* @class
* @constructor
* @param {cercaliax.service.RoutingOptions} options
*/
cercalia.service.Routing = function(options) {
this.cercaliaKey_ = cercaliaGlobals.key; //Esta variable siempre se pasara al descargar la API
this.server_ = servers.servlet;
var options = options ? options : {};
/**
* @private
* @type {boolean}
*/
this.async_ = true;
/**
* @type {cercalia.LonLat|cercaliax.service.RoutingStep}
* @private
*/
this.origin_ = options.origin ? options.origin : null;
/**
* @type {cercalia.LonLat|cercaliax.service.RoutingStep}
* @private
*/
this.destination_ = options.destination ? options.destination : null;
/**
* @type {Array.<cercalia.LonLat>|Array.<cercaliax.service.RoutingStep>|undefined}
* @private
*/
this.steps_ = options.steps ? options.steps : [];
/**
* @type {string}
* @private
*/
this.weight_ = options.weight ? options.weight : 'time';
/**
* @type {boolean}
* @private
*/
this.report_ = options.report ? 1 : 0;
/**
* @type {string}
* @private
*/
this.lang_ = options.lang ? options.lang : (cercaliaGlobals.lang?cercaliaGlobals.lang:null);
/**
* @type {number}
* @private
*/
this.tolerance_ = options.tolerance ? options.tolerance : 5;
/**
* @type {number}
* @private
*/
this.edges_ = options.edges ? 1 : 0;
/**
* @type {Array.<string>}
* @private
*/
this.poicats_ = options.poicats ? options.poicats : [];
/**
* @type {boolean}
* @private
*/
this.reorder_ = options.reorder ? 1 : 0;
/**
* @type {boolean}
* @private
*/
this.toll_ = options.toll ? 1 : 0;
/**
* @type {number}
* @private
*/
this.mindist_ = options.mindist ? options.mindist : 1000;
/**
* @type {string}
* @private
*/
this.intoll_x_ = options.intoll_x ? options.intoll_x : "1";
/**
* @type {boolean}
* @private
*/
this.version_ = options.version ? options.version : 1;
/**
* @type {string}
* @private
*/
this.routeid_ = null;
/**
* @type {string}
* @private
*/
this.wkt_ = null;
/**
* @type {string}
* @private
*/
this.arrayStages_ = null;
/**
* @type {Object}
* @private
*/
this.response_ = null;
/**
* @type {cercalia.service.ReverseGeocoding}
* @private
*/
this.reverseGeocoding_ = new cercalia.service.ReverseGeocoding();
/**
* Nombre de la classe
* @private
* @type {string}
*/
this.CLASS_NAME_ = "cercalia.service.Routing";
};
/**
* Indica inicio ruta
* @param {cercalia.LonLat|cercaliax.service.RoutingStep} origin
*/
cercalia.service.Routing.prototype.setOrigin = function(origin) {
if (origin instanceof cercalia.LonLat) {
this.origin_ = origin;
} else if (origin instanceof Object) {
this.origin_ = origin;
} else {
console.error(origin);
alert('Parámetro desconocido: ' + origin);
}
};
/**
* @return {cercalia.LonLat|cercaliax.service.RoutingStep} lonLat Inicio de la ruta
*/
cercalia.service.Routing.prototype.getOrigin = function() {
return this.origin_;
};
/**
* Indica inicio ruta
* @param {cercalia.LonLat|cercaliax.service.RoutingStep} destination
*/
cercalia.service.Routing.prototype.setDestination = function(destination) {
if (destination instanceof cercalia.LonLat) {
this.destination_ = destination;
} else if (destination instanceof Object) {
this.destination_ = destination;
} else {
console.error(destination);
alert('Parámetro desconocido: ' + destination);
}
};
/**
* @return {cercalia.LonLat|cercaliax.service.RoutingStep} lonLat Final de la ruta
*/
cercalia.service.Routing.prototype.getDestination = function() {
return this.destination_;
};
/**
* @param {Array.<cercalia.LonLat>|Array.<cercaliax.service.RoutingStep>} steps
*/
cercalia.service.Routing.prototype.setSteps = function(steps) {
this.steps_ = steps;
};
/**
* @return {Array.<cercalia.LonLat>|Array.<cercaliax.service.RoutingStep>} steps
*/
cercalia.service.Routing.prototype.getSteps = function() {
return this.steps_;
};
/**
* Indica inicio ruta
* @param {boolean} reporting
*/
cercalia.service.Routing.prototype.setReporting = function(reporting) {
this.report_ = reporting ? 1 : 0;
};
/**
* @return {boolean} report
*/
cercalia.service.Routing.prototype.isReporting = function() {
return this.report_==1;
};
/**
* Indica la tolerancia de la ruta
* @param {number} tolerance
*/
cercalia.service.Routing.prototype.setTolerance = function(tolerance) {
this.tolerance_ = tolerance ? tolerance : 5;
};
/**
* @return {number} tolerance
*/
cercalia.service.Routing.prototype.getTolerance = function() {
return this.tolerance_;
};
/**
* Indica si se devolveran los edges de la ruta
* @param {number} edges
*/
cercalia.service.Routing.prototype.setEdges = function(edges) {
this.edges_ = edges ? 1 : 0;
};
/**
* @return {number} edges
*/
cercalia.service.Routing.prototype.getEdges = function() {
return this.edges_;
};
/**
* @param {Array.<string>} poicats
*/
cercalia.service.Routing.prototype.setPoicats = function(poicats) {
this.poicats_ = poicats;
};
/**
* @return {Array.<string>} poicats
*/
cercalia.service.Routing.prototype.getPoicats = function() {
return this.poicats_;
};
/**
* @param {boolean} reorder
*/
cercalia.service.Routing.prototype.setReorder = function(reorder) {
this.reorder_ = (reorder ? 1 : 0);
};
/**
*
* @return {boolean} reorder
*/
cercalia.service.Routing.prototype.isReorder = function() {
return this.reorder_;
};
/**
* @param {boolean} toll
*/
cercalia.service.Routing.prototype.setToll = function(toll) {
this.toll_ = toll;
};
/**
* @return {boolean} toll
*/
cercalia.service.Routing.prototype.getToll = function() {
return this.toll_;
};
/**
* @param {String} intoll_x
*/
cercalia.service.Routing.prototype.setToll_x = function(intoll_x) {
this.intoll_x_ = intoll_x;
};
/**
* @return {String} intoll_x
*/
cercalia.service.Routing.prototype.getToll_x = function() {
return this.intoll_x_;
};
/**
* @param {boolean} mindist
*/
cercalia.service.Routing.prototype.setMindist = function(mindist) {
this.mindist_ = mindist;
};
/**
* @return {boolean} toll
*/
cercalia.service.Routing.prototype.getMindist = function() {
return this.mindist_;
};
/**
* Cambia la peticion al servidor de ruta de forma sincrona (false) /asincrona (true).
* @param {boolean} async
*/
cercalia.service.Routing.prototype.setAsync = function(async) {
this.async_ = async;
};
/**
* @return {boolean} async
*/
cercalia.service.Routing.prototype.getAsync = function(async) {
return this.async_;
};
/**
* Devuelve el weight de la ruta actual.
* @return {string} Route weight
*/
cercalia.service.Routing.prototype.getWeight = function() {
return this.weight_;
};
/**
* Cambia el weight del caclulo de la ruta.
* @param {string} async
*/
cercalia.service.Routing.prototype.setWeight = function(weight) {
this.weight_ = weight;
};
/**
* Reinicializa los valores a null
*/
cercalia.service.Routing.prototype.clear = function() {
this.origin_ = null;
this.destination_ = null;
this.steps_ = [];
//this.weight_ = null;
//this.report_ = null;
//this.tolerance_ = null;
//this.edges_ = null;
this.poicats_ = [];
this.reorder_ = null;
this.toll_ = null;
this.mindist_ = null;
this.routeid_ = null;
this.wkt_ = null;
this.arrayStages_ = null;
this.response_ = null;
};
/**
* Calcula la ruta especificando una funcion de callback que se ejecuta al volver el resultado
* @param {Function} callbackFn
* @param {Function} callbackErrorFn
*/
cercalia.service.Routing.prototype.calculateRoute = function(callbackFn, callbackErrorFn) {
var self = this;
var cmdRouteVersion = this.version_ == 2 ? 'routingstage' : 'routing';
//Parámetros obligatorios
var params = {
key: this.cercaliaKey_,
cmd: cmdRouteVersion,
weight: this.weight_,
tolerance: this.tolerance_,
edges: this.edges_,
report: this.report_,
splitGeom: '1',
version: this.version_,
iweight: "realtime" //per defecte, posa el temps real de la ruta
};
//Generamos los parámetros de forma dinámica según los valors de la variables origin/destination/steps
//Origen
if (this.origin_ instanceof cercalia.LonLat) {
params["mo_o"] = this.origin_.getLat() + "," + this.origin_.getLon() + "|" + cercalia.i18n._('Origin');
params["intoll_o"] = this.intoll_x_; // posem el parametre 'intoll_o'
} else {
if (this.origin_.streetId) {
params["stc_o"] = this.origin_.streetId;
if (this.origin_.streetNum) {
params["stnum_o"] = this.origin_.streetNum;
}
} else if (this.origin_.cityId) {
params["ctc_o"] = this.origin_.cityId;
} else if (this.origin_.municipalityId) {
params["munc_o"] = this.origin_.municipalityId;
} else {
alert('No se puede calcular la ruta: El origen es incorrecto');
}
}
//Pasos intermedios (opcional)
this.steps_.forEach(function(elem,i) {
if (elem instanceof cercalia.LonLat) {
params["mo_"+(i+1)] = elem.getLat() + "," + elem.getLon() + "|" + cercalia.i18n._('Step "%"', (i+1) );
params["intoll_"+(i+1)] = this.intoll_x_; // posem el parametre 'intoll_x'
} else {
if (elem.streetId) {
params["stc_"+(i+1)] = elem.streetId;
if (elem.streetNum) {
params["stnum_"+(i+1)] = elem.streetNum;
}
} else if (elem.cityId) {
params["ctc_"+(i+1)] = elem.cityId;
} else if (elem.municipalityId) {
params["munc_"+(i+1)] = elem.municipalityId;
} else {
alert('No se puede calcular la ruta: La etapa ('+(i+1)+') es inválida');
}
}
});
//Destination
if (this.destination_ instanceof cercalia.LonLat) {
params["mo_d"] = this.destination_.getLat() + "," + this.destination_.getLon() + "|" + cercalia.i18n._('Destination');
params["intoll_d"] = this.intoll_x_; // posem el parametre 'intoll_d'
} else {
if (this.destination_.streetId ) {
params["stc_d"] = this.destination_.streetId;
if (this.destination_.streetNum) {
params["stnum_d"] = this.destination_.streetNum;
}
} else if (this.destination_.cityId) {
params["ctc_d"] = this.destination_.cityId;
} else if (this.destination_.municipalityId) {
params["munc_d"] = this.destination_.municipalityId;
} else {
alert('No se puede calcular la ruta: El destino es incorrecto');
return;
}
}
//Parametros opcionales
//if (this.poicats_.length>0) params.getpoicats = this.poicats_.join(",");
if (this.reorder_) {
params.reorder = this.reorder_;
}
if (this.report_) {
params.lang = this.lang_ ? this.lang_ : 'es';
params.mindist = this.mindist_;
}
if (this.toll_) {
params.toll = this.toll_;
}
cercalia.jQuery.ajax({
type: "GET",
method: "GET",
dataType: cercalia.Util.isIEUnderTen() ? "jsonp" : "json",
//contentType: 'application/json; charset=utf-8',
crossDomain: true,
url: this.server_,
data: params,
async: this.async_ ? this.async_ : true,
success: function(data) {
self.response_ = data;
if (data.cercalia.error) {
var error = data.cercalia.error;
cercalia.Exception('Cercalia Error:' + error.id + ', type_id:' + error.type + ', value:' + error.value);
if (callbackErrorFn)callbackErrorFn(data);
return;
}
// self.routeid_ = data.cercalia.geometry.route.id; //old
// ara el 'data.cercalia.geometry' és una array
self.routeid_ = data.cercalia.route.id;
var routeGeomSteps = cmdRouteVersion=="routingstage" ? data.cercalia.route.stages.stage : data.cercalia.geometry.route;
if (routeGeomSteps instanceof Array) {
self.wkt_ = self.createWKTWithArrayLineString_(routeGeomSteps);
self.arrayStages_ = routeGeomSteps;
} else {
alert('cercalia.service.routing: Error1');
}
// if (cmdRouteVersion=="routingstage") {
// } else {
// if (data.cercalia.geometry.route instanceof Array) {
// self.wkt_ = self.createWKTWithArrayLineString_(data.cercalia.geometry.route);
// self.arrayStages_ = data.cercalia.geometry.route;
// } else {
// alert('cercalia.service.routing: Error2');
// // // Per aqui no hauria de passar mai!!!
// // self.wkt_ = data.cercalia.geometry.route.wkt.value;
// // self.arrayStages_ = [ data.cercalia.geometry.route ];
// }
// }
//Actualitzem l'origen/desti/step si cal
self.updateStops_(data);
callbackFn(data);
},
error: function(a, b, c) {
cercalia.AJAXException(a, b, c);
if (callbackErrorFn)callbackErrorFn(a);
}
});
};
/**
* @private
* @param {Object|Array<Object>} data - cercalia Json or Array of Cercalia stops
*
*/
cercalia.service.Routing.prototype.updateStops_ = function (data) {
if (data && ((data.cercalia && data.cercalia.route && data.cercalia.route.stoplist && data.cercalia.route.stoplist.stop)
|| (Array.isArray(data) && data.length > 1 && data[0].ge )))
var arrayPoints = Array.isArray(data) ? data : data.cercalia.route.stoplist.stop;
//si l'origen no és una 'cercalia.LonLat' agafem l'origen de la ruta i creem la LonLat per l'origen
if (!this.origin_.getClass || this.origin_.getClass() != "cercalia.LonLat") {
var coordOrigin = this.getCoordFromResponse_(arrayPoints[0]);
this.origin_ = this.fillLabel_(new cercalia.LonLat(coordOrigin.x, coordOrigin.y), arrayPoints[0]);
}
//si destí no és una 'cercalia.LonLat' agafem el destí de la ruta i creem la LonLat per el desti
if (!this.destination_.getClass || this.destination_.getClass() != "cercalia.LonLat") {
var coordDestination = this.getCoordFromResponse_(arrayPoints[arrayPoints.length-1]);
this.destination_ = this.fillLabel_(new cercalia.LonLat(coordDestination.x, coordDestination.y), arrayPoints[arrayPoints.length-1]);
}
if (arrayPoints && arrayPoints.length > 2 && this.steps_) {
for (var index = 0 ; index < this.steps_.length; index++) {
index = parseInt(index);
//si l'step no és una 'cercalia.LonLat' agafem l'step de la ruta i creem la LonLat per l'step
if (!this.steps_[index].getClass || this.steps_[index].getClass() != "cercalia.LonLat") {
if (arrayPoints[index + 1]) {
var coord = this.getCoordFromResponse_(arrayPoints[index + 1]);
this.steps_[index] = this.fillLabel_(new cercalia.LonLat(coord.x, coord.y),arrayPoints[index + 1]);
}
}
}
}
};
/**
* @private
* @param {cercalia.LonLat} lonlat
* @param {Object} stopCercalia - stop of cercalia Json
* @return {cercalia.LonLat}
*/
cercalia.service.Routing.prototype.fillLabel_ = function (lonlat, stopCercalia) {
if (stopCercalia && (stopCercalia.ge || stopCercalia.name)) {
var label = stopCercalia.ge ? stopCercalia.ge.name.value : stopCercalia.name.value;
lonlat.label = label;
}
return lonlat;
};
/**
* @private
* @param {Object} data
* @return {Object} coord
*/
cercalia.service.Routing.prototype.getCoordFromResponse_ = function (data) {
var obj = null
if (data.ge) {
obj = { x: data.ge.coord.x, y: data.ge.coord.y };
}
if (data.mo) {
obj = { x: data.mo.coord.x, y: data.mo.coord.y };
}
return obj;
};
/**
* Obtiene WKT de la ruta calculada
* @return {string} WKT de la ruta calculada. Devuelve null si no se ha calculado ninguna
*/
cercalia.service.Routing.prototype.getWKT = function() {
return this.wkt_;
};
/**
* Obtiene WKT de la ruta calculada
* @return {string} WKT de la ruta calculada. Devuelve null si no se ha calculado ninguna
*/
cercalia.service.Routing.prototype.getStages = function() {
return this.arrayStages_;
};
/**
* Obtiene el WKT para las etapas especificadas por parámetro. Anteriormente la ruta debe ser calculada con
* el parámetro "report=true"
*
* @param {Array.<stringr>} substages Subetapas. p.e: ["1,2", "3,4,5"]
* @param {function} callbackFn Funcion de callback
*/
cercalia.service.Routing.prototype.getSubstageWKT = function (substages, callbackFn) {
var params = {
key: this.cercaliaKey_,
cmd : 'geometry',
routeid : this.routeid_,
routeweight : this.weight_,
routesubstage : "["+substages.join("],[") + "]",
tolerance : this.tolerance_/*,
getpoicats: this.poicats_.join(",")*/
};
cercalia.jQuery.ajax({
dataType: "json",
url: this.server_,
data: params,
success: function(data) {
try {
self.response_ = data;
if (data.cercalia.error) {
var error = data.cercalia.error;
cercalia.Exception('Cercalia Error:' + error.id + ', type_id:' + error.type + ', value:' + error.value);
}
callbackFn(data);
} catch (e) {
console.error(e);
}
},
error: cercalia.AJAXException
});
};
/**
* @private
* @return {Array.<cercalia.LonLat>}
*/
cercalia.service.Routing.prototype.parsewkt_ = function(ps) {
var i, j, lat, lng, tmp, tmpArr;
var arr = [];
var m = ps.match(/\([^\(\)]+\)/g); //match '(' and ')' plus contents between them which contain anything other than '(' or ')'
if (m !== null) {
for (i = 0; i < m.length; i++) {
//match all numeric strings
tmp = m[i].match(/-?\d+\.?\d*/g);
if (tmp !== null) {
//convert all the coordinate sets in tmp from strings to Numbers and convert to LatLng objects
for (j = 0, tmpArr = []; j < tmp.length; j+=2) {
lng = Number(tmp[j]);
lat = Number(tmp[j + 1]);
tmpArr.push(new cercalia.LonLat(lng, lat));
}
arr.push(tmpArr);
}
}
}
//array of arrays of LatLng objects, or empty array
return arr;
};
/**
* @private
*/
cercalia.service.Routing.prototype.parsewktInArray_ = function(ps) {
//console.log("wkt: " + ps);
var i, j, lat, lng, tmp, //tmpArr,
arr = [],
//match '(' and ')' plus contents between them which contain anything other than '(' or ')'
m = ps.match(/\([^\(\)]+\)/g);
if (m !== null) {
for (i = 0; i < m.length; i++) {
//match all numeric strings
tmp = m[i].match(/-?\d+\.?\d*/g);
if (tmp !== null) {
//convert all the coordinate sets in tmp from strings to Numbers and convert to LatLng objects
for (j = 0, tmpArr = []; j < tmp.length; j+=2) {
lng = Number(tmp[j]);
lat = Number(tmp[j + 1]);
arr.push(new cercalia.LonLat(lng, lat));
}
//arr.push(tmpArr);
}
}
}
//array of arrays of LatLng objects, or empty array
return arr;
};
/**
* Get response
* @return {Object} response
*/
cercalia.service.Routing.prototype.getResponse = function() {
return this.response_;
};
/**
* @private
* @param {Array.<string>}
*/
cercalia.service.Routing.prototype.createWKTWithArrayLineString_ = function(array) {
//TODO:
if (array == null) {
return '';
}
var wkt = '';
for (var i = 0; i < array.length ; i++ ) {
var route = array[i];
if (route.wkt && route.wkt.value && route.wkt.value.indexOf('EMPTY') === -1) {
var m = route.wkt.value.match(/\([^\(\)]+\)/g);
for (var j = 0 ; j < m.length ; j++ ) {
var mWKT = '';
if (wkt !== '') {
mWKT = ',';
}
mWKT += m[j];
wkt += mWKT;
}
}
}
var wktStr;
if (array.length === 1) {
if (wkt.length !== 0) {
wktStr = 'LINESTRING ' + wkt;
}
wktStr = 'LINESTRING EMPTY';
} else {
wktStr = 'MULTILINESTRING ( ' + wkt +' )';
}
return wktStr;
};
/**
* Get classname of object
* @return {string}
*/
cercalia.service.Routing.prototype.getClass = function() {
return this.CLASS_NAME_;
};
/**
* clone cercalia.service.Routing to cercalia.service.LogisticsRouting
* @param {cercalia.service.LogisticsRouting} logisticsService
*/
cercalia.service.Routing.prototype.setOptionsToLogisticsService = function(logisticsService) {
//var logisitcsService = new cercalia.service.LogisticsRouting();
logisticsService.setOrigin(this.getOrigin());
logisticsService.setDestination(this.getDestination());
logisticsService.setSteps(this.getSteps());
logisticsService.setReporting(this.isReporting());
logisticsService.setTolerance(this.getTolerance());
logisticsService.setEdges(this.getEdges());
logisticsService.setPoicats(this.getPoicats());
logisticsService.setReorder(this.isReorder());
logisticsService.setToll(this.getToll());
logisticsService.setToll_x(this.getToll_x());
logisticsService.setMindist(this.getMindist());
logisticsService.setAsync(this.getAsync());
logisticsService.getWeight(this.setWeight());
};