/** Lissajous Figure Track Recorder Test by Robert John Morton UK-YE572246C */ /* Applet version of a program to test large area track recorder linearity by tracing out a variant of Lissajous figues. Completed Fri 10 Oct 1997 */ import java.awt.*; import java.lang.System; class SinCoord { // CLASS TO CREATE AND MANIPULATE x-y CO-ORDINATE OBJECTS double a, // main phase angle A, // quadrant main angle q, // phase angle Q; // quadrant phase angle int pc; // phase cycle counter boolean f, // 'first main cycle complete' flag c; // 'current main cycle completed' flag //FINDS VALUE OF CO-ORDINATE CORRESPONDING TO INCREMENTED ANGLE public int Advance(double d, double p, int m, int R, int B) { int x = B + (int)(R * Math.sin(a * m + q)); if((a += d) > 6.2831873) { // On completion of each cycle, a = 0; // reset the angle to 'zero' c = true; // and set the 'cycle completed' flag. } if((A += d) > 6.256) { // if painter has completed first 6 radians, A = 0; // set the wiper to start. f = true; } if((q += p) > 6.2831853) // when phase angle = 2Pi q = 0; // reset it to zero if((Q += p) > 1.570796325) { // if just completed another two quadrants pc++; // increment phase cycle counter Q = 0; // reset the quadrant phase differential } return(x); //return new x or y co-ordinate } public void Reset() { // RESET THE VALUES IN A CO-ORDIATE OBJECT pc = 0; // phase cycle counter a = 0; // main angle A = 0; // quadrant main angle q = 0; // phase angle Q = 0; // quadrant phase angle f = false; // 'first main cycle complete' flag c = false; // 'current main cycle completed' flag } } public class trackrec extends java.applet.Applet implements Runnable { static double d = .00872664626, // delta-a primary angular velocity p = .001090830783; // phase differential incrementer long TimeFrame = 15, // inter plot time frame T; // time a new plot is due to begin int m = 1; // y-frequency multiplier boolean Trace = true, // trace colour switch flip = true; // trigger to flip track trace colour Color colour, // track trace colour Dots[][]; // to store the picture so far Thread TH; // declare a thread reference variable SinCoord X1, // current x co-ordinate of trace Y1; // current y co-ordinate of trace public void init() { X1 = new SinCoord(); // create a new x co-ordinate object Y1 = new SinCoord(); // create a new y co-ordinate object Dots = new Color[180][180]; // to preserve the trace so far // set the whole raster to the background colour for(int x = 0 ; x < 180 ; x++) for(int y = 0 ; y < 180 ; y++) Dots[x][y] = Color.lightGray; // Set the system time when the first time frame will end. T = System.currentTimeMillis() + TimeFrame; } public void paint(Graphics g) { // PAINT / RE-PAINT THE PICTURE SO FAR // for each of the 180 lines in the picture for(int x = 0 ; x < 180 ; x++) { int Y = 0, // starting dot of next single-colour stretch of line y = 0; // to find next pixel in current line with a different // colour //make colour of first dot the reference colour Color c = Dots[x][Y]; while(++y < 180) { // while not yet reached end of current line /* If this dot a different colour from previous dot set colour to colour of previous dot draw line from start dot to previous dot make reference colour that of this dot. */ if(c != Dots[x][y]) { g.setColor(c); g.drawLine(x,Y,x,y - 1); c = Dots[x][Y = y]; } } /* Set colour for final stretch of current line, draw the last stretch of the current line. */ g.setColor(c); g.drawLine(x,Y,x,y - 1); } } // called in response a request for a repaint() public void update(Graphics g) { if (flip) { // if just completed a cycle if (Trace) { // If just finished wiping, colour = Color.black; // prepare to paint the trace Trace = false; // and set flag = 'painting' } else { // else, colour = Color.white; // prepare to wipe the trace Trace = true; // and set flag = 'wiping'. } X1.Reset(); Y1.Reset(); // reset SinCoord objects X1.a = 1.570796325; // initialise main angle Y1.a = 1.570796325; // to 90 degrees (pi/2) flip = false; // cancel 'time to flip' flag } g.setColor(colour); // paint/wipe in approp colour int x = X1.Advance(d,p,1,80,85), // advance to the next x-position y = Y1.Advance(d,0,m,80,85); // advance to the next y-position g.drawLine(x,y,x,y); // Draw the next bit of line and Dots[x][y] = colour; // put the dot in the raster buffer } public void run() { // run the Track Recorder painting thread while(true) { // permanent loop broken by external event if(X1.pc > 1) // if just completed a phase quadrant flip = true; // trigger a trace colour flip repaint(); // request a rationalised call to update() /* Get time left in this plot's time frame [minimum 5 milli- seconds] then put thread to sleep for this remaining time. */ long s = T - System.currentTimeMillis(); if (s < 5) s = 5; try { Thread.currentThread().sleep(s); } /* If any exception occurs during the thread's sleep period, catch it and trigger a restart of the applet. */ catch (InterruptedException e) { flip = true; } // get when next plot's time frame will end T = System.currentTimeMillis() + TimeFrame; } } /* Start the program thread by creating the thread object and starting it running by requesting a call to run(). */ public void start() { TH = new Thread(this); TH.start(); } public void stop() { TH = null; } // Stop this a program thread }