/**
* @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_;
};