Spline.java

//This applet implements interpolation using relaxed cubic splines
//The user can click on six points and move them around and the
//spline will be redrawn in real time
import java.awt.*;
import java.applet.Applet;
public class Spline extends Applet {
Point[] points; //points to be interpolated
Point[] control; //control points
int numpoints;
Image offscreenImg; //used in double buffering
Graphics offscreenG;
double t; //time variable
static final double k = .05; //partition length
int moveflag; //point movement
Button polygon;
boolean poly = false;
//this method initializes the applet
public void init() {
//start off with 6 points
points = new Point[6];
control = new Point[6];
numpoints = 6;
moveflag = numpoints;
int increment = (int)((size().width-60)/(numpoints-1));
for(int i=0;i<numpoints;i++)
points[i] = new Point((i*increment)+30,(int)(size().height/2));
//create offscreen buffer
offscreenImg = createImage(size().width,size().height);
offscreenG = offscreenImg.getGraphics();
//put "Polygon" button on screen
polygon = new Button("Polygon");
add(polygon);
}
//this method is called by the repaint() method
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
//points to be plotted
int x1,y1,x2,y2;
//Clear screen and set colors
setBackground(Color.white);
offscreenG.setColor(Color.white);
offscreenG.fillRect(0,0,size().width,size().height);
offscreenG.setColor(Color.black);
//check if user wants control polygon and points drawn
1


Spline.java
if(poly) {
//draw control polygon and control points
for(int i=0;i<numpoints-1;i++) {
offscreenG.fillOval(points[i].x-2,points[i].y-2,4,4);
offscreenG.fillOval((int)(.6667*control[i].x+.3333*control[i+1].x)
-2,

(int)(.6667*control[i].y+.3333*control[i+1].y)
-2,4,4);
offscreenG.fillOval((int)(.3333*control[i].x+.6667*control[i+1].x)
-2,

(int)(.3333*control[i].y+.6667*control[i+1].y)
-2,4,4);
offscreenG.fillOval(points[i+1].x-2,points[i+1].y-2,4,4);
offscreenG.drawLine(points[i].x,points[i].y,(int)(.6667*control[i]
.x+

.3333*control[i+1].x),(int)(.6667*control[i].y
+
.3333*control[i+1].y));
offscreenG.drawLine((int)(.6667*control[i].x+.3333*control[i+1].x)
,

(int)(.6667*control[i].y+.3333*control[i+1].y)
,

(int)(.3333*control[i].x+.6667*control[i+1].x)
,

(int)(.3333*control[i].y+.6667*control[i+1].y)
);
offscreenG.drawLine((int)(.3333*control[i].x+.6667*control[i+1].x)
,

(int)(.3333*control[i].y+.6667*control[i+1].y)
,
points[i+1].x,points[i+1].y);
}
}
//Change interpolating points into control points
control[0] = new Point(points[0].x,points[0].y);
control[numpoints-1] = new Point(points[numpoints-1].x,
points[numpoints-1].y);
x1=(int)(1.6077*(double)points[1].x-.26794*(double)points[0].x-
.43062*(double)points[2].x+.11483*(double)points[3].x-
.028708*(double)points[4].x+.004785*(double)points[5].x);
y1=(int)(1.6077*(double)points[1].y-.26794*(double)points[0].y-
.43062*(double)points[2].y+.11483*(double)points[3].y-
2

Spline.java
.028708*(double)points[4].y+.004785*(double)points[5].y);

control[1] = new Point(x1,y1);
x1=(int)(-.43062*(double)points[1].x+.07177*(double)points[0].x+
1.7225*(double)points[2].x-.45933*(double)points[3].x+
.11483*(double)points[4].x-.019139*(double)points[3].x);

y1=(int)(-.43062*(double)points[1].y+.07177*(double)points[0].y+
1.7225*(double)points[2].y-.45933*(double)points[3].y+
.11483*(double)points[4].y-.019139*(double)points[3].y);

control[2] = new Point(x1,y1);
x1=(int)(.11483*(double)points[1].x-.019139*(double)points[0].x-
.45933*(double)points[2].x+1.7225*(double)points[3].x-
.43062*(double)points[4].x+.07177*(double)points[5].x);

y1=(int)(.11483*(double)points[1].y-.019139*(double)points[0].y-
.45933*(double)points[2].y+1.7225*(double)points[3].y-
.43062*(double)points[4].y+.07177*(double)points[5].y);

control[3] = new Point(x1,y1);
x1=(int)(-.028708*(double)points[1].x+.004785*(double)points[0].x+
.114835*(double)points[2].x-.43062*(double)points[3].x+
1.6077*(double)points[4].x-.26794*(double)points[5].x);

y1=(int)(-.028708*(double)points[1].y+.004785*(double)points[0].y+
.114835*(double)points[2].y-.43062*(double)points[3].y+
1.6077*(double)points[4].y-.26794*points[5].y);

control[4] = new Point(x1,y1);
//Plot points
for(int i=0;i<numpoints;i++)
offscreenG.fillOval(points[i].x-2,points[i].y-2,4,4);

//draw n bezier curves using Bernstein Polynomials
x1=points[0].x;
y1=points[0].y;
for(int i=1;i<numpoints;i++) {
for(t=i-1;t<=i;t+=k) {
x2=(int)((double)points[i-1].x+(t-(i-1))*(-3*(double)points[i-1].x
+
3*(.6667*(double)control[i-1].x+.3333*(double)control[i].x)+
(t-(i-1))*(3*(double)points[i-1].x-6*(.6667*(double)control[i-1
].x+
.3333*(double)control[i].x)+3*(.3333*(double)control[i-1].x+
.6667*(double)control[i].x)+(-(double)points[i-1].x+
3*(.6667*(double)control[i-1].x+.3333*(double)control[i].x)-
3*(.3333*(double)control[i-1].x+.6667*(double)control[i].x)+
(double)points[i].x)*(t-(i-1)))));
y2=(int)((double)points[i-1].y+(t-(i-1))*(-3*(double)points[i-1].y
+
3*(.6667*(double)control[i-1].y+.3333*(double)control[i].y)+
(t-(i-1))*(3*(double)points[i-1].y-6*(.6667*(double)control[i-1
].y+
.3333*(double)control[i].y)+3*(.3333*(double)control[i-1].y+
.6667*(double)control[i].y)+(-(double)points[i-1].y+
3*(.6667*(double)control[i-1].y+.3333*(double)control[i].y)-
3


Spline.java
3*(.3333*(double)control[i-1].y+.6667*(double)control[i].y)+
(double)points[i].y)*(t-(i-1)))));
offscreenG.drawLine(x1,y1,x2,y2);
x1=x2;
y1=y2;
}
}
//draw buffered image to screen
g.drawImage(offscreenImg,0,0,this);
}
//check if user has pushed polygon button
public boolean action(Event e, Object o) {
if (e.target == polygon) {
if(poly)
poly = false;
else
poly = true;
repaint();
return true;
}
return false;
}
//Check if user has clicked on point
public boolean mouseDown(Event evt, int x, int y) {
Point p = new Point(x,y);
for(int i=0;i<numpoints;i++)
for(int j=-2;j<3;j++)
for(int l=-2;l<3;l++)
if(p.equals(new Point(points[i].x+j,
points[i].y+l)))
//set moveflag to the ith point
moveflag=i;
return true;
}
public boolean mouseDrag(Event evt, int x, int y) {
//check if user is trying to drag an old point
if(moveflag < numpoints) {
//move the point and redraw screen
points[moveflag].move(x,y);
repaint();
}
return true;
}
//if user unclicks mouse, reset moveflag
public boolean mouseUp(Event evt, int x, int y) {
moveflag = 6;
return true;
}

}
4