/*
 * Created on 24.10.2007
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author Branislav
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;

public class LiangBarskyLCA extends Applet implements MouseListener, MouseMotionListener {

    Image buffer;
    Graphics doublebuffer;    
    
    int width, height;
    int mx, my;  // the mouse coordinates
    int buttonPressed = -1;
    int inArea = 0;    

    float t0,t1;
    float[] pointsX = new float[6];
    float[] pointsY = new float[6];

    float xdelta,ydelta;
    float p,q,r;
    float rx1,rx2,ry1,ry2;
    boolean dl1;
    int moveby;
    
    public void init() {
        setSize(300,200);
        width = getSize().width;
        height = getSize().height;
        setBackground( Color.white );

        mx = width/2;
        my = height/2;
        
        
        moveby = 0;
        
        pointsX[0] = 50;
        pointsX[1] = 250;
        pointsY[0] = 50;
        pointsY[1] = 150;
        pointsX[2] = 20;
        pointsX[3] = 280;
        pointsY[2] = 50;
        pointsY[3] = 150;
        
        pointsX[4] = pointsX[0];
        pointsX[5] = pointsX[1];
        pointsY[4] = pointsY[1];
        pointsY[5] = pointsY[0];

        rx1 = pointsX[2];
        rx2 = pointsX[3];
        ry1 = pointsY[2];
        ry2 = pointsY[3];

        
        
    

        addMouseListener( this );
        addMouseMotionListener( this );
        
        buffer = createImage(300,200);
        doublebuffer = buffer.getGraphics();
    }
    
    public void doIt(Graphics g) {

        dl1 = true;
        t0 = 0;
        t1 = 1;

        xdelta = pointsX[3] - pointsX[2];
        ydelta = pointsY[3] - pointsY[2];

    // clipping by left edge
        p = -xdelta;
        if(pointsX[0] <= pointsX[1]) {
          q = -(pointsX[0] - pointsX[2]);
        } else {
          q = -(pointsX[1] - pointsX[2]);
        }  
        if(p < 0) {
          r = q/p;
          if(r > t1) {

    //        Do not draw the line
            dl1 = false;
          } else {
            if(r > t0) {
              t0 = r;
            }
          }
    
        } else if(p > 0) {
          r = q/p;
          if(r < t0) {
 
    //        Do not draw the line
            dl1 = false;
          }
          else {
            if(r < t1) {
              t1 = r;
            }  
          }
    
        } else {

          if(q < 0) {
            dl1 = false;
          }
        }
           
        // clipping by right edge
        p = xdelta;
        if(pointsX[0] <= pointsX[1]) {
          q = pointsX[1] - pointsX[2];
        } else {
          q = pointsX[0] - pointsX[2];
        }
        if(p < 0) {
          r = q/p;
          if(r > t1) {

    //        Do not draw the line
            dl1 = false;
          } else if(r > t0) {
              t0 = r;
          }
    
        } else if(p > 0) {
          r = q/p;
          if(r < t0) {

    //        Do not draw the line
            dl1 = false;
          } else if(r < t1) {
              t1 = r;
          }
    
        } else {

          if(q < 0) {
            dl1 = false;
          }  
        }
    
        // clipping by top edge
        p = -ydelta;
        if(pointsY[0] <= pointsY[1]) {
          q = -(pointsY[0] - pointsY[2]);
        } else {
          q = -(pointsY[1] - pointsY[2]);
        }
        if(p < 0) {
          r = q/p;
          if(r > t1) {

    //        Do not draw the line
            dl1 = false;
          } else if(r > t0) {
              t0 = r;
          }
    
        } else if(p > 0) {
          r = q/p;
          if (r < t0) {

    //        Do not draw the line
            dl1 = false;
          } else if(r < t1) {
              t1 = r;
          }
    
        } else {

          if(q < 0) {
            dl1 = false;
          }
        }  
    
        // clipping by bottom edge
        p = ydelta;
        if(pointsY[0] <= pointsY[1]) {
          q = pointsY[1] - pointsY[2];
        } else {
          q = pointsY[0] - pointsY[2];
        }  
        if(p < 0) {
          r = q/p;
          if(r > t1) {

    //        Do not draw the line
            dl1 = false;
          } else if(r > t0) {
              t0 = r;
          }
    
        } else if(p > 0) {
          r = q/p;
          if (r < t0) {

    //        Do not draw the line
            dl1 = false;
          } else if(r < t1) {
              t1 = r;
          }
        } else {

          if(q < 0) {
            dl1 = false;
          }
        }  

        myDrawRect(g,Math.round(pointsX[0]),Math.round(pointsY[0]),Math.round(pointsX[1]),Math.round(pointsY[1]),Color.black,Color.white);
        
        if(dl1) {
          rx1 = pointsX[2]+(t0*xdelta);
          ry1 = pointsY[2]+(t0*ydelta);
          rx2 = pointsX[2]+(t1*xdelta);
          ry2 = pointsY[2]+(t1*ydelta);
          
          if(t0 != 0) {
              g.setColor(Color.red);
              myDrawLine(g,Math.round(pointsX[2]),Math.round(pointsY[2]),Math.round(rx1),Math.round(ry1));
          }
          if(t1 != 1) {
              g.setColor(Color.red);
              myDrawLine(g,Math.round(rx2),Math.round(ry2),Math.round(pointsX[3]),Math.round(pointsY[3]));              
          }
          g.setColor(Color.blue);
          myDrawLine(g,Math.round(rx1),Math.round(ry1),Math.round(rx2),Math.round(ry2));
          myDrawLine(g,Math.round(rx1+1),Math.round(ry1),Math.round(rx2+1),Math.round(ry2));
          myDrawLine(g,Math.round(rx1-1),Math.round(ry1),Math.round(rx2-1),Math.round(ry2));
          myDrawLine(g,Math.round(rx1),Math.round(ry1+1),Math.round(rx2),Math.round(ry2+1));
          myDrawLine(g,Math.round(rx1),Math.round(ry1-1),Math.round(rx2),Math.round(ry2-1));
          g.setColor(Color.white);
          
          

        } else {
          g.setColor(Color.red);
          myDrawLine(g,Math.round(pointsX[2]),Math.round(pointsY[2]),Math.round(pointsX[3]),Math.round(pointsY[3]));          
        }

        
    }

    public void mouseEntered( MouseEvent e ) {
        // called when the pointer enters the applet's rectangular area
    }
    public void mouseExited( MouseEvent e ) {
        // called when the pointer leaves the applet's rectangular area
    }
    public void mouseClicked( MouseEvent e ) {
        // called after a press and release of a mouse button
        // with no motion in between
        // (If the user presses, drags, and then releases, there will be
        // no click event generated.)
    }    
    public void mouseMoved( MouseEvent e ) {  // called during motion when no buttons are down
        mx = e.getX()+1;
        my = e.getY()+1;
        showStatus( "Mouse at (" + mx + "," + my + ")" );
        repaint();        
        e.consume();
    }
    
    public void mousePressed( MouseEvent e ) {  // called after a button is pressed down
        buttonPressed = closestPoint(30);
        mx = e.getX()+1;
        my = e.getY()+1;
        showStatus( "Mouse at (" + mx + "," + my + ")" ); 
        if(buttonPressed==0) {
            pointsX[0] = mx;
            pointsY[0] = my;
            pointsX[4] = pointsX[0];
            pointsY[5] = pointsY[0];
        } else if(buttonPressed==1) {
            pointsX[1] = mx;
            pointsY[1] = my;
            pointsX[5] = pointsX[1];
            pointsY[4] = pointsY[1];
        } else if(buttonPressed==2) {
            pointsX[2] = mx;
            pointsY[2] = my;
        } else if(buttonPressed==3) {
            pointsX[3] = mx;
            pointsY[3] = my;
        } else if(buttonPressed==4) {
            pointsX[0] = mx;
            pointsY[1] = my;
            pointsX[4] = pointsX[0];
            pointsY[4] = pointsY[1];
        } else if(buttonPressed==5) {
            pointsX[1] = mx;
            pointsY[0] = my;
            pointsX[5] = pointsX[1];
            pointsY[5] = pointsY[0];
        }                
        repaint();
        // "Consume" the event so it won't be processed in the
        // default manner by the source which generated it.
        e.consume();
    }
    
    public void mouseReleased( MouseEvent e ) {  // called after a button is released
        buttonPressed = -1;
        repaint();
        e.consume();
    }
    
    public void mouseDragged( MouseEvent e ) {  // called during motion with buttons down
        mx = e.getX()+1;
        my = e.getY()+1;
        showStatus( "Mouse at (" + mx + "," + my + ")" );
        if(buttonPressed==0) {
            pointsX[0] = mx;
            pointsY[0] = my;
            pointsX[4] = pointsX[0];
            pointsY[5] = pointsY[0];
        } else if(buttonPressed==1) {
            pointsX[1] = mx;
            pointsY[1] = my;
            pointsX[5] = pointsX[1];
            pointsY[4] = pointsY[1];
        } else if(buttonPressed==2) {
            pointsX[2] = mx;
            pointsY[2] = my;
        } else if(buttonPressed==3) {
            pointsX[3] = mx;
            pointsY[3] = my;
        } else if(buttonPressed==4) {
            pointsX[0] = mx;
            pointsY[1] = my;
            pointsX[4] = pointsX[0];
            pointsY[4] = pointsY[1];
        } else if(buttonPressed==5) {
            pointsX[1] = mx;
            pointsY[0] = my;
            pointsX[5] = pointsX[1];
            pointsY[5] = pointsY[0];
        }        
        repaint();
        e.consume();
    }
   
    public void myDrawRect(Graphics g, int x1, int y1, int x2, int y2, Color ocol, Color icol) {
        Color c = g.getColor();
        g.setColor(ocol);
        if( (x1 <= x2)&&(y1 <= y2) )
            g.drawRect(x1-1,y1-1,x2-x1,y2-y1);
        else if( (x1 > x2)&&(y1 > y2) )
            g.drawRect(x2-1,y2-1,x1-x2,y1-y2);
        else if( (x1 > x2)&&(y1 <= y2) )
            g.drawRect(x2-1,y1-1,x1-x2,y2-y1);
        else if( (x1 <= x2)&&(y1 > y2) )
            g.drawRect(x1-1,y2-1,x2-x1,y1-y2);
        g.setColor(icol);
        if( (x1 <= x2)&&(y1 <= y2) )
            g.fillRect(x1,y1,x2-x1-1,y2-y1-1);
        else if( (x1 > x2)&&(y1 > y2) )
            g.fillRect(x2,y2,x1-x2-1,y1-y2-1);
        else if( (x1 > x2)&&(y1 <= y2) )
            g.fillRect(x2,y1,x1-x2-1,y2-y1-1);
        else if( (x1 <= x2)&&(y1 > y2) )
            g.fillRect(x1,y2,x2-x1-1,y1-y2-1);
        g.setColor(c);
    }
   
    public void myDrawLine(Graphics g, int x1, int y1, int x2, int y2) {
         g.drawLine(x1-1,y1-1,x2-1,y2-1);
    }
    public int closestPoint(int dist) {
        float d = -1;
        float d0;
        int c = -1;
        for(int i = 0; i<=5; i++) {
            d0 = (float)Math.sqrt(Math.abs(pointsX[i]-mx)*Math.abs(pointsX[i]-mx)+Math.abs(pointsY[i]-my)*Math.abs(pointsY[i]-my));
            if(((d<0) || (d>d0))&& (d0<Math.abs(dist))) {
                d = d0;
                c = i;
            }
        }
        return c;
    }
    public void paint( Graphics g ) {
        myDrawRect(doublebuffer,1,1,400,400,Color.white,Color.white);
        doIt(doublebuffer);

        int c = closestPoint(30);
        if(c!=-1)
            myDrawRect(doublebuffer,Math.round(pointsX[c])-3,Math.round(pointsY[c])-3,Math.round(pointsX[c])+3,Math.round(pointsY[c])+3,Color.green,Color.green);
//        doublebuffer.setColor(Color.black);
//        doublebuffer.drawString("" + buttonPressed,5,15);
        g.drawImage(buffer,0,0,this);
    }
    
    public void update (Graphics g) {
        paint(g);
    }
         
}
