/**
*	Constructor de l'objecte. Hi ha varies opcions segons el número de parametres.
*	1 parametre: Extent serialitzat.
*	2 parametre: coordenada, coordenada.
/	
*/
function NExtent() {
	if (arguments.length == 1)
		this.deserialize(arguments[0]);	
//TODO:	else if (arguments.length == 4)
//TODO:		 this.init2(arguments[0],arguments[1],arguments[2],arguments[3]);	
	else
		this.init(arguments[0],arguments[1]);

}

/**
*	Constructor de l'objecte.
*	@param {NPoint} point1 una coordenada
*	@param {NPoint} point2 una coordenada
*	@private
*/
NExtent.prototype.init = function(point1,point2) {
  this.point1 = point1;
  this.point2 = point2;
};

/**
*
*/
/*NExtent.prototype.init2 = function(center,scale,widthPixels,heightPixels) {
	try {
		var coord1=this.pixelsToCoordsWithParams (0,0,widthPixels,heightPixels,center,scale);
		var coord2=this.pixelsToCoordsWithParams (widthPixels,heightPixels,widthPixels,heightPixels,center,scale);
	}
	catch (e) {
		alert("Error a NExtent.init2()\n"+e.message);
	}
}*/

/**
*	Retorna una coordenada
*	@return {NPoint}
*/
NExtent.prototype.getPoint1 = function() {
  return this.point1;
};

/**
*	Retorna una coordenada
*	@return {NPoint}
*/
NExtent.prototype.getPoint2 = function() {
  return this.point2;
};

/**
*	Estableix una coordenada
*	@param {NPoint} point la coordenada
*/
NExtent.prototype.setPoint1 = function(point) {
  this.point1 = point;
};

/**
*	Estableix una coordenada
*	@param {NPoint} point la coordenada
*/
NExtent.prototype.setPoint2 = function(point) {
  this.point2 = point;
};

/**
*	retorna la coordenada x mínima
*	@return {Float}
*/
NExtent.prototype.getMinX = function() {
	return parseFloat((this.getPoint1().getX() < this.getPoint2().getX()) ? this.getPoint1().getX() : this.getPoint2().getX());
};

/**
*	retorna la coordenada x màxima
*	@return {Float}
*/
NExtent.prototype.getMaxX = function() {
	return parseFloat((this.getPoint1().getX() > this.getPoint2().getX()) ? this.getPoint1().getX() : this.getPoint2().getX());
};

/**
*	retorna la coordenada y mínima
*	@return {Float}
*/
NExtent.prototype.getMinY = function() {
	return parseFloat((this.getPoint1().getY() < this.getPoint2().getY()) ? this.getPoint1().getY() : this.getPoint2().getY());
};

/**
*	retorna la coordenada y màxima
*	@return {Float}
*/
NExtent.prototype.getMaxY = function() {
	return parseFloat((this.getPoint1().getY() > this.getPoint2().getY()) ? this.getPoint1().getY() : this.getPoint2().getY());
};

/**
*	genera un string que representa aquesta extensió.
*	@return {String}
*/
NExtent.prototype.toString = function() {
  return "[ " + this.point1.toString() + " , " + this.point2.toString() + " ]";
};

/**
*	Retorna el denominador d'escala d'aquesta extensió.
*	@param {Float} widthPixels amplada de la imatge en pixels.
*	@return {Float}
*/
NExtent.prototype.getScaleDenominator = function(widthPixels) {
	var ret = 0.0;
	//theValue = (520pixels) / (72 * 39.3701) * valor;
	//	(1m = 39.3701 inches)  inch=pulgada

	ret = ( (this.getMaxX() - this.getMinX()) * (96 * 39.3701) ) / ( widthPixels );
	return ret;
};

/**
*	A partir de l'extensió i una escala, calcula l'amplada en pixels que ha de tenir la imatge
*	@param {Number} scaleDen el denominador d'escala
*	@return {Number}
*/
NExtent.prototype.getPixelsWidth = function(scaleDen) {
	try {	
		return ( (this.getMaxX() - this.getMinX()) * (96 * 39.3701) ) / ( scaleDen );	
	}
	catch (e) {
		alert("Error a NExtent.getPixelsWidth()\n"+e.message);
	}
};

