/** * Navigation Information Display Panel for Moving Map package * @author Robert J Morton * @version 16 December 1997 */ import javax.swing.*; // Java Swing GUI utilities import java.awt.*; // Java Abstract Windowing Toolkit class navpanel extends JPanel implements navconst { private static final long serialVersionUID = 10L; // what the hell this is for, I don't know! private static navpanel np; // reference to this nav panel's own object private FontMetrics fm; // type-face dimensions etc. private loader ld; // reference to the loader object private aircraft ac; // reference to (current) aircraft object private movmap MM; // reference to the movmap applet class private Color fg; // foreground colour for printing private Font font; // reference to a text font (or typeface) private boolean podePaint = false, // can paint/repaint nav data when true trace = false, FTT = true; private int fh = 17, // font height (height of a line of text) ne, // end position of numeric field (excluding sign) VY = 5, // top margin for start of text vy, // start height of first numeric value fn; // field number index for the above array private String headings = " Latitude Longitude Height Speed Heading " + "Req Hdg ROT WP Hgt WP Dist WP Name", VALS[] = new String[13], // array for field values SIGN[] = new String[13], // array for corresponding signs wpname = "", // waypoint name buffer sign = ""; // sign of the displayed field value navpanel(movmap MM, Color fg, aircraft ac, boolean trace) { this.MM = MM; // reference to current instance of movmap applet this.fg = fg; // foreground colour this.ac = ac; // reference to (current) aircraft object np = this; // reference to nav panel object this.trace = trace; // Set general font for screen lettering and get its dimensions etc. font = new Font("Serif",Font.BOLD,12); fm = getFontMetrics(font); /* Width of numeric display string + width of plus sign (assumed wider than minus sign) + inset. */ ne = fm.stringWidth("000:00.00") + fm.stringWidth("+") + 15; FTT = true; } void setLoader(loader ld) {this.ld = ld;} /* RE-DRAW THE PANEL IN THE EVENT OF IT BEING ECLIPSED OR UPDATED The navigational data can be painted only after the background image, the route names and the waypoints of the default route have all been loaded. Painting before this time would mean painting data from variables within class instances that had not yet been created. DefaultsLoaded() returns true when both route names and a full set of default waypoints exist with- in the system. The local flag podePaint is set true once DefaultsLoaed() has returned true for the first time. If it goes false later during the loading of another route's waypoints, repainting of the navigational data can still take place without any problems. */ public void paint(Graphics g) { if(!podePaint) { if(!ld.DefaultsLoaded()) return; podePaint = true; } g.setColor(MM.getPanelColour()); // clear the panel g.fillRect(0,0,137,300); vy = VY + fh + fh; // go to line height of first field value g.setFont(font); // activate the required font g.setColor(fg); // set text colour g.drawString(wpname,15,vy); // display the name of the current waypoint vy += fh; // advance down a line for(int i = 0; i < 13; i++) { // for each of the nav data fields if(i == 6) vy += fh + 13; // miss 2 lines before line 6 String v = VALS[i]; // value of nav data field /* Display the value and its sign right justified in the numeric field. 'vy' is the height of the display line. */ g.drawString(v + SIGN[i],ne - fm.stringWidth(v),vy); vy += fh; // advance downwards to the next line } } /* It is necessary to update the nav data on the run() thread, independently of graphics because otherwise it will upset the repainting of the route selector drop-down list. */ void atualizar() { waypnt wp = waypnt.getCurrent(); // get ref of current waypoint object wpname = wp.getName(); // get name of current waypoint fn = 0; // FOR WAYPOINT VALS[0] = convert(wp.getLat(),true); SIGN[0] = sign; // latitude VALS[1] = convert(wp.getLng(),true); SIGN[1] = sign; // longitude VALS[2] = convHgt(wp.getHgt()); SIGN[2] = sign; // height VALS[3] = convert(wp.getDst(),false); SIGN[3] = sign; // distance VALS[4] = convert(wp.getrBrg(),false); SIGN[4] = sign; // bearing VALS[5] = convert(wp.getOutRad(),false); SIGN[5] = sign; // outbnd radial // FOR AIRCRAFT VALS[ 6] = convert(ac.getLat(),true); SIGN[ 6] = sign; // latitude VALS[ 7] = convert(ac.getLng(),true); SIGN[ 7] = sign; // longitude VALS[ 8] = convHgt(ac.getHgt()); SIGN[ 8] = sign; // height VALS[ 9] = convert(ac.getSpd(),false); SIGN[ 9] = sign; // speed VALS[10] = convert(ac.getHdg(),false); SIGN[10] = sign; // heading VALS[11] = convert(ac.getRqH(),false); SIGN[11] = sign; // requ'd heading VALS[12] = convert(ac.getROT(),false); SIGN[12] = sign; // rate of turn // radians/min repaint(); if(!trace) return; if(FTT) { System.out.println(headings); FTT = false; } String v[] = new String[13]; for(int i = 0; i < 13; i++) v[i] = VALS[i] + SIGN[i] + " "; System.out.printf("%9s", v[6]); // aircraft latitude System.out.printf("%11s",v[7]); // aircraft longitude System.out.printf("%9s",v[8]); // aircraft height System.out.printf("%8s",v[9]); // aircraft speed System.out.printf("%9s",v[10]); // aircraft heading System.out.printf("%9s",v[11]); // aircraft's required heading System.out.printf("%9s",v[12]); // airctraft's rate of turn System.out.printf("%9s",v[2]); // waypoint height System.out.printf("%10s",v[3]); // waypoint distance System.out.printf("%-20s %n",wpname); // waypoint distance } private String convert(double c, boolean b) { String v = ""; // display string if(fn == 2) v = getDist(c); // field #2 is 'waypoint distance' else if(fn == 7) v = getSpeed(c); // field #7 is 'aircraft speed' else if(b) v = getLatLng(c,fn); // if flag set it is a lat or lng else v = getBrg(c,fn); // else it must be a 'bearing' value fn++; return v; } private String convHgt(double x) { // CONVERT HEIGHT String s = ""; if(x < 0) { sign = "-"; x = -x; } else sign = "+"; return String.format("%5.1f",x); } /* CONVERT AIRCRAFT SPEED FROM DOUBLE TO STRING. SPEED IS ALWAYS POSITIVE. find the number of whole kilometres per hour. */ private String getSpeed(double s) { sign = ""; return "" + (int)Math.floor(s * KphRps); } // CONVERT WAYPOINT DISTANCE FROM DOUBLE TO STRING private String getDist(double c) { double x; if(wpenc.getCurrent().getToFlag()) { x = -c; // if the aircraft is approaching the waypoint: sign = "-"; // reverse the sign of the distance } else { // else aircraft must be receding from the waypoint x = +c; // so display its distance as positive sign = "+"; } int d = (int)Math.floor(c *= KPR); // number of whole kilometres // Form it into a display string and tack on the tenths of a kilometre. return "" + d + "." + (int)Math.floor(10 * (c - d)); } // CONVERT A LATITUDE OR LONGITUDE INTO A DISPLAY STRING private String getLatLng(double c, int fn) { boolean sc = true; // the sign of c if(c < 0) { // if 'c' is negative c = -c; // make it positive sc = false; // and set sign negative } int d = (int)Math.floor(c *= DPR); // integral number of degrees if(fn == 0 || fn == 5) // If it is a latitude if(sc) // then if it is positive sign = "N"; // it must be North else // else it must be negative sign = "S"; // it must be South else // else it must be a longitude if(sc) // so if it is positive sign = "E"; // it must be East else // else it must be negative sign = "W"; // so it is West /* Then find number of whole minutes, assuming initially that it fits without padding but pad it with a 0 but if it's less than 10. */ int m = (int)Math.floor(c = 60 * (c - d)); String ms = ms = ":" + m; if(m < 10) ms = ":0" + m; /* Then get the hundredths of a minute of arc and prefix it with a decimal point and pad it with a 0 if it's less than 10. */ int f = (int)Math.floor(100 * (c - m)); String fs = "." + f; if(f < 10) fs = ".0" + f; return "" + d + ms + fs; // return it as a string } // STRING OF AN ANGULAR FIELD private String getBrg(double c, int fn) { if(fn == 10) { // If displaying rate of turn, c *= 60; // convert to degrees per minute if(c < 0) { // if 'c' is negative sign = "-"; // make its sign a '-' c = -c; // make 'c' positive } else // else, 'c' must be positive sign = "+"; // make its sign a '+' } else { // All other bearings (other than rates of turn) sign = ""; // have no sign so if(c < 0) // sif it is negative c += Twoπ; // rationalise it as a positive 0 to 360 angle. } /* Find the integral number of degrees and return it as a string, tacking on the tenths of a degree. */ int d = (int)Math.floor(c *= DPR); return "" + d + "." + (int)Math.floor(10 * (c - d)); } }