/** * Sigmoid Function Generator * @author Robert J Morton UK-YE572246C * @version 15 December 1997 Generates either: a unipolar sigmoid in which both x and y range from 0 to +1, or a bipolar sigmoid in which both x and y range from -1 to +1. Which type of sigmoid is produced is determined by the content of the 'param' tag within the 'applet' tag used to invoke the applet. The code of this applet could easily be extended to include the generation of the look-up table previously done by the 'C' program described in the text. */ import java.awt.*; public class sigmoid extends java.applet.Applet implements Runnable { boolean finished = false, // indicates when the curve has been completed TypeFlag = false; // set for unipolar presentation int s = 200, // pixels per unit real (scaling factor) H = 0, V = s - 1, // window co-ordinate of graphical origin X = 228, Y = 229, // dimensions (in pixels) of the applet window bx = 14, by = 15; // x and y margins long TF = 50, // total Time Frame for the update cycle T; // time at which the next new cycle is due to begin double k = .025, // non-linearity constant y = k / 4, // output value x = 0, // input value dx = k / 10; // plotting (or look-up table) increment Image I = null; // reference for an off-screen image I Graphics i = null; // graphics context for the off-screen image Thread TH; // declare a thread reference variable Color tr = new Color(0,255,128), // green trace colour tx = new Color(1,1,1); // colour for lettering // lettering font for annotations Font font = new Font("Dialog",Font.PLAIN,12); public void init() { // INITIALISE THE APPLET int Xy, Yx; // co-ords of axis labels setBackground(Color.black); I = createImage(X,Y); // Create an off-screen image I and i = I.getGraphics(); // get its graphics context reference. // if applet parameter 'type' = 'bipolar' if(getParameter("type").equals("bipolar")) { TypeFlag = true; // set the TypeFlag true; k = .011; // non-linearity constant y = 0; // output value x = 0; // input value dx = .0025; // plotting (or look-up table) increment s = 100; // pixels per unit real (scaling factor) H = 100; // window co-ordinate of graphical origin V = 100; Xy = V + by; // co-ords of axis letters Yx = H - 10; } else { // Else, we're doing a unipolar graph, Xy = V - 5; // so set co-ords of axis letters. Yx = H + 5; } i.setColor(Color.black); // Clear the off-screen image to black. i.fillRect(0,0,X,Y); i.setFont(font); // set up the annotation font i.setColor(Color.white); // Draw the x and y axes in white. i.drawLine(0,V,X - bx - bx,V); i.drawLine(H,0,H,Y - by - by); // Letter the x and y axes in white lettering. i.drawString("X",X - bx - bx - 10,Xy); i.drawString("Y",Yx,10); i.setColor(tr); // set colour to paint the graph trace on the image // set the end time of the first time frame T = System.currentTimeMillis() + TF; repaint(); } public void paint(Graphics g) { // RE-DRAW THE OFF-SCREEN IMAGE g.drawImage(I,bx,by,null); // WHEN APPLET BECOMES UNECLIPSED } public void update(Graphics g) { // RE-DRAW THE OFF-SCREEN IMAGE g.drawImage(I,bx,by,null); // WHEN TRACE HAS BEEN UPDATED } public void plot() { // PLOT THE SIGMOID GRAPH if(x > 1 || y > 1) // if plot has reached edge of graph, finished = true; // set the 'finished' flag. else { // else, if not yet finished plotting graph int h = (int)(s * x), // Convert the horizontal and v = (int)(s * y), // vertical plots to pixels. a = h, // simplify pixel co-ordinates b, c = V - v, d; if(TypeFlag) { // if doing unipolar version of sigmoid a = H - h; // simplify the pixel co-ordinates b = H + h; c = V + v; d = V - v; // Do next plot in lower left quadrant on off-screen image. i.drawLine(b,d,b,d); y += k * (1 - y); // advance output difference equation } else y += k * y * (1 - y); // advance output difference equation x += dx; // advance the input value i.drawLine(a,c,a,c); // Do next plot in upper right quadrant } // on the off-screen image. repaint(); } public void run() { // run the plotting thread while(TH != null) { // permanent loop while thread is alive if(!finished) // if not yet finished, do next plot plot(); // if not yet finished, do next plot /* Get time remaining in this cycle's time frame, imposing a lower limit of 5 milliseconds. Put thread to sleep for this remaining time. Catch any exceptions that may occur during thread's sleep but do nothing about them as they're expected external events that are handled elsewhere. */ long s = T - System.currentTimeMillis(); if (s < 5) s = 5; try { TH.sleep(s); } catch (InterruptedException e) { } // Set finish time of next time frame. T = System.currentTimeMillis() + TF; } } /* Start the program thread by creating the thread object and starting it running. [returns a call to run()]. */ public void start() { TH = new Thread(this); TH.start(); } public void stop() { TH = null; } // Stop program thread }