// FixedPoint Applet // Concept by Bill Ziemer // Programming by Brendon Cheves & Bill Ziemer // e-mail: brendon@csulb.edu wziemer@csulb.edu // Copyright 1996 by California State University, Long Beach // expr package Copyright 1996 by Darius Bacon // Created 10/22/96 // Last update 10/22/96 // java packages import java.applet.*; import java.awt.*; import java.lang.Math; // our packages import expr.*; // f(x) parser by Darius Bacon import cool_utils.*; // cool utilities we made public class FixedPoint extends Applet { static final boolean DEBUG = false; double first = 0, last = 1; double[] spiderPoints; Color current_color = Color.black; Button helpButton, aboutButton, plusdx, minusdx, okBtn; Label sliderLabel, pOldLabel, pNewLabel, realFixedPointLabel, errorLabel; int nLimit, npoints = 0; double theSum, theIntegral, realFixedPoint, approxErr, error; CardLayout theCards; String theTopStyle = "Constant"; Canvas theCanvas; Panel theDrawingPanel, sliderPanel, theFeedbackPanel, okBtnPanel, mainCd, aboutCd, helpCd, theAboutPanel, theHelpPanel, dxPanel; Rectangle dxWidth; Image offscreenImage; Graphics offscreenGraphics, offscreenInstance; MultiLineLabel aboutLabel; Dimension d; // EZGridLayout manager stuff EZGridSettings gridSettings; EZGridLayout EZGL; // Our function class, based on the Java Polygon class ZFunction theFunction; public void init() { resize(640,420); error = 1E-10; theFunction = new ZFunction(); // create a card layout theCards = new CardLayout(10,10); this.setLayout(theCards); // create the main card mainCd = new Panel(); this.add("main",mainCd); mainCd.setLayout(new BorderLayout(10,10)); // create the about card aboutCd = new Panel(); this.add("about",aboutCd); aboutCd.setLayout(new BorderLayout(10,10)); // create the help card helpCd = new Panel(); this.add("help",helpCd); helpCd.setLayout(new BorderLayout(10,10)); // create the drawing panel and add it to the main cd theDrawingPanel = new Panel(); mainCd.add("Center",theDrawingPanel); theDrawingPanel.setLayout(new BorderLayout(10,10)); // create the EZGridLayout EZGL = new EZGridLayout(12,2); // create the feedback panel and add it to the main cd theFeedbackPanel = new Panel(); mainCd.add("South",theFeedbackPanel); theFeedbackPanel.setLayout(EZGL); minusdx = new Button("-"); gridSettings = new EZGridSettings(minusdx,1,1,1,1); theFeedbackPanel.add(minusdx); EZGL.addLayoutInfo(gridSettings); sliderLabel = new Label(); sliderLabel.setText("n = " + String.valueOf(npoints+1)); gridSettings = new EZGridSettings(sliderLabel,2,1,1,1); theFeedbackPanel.add(sliderLabel); EZGL.addLayoutInfo(gridSettings); plusdx = new Button("+"); gridSettings = new EZGridSettings(plusdx,3,1,1,1); theFeedbackPanel.add(plusdx); EZGL.addLayoutInfo(gridSettings); pOldLabel = new Label(); gridSettings = new EZGridSettings(pOldLabel,4,1,3,1); theFeedbackPanel.add(pOldLabel); EZGL.addLayoutInfo(gridSettings); pNewLabel = new Label(); gridSettings = new EZGridSettings(pNewLabel,7,1,3,1); theFeedbackPanel.add(pNewLabel); EZGL.addLayoutInfo(gridSettings); realFixedPointLabel = new Label(); gridSettings = new EZGridSettings(realFixedPointLabel,10,1,3,1); theFeedbackPanel.add(realFixedPointLabel); EZGL.addLayoutInfo(gridSettings); errorLabel = new Label(); gridSettings = new EZGridSettings(errorLabel,7,2,3,1); theFeedbackPanel.add(errorLabel); EZGL.addLayoutInfo(gridSettings); helpButton = new Button("Help"); gridSettings = new EZGridSettings(helpButton,1,2,1,1); theFeedbackPanel.add(helpButton); EZGL.addLayoutInfo(gridSettings); aboutButton = new Button("About..."); gridSettings = new EZGridSettings(aboutButton,2,2,1,1); theFeedbackPanel.add(aboutButton); EZGL.addLayoutInfo(gridSettings); theFeedbackPanel.resize(preferredSize()); // create the about panel and add it to the about cd theAboutPanel = new Panel(); aboutCd.add("Center",theAboutPanel); theAboutPanel.setLayout(new FlowLayout()); // create the OK button panel and add it to the about cd okBtnPanel = new Panel(); aboutCd.add("South",okBtnPanel); // add the stuff to the about panel Font theFont = new Font("TimesRoman", Font.BOLD, 18); aboutLabel = new MultiLineLabel( "Riemann Sum Applet\nCopyright 1996 by California State University, Long Beach\nWritten by Bill Ziemer and Brendon Cheves\nFunction Parsing Copyright 1996 by Darius Bacon", 10, 10, MultiLineLabel.CENTER); aboutLabel.setFont(theFont); theAboutPanel.add(aboutLabel); // add the OK button okBtn = new Button("OK"); okBtnPanel.add(okBtn); // initialize the offscreen stuff d = theDrawingPanel.size(); offscreenImage = this.createImage(600,500); offscreenGraphics = (Graphics)offscreenImage.getGraphics(); if (offscreenGraphics == null) System.out.println("Error: Null offscreen graphics"); // set up the initial screen theFunction.parse("(1-x^2) / 2"); spiderPoints = new double[1]; npoints = 0; nLimit = 0; spiderPoints[0] = 0.2; realFixedPoint = theFunction.fixedPoint(0.2,error); first = theFunction.xMin; last = theFunction.xMax; // finally, show the main card theCards.show(this,"main"); } public void paint(Graphics g) { // who cares about g, we know where we want to draw offscreenGraphics.clearRect(0,0,600,500); offscreenGraphics.setColor(Color.white); offscreenGraphics.fillRect(0,0,600,500); theFunction.plot((Graphics)offscreenGraphics); drawWeb(offscreenGraphics); drawAxis(offscreenGraphics); drawLimits(offscreenGraphics); drawLabels(offscreenGraphics); // force the offscreen buffer to draw into the drawing panel theDrawingPanel.getGraphics().drawImage(offscreenImage,0,0,theDrawingPanel); } // Override update() for double buffering public void update(Graphics g) { paint(g); } public Insets insets() { return new Insets(10,10,10,10); } // handle GUI events public boolean action(Event e, Object arg) { if(e.target == minusdx) { if(npoints > 0) { npoints--; paint(theDrawingPanel.getGraphics()); } return true; } else if(e.target == plusdx) { double[] tmp; npoints++; if(npoints > nLimit) { tmp = new double[npoints+1]; System.arraycopy(spiderPoints, 0, tmp, 0, npoints); spiderPoints = tmp; nLimit = npoints; spiderPoints[npoints] = theFunction.value(spiderPoints[npoints-1]); System.out.println("p(" + (npoints) + ") = " + spiderPoints[npoints]); } paint(theDrawingPanel.getGraphics()); return true; } else if(e.target == aboutButton) { theCards.show(this,"about"); return true; } else if(e.target == okBtn) { theCards.show(this,"main"); return true; } else return super.action(e,arg); } // draw the axis public void drawAxis(Graphics g) { g.setColor(Color.black); // x axis g.drawLine(0,theFunction.yRealToPixel(first),580,theFunction.yRealToPixel(first)); g.drawString("X",585,theFunction.yRealToPixel(first) + 4); // y axis g.drawLine(40,20,40,500); g.drawString("Y",38,17); //draw y = x g.drawLine(theFunction.xRealToPixel(first),theFunction.yRealToPixel(first), theFunction.xRealToPixel(last),theFunction.yRealToPixel(last)); g.drawString("y = x", theFunction.xRealToPixel(last), theFunction.yRealToPixel(last)); } // draw all the necessary labels public void drawLabels(Graphics g) { g.setColor(Color.black); sliderLabel.setText("n = " + String.valueOf(npoints)); pOldLabel.setText("p("+(npoints)+") = " + String.valueOf( spiderPoints[npoints] - ((1E6 * spiderPoints[npoints]) % 1) / 1E6)); pNewLabel.setText("p("+(npoints+1)+") = " + String.valueOf( theFunction.value(spiderPoints[npoints]) - ((1E6 * theFunction.value(spiderPoints[npoints])) % 1) / 1E6)); realFixedPointLabel.setText("Real Fixed Point = " + String.valueOf(realFixedPoint - ((1E6 * realFixedPoint) % 1) / 1E6)); errorLabel.setText("Error = " + String.valueOf( realFixedPoint - theFunction.value(spiderPoints[npoints]) )); } // draw limits in the proper places public void drawLimits(Graphics g) { g.setColor(Color.red); // x limit g.drawString(String.valueOf(last),(int)theFunction.XSCALE + 44,theFunction.yRealToPixel(first) + 14); g.drawLine((int)theFunction.XSCALE + 40,theFunction.yRealToPixel(first) - 2,(int)theFunction.XSCALE + 40,theFunction.yRealToPixel(first) + 2); // y limit theFunction.xvar.set_value(last); g.drawString(String.valueOf(theFunction.expr.value() - ((1E2 * theFunction.expr.value()) %1) / 1E2),5,theFunction.yRealToPixel(theFunction.expr.value()) + 3); g.drawLine(38,theFunction.yRealToPixel(theFunction.expr.value()),42,theFunction.yRealToPixel(theFunction.expr.value())); // fixed point drawDashedLine(theFunction.xRealToPixel(realFixedPoint), theFunction.yRealToPixel(realFixedPoint), theFunction.xRealToPixel(realFixedPoint), theFunction.yRealToPixel(first),g); } public void drawWeb(Graphics g) { int x1,x2,y1,y2; //draw the history of iterations in green g.setColor(Color.green); for(int i=0; i < npoints; i++) { x1 = theFunction.xRealToPixel(spiderPoints[i]); x2 = theFunction.xRealToPixel(spiderPoints[i+1]); y1 = theFunction.yRealToPixel(first); y2 = theFunction.yRealToPixel(spiderPoints[i+1]); g.drawLine( x1, y1, x1, y2); g.drawLine( x1, y2, x2, y2); g.drawLine( x2, y2, x2, y1); } // draw the current iteration in red x1 = theFunction.xRealToPixel(spiderPoints[npoints]); x2 = theFunction.xRealToPixel(theFunction.value(spiderPoints[npoints])); y1 = theFunction.yRealToPixel(first); y2 = theFunction.yRealToPixel(theFunction.value(spiderPoints[npoints])); g.setColor(Color.red); if( (first < spiderPoints[npoints]) && (spiderPoints[npoints] < last)) { drawArrowheadLine(x1, y1, x1, y2,g); drawArrowheadLine(x1, y2, x2, y2,g); drawArrowheadLine(x2, y2, x2, y1,g); g.drawString("p(" + (npoints) + ")",x1-5,y1 + 14); g.drawString("p(" + (npoints+1) + ")",x2-5,y1 + 28); g.drawString("f(p(" + (npoints) + "))", 0, y2+5 ); g.drawLine(38,theFunction.yRealToPixel(theFunction.expr.value()),42,theFunction.yRealToPixel(theFunction.expr.value())); } } // Return info for an about box browser option public String getAppletInfo() { return "Fixed Point Java Applet by Bill Ziemer & Brendon Cheves"; } // Called from JavaScript only public void drawFunction(String f, String g) { theFunction.parse(f); npoints = 0; nLimit = 0; Float gWrapInFloat = new Float(g); spiderPoints[0] = gWrapInFloat.doubleValue(); realFixedPoint = theFunction.fixedPoint(gWrapInFloat.doubleValue(),error); first = theFunction.xMin; last = theFunction.xMax; System.out.println("p(0) = " + spiderPoints[0]); //paint(theDrawingPanel.getGraphics()); repaint(); } // Unitl we can get CoolGraphics.class working, got to put these cool utilities here public void drawArrowheadLine(int x1, int y1, int x2, int y2, Graphics g) { int a = 0; int arrowW = 26, arrowH = 26; int arrowX, arrowY; // draw the line first g.drawLine(x1, y1, x2, y2); // calculate arrowhead locations arrowX = x2 - (arrowW / 2); arrowY = y2 - (arrowH / 2); if(x1 == x2) { if (y2 > y1) { a = 270; } else { a = 90; } } else { a = (int)Math.atan((double)(y2 - y1) / (double)(x2 - x1)); // -90 to 90 if(x2 < x1) { a = 180 - a; } } // draw the arrowhead g.fillArc(arrowX, arrowY, arrowW, arrowH, a + 165, 30); } public void drawDashedLine(int x1, int y1, int x2, int y2, int dashLength, Graphics g) { dashedLine(x1, y1, x2, y2, dashLength,g); } public void drawDashedLine(int x1, int y1, int x2, int y2, Graphics g) { dashedLine(x1, y1, x2, y2, 4,g); } private void dashedLine(int x1, int y1, int x2, int y2, int dashLength, Graphics g) { float m; int i, tmp; if(x2 < x1) { tmp = x1; x1 = x2; x2 = tmp; tmp = y1; y1 = y2; y2 = tmp; } if(x2 != x1) { m = (y2 - y1) / (x2 - x1); for(i = x1; i < x2; i += (2 * dashLength)) { g.drawLine( i, (int)((m * (i - x1)) + y1), (int)(i + Math.sqrt(dashLength / (1 + (m*m)))), (int)((m * ((i + Math.sqrt(dashLength / (1 + (m*m)))) - x1)) + y1)); } // guarantee last dash if( (i * 2 * dashLength + x1 < x2)) { g.drawLine( i * 2 * dashLength + x1, (int)((m * (i * 2 * dashLength)) + y1), x2, y2); } } else // vertical { if(y2 < y1) { tmp = y1; y1 = y2; y2 = tmp; } for(i = y1; i < y2; i += (2 * dashLength)) { g.drawLine( x1, i, x1, i + dashLength); } // guarantee last dash if( (i * 2 * dashLength + y1 < y2)) { g.drawLine( x1, i * 2 * dashLength + y1, x1, y2); } } } }