Source: temp/jsdocinputdirs/cercalia.service.routing.js

/**
 * 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());
};