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

/**
 * @classdesc
 * 
 * Class designed for route calculation.  
 * 
 * @constructor
 * @param {cercaliax.service.DistanceOptions} options Params and options for distance calculation
 */ 
cercalia.service.Distance = function(options) {
	
	/**
	 * Class name
	 * @private
	 * @type {string}
	 */
	this.CLASS_NAME_ = "cercalia.service.Distance";
	
	this.cercaliaKey_ = cercaliaGlobals.key;	//Esta variable siempre se pasara al descargar la API
	
	this.server_ = servers.servlet;

	var options = options ? options : {};
	
	/**
	 * @type {cercalia.LonLat}
	 * @private
	 */
	this.origin_ = options.origin ? options.origin : null;

	/**
	 * @type {cercalia.LonLat}
	 * @private
	 */
	this.destination_ = options.destination ? options.destination : null;
	
	/**
	 * @type {Array.<cercalia.LonLat>}
	 * @private
	 */
	this.steps_ = options.steps ? options.steps : [];
	
	/**
	 * @type {string}
	 * @private
	 */
	this.weight_ = options.weight ? options.weight : 'line';
	
	/**
	 * @type {string}
	 * @private
	 */
	this.calculateGeometry_ = options.calculateGeometry ? 1 : 0; 
	
	
	/**
	 * @type {number}
	 * @private
	 */
	this.distance_ = null;
	
};


/**
 * @param {cercalia.LonLat} lonLat Assign the origin of distance calculation
 */
cercalia.service.Distance.prototype.setOrigin = function(lonLat) {
	if(lonLat instanceof cercalia.LonLat){
		this.origin_ = lonLat;
	} else {
		alert('No es un objeto tipo LonLat');
	}
};

/**
 * @return {cercalia.LonLat} Returns the origin assigned previously
 */
cercalia.service.Distance.prototype.getOrigin = function() {
	return this.origin_;
};

/**
 * @param {cercalia.LonLat} lonLat Destination
 */
cercalia.service.Distance.prototype.setDestination = function(lonLat) {
	if(lonLat instanceof cercalia.LonLat){
		this.destination_ = lonLat;
	} else {
		alert('No es un objeto tipo LonLat');
	}
};

/**
 * @return {cercalia.LonLat} Returns the destination assigned previously
 */
cercalia.service.Distance.prototype.getDestination = function() {
	return this.destination_;
};

/**
 * @param {Array.<cercalia.LonLat>} steps Array with steps
 */
cercalia.service.Distance.prototype.setSteps = function(steps) {
	this.steps_ = steps;
};

/**
 * @return {Array.<cercalia.LonLat>} destination
 */
cercalia.service.Distance.prototype.getSteps = function() {
	return this.steps_;
};


/**
 * @param {string} weight 
 */
cercalia.service.Distance.prototype.setWeight = function(weight) {
	this.weight_ = weight ? weight: 'line';
};

/**
 * Values = [line|time|distance|money]
 * @return {string} weight
 */
cercalia.service.Distance.prototype.getWeight = function() {
	return this.weight_;
};


/**
 * @param {boolean} calculateGeometry
 */
cercalia.service.Distance.prototype.setCalculateGeometry = function(calculateGeometry) {
	this.calculateGeometry_ = calculateGeometry ? 1: 0;
};

/**
 * Returns if calculate geometry function it's on or off
 * @return {boolean} calculateGeometry
 */
cercalia.service.Distance.prototype.isCalculateGeometry = function() {
	return this.calculateGeometry_==1;
};



/**
 * Distance calculation with the assigned parameters, and returns the data to the callback function
 * specified by parameter by the user. 
 * @param {Function} callbackFn callback funcion
 */
