function Line(p1,p2)
{
    this._p1 = p1;
    this._p2 = p2;
}
Line.prototype= new Extra_Graphics();
Line.prototype.constructor= Line;
Line.prototype.draw=function()
{
    try{
        var pxl1 = _MAP_WRAPPER.convert_to_pixel(this._p1._x,this._p1._y,true);
        var pxl2 = _MAP_WRAPPER.convert_to_pixel(this._p2._x,this._p2._y,true);
        _jg.setStroke(this._stroke);
        _jg.setColor(this._color);
        _jg.setPrintable(this._printable);
        this.clip(pxl1[0],pxl2[0],pxl1[1],pxl2[1]);
    }catch(e)
    {
        alert("Line.draw(): "+e);
        return false;
    }
};
/*
Cohen Sutherland algorith for Line Clipping
 */
Line.prototype.clip=function(x1,x2,y1,y2)
{
    try{
        var c1 = this.code(x1,y1);
        var c2= this.code(x2,y2);
        var dx=0.0;
        var dy=0.0;
        while( c1 | c2 )
        {
            if(c1 & c2)
                return;
            dx=x2-x1;
            dy=y2-y1;
            if(c1)
            {
                if(x1 < 0)
                {
                    y1+=dy*(0-x1)/dx;
                    x1=0;
                }else if(x1>_MAP_WRAPPER.get_width())
                {
                    y1+=dy*(_MAP_WRAPPER.get_width()-x1)/dx;
                    x1=_MAP_WRAPPER.get_width();
                }else if(y1 < 0)
                {
                    x1+=dx*(0-y1)/dy;
                    y1=0;
                }else if(y1  > _MAP_WRAPPER.get_height())
                {
                    x1+=dx*(_MAP_WRAPPER.get_height()-y1)/dy;
                    y1=_MAP_WRAPPER.get_height();
                }
				
                c1=this.code(x1,y1);
            }
            else
            {
                if(x2 < 0)
                {
                    y2+=dy*(0-x2)/dx;x2=0;
                }else if(x2 > _MAP_WRAPPER.get_width())
                {
                    y2+=dy*(_MAP_WRAPPER.get_width()-x2)/dx;x2=_MAP_WRAPPER.get_width();
                }else if(y2 < 0)
                {
                    x2+=dx*(0-y2)/dy;y2=0;
                }else if(y2 > _MAP_WRAPPER.get_height())
                {
                    x2+=dx*(_MAP_WRAPPER.get_height()-y2)/dy;y2=_MAP_WRAPPER.get_height();
                }
				
                c2=this.code(x2,y2);
            }
			
        }
		
        _jg.drawLine(parseInt(x1),parseInt(y1),parseInt(x2),parseInt(y2));
		
    }catch(e)
    {
        alert("Line.clip(): "+e);
        return false;
    }
};
Line.prototype.code=function(x,y)
{
    return  (x < 0)<<3 | (x>_MAP_WRAPPER.get_width())<<2 | (y<0)<<1 | (y>_MAP_WRAPPER.get_height());
};
Line.prototype.to_post_request=function()
{
    res = new Array();
    res[0] = this._p1._x+"_"+this._p2._x;
    res[1]= this._p1._y+"_"+this._p2._y;
    return res;
};

Line.prototype.compute_direction_vector=function()
{
    return new Point(this._p2._x-this._p1._x,this._p2._y-this._p1._y);
};

/*
dotLineLength(x: Integer, y: Integer, x0: Integer, y0: Integer, x1: Integer, y1: Integer, 
[overLine: Boolean = False]): Double
Distance from a point to a line or segment.
x point's x coord
y point's y coord
x0 x coord of the line's A point
y0 y coord of the line's A point
x1 x coord of the line's B point
y1 y coord of the line's B point
overLine specifies if the distance should respect the limits of the segment (overLine = true) 
or if it should consider the segment as an infinite line (overLine = false),
 if false returns the distance from the point to the line, otherwise 
 the distance from the point to the segment
 */
Line.prototype.distance_from_point = function(x,y,o){
    try{
        var x0=this._p1._x;
        var y0=this._p1._y;
        var x1=this._p2._x;
        var y1=this._p2._y;
		
		
		
        function lineLength(x, y, x0, y0){
            return Math.sqrt((x -= x0) * x + (y -= y0) * y);
        }
        if(o && !(o = function(x, y, x0, y0, x1, y1){
            if(!(x1 - x0)) return {x: x0, y: y};
            else if(!(y1 - y0)) return {x: x, y: y0};
            var left, tg = -1 / ((y1 - y0) / (x1 - x0));
            return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
        }(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
            var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
            return l1 > l2 ? l2 : l1;
        }
        else {
            var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
            return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
        }
    }catch(e)
    {
    	alert("Line.dotLineLength() "+e);
    	return false;
    }
};
/*Returns intersection point between lines*/
Line.prototype.intersect_point_line = function(line){
    var a1=this._p2._y-this._p1._y;
    var b1 = this._p1._x-this._p2._x;
    var c1 = this._p2._x*this._p1._y-this._p1._x*this._p2._y;
	
    var a1=line._p2._y-line._p1._y;
    var b1 = line._p1._x-line._p2._x;
    var c1 = line._p2._x*line._p1._y-line._p1._x*line._p2._y;
	
    var denom = a1*b2-a2*b1;
    if(denom == 0)
    {
        alert("Lines are parralel");
        return false;
    }
	
    var x=(b1*c2-b2*c1)/denom;
    var y=(a2*c1-a1*c2)/denom;
	
    return new Point(x,y);
};
Line.prototype.move = function(vx,vy){
    this._p1._x+=vx;
    this._p2._x+=vx;
    this._p1._y+=vy;
    this._p2._y+=vy;
};
Line.prototype.intersect_line = function(line)
{

        var point_line1 = this._p1;
        var point_line2 = line._p1;

        var direction_point1 = this.compute_direction_vector();
        var direction_point2 = line.compute_direction_vector();

        if (direction_point1._x*direction_point2._x+direction_point1._y*direction_point2._y == 0) {
            return null;
        }
        /* Calcolo il parametro k */
        var k = ( ( point_line2._x - point_line1._x ) * direction_point1._y
                + ( point_line1._y-point_line2._y)*direction_point1._x )
                / ( ( direction_point1._x * direction_point2._y )
                - ( direction_point1._y * direction_point2._x ) );

        /* Creo un nuovo punto con coordinate sull'intersezione tra le due rette */
        var intersec = new Point(point_line2._x + k*direction_point2._x, point_line2._y + k*direction_point2._y);
    
        return intersec;
};