/**
*	A partir de l'extensió i una escala, calcula l'alçada en pixels que ha de tenir la imatge
*	@param {Number} scaleDen el denominador d'escala
*	@return {Number}
*/
NExtent.prototype.getPixelsHeight = function(scaleDen) {
	try {	
	return ( (this.getMaxY() - this.getMinY()) * (96 * 39.3701) ) / ( scaleDen );
	}
	catch (e) {
		alert("Error a NExtent.getPixelsHeight()\n"+e.message);
	}
};

/**
*	Calcula el centre X de la extensió.
*	@private
*/
NExtent.prototype.getCenterX = function() {
	var ret = 0.0;
	ret = (this.getMaxX() + this.getMinX()) / 2;
	return ret;
};

/**
*	Calcula el centre Y de la extensió.
*	@private
*/
NExtent.prototype.getCenterY = function() {
	var ret = 0.0;
	ret = (this.getMaxY() + this.getMinY()) / 2;
	return ret;
};

/**
*	Calcula el centre de la extensió.
*	@return {NPoint} el centre.
*/
NExtent.prototype.getCenter = function() {
	var ret = new NPoint(this.getCenterX(),this.getCenterY());
	return ret;
};

/**
*	Quadra la proporció de la extensió respecte a les mides de la imatge. 
*	@param {Float} widthPixels amplada en pixels de la imatge
*	@param {Float} heightPixels alçada en pixels de la imatge
*	@return {void}
*/
NExtent.prototype.squarePixels = function(widthPixels,heightPixels) {
	//DebugOut("NExtent.squarePixels() width x height: "+widthPixels+" x "+heightPixels,DEBUG);
	var centerX = Math.round(this.getMinX() + (Math.abs(this.getMaxX() - this.getMinX()) / 2));
	var centerY = Math.round(this.getMinY() + (Math.abs(this.getMaxY() - this.getMinY()) / 2));
	
	var extentScale=0;

	//Calculem l'escala per x i per y i ens quedem amb la mes gran
	var extentScaleX=(this.getMaxX() - this.getMinX()) / ( parseFloat(widthPixels) / (96 * 39.3701) );
	var extentScaleY=(this.getMaxY() - this.getMinY()) / ( parseFloat(heightPixels) / (96 * 39.3701) );

	if (extentScaleX>extentScaleY) extentScale=extentScaleX;
	else  extentScale=extentScaleY;

	var coordsWidth =  parseFloat(widthPixels) / (96 * 39.3701) * extentScale;
	var coordX0 = centerX - coordsWidth/2;
	var coordX1 = centerX + coordsWidth/2;
	var coordsHeight =  parseFloat(heightPixels) / (96 * 39.3701) * extentScale;
	var coordY0 = centerY - coordsHeight/2;
	var coordY1 = centerY + coordsHeight/2;
	this.setPoint1(new NPoint(coordX0,coordY0));
	this.setPoint2(new NPoint(coordX1,coordY1));
	return;
};

/**
*	Clona l'objecte
*	@return {NExtent}
*/
NExtent.prototype.clone = function() {
	return new NExtent(this.point1.clone(),this.point2.clone());
}

/**
*	TODO!!!
*	Aplica un % a l'escala de la extensió, mantenint el centre.
*	exemple: escala=100.000
*		inc: 0.1 -> escala=  10.000
*		inc: 0.5 -> escala=  50.000
*		inc: 1.1 -> escala= 110.000
*		
*	@param {Float} inc El tant per u a aplicar a l'escala. 
*/
NExtent.prototype.scaleIncrement = function(inc) {
	alert("TODO: NExtent.scaleIncrement()");
}


/**
*	Serialitza l'objecte: "x0,y0#x1,y1".
*	@return {String}
*/
NExtent.prototype.serialize = function() {
	return this.point1.serialize()+"#"+this.point2.serialize();
}
/**
*	Deserialitza l'objecte: "x0,y0#x1,y1".
*	@return {void}
*/
NExtent.prototype.deserialize = function(str) {
	var a=str.split("#");
	this.point1=new NPoint(a[0]);
	this.point2=new NPoint(a[1]);

}

/**
*	Recentra la extensió a la coordenada del paràmetre.
*	@param {NPoint} point el centre al que centrar l'extensió.
*	@return {void}
*/
NExtent.prototype.centerTo = function(point) {
	try {
		var despX=this.getCenterX()-point.getX();
		var despY=this.getCenterY()-point.getY();

		this.point1.setX(this.point1.getX()-despX);
		this.point1.setY(this.point1.getY()-despY);
		this.point2.setX(this.point2.getX()-despX);
		this.point2.setY(this.point2.getY()-despY);

	}
	catch (e) {
		alert("Error a NExtent.centerTo()\n"+e.message);
	}

}

