import java.awt.*; /** Program: Sine Purpose: graph sine with varying-degree Taylor approx @author: Paul Garrett, garrett@math.umn.edu @version: Mon 7 July, 16:00 CDT 1997 */ /* Low-res screen allows 550 wide but only 320 high */ public class Sine extends java.applet.Applet { boolean updating; // device ... to keep old curves... final int nwx = 5; // nw corner of drawing surface x-coord final int nwy = 5; // nw corner of drawing surface x-coord final int height = 310; // 'height' of area for drawing final int width = 415; // 'width' of area for drawing final int vert_scale = 20; // pixels per unit final int horiz_scale = 20; // pixels per unit final int v_gridsize = 20; // pixels between gridlines?! final int h_gridsize = 20; // pixels between gridlines?! // 'gridsize' should be divisor of "vert_scale", etc., ... ? final int inc = 3; // pixel-size in which to draw the curve final int rangeOfIndex = (int) width/(2*h_gridsize); // to draw vertical gridlines final int rangeOfJndex = (int) height/(2*v_gridsize); // to draw horizontal gridlines final int rangeOfInc = (int) width/(2*inc); double[] theCoefficients; // of arbitrary degree polynomial final int degree = 40; // to know when we're done int deg; // this is what we know at any one moment final int left = 430; // these are coords for the clickbox final int right = 540; final int top = 50; final int bottom = 80; /*******************/ // final String theURL = "http://www.math.umn.edu/~garrett/qy/Sine.html"; // final boolean restrictAccess = true; // switch restrictions on URL /******************************/ double theFunction(double input) { // Taylor approx to sine... // Note that this calls 'deg' rather than 'degree' double output; output = theCoefficients[deg] * input; for (int i = deg-1; i >= 0; i--) { output = (1.0 - output * input) * theCoefficients[i] * input; } if (output > 1000.0) { output = 1000.0; } else if (output < -1000.0) { output = -1000.0; } // NB this assumes deg>0 ? return output; } void initCoefs() { // these are not Taylor coefs, but rather the // coefficients convenient for computation... // compute lotsa them... maybe 50? but fixed total... theCoefficients = new double[degree+1]; theCoefficients[0] = 1.0; for (int i=1; i<=degree; i++) { // only index _non_zero coefficients theCoefficients[i] = 1.0/((double) (2*i*(2*i+1))); } } int normPara(int para) { // from counter to x-coord int thePara; thePara = nwx + width/2 + inc * para; return thePara; } int normOut(double output) { // function output to vertical coord int theY; theY = nwy + height/2 - (int) (output * vert_scale); return theY; } double normIn(int in) { // from counter to function input double theX; theX = ((double) (in * inc)) / ((double) horiz_scale); return theX; } public void init() { // stick some coefficients in, tell degree // if (! restrictAccess || // this.getDocumentBase().toString().equals(theURL)) { deg = 0; initCoefs(); // } updating = false; repaint(); } void drawGrid (Graphics g) { for (int i = -rangeOfIndex; i <= rangeOfIndex; i++) { // vertical lines g.drawLine(nwx + width/2 + h_gridsize * i, nwy, nwx + width/2 + h_gridsize * i, nwy + height); } for (int i = -rangeOfJndex; i <= rangeOfJndex; i++) { // horizontal lines g.drawLine(nwx, nwy + height/2 + v_gridsize * i, nwx + width, nwy + height/2 + v_gridsize * i); } g.fillRect(nwx + width/2 - 1, nwy, 3, height); // y-axis g.fillRect(nwx, nwy + height/2 - 1, width, 3); // x-axis // arrow on y-axis int[] xs = {nwx + width/2, nwx + width/2 - 6, nwx + width/2, nwx + width/2 + 6}; int[] ys = {nwy-2, nwy + 10, nwy + 6, nwy + 10}; g.fillPolygon(new Polygon(xs, ys, 4)); // arrow on x-axis int[] xs2 = {width + nwx + 2, width+ nwx - 10, width + nwx - 6, width + nwx - 10}; int[] ys2 = {nwy + height/2, nwy + height/2 - 6, nwy + height/2, nwy + height/2 + 6}; g.fillPolygon(new Polygon(xs2, ys2, 4)); } public void update(Graphics g) { paint(g); // no clearing of screen, just over-paint // problem if applet is overlaid by some other window... } public void paint(Graphics g) { if (updating == true) { tellDegree(g); g.setColor(Color.white); for (int i = -rangeOfInc ; i < rangeOfInc; i++) { g.drawLine( normPara(i), normOut(theFunction(normIn(i))), normPara(i+1), normOut(theFunction(normIn(i+1)))); } g.setColor(Color.black); updating = false; } else { g.setColor(Color.gray); g.fillRect(0,0,600,320); g.setColor(Color.black); drawClickBox(g); tellDegree(g); drawGrid(g); g.setColor(Color.white); for (int i = -rangeOfInc ; i < rangeOfInc; i++) { g.drawLine( normPara(i), normOut(theFunction(normIn(i))), normPara(i+1), normOut(theFunction(normIn(i+1)))); } g.setColor(Color.red); for (int i = -rangeOfInc ; i < rangeOfInc; i++) { g.drawLine( normPara(i), normOut(Math.sin(normIn(i))), normPara(i+1), normOut(Math.sin(normIn(i+1)))); } g.setColor(Color.black); g.drawRect(left,top+100,50,20); g.drawString("Reset",left+5,top+100+20-3); // 'Reset' clickbox } } void drawClickBox(Graphics g) { g.drawRect(left,top,right-left,bottom-top); g.drawString("Increase degree",left+5,bottom-3); } void tellDegree(Graphics g) { g.setColor(Color.gray); g.fillRect(left,top+40,right-left,bottom-top); g.setColor(Color.black); // g.drawRect(left,top+40,right-left,bottom-top); g.drawString("Degree "+(deg*2+1),left+5, bottom+40-3); } public final boolean mouseDown(Event e, int x, int y) { if (x>=left && x<=right && y>=top && y<= bottom && deg <= 49) { deg++; updating = true; repaint(); } else if (x>=left && x<=left+50 && y<=top+100+20-3 && y>=top+100) { init(); } return true; } } // The End