
import java.awt.*;
import java.applet.*;
import java.util.*;

public class CurvePanel
  extends Applet
{
  public Hashtable htDr;
  private int W;
  private int H;
  private Dot grabbedDot;
  private int xBase = 250;
  private int yBase = 250;

  private boolean showContrib = true;
  private boolean doSpline = false;
  private boolean doLagrange = true;

  private Color gold = new Color( 255, 215, 0 );
  private Color steelBlue = new Color( 70, 130, 180 );
  private Color curveColor[] = {
                             Color.cyan, Color.magenta, Color.yellow,
                             Color.red, Color.green, Color.blue,
                             Color.orange, Color.pink
                           };

  public CurvePanel()
  {
    this( 500, 500 );
  }

  public CurvePanel( int w, int h )
  {
    W = w;
    H = h;
    htDr = new Hashtable();
    setBackground( Color.black );
  }

  public Dimension minimumSize()
  {
    return new Dimension( W, H );
  }
  public Dimension preferredSize()
  {
    return minimumSize();
  }

  public void paint( Graphics g )
  {
    Enumeration e = htDr.elements();

    while( e.hasMoreElements() ) {
      Drawable dr = (Drawable)( e.nextElement() );
      dr.paint( g );
    }
  }

  public void addDrawable( String name, Drawable dr )
  {
    htDr.put( name, dr );
  }

  public Drawable getDrawable( String name )
  {
    return (Drawable)( htDr.get( name ) );
  }

  public Dot closestDot( int x, int y )
  {
    Dot d = null;
    Enumeration e = htDr.elements();

    int minSep = 7;

    while( e.hasMoreElements() ) {
      Drawable dr = (Drawable)( e.nextElement() );
      if( dr instanceof Dot ) {
        Dot a = (Dot)dr;
        int sep =  a.separation( x, y );
        if( ( sep < 6 ) && ( minSep > sep ) ) {
          minSep = sep;
          d = a;
        }
      }
    }
    return d;
  }

  public boolean handleEvent( Event evt )
  {
    if( evt.id == Event.MOUSE_DOWN ) {
      grabbedDot = closestDot( evt.x, evt.y );
    }
    if( evt.id == Event.MOUSE_DRAG ) {
      if( grabbedDot != null ) {
        grabbedDot.requestMove( evt.x, evt.y );
        repaint();
      }
    }
    if( evt.id == Event.MOUSE_UP ) {
      if( grabbedDot != null ) {
        grabbedDot.requestMove( evt.x, evt.y );
        repaint();
      }
    }
    return super.handleEvent( evt );
  }

  public void init()
  {
    init( 5 );
  }

  public void init( int n )
  {
    htDr.clear();
    int i;
    Dot p[] = new Dot[n];
    Dot q[] = new Dot[n];
    double ang, angstep, rad;
    int x, y;
    angstep = 2.0 * Math.PI / n;
    for( i = 0; i < n; i++ ) {
      String dotName = "p" + i;
      ang = ( 0.1 * Math.random() + i ) * angstep;
      rad = 120.0 + 80.0 * Math.random();
      x = 200 + (int)( rad*Math.cos(ang) );
      y = 300 - (int)( rad*Math.sin(ang) );
      p[i] = new Dot( dotName, x, y, true, true, Color.green );
      addDrawable( dotName, p[i] );
    }
    PSegment loop = new PSegment( "loop", p, steelBlue );
    addDrawable( "loop", loop );

    angstep = 0.5 * Math.PI / n;
    for( i = 0; i < n; i++ ) {
      String dotName = "q" + i;
      ang = ( 0.1 * Math.random() + i ) * angstep;
      rad = 150.0 + 80.0 * Math.random();
      x = 250 + (int)( rad*Math.cos(ang) );
      y = 250 - (int)( rad*Math.sin(ang) );
      q[i] = new Dot( dotName, x, y, true, true, Color.blue );
      addDrawable( dotName, q[i] );
    }
    QSegment curve = new QSegment( "curve", q, gold );
    addDrawable( "curve", curve );

    repaint();
  }

  public static void main( String[] args )
  {
    CurvePanel p = new CurvePanel( 500, 500 );
    p.init();
    KFrame fr = new KFrame( "Open and Closed Curves" );
    fr.add( "Center", p );
    fr.pack();
    fr.show();
  }
}