/**
*	Genera un poligon de 4 punts a partir de la extensió
*	@return {NPolygon}
*/
NExtent.prototype.getPolygon = function() {
	try {
		var polygon=new NPolygon();
		polygon.add(new NPoint(this.getMinX(),this.getMinY()));
		polygon.add(new NPoint(this.getMinX(),this.getMaxY()));
		polygon.add(new NPoint(this.getMaxX(),this.getMaxY()));
		polygon.add(new NPoint(this.getMaxX(),this.getMinY()));
		return polygon;

	}
	catch (e) {
		alert("Error a NExtent.getPolygon()\n"+e.message);
	}

}



/**
*	Constructor de l'objecte.
*/
function NPolygon() {
		this.init();

}

/**
*	Constructor de l'objecte.
*	@private
*/
NPolygon.prototype.init = function() {
  try {
  		this.points=new Array();
  }
  catch (e) {
		alert("Error a NPolygon.init()\n"+e.message);
  }
};

/**
*	Afegeix un nou punt al poligon.
*	@param {NPoint} point el nou punt.
*/
NPolygon.prototype.add = function(point) {
	try {
		this.points.push(point);	
	}
  catch (e) {
		alert("Error a NPolygon.add()\n"+e.message);
  }
};

/**
*	Retorna un element
*	@return {NPoint}
*/
NPolygon.prototype.get = function(pos) {
	try {
		return this.points[pos];	
	}
  catch (e) {
		alert("Error a NPolygon.add()\n"+e.message);
  }
};

/**
*	Retorna el numero de punts del poligon.
*	@return {Number}
*/
NPolygon.prototype.size = function() {
	try {
		return this.points.length;
	}
  catch (e) {
		alert("Error a NPolygon.size()\n"+e.message);
  }
};


/**
*	Retorna l'extensió que engloba aquest poligon.
*	@return {NExtent}
*/
NPolygon.prototype.getExtent = function() {
	try {
		var minX=Number.MAX_VALUE;
		var minY=Number.MAX_VALUE;
		var maxX=Number.MIN_VALUE;
		var maxY=Number.MIN_VALUE;

		for (var i=0;i<this.points.length ;i++) {
			var x=this.points[i].getX();
			var y=this.points[i].getY();
			if (minX>x) minX=x;
			if (maxX<x) maxX=x;
			if (minY>y) minY=y;
			if (maxY<y) maxY=y;
		}

		return new NExtent(new NPoint(minX,minY),new NPoint(maxX,maxY));
	}
  catch (e) {
		alert("Error a NPolygon.size()\n"+e.message);
  }
};


/**
*	Aplica una rotació a tots els elements del poligon.
*	@param {Float} angle de rotació en radiants.
*	@param {NPoint} punt sobre el que rotar.
*	@return {void}
*/
NPolygon.prototype.rotate = function(angle,center) {
	try {

		for (var i=0;i<this.points.length ;i++) {
			this.points[i].rotate(angle,center);
		}

	}
  catch (e) {
		alert("Error a NPolygon.size()\n"+e.message);
  }
}


/**
*	Recentra el poligon a la coordenada del paràmetre.
*	@param {NPoint} point el centre al que centrar el poligon.
*/
NPolygon.prototype.centerTo = function(point) {
	try {
		var extent=this.getExtent();
		var despX=extent.getCenterX()-point.getX();
		var despY=extent.getCenterY()-point.getY();

		for (var i=0;i<this.points.length ;i++) {
			this.points[i].setX(this.points[i].getX()-despX);
			this.points[i].setY(this.points[i].getY()-despY);
		}

	}
	catch (e) {
		alert("Error a NPolygon.centerTo()\n"+e.message);
	}

}

/**
*	Aplica una rotació a tots els elements del poligon.
*	@return {String}
*/
NPolygon.prototype.toString = function() {
	try {
		var r=new Array();
		for (var i=0;i<this.points.length ;i++) {
			r.push(this.points[i]);
		}
		return r.join("\n");
	}
  catch (e) {
		alert("Error a NPolygon.toString()\n"+e.message);
  }
}