
import java.awt.*;
import java.io.*;

public class QSegment
  implements Drawable
{
  public String name;
  public Dot p[];
  public Color color;

  public QSegment( String name, Dot p[], Color color )
  {
    this.name = name;
    this.p = p;
    this.color = color;
  }

  public void paint( Graphics g )
  {
    if( color != null )
      g.setColor( color );

    int i, n;
    n = p.length - 1;
    double x[] = new double[n+1];
    double y[] = new double[n+1];
    for( i = 0; i <= n; i++ ) {
      x[i] = p[i].getX();
      y[i] = p[i].getY();
    }
    double cx[] = findCoefs( x, n );
    double cy[] = findCoefs( y, n );
    for( i = 0; i < n; i++ )
      drawBezier( g, p[i].getX(), p[i].getY(),
        (int)(x[i] + cx[i]), (int)(y[i] + cy[i]),
          (int)(x[i+1] - cx[i+1]), (int)(y[i+1] - cy[i+1]),
            p[i+1].getX(), p[i+1].getY() );
  }
  public void drawBezier( Graphics g,
    int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3 )
  {
    int i, n;
    double t, t_;
    double step;
    double a, b, c, d;
    int x, y, lastx, lasty;
    /*
    x0 = p[0].getX(); y0 = p[0].getY();
    x1 = p[1].getX(); y1 = p[1].getY();
    x2 = p[2].getX(); y2 = p[2].getY();
    x3 = p[3].getX(); y3 = p[3].getY(); */
    lastx = x0; lasty = y0;
    n = 30;
    step = 1.0 / n;
    for( i = 1; i <= n; i++ ) {
      t = i * step;
      t_ = 1.0 - t;
      a = t_ * t_ * t_;
      b = 3 * t_ * t_ * t;
      c = 3 * t_ * t * t;
      d = t * t * t;
      x = (int) ( a * x0 + b * x1 + c * x2 + d * x3 );
      y = (int) ( a * y0 + b * y1 + c * y2 + d * y3 );
      g.drawLine( lastx, lasty, x, y );
      lastx = x; lasty = y;
    }
    g.drawLine( x1, y1, x1, y1 );
    g.drawLine( x2, y2, x2, y2 );
  }

  public static double[] findCoefs( double a[], int n )
  {
    int i, j;
    double b[] = new double[n+1];
    double r[] = new double[n+1];
    double c[] = new double[n+1];

    b[0] = 2 * ( a[1] - a[0] ) / 3.0;
    for( i = 1; i < n; i++ )
      b[i] = a[i+1] - a[i-1];
    b[n] = 2 * ( a[n] - a[n-1] ) / 3.0;

    r[n] = 1;
    r[n-1] = 1;
    for( i = n-2; i >= 0; i-- )
      r[i] = 4 * r[i+1] - r[i+2];
    for( i = 1; i<=n; i+=2 )
      r[i] = -r[i];

    c[0] = 0.0;
    for( i = n; i>=0; i-- )
      c[0] += r[i] * b[i];
    c[0] /= (r[0] + r[1]);
    c[1] = b[0] - c[0];
    for( i = 1; i < n; i++ )
      c[i+1] = b[i] - 4 * c[i] - c[i-1]; 
    return c;
  }
  public void printPS( PrintStream O, int w, int h )
  {
    printPS( O, w, h, null );
  }
  public void printPS( PrintStream O, int w, int h , Dot fromPt )
  {
    // O.print( "  " );
    // super.printPS( O, w, h );
    int i, n;
    n = p.length - 1;
    double x[] = new double[n+1];
    double y[] = new double[n+1];
    for( i = 0; i <= n; i++ ) {
      int idx = ( fromPt == p[n] ) ? (n-i) : i;
      x[i] = p[idx].getX();
      y[i] = p[idx].getY();
    }
    double cx[] = findCoefs( x, n );
    double cy[] = findCoefs( y, n );
    if( fromPt == null ) {
      O.print( "  " );
      O.print( (int)x[0] );
      O.print( " " );
      O.print( h - (int)y[0] );
      O.println( " moveto" );
    }
    for( i = 0; i < n; i++ ) {
      O.print( "  " );
      O.print( (int)(x[i] + cx[i]) );
      O.print( " " );
      O.print( h - (int)(y[i] + cy[i]) );
      O.print( " " );
      O.print( (int)(x[i+1] - cx[i+1]) );
      O.print( " " );
      O.print( h - (int)(y[i+1] - cy[i+1]) );
      O.print( " " );
      O.print( (int)x[i+1] );
      O.print( " " );
      O.print( h - (int)y[i+1] );
      O.println( " curveto" );
    }
  }

  public int getX()
  {
    return 0;
  }
  public int getY()
  {
    return 0;
  }
}
