/** * Navigation Information Display Panel for Moving Map package * @author Robert J Morton YE572246C * @version 16 December 1997 */ import javax.swing.*; // Java Swing GUI utilities import java.awt.*; // Java Abstract Windowing Toolkit class navpanel extends JPanel implements navconst { // what the hell this is for, I don't know! private static final long serialVersionUID = 2007L; private static navpanel np; // reference to this nav panel's own object private Font font; // reference to a text font (or typeface) private FontMetrics fm; // type-face dimensions etc. private loader ld; // reference to the loader object private aircraft ac; // reference to (current) aircraft object private int fh; // font height (height of a line of text) private int ne; // end position of numeric field (excluding sign) private int VY = 3; // top margin for start of text private int vy; // start height of first numeric value private int fn; // field number index for the above array private String wpname = "", // waypoint name buffer sign = ""; // sign of the displayed field value private movmap MM; // reference to the movmap applet class private Color fg; // foreground colour for printing private boolean podePaint = false; // can paint/repaint nav data when true private String VALS[] = new String[11], // array for field values SIGN[] = new String[11]; // array for corresponding signs navpanel(movmap MM, Color fg, aircraft ac) { 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 // Create a font for screen lettering and get its letter dimensions etc font = new Font("Serif",Font.BOLD,12); fm = getFontMetrics(font); ne = fm.stringWidth("000:00.00") // width of numeric display string + fm.stringWidth("+") // width of + sign (assumed wider than - sign) + 15; // inset fh = 18; // [fm.getHeight();] get the full height of a line of text } 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 vari- ables within class instances that had not yet been created. DefaultsLoaded() returns true when both route names and a full set of default waypoints exist within 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.drawImage(movmap.IMG3,0,0,this); // draw the panel's background photo vy = VY + fh + fh; // go to line height of first field value g.setFont(font); // activate the required font g.setColor(fg); // and 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 < 11; i++) { // for each of the nav data fields if(i == 5) vy += fh + fh +2; // miss 2 lines before line 5 String v = VALS[i]; // value for the nav data field /* Display the value and its sign right justified in the numeric field at height 'vy' 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(); // reference of current waypoint object wpname = wp.getName(); // name of current waypoint fn = 0; // field number index // Display the waypoint data: VALS[0] = convert(wp.getLat(), true); SIGN[0] = sign; // latitude VALS[1] = convert(wp.getLng(), true); SIGN[1] = sign; // longitude VALS[2] = convert(wp.getDst(), false); SIGN[2] = sign; // distance VALS[3] = convert(wp.getrBrg(), false); SIGN[3] = sign; // bearing // Display the selected outbound radial. VALS[4] = convert(wp.getOutRad(), false); SIGN[4] = sign; // Display the aircraft data: VALS[5] = convert(ac.getLat(), true); SIGN[5] = sign; // latitude VALS[6] = convert(ac.getLng(), true); SIGN[6] = sign; // longitude VALS[7] = convert(ac.getSpd(), false); SIGN[7] = sign; // speed VALS[8] = convert(ac.getHdg(), false); SIGN[8] = sign; // heading // Display the required heading and rate of turn. VALS[9] = convert(ac.getRqH(), false); SIGN[9] = sign; VALS[10] = convert(ac.getROT(), false); SIGN[10] = sign; repaint(); } 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's a lat or lng else v = getBrg(c, fn); // else it must be a 'bearing' fn++; return v; } // CONVERT AIRCRAFT SPEED FROM DOUBLE TO STRING private String getSpeed(double s) { sign = ""; // speed is always positive // Return the rounded whole number of kilometres per hour return "" + (int)Math.floor(s * KphRps); } // CONVERT the WAYPOINT DISTANCE FROM DOUBLE TO STRING private String getDist(double c) { double x; // If aircraft is receding from the waypoint: if(wpenc.getCurrent().getToFlag()) { x = -c; // reverse the sign of the distance sign = "-"; // and display it as negative } else { // else aircraft is receding from the waypoint x = +c; // so display the distance as positive sign = "+"; } int d = (int)Math.floor(c *= KPR); // find number of whole kilometres // Return it as 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); // find the integral number of units if(fn == 0 || fn == 5) { // if it is a latitude if(sc) // if it has a positive magnitude sign = "N"; // it is North else // else it has a negative magnitude sign = "S"; // so it is South } else { // else it must be a longitude if(sc) // if it has a positive magnitude sign = "E"; // it is East else // else it has a negative magnitude sign = "W"; // so it is West } int m = (int)Math.floor(c = 60 * (c - d)); // whole number of minutes String ms = ms = ":" + m; // assume initially that it needs no padding if(m < 10) ms = ":0" + m; // pad it with a '0' if it's less than 10 int f = (int)Math.floor(100 * (c - m)); // hundredths of a minute of arc String fs = "." + f; // prefix it with a decimal point if(f < 10) fs = ".0" + f; // pad it with a 0 if it's less than 10 return "" + d + ms + fs; // form it all into a string } private String getBrg(double c, int fn) { // STRING OF A BEARING FIELD 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' itself positive } else // else sign = "+"; // make the sign a '+' } else { // else, all other bearings have no sign (0-360) sign = ""; // so kill its sign if(c < 0) // if it is negative c += Twoπ; // rationalise it as a 0 to 360 value } int d = (int)Math.floor(c *= DPR); // find the integral number of units /* Return the bearing in the form of a string with the tenths of a degree tacked on the end. */ return "" + d + "." + (int)Math.floor(10 * (c - d)); } }