//
import java.awt.*; public class testCubic extends BufferedApplet { int w = 0, h, type = 0, is = -1; Cubic spline; double G[] = {0,1,0,1}; Rectangle S[] = new Rectangle[4]; Color splineBgColor = new Color(240,240,255); Color bgColor = new Color(200,200,200); Color sliderColor = new Color(255,240,240); Color slideColor = new Color(220,200,200); String name[] = {"BEZIER", "BSPLINE", "CATMULL-ROM", "HERMITE"}; Font font = new Font("Helvetica", Font.PLAIN, 30); Color dotColor[] = {Color.black,Color.red,Color.green.darker(),Color.blue}; public void render(Graphics g) { if (w == 0) { w = bounds().width; h = bounds().height; createSpline(); for (int i = 0 ; i < 4 ; i++) S[i] = new Rectangle(h/3, (h/3-80)/2 + 20*i, h/3, 20); } // DRAW THE BACKGROUND COLOR g.setColor(bgColor); g.fillRect(0,0,w,h); // DRAW THE SPLINE g.setColor(splineBgColor); g.fill3DRect(h/3,h/3,h/3,h/3, true); g.setColor(Color.black); g.drawRect(h/3,h/3,h/3,h/3); for (int x = h/3 ; x < 2*h/3 ; x++) { int y = Y2y(spline.eval(x2X(x))); g.drawLine(x,y,x,y+1); } switch (type){ case 0: drawDots(g, 0, 1./3, 2./3, 1); break; case 1: drawDots(g, -.95, 0, 1, 1.95); break; case 2: drawDots(g, -.95, 0, 1, 1.95); break; case 3: drawDots(g, 0, 1, .1, .9); break; } // DRAW THE SLIDERS for (int i = 0 ; i < 4 ; i++) { Rectangle s = S[i]; g.setColor(sliderColor); g.fill3DRect(s.x, s.y, s.width, s.height, true); int x = (int)(s.x + s.height/2 + G[i] * (s.width - s.height)); g.setColor(dotColor[i]); g.fill3DRect(x-s.height/2, s.y, s.height-1, s.height-1, true); } // SHOW THE SPLINE TYPE g.setColor(Color.black); g.setFont(font); g.drawString(name[type], h/3, 5*h/6); } // DRAW THE FOUR KNOT DOTS void drawDots(Graphics g, double a, double b, double c, double d) { g.setColor(dotColor[0]); drawDot(g, a, G[0]); g.setColor(dotColor[1]); drawDot(g, b, G[1]); g.setColor(dotColor[2]); drawDot(g, c, G[2]); g.setColor(dotColor[3]); drawDot(g, d, G[3]); } void drawDot(Graphics g, double X, double Y) { g.fillOval(X2x(X) - 10, Y2y(Y) - 10, 20, 20); } // CONVERT BETWEEN PIXELS AND SPLINE COORDINATES double x2X(int x) { return (x-h/3.) / (h/3.); } double y2Y(int y) { return 1 - (y-h/3.) / (h/3.); } int X2x(double X) { return (int)(h/3 + X*h/3); } int Y2y(double Y) { return (int)(h/3 + (1-Y)*h/3); } // RESPOND TO USER INPUT public boolean mouseDown(Event e, int x, int y) { // CHANGING SPLINE TYPE if (y > 2*h/3) { type = (type + 1) % 4; createSpline(); return true; } // STARTING TO DRAG ON A SLIDER for (is = 3 ; is >= 0 ; is--) if (S[is].contains(x,y)) { setG(x); break; } return true; } public boolean mouseDrag(Event e, int x, int y) { if (is >= 0) setG(x); return true; } // SET ONE GEOMETRY INPUT VALUE void setG(int x) { Rectangle s = S[is]; G[is] = Math.max(0, Math.min(1, ((double)x - (s.x + s.height/2)) / (s.width - s.height))); createSpline(); } // CREATE THE SPLINE void createSpline() { switch (type) { case 0: spline = new Cubic(Cubic.BEZIER , G); break; case 1: spline = new Cubic(Cubic.BSPLINE , G); break; case 2: spline = new Cubic(Cubic.CATMULL_ROM, G); break; case 3: spline = new Cubic(Cubic.HERMITE , G); break; } damage = true; } }