import java.awt.*; /** Program: Exp Purpose: graph exp with varying-degree Taylor approx @author: Paul Garrett, garrett@math.umn.edu @version: Mon 7 July, 16:00 CDT 1997 */ /* Low-res screen allows 600 wide but only 350 high */ public class Exp 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 = 400; // 'width' of area for drawing final int vert_scale = 10; // pixels per unit final int horiz_scale = 60; // pixels per unit final int v_gridsize = 10; // pixels between gridlines?! final int h_gridsize = 60; // 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 = 20; // to know when we're done int deg; // this is what we know at any one moment final int left = 420; // these are coords for the clickbox final int right = 540; final int top = 50; final int bottom = 80; final boolean restrictAccess = true; final String theURL = "http://www.math.umn.edu/~garrett/qy/Exp.html"; /******************************/ 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 = (output + 1.0) * theCoefficients[i] * input; // good, generally... } output = output + theCoefficients[0]; // NB this assumes deg>0 return output; } 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; } void initCoefs() { // these are not Taylor coefs, but rather the // coefficients convenient for computation... // compute lotsa them... maybe 50? but fixed total... if (! restrictAccess || this.getDocumentBase().toString().equals(theURL)) { theCoefficients = new double[degree+1]; theCoefficients[0] = 1.0; for (int i=1; i<=degree; i++) { theCoefficients[i] = 1.0/((double) i); } } } public void init() { // stick some coefficients in, tell degree deg = 1; 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.red); for (int i = -rangeOfInc ; i < rangeOfInc; i++) { g.drawLine( normPara(i), normOut(Math.exp(normIn(i))), normPara(i+1), normOut(Math.exp(normIn(i+1)))); } g.setColor(Color.black); updating = false; } else { g.setColor(Color.gray); g.fillRect(0,0,600,350); 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.exp(normIn(i))), normPara(i+1), normOut(Math.exp(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,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 < degree-1) { deg++; updating = true; repaint(); } else if (x>=left && x<=left+50 && y<=top+100+20-3 && y>=top+100) { init(); } return true; } } // The End