/** Air Navigation Waypoint Intercept Demonstrator by Robert J Morton UK-YE572246C 21 Oct 1997 */ /* A demonstrator applet for the Waypoint Encounter class: NavEncPG.class which in turn uses the classes: Aircraft.class and Waypoint.class */ import java.awt.*; // abstract window tool kit for applet import java.lang.System; // needed for system time services public class wpapplet extends java.applet.Applet implements Runnable { String //Field names Names[] = { "WAYPOINT ENCOUNTER","","Waypoint Name","","Selected Radial", "Aircraft Bearing","Radial Deviation","","Station Bearing", "Steering Offset","Required Heading","","Distance" }, //leading zeros for displaying numeric values Zeros[] = {"","0","00","000"}; int SelRad = -44, // Selected Radial in angular degrees XM = 190, // x margin between left edge and start of tracking area fh, // font height (height of a line of text) fa, // font ascent (height of letters above base line) nw, // width in pixels of longest field name vw, // width in pixels of standard value string NY, // top margin for start of text VY, vy, // start height of first numeric value X=520, Y=200; // window and image buffer dimensions // values from previous pass of update() int[] OldVal={999,999,999,999,999,999,999}; long TF = 50, // inter-plot time frame (milliseconds) T; // future system time at which a new plot is due to begin Thread TH; // declare a program thread reference variable aircraft ac; // reference to an aircraft object waypoint wp; // reference to a waypoint object wpencpg en; // reference to an encounter object wpcolour ca; // reference to a colour array object Color TFC = Color.white; // text foreground colour //reference to a font (or typeface) for the text in this applet Font font = new Font("Dialog",Font.PLAIN,12); FontMetrics fm; // reference to the font's dimensions etc. Image buffer = null; // reference for an off-screen image buffer Graphics gc = null; // graphics context for the off-screen image public void init() { // INITIALISE THE APPLET // Create the off-screen image buffer and get its graphics context. buffer = createImage(X,Y); gc = buffer.getGraphics(); // Fill the off-screen image with the background colour. gc.setColor(Color.black); gc.fillRect(0,0,X,Y); ac = new aircraft(); // create an aircraft object wp = new waypoint(); // create a waypoint object en = new wpencpg(); // create an encounter object ca = new wpcolour(); // create a colour array object fm = getFontMetrics(font); // get the dimensions etc for this font fh = fm.getHeight(); // get the full height of a line of text fh = 14; // Netscape Navigator problem fa = fm.getAscent(); // get the font's ascent (ht above baseline) fa = 10; // Netscape Navigator problem // width of the longest field name + 10pixels nw = fm.stringWidth(Names[10]) + 20; vw = fm.stringWidth("000+"); // width of numeric value readout string NY = 5; // top 'margin' for text // starting height of first numeric value field VY = NY + fh + fh + fh + fh; // Set System Time at which the first time frame will terminate. T = System.currentTimeMillis() + TF; } private void reset(){ // PAINT THE SUPERSTRUCTURE FOR A NEW RUN /* Clear the text area by filling it with its background colour then set up the text area's font to print in white lettering. */ gc.setColor(Color.black); gc.fillRect(0,0,XM,ca.YH); gc.setFont(font); gc.setColor(Color.white); int y = NY; // Set the vertical start position for the text. /* Display each of the 13 Field Names, each on a separate line, additionally showing the waypoint's name on the third line. */ for(int i = 0 ; i < 13 ; i++) { gc.drawString(Names[i], 10, y += fh); if(i == 2) gc.drawString(wp.N, nw, y); } // For each line of pixels in the map area ... for(y = 0 ; y < ca.YH ; y++) { int X = 0, // starting dot of next single-colour stretch of line x = 0; // to find next pixel in current line with a different colour // Make the colour of the first dot the reference colour. Color c = ca.C[X][y]; // While we've not yet reached the end of the current line of pixels while(++x < ca.XW) { /* If this dot's a different colour from previous dot, set the colour to that of the previous dot, draw the line from the start dot to the previous dot then make the new reference colour that of this dot. */ if(c != ca.C[x][y]) { gc.setColor(c); gc.drawLine(XM + X,ca.YH - y - 1,XM + x - 1,ca.YH - y - 1); c = ca.C[X = x][y]; } } /* Set the colour for the final stretch of the current line, then draw the the final stretch. */ gc.setColor(c); gc.drawLine(XM + X,ca.YH - y - 1,XM + x - 1,ca.YH - y - 1); } repaint(); // re-display the off-screen image } //PAINT THE INITIAL IMAGE from the off-screen image buffer public void paint(Graphics g) { g.drawImage(buffer, 0, 0, null); } //PAINT THE IMAGE SO FAR from the off-screen image buffer public void update(Graphics g) { g.drawImage(buffer, 0, 0, null); } // DISPLAY A NUMERIC VALUE FOR A FIELD ON THE OFF-SCREEN IMAGE void ShowNum(Graphics g,double a,int n){ if(n < 6) // If displaying a field that contains an angular a *= en.DegRad; // value, convert the value from radians to degrees. String sign; // Create a string containing sign of integer 'a'. if(a < 0) { sign = "-"; a = -a; } else sign = "+"; int i = (int)a; // convert it to an integer and round it off if((a -= i) > .5) i++; vy += fh; // advance downwards to new text line if(i != OldVal[n]){ // if this value has changed since the last update /* Remember this time's (changed) value for next time then convert it to a String. */ OldVal[n] = i; String s = String.valueOf(i); // Compute the number of leading zeros required. i = 3 - s.length(); if(i < 0) i = 0; /* Set to background colour and wipe the numeric field's display area then set to foreground colour and display the string. */ gc.setColor(Color.black); gc.fillRect(nw,vy - fa,vw,fh); gc.setColor(Color.white); gc.drawString(Zeros[i] + s + sign,nw,vy); } } void advance() { // ADVANCE THE AIRCRAFT ALONG THE TRACK int // current 'window co-ordinates' of aircraft x = (int)(ac.x + XM), y = (int)(ca.YH - ac.y); gc.setColor(ca.ATC); // Set the colour of the aircraft track gc.drawLine(x, y, x, y); // and draw the next bit of it. vy = VY; // set vertical start position of first numeric field gc.setFont(font); // activate the chosen font and then display... ShowNum(gc,en.OSR,0); // outbound selected radial ShowNum(gc,en.tBrg,1); // bearing of aircraft from waypoint ShowNum(gc,en.RadDev,2); // aircraft's deviation from the // selected outbound radial vy += fh; // miss a line ShowNum(gc, en.rBrg,3); // bearing of waypoint from aircraft ShowNum(gc, en.StrOff,4); // steering offset ShowNum(gc, en.ReqHdg,5); // required heading vy += fh; // miss a line // Show distance 'to' waypoint as negative and 'from' it as positive. double a = en.Dst; if(en.approach) a =- a; ShowNum(gc,a,6); repaint(); // re-display the off-screen image } public void run() { // RUN THE WAYPOINT ENCOUNTER PROGRAM THREAD while(TH != null) { // while the run() thread remaims alive... // if aircraft has just passed out of range ... if(en.outofRange(ac, wp)) { // if selected radial has come full circle, start over if((SelRad += 44) > 359) SelRad -= 360; /* Set up the new selected radial, initialise the colour array and initialise a new fly-past of the waypoint. */ en.SetRadial(ac,wp,SelRad); ca.InitC(ac,wp,en.OSR); reset(); } else // Else, plot the aircraft's new ca.PlotPosn(ac); // position on the display raster advance(); // advance the aircraft along its track /* Get time remaining in this Time Frame, imposing upon it a lower limit of 5 milliseconds, then put thread to sleep for this amount of time. Catch any exceptions that may occur while thread is asleep but do nothing about them because they are normal external events. */ long s = T - System.currentTimeMillis(); if(s < 5) s = 5; try{ TH.sleep(s); } catch(InterruptedException e) { } // Set the System Time at which the next time frame will terminate. T = System.currentTimeMillis() + TF; } } /* 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 PROGRAM THREAD }