3 // NavigationVisComp.java
6 // Seth Widoff (core functionality)
7 // Michael Kircher (mk1@cs.wustl.edu)
10 // This is a Visualization Component for displaying navigation.
12 // ============================================================================
19 public class NavigationVisComp
extends Panel
implements VisComp
21 private Alt_Horizon alt_hor_
= new Alt_Horizon ();
22 private Position pos_
= new Position ();
24 public NavigationVisComp ()
26 setLayout (new BorderLayout (0, 2));
27 add ("Center", alt_hor_
);
31 public void setName (String title
) {
34 public int getProperty () {
35 return Properties
.NAVIGATION
;
38 public void update (java
.util
.Observable observable
, java
.lang
.Object obj
) {
39 Navigation navigation_
= null;
41 navigation_
= (Navigation
) obj
;
43 catch (Exception excp
) {
44 System
.out
.println (excp
);
45 System
.out
.println ("Visualization Component received wrong data type!");
47 if (navigation_
!= null) {
48 // make sure all the values are in the proper range.
49 navigation_
.roll
= (navigation_
.roll
> 180 || navigation_
.roll
< -180) ?
51 navigation_
.pitch
= (navigation_
.pitch
> 90 || navigation_
.pitch
< -90) ?
52 0 : navigation_
.pitch
;
54 // update the artificial horizon
55 alt_hor_
.update_display (navigation_
.roll
, navigation_
.pitch
);
57 navigation_
.pitch
= (navigation_
.position_latitude
> 90 || navigation_
.position_latitude
< -90) ?
58 0 : navigation_
.position_latitude
;
59 navigation_
.pitch
= (navigation_
.position_longitude
> 100 || navigation_
.position_longitude
< 00) ?
60 0 : navigation_
.position_longitude
;
61 navigation_
.pitch
= (navigation_
.altitude
> 90 || navigation_
.altitude
< -90) ?
62 0 : navigation_
.altitude
;
63 navigation_
.pitch
= (navigation_
.heading
> 180 || navigation_
.heading
< -180) ?
64 0 : navigation_
.heading
;
66 // update the position display
67 pos_
.update_display (navigation_
.position_latitude
,
68 navigation_
.position_longitude
,
78 private final static Color GREEN
= new Color (0, 100, 0),
79 BLUE
= new Color (30, 144, 255);
81 private Graphics offgraphics_
;
82 private Image offscreen_
;
83 private Dimension offscreensize_
;
85 private int roll_
= 0, pitch_
= 0;
87 public void update_display (int roll
, int pitch
)
95 public Dimension
getPreferredSize ()
97 return new Dimension (180, 180);
100 public Dimension
getMinimumSize ()
102 return new Dimension (80, 80);
105 public void paint (Graphics g
)
110 public void update (Graphics g
)
112 Dimension d
= getSize ();
113 int rad
, angles
[] = { 180, 0 };
116 if ((offscreen_
== null) || (d
.width
!= offscreensize_
.width
) ||
117 (d
.height
!= offscreensize_
.height
))
119 offscreen_
= createImage (d
.width
, d
.height
);
120 offscreensize_
= new Dimension (d
.width
, d
.height
);
121 offgraphics_
= offscreen_
.getGraphics ();
122 offgraphics_
.setFont (getFont());
124 // g.setColor (Color.lightGray);
125 // g.draw3DRect (0, 0, d.width - 1, d.height - 1, true);
126 // g.draw3DRect (1, 1, d.width - 3, d.height - 3, true);
127 // g.draw3DRect (2, 2, d.width - 5, d.height - 5, true);
130 offgraphics_
.setColor (getBackground());
131 offgraphics_
.fillRect (0, 0, d
.width
, d
.height
);
132 offgraphics_
.setColor (BLUE
);
134 // Calculate from the dimensions, the largest square.
135 center
= new Point (d
.width
/ 2, d
.height
/ 2);
136 rad
= ((center
.x
< center
.y
) ? center
.x
: center
.y
);
138 // Draw a circle of blue
139 offgraphics_
.fillOval (center
.x
- rad
, center
.y
- rad
,
142 // Roll the horizon based on the roll angle
144 roll_horizon (rad
, angles
);
146 // Pitch the horizon based on the pitch angle
148 pitch_horizon (rad
, angles
);
150 // Draw the resulting terrain
151 draw_horizon (rad
, center
, angles
);
153 // Draw the plotted Image.
154 g
.drawImage (offscreen_
, 0, 0, null);
157 private void draw_horizon (int rad
, Point center
, int[] angles
)
161 ((angles
[0] > angles
[1]) ?
162 (360 - angles
[0]) + angles
[1] :
163 (angles
[1] - angles
[0]));
165 Polygon remainder
= new Polygon ();
167 offgraphics_
.setColor (GREEN
);
168 offgraphics_
.fillArc (center
.x
- rad
, center
.y
- rad
,
170 angles
[0], arc_angle
);
174 if ((pitch_
> 0 && Math
.abs (roll_
) < 90) ||
175 (pitch_
< 0 && Math
.abs (roll_
) >= 90))
176 offgraphics_
.setColor (BLUE
);
178 int cover_angle
= (angles
[0] + arc_angle
/2 + ((arc_angle
< 180) ?
180 : 0)) % 360;
180 // System.out.println (points[0] + " " + points[1]);
182 // System.out.println (accepted_point);
184 remainder
.addPoint (center
.x
+ polar_to_rect_x (rad
, cover_angle
),
185 center
.y
- polar_to_rect_y (rad
, cover_angle
));
186 remainder
.addPoint (center
.x
+ polar_to_rect_x (rad
, angles
[0]),
187 center
.y
- polar_to_rect_y (rad
, angles
[0]));
188 remainder
.addPoint (center
.x
+ polar_to_rect_x (rad
, angles
[1]),
189 center
.y
- polar_to_rect_y (rad
, angles
[1]));
190 offgraphics_
.fillPolygon (remainder
);
191 //offgraphics_.setColor (getBackground ());
192 //offgraphics_.drawPolygon (remainder);
196 private void pitch_horizon (int rad
, int[] angles
)
198 boolean upside_down
= Math
.abs (roll_
) >= 90;
199 int angle_shift
= (int) Math
.round ((double)(90 - (Math
.abs (roll_
) % 180)) / 90.0 * pitch_
);
201 // System.out.println ("angle_shift " + angle_shift);
203 angles
[0] += angle_shift
;
204 angles
[1] -= angle_shift
;
209 private void roll_horizon (int rad
, int[] angles
)
211 // Roll the left and right points of the terrain.
222 private int polar_to_rect_x (int rad
, int angle
)
224 return (int) Math
.round (rad
* Math
.cos ((double)angle
* Math
.PI
/180.0));
227 private int polar_to_rect_y (int rad
, int angle
)
229 return (int) Math
.round (rad
* Math
.sin ((double)angle
* Math
.PI
/180.0));
232 private double caclulate_slope (int rad
, int[] angles
)
234 int x1
= polar_to_rect_x (rad
, angles
[0]),
235 x2
= polar_to_rect_x (rad
, angles
[1]),
236 y1
= polar_to_rect_y (rad
, angles
[0]),
237 y2
= polar_to_rect_y (rad
, angles
[1]);
239 return ((double) (y2
- y1
)) / ((double) (x2
- x1
));
242 private Point
[] line_circle_intesect (int rad
, double y_intercept
, double slope
)
244 double r_2
= (double)(rad
* rad
),
247 b_x
= 2.0 * slope
* y_intercept
,
248 c_x
= y_intercept
* y_intercept
- r_2
;
249 int[] x_roots
= quad_eq (a_x
, b_x
, c_x
),
250 y_roots
= { (int) Math
.round ((double)((double) x_roots
[0])*slope
+ y_intercept
),
251 (int) Math
.round ((double)((double) x_roots
[1])*slope
+ y_intercept
) };
252 Point
[] points
= new Point
[2];
254 points
[0] = new Point (x_roots
[0], y_roots
[0]);
255 points
[1] = new Point (x_roots
[1], y_roots
[1]);
260 private int calculate_angle (int rad
, int x
, int y
)
264 sin_value = Math.asin ((double)y / (double)rad),
265 tan_value = Math.atan ((double)y / (double)x);
268 angle = (x != 0) ? tan_value : sin_value +
269 ((y < 0) ? 2*Math.PI : 0);
271 angle = Math.PI + tan_value;
273 return (int) Math.round (angle * 180.0 / Math.PI);
277 sin_value
= Math
.asin ((double)Math
.abs (y
) / (double)rad
);
279 if (x
>= 0 && y
>= 0)
281 else if (x
< 0 && y
>= 0)
282 angle
= sin_value
+ Math
.PI
/2.0;
283 else if (x
< 0 && y
< 0)
284 angle
= sin_value
+ Math
.PI
;
285 else if (x
>= 0 && y
< 0)
286 angle
= sin_value
+ 3.0*Math
.PI
/2.0;
288 return (int) Math
.round (angle
* 180.0 / Math
.PI
);
291 private int[] quad_eq (double a
, double b
, double c
)
293 int[] roots
= new int [2];
294 double body
= Math
.sqrt (b
*b
- 4.0*a
*c
);
296 roots
[0] = (int) Math
.round ((-b
+ body
) / (2.0 * a
));
297 roots
[1] = (int) Math
.round ((-b
- body
) / (2.0 * a
));
302 private int distance (Point point1
, Point point2
)
304 double xdiff
= point1
.x
- point2
.x
,
305 ydiff
= point1
.y
- point2
.y
;
307 return (int) Math
.round (Math
.sqrt (xdiff
*xdiff
+ ydiff
*ydiff
));
311 class Position
extends Panel
313 private final static Font FONT
= new Font ("Dialog", Font
.BOLD
, 12);
314 private final static char DEGREE
= '\u00B0';
316 private Label lat_
= new Label ("0" + DEGREE
+ " N", Label
.RIGHT
),
317 long_
= new Label ("0" + DEGREE
+ " S", Label
.RIGHT
),
318 alt_
= new Label ("0 Kft", Label
.RIGHT
),
319 heading_
= new Label ("0" + DEGREE
+ " ", Label
.RIGHT
);
323 Panel grid_panel
= new Panel ();
326 long_
.setFont (FONT
);
328 heading_
.setFont (FONT
);
330 setLayout (new GridLayout (1, 4));
337 public void update_display (int lat
, int lon
, int alt
, int heading
)
340 Math
.abs (lat
) + "" + DEGREE
+ ((lat
> 0) ?
" N" : " S");
342 Math
.abs (lon
) + "" + DEGREE
+ ((lon
> 0) ?
" E" : " W");
344 lat_
.setText (lat_str
);
345 long_
.setText (long_str
);
346 alt_
.setText (alt
+ " Kft");
347 heading_
.setText (heading
+ "" + DEGREE
+ " ");