
import java.awt.*;

public class line extends shape
{
     point p, q;
     double dragX, dragY;

     public line(point P, point Q)
     {
	  p = P; 
	  q = Q;
     }

     public line(double x1, double y1, double x2, double y2)
     {
	  p = new point(x1, y1);
	  q = new point(x2, y2);
     }

     public line(point P, double m)
     {
	  p = P;
	  q = new point(p.x + .3, q.x + .3 * m);
     }

     public boolean exists()
     {
	  if (p.exists() && q.exists())
	       return(true);
	  else 
	       return(false);
     }

     public point intersect(shape s, int whichPoint)
     {
	  if (s instanceof line)
	       return(gMath.intersect(this, (line)s));
	  else
	       return(null);
     }

     public void resetTranslated()
     {
	  translated = false;
	  
	  p.resetTranslated();
	  q.resetTranslated();
     }

     public boolean translate(double dx, double dy)
     {
	  if (translated)
	       return(false);

	  translated = true;
	  
	  p.translate(dx, dy);
	  q.translate(dx, dy);

	  return(true);
     }

     public void draw(GeometryWindow G)
     {
	  if (!exists() || hidden)
	       return;

	  point[] P = new point[2];
	  int curPoint = 0;
	  double x, y;
	  
	  G.setColor(color);

	  double m = slope();
	  if (Math.abs(m) > 1e3)
	  {
	       G.drawSegment(p.x, G.yll, p.x, G.yur);
	       return;
	  }
	  else if (Math.abs(m) < 1e-3)
	  {
	       G.drawSegment(G.xll, p.y, G.xur, p.y);
	       return;
	  }
	  
	  x = G.xll; y = m*(x - p.x) + p.y;
	  if ( (y > G.yll) && (y < G.yur) )
	  {
	       P[curPoint] = new point(x, y);
	       curPoint++;
	  }

	  x = G.xur; y = m*(x - p.x) + p.y;
	  if ( (y > G.yll) && (y < G.yur) )
	  {
	       P[curPoint] = new point(x, y);
	       curPoint++;
	  }
	  
	  if (curPoint < 2)
	  {
	       y = G.yll; x = (y - p.y) / m + p.x;
	       if ( (x > G.xll) && (x < G.xur) )
	       {
		    P[curPoint] = new point(x, y);
		    curPoint++;
	       }
	  }

	  if (curPoint < 2)
	  {
	       y = G.yur; x = (y - p.y) / m + p.x;
	       if ( (x > G.xll) && (x < G.xur) )
	       {
		    P[curPoint] = new point(x, y);
		    curPoint++;
	       }
	  }

	  if (curPoint == 2)
	  {
	       G.setColor(color);
	       G.drawSegment(P[0].x, P[0].y, P[1].x, P[1].y);
	  }
     }

     public double slope()
     {
	  if (Math.abs(p.x - q.x) < 1e-10)
	       return(1e10);
	  else if (p.x < q.x)
	       return((q.y - p.y) / (q.x - p.x));
	  else
	       return((p.y - q.y) / (p.x - q.x));
     }

     public boolean isNear(double X, double Y)
     {
	  double nx = -(q.y - p.y);
	  double ny = q.x - p.x;
	  double length = Math.sqrt(nx * nx + ny * ny);
	  nx /= length;
	  ny /= length;

	  double baseDist = p.x * nx + p.y * ny;
	  double pointDist = X * nx + Y * ny;

	  if (Math.abs(pointDist - baseDist) < clickRange)
	       return(true);
	  else
	       return(false);
     }

     public point coordOnShape(double X, double Y)
     {
	  double nx = -(q.y - p.y);
	  double ny = q.x - p.x;
	  double length = Math.sqrt(nx * nx + ny * ny);
	  nx /= length;
	  ny /= length;

	  double baseDist = p.x * nx + p.y * ny;
	  double pointDist = X * nx + Y * ny;

	  X -= nx * (pointDist - baseDist);
	  Y -= ny * (pointDist - baseDist);
	  
	  return(new point(X, Y));
     }

     public pointOnShape pointOnShape(double X, double Y)
     {
	  return(new pointOnLine(X, Y, this));
     }

     public boolean mouseDown(double X, double Y)
     {
	  if (hidden)
	       return(false);

	  double nx = -(q.y - p.y);
	  double ny = q.x - p.x;
	  double length = Math.sqrt(nx * nx + ny * ny);
	  nx /= length;
	  ny /= length;

	  double baseDist = p.x * nx + p.y * ny;
	  double pointDist = X * nx + Y * ny;

	  if (Math.abs(pointDist - baseDist) < clickRange)
	  {
	       dragging = true;
	       
	       double dx = (pointDist - baseDist) * nx;
	       double dy = (pointDist - baseDist) * ny;

	       resetTranslated();
	       translate(dx, dy);
	       
	       dragX = X;
	       dragY = Y;
	       return(true);
	  }
	  return(false);
     }

     public boolean mouseDrag(double X, double Y)
     {
	  if (dragging)
	  {
	       double dx = X - dragX;
	       double dy = Y - dragY;
	       
	       resetTranslated();
	       translate(dx, dy);

	       dragX = X;
	       dragY = Y;

	       return(true);
	  }
	  return(false);
     }

     public boolean mouseUp(double X, double Y)
     {
	  dragging = false;
	  return(false);
     }
};