cercalia.service.Distance.prototype.calculate = function(callbackFn) {	
	
	var self = this;
	
	if(typeof(callbackFn) == "function"){
	
		switch(this.weight_){
		
			//Calculo en linea recta
			case 'line':
				
				var obj = {
						cercalia : {
							distance : null,
							weight : this.weight_,
							stages : {
								stage : []
							},
							stoplist : {
								stop : []
							}
						}
				};
				
				//Preparamos un array
				var arrCoordinatesSorted = [];
		
				
				arrCoordinatesSorted.push([this.origin_.getLon() , this.origin_.getLat()]);
				obj.cercalia.stoplist.stop.push({
						id : 0,
						coord : {
							x: this.origin_.getLon(),
							y: this.origin_.getLat()
						}
				});
				
				
				this.steps_.forEach(function(elem,i){
					arrCoordinatesSorted.push([elem.getLon() , elem.getLat()]);
					
					obj.cercalia.stoplist.stop.push({
							id : i+1,
							coord : {
								x: elem.getLon(),
								y: elem.getLat()
							}
					});
				});
				
				arrCoordinatesSorted.push([this.destination_.getLon() , this.destination_.getLat()]);
				obj.cercalia.stoplist.stop.push({
						id : this.steps_.length+1,
						coord : {
							x: this.destination_.getLon(),
							y: this.destination_.getLat()
						}
				});

				
				
				//Calculamos distancia etapa a etapa
				var total = 0;
				
				for(var i = 0 ; i < arrCoordinatesSorted.length-1 ; i++){
	
					//var dist = self.cosineDistance_(ol.sphere.WGS84.radius, arrCoordinatesSorted[i],arrCoordinatesSorted[i+1]);
					//var dist = self.cosineDistance_(6378137, arrCoordinatesSorted[i],arrCoordinatesSorted[i+1]);
					var p1 = ol.proj.transform(arrCoordinatesSorted[i],'EPSG:4326','EPSG:3857');
					var p2 = ol.proj.transform(arrCoordinatesSorted[i+1],'EPSG:4326','EPSG:3857');

					var dist = new ol.geom.LineString([p1, p2]).getLength();
					dist = cercalia.Util.metersToKm(dist);
					
					total += dist;
					
					obj.cercalia.stages.stage.push({
							id : i,
							dist : dist
					});
	
				}
				
				obj.cercalia.distance = total;
				
				callbackFn(obj);
				
				
				break;
			/* Los tres casos */
			case 'time':
			case 'distance':
			case 'money':
		
				var mo_o = this.origin_.getLat() + "," + this.origin_.getLon();
				var mo_d = this.destination_.getLat() + "," + this.destination_.getLon();
				
				var params = {
					key : this.cercaliaKey_,
					weight: this.weight_,
					cmd : 'distance',
					mo_o: mo_o,
					mo_d: mo_d
				};
				
				//Si queremos la geometria
				if(this.calculateGeometry_){
					params.calculateGeometry = "1";
				}
				
				this.steps_.forEach(function(elem,i){
					params['mo_'+(i+1)] = elem.getLat() + "," + elem.getLon();
				});
				

				cercalia.jQuery.ajax({
					type: "GET",
					method: "GET",
					dataType: cercalia.Util.isIEUnderTen() ? "jsonp" : "json",
					//contentType: 'application/json; charset=utf-8',
					async:true,
					url: this.server_,
					data: params,
					success: function(data){
						try {
							data.cercalia.weight = self.weight_;
							callbackFn(data);
						} catch (e){
							console.error(e);
						}
					},
					error: cercalia.AJAXException
				});
				
				
				break;
	
		}
	} else {
		alert('El parametro no es una funcion!');
	}

};


/**
 * @private
 * @param {number} radius
 * @param {number} c1
 * @param {number} c2
 * @return {Number} Distance in meters
 */
cercalia.service.Distance.prototype.cosineDistance_ = function(radius, c1, c2) {
	var lat1 = this.toRadians_(c1[1]);
	var lat2 = this.toRadians_(c2[1]);
	var deltaLon = this.toRadians_(c2[0] - c1[0]);
	
	return radius * Math.acos(
			Math.sin(lat1) * Math.sin(lat2) +
			Math.cos(lat1) * Math.cos(lat2) * Math.cos(deltaLon)
	);
};

/**
 * Converts degrees to radians.
 * @private
 * @param {number} angleDegrees Angle in degrees.
 * @return {number} Angle in radians. 
 */
cercalia.service.Distance.prototype.toRadians_ = function(angleDegrees){
	return angleDegrees * Math.PI / 180;
};



/**
 * 
 * @private
 * @param {ol.geom} geometry
 * @return {string} 
 */
cercalia.service.Distance.prototype.formatLength_ = function(geometry) {

	var length = Math.round(geometry.getLength() * 100) / 100;
	var output;
	if (length > 100) {
		output = (Math.round(length / 1000 * 100) / 100) + 'km';
	} else {
		output = (Math.round(length * 100) / 100) + 'm';
	}
	
	return output;
};

/**
* Returns the object type.
* @return {string}
*/
cercalia.service.Distance.prototype.getClass = function(){
	return this.CLASS_NAME_;
};