/** * Time Graph Class for Rob's * Difference Equation Iteration Demonstrator Applet * @author Robert J Morton * @version 27 November 1997 modified 07 August 2009, 18 April 2012 */ /* Plots values of a real variable x which is passed to it against time. It plots directly onto the screen and an off-screen saver image. */ import java.awt.*; // for graphics operations (GUI) import javax.swing.*; // library for constructing Swing GUI class timegr extends JPanel{ private static final int yMAX = 160, // height of the wipe rectange tMAX = 500, // extent of time axis HB = 25, VB = 15; // window co-ordinates of top left corner of graph private int t, // current plot position on time axis u, // current wipe position on time axis y1, // local co-ordinate of previous plot y2, // local co-ordinate of current plot Y; // local co-ordinates of graph's real origin private static final Color axis = Color.gray, // colour of the graph's axes trace = new Color(0,128,64); // colour of time line trace private boolean PlotMode = false, // true when plotting points only: not joined lines ScanMode = true, // true when scanning continuously: not single shot EqnFlag = false, // true when using equation X = X**2 + C ready = false; // inhibits the initial paint after construction private double k; // vertical real-to-pixel conversion factor private difeqnap ap; // instance reference of the main applet private setbutt sb; // instance reference of the setbutt class private formula f; // instance reference of formula iteration class private Graphics gi; // graphics context reference for off-screen image private Color bg; // background colour private Font font; // font for graph axis annotations private FontMetrics fm; // dimensions of lettering etc for chosen font private Image TG = null; // instance reference to time-graph image timegr(difeqnap ap, Color bg, formula f, Graphics g, Font font, Image TG) { this.ap = ap; // nstance reference of the main applet this.f = f; // instance reference of the formula iteration class this.bg = bg; // background colour for the time graph gi = g; // graphics reference of the bounce-graph image this.font = font; // copy font reference to local variable this.TG=TG; // copy instance reference to time-graph image fm = getFontMetrics(font); // get dimensions for this font's lettering } void setSB(setbutt b) { sb = b; // instance reference of setbutt class } void setEF(boolean b) { EqnFlag = b; // set which equation to use } void setPM(boolean b) { PlotMode = b; // set 'line graph' or 'spot value' plotting } void setSM(boolean b) { ScanMode = b; // set for 'single-scan' or 'continuous' } void setReady(boolean b) { ready = b; // set when applet's run loop is initialised } void reset() { // INITIALISE/RESET THE TIME-GRAPH IMAGE t=1; // horizontal position of plot on time axis u=61; // horizontal position of wipe on time axis gi.setColor(bg); // set background colour for time-graph image gi.fillRect(0,0,545,180); // clear the whole image to background colour int K = 160; // pixels per unit real for x = cx(1-x) x = 218, // axis positions for x=cx(1-x) y = 352; if(EqnFlag) { // if using equation x=x*2+c K = 40; // number of pixels per unit real for x=x**2+c x = 298; // axis positions for x=x*2+c graph y = 272; } k = (double)K; // convert to a double multiplication factor gi.setColor(axis); // colour in which to draw the graph's axes gi.drawLine(HB,VB,HB,VB + yMAX); // draw the y-axis Y = 160; // relative position of vertical axis origin if(EqnFlag) Y = 80; gi.drawLine(HB,VB + Y,HB + tMAX,VB + Y); // draw the time-axis String s=""; // for numbers of the graph's vertical scale x=HB-6; // x co-ordinate of the vertical scale numbers int n; // actial value of the scale number gi.setFont(font); // set font for axis annotations if(EqnFlag) { // if we're using x = x**2 + c n = 2; // start at top of scale /* For every point 40 pixels apart (every 1.00 real): get the vertical coordinate of the next scale mark, draw the short horizontal mark, convert scale number to string form, draw the string onto the panel. */ for(y = 0 ; y < 161 ; y += 40, n--) { int v = VB + y; gi.drawLine(x,v,HB,v); s = String.valueOf(n); gi.drawString(s,x - fm.stringWidth(s),v + 3); } } else { // but if we're using x = cx(1 - x) n = 10; // top of scale (times 10) /* For every poinr 32 pixels apart (every 0.2): get vertical co-ordinate of next scale mark then draw it on the panel. */ for(y = 0 ; y < 161 ; y += 32) { int v = VB + y; gi.drawLine(x,v,HB,v); /* If the mark is at the top or bottom of the scale, set it to 1 or 0 respectively; otherwise, calculate the number, draw it on the panel.*/ if(n == 10) s = "1"; else if(n == 0) s = "0"; else s = "." + String.valueOf(n); gi.drawString(s, x - fm.stringWidth(s),v + 3); n -= 2; // decrement to next mark } } int z = 178; if(EqnFlag) z = 98; // vertical co-ordinate of 't' label gi.setColor(Color.black); // lettering is in black gi.drawString("x",23,11); // draw x label gi.drawString("t",HB + tMAX + 6,z); // draw t label repaint(); // paint the graph axes onto the panel y2 = Y; // set starting point for plotting the graph ready = true; } public void paint(Graphics g) { g.drawImage(TG, 0, 0, null); // (re)draw on screen from time graph image } public void update(Graphics g) { g.drawImage(TG, 0, 0, null); // (re)draw on screen from time graph image } void Plot() { double x = f.getX(); // get new value of x from iteration formula y1 = y2; // this time's old plot is last time's new plot y2 = Y - (int)(k * x); // co-ords of this time's new plot Line(gi); // put new plot on off-screen image if(ScanMode) // if in continuous scan mode Wipe(gi); // wipe oldest plot on off-screen image if((u += 5) > tMAX) u = 1; // wrap time axis if((t += 5) > tMAX) { // if trace has reached end of time axis if(PlotMode) // if doing spot plots t -= 5; // cancel the time axis advance else { // else if doing continuous graph if(!ScanMode) { // if program is in single-scan mode sb.Stop(); // halt at end of first Time Graph scan System.out.println("timegr.java: Stopped because the"); System.out.println("single scan has been completed."); return; // signal to stop the program on return } t = 1; // fly back to start of time axis } } repaint(); return; // not yet at end of scan } // DRAW LINE BETWEEN OLD AND NEW PLOTS private void Line(Graphics g) { int x = HB + t, // x co-ordinate of old plot y = VB + y2; // y co-ordinate of new plot g.setColor(trace); // set the color for the graph trace /* If doing spot plots, draw the new plot, else if doing continuous line, draw line between old and new plots. */ if(PlotMode) g.drawLine(x,y,x + 5,y); else g.drawLine(x,VB + y1,x + 5,y); } // WIPE OLD TRACE 60 PIXELS AHEAD OF NEW TRACE private void Wipe(Graphics g) { g.setColor(bg); // set background colour for time graph int y = VB + Y; // y co-ordinate of the time axis g.fillRect(HB + u,VB,7,yMAX); // wipe the next bit of the old trace g.setColor(axis); // set colour in which to re-draw bombed bit of axis g.drawLine(HB,y,HB + tMAX,y); // replace the wiped bit of the time axis } }