* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_12;
+package org.altusmetrum.altosuilib_14;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.concurrent.*;
import javax.imageio.*;
-import org.altusmetrum.altoslib_12.*;
+import org.altusmetrum.altoslib_14.*;
public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosMapInterface {
Graphics2D g;
Font tile_font;
Font line_font;
+ AltosMapMark nearest_mark;
static Point2D.Double point2d(AltosPointDouble pt) {
return new Point2D.Double(pt.x, pt.y);
class MapMark extends AltosMapMark {
public void paint(AltosMapTransform t) {
- AltosPointDouble pt = t.screen(lat_lon);
-
- g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-
- if (0 <= state && state < AltosUIMap.stateColors.length)
- g.setColor(AltosUIMap.stateColors[state]);
- else
- g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+ double lat = lat_lon.lat;
+ double lon;
+ double first_lon = t.first_lon(lat_lon.lon);
+ double last_lon = t.last_lon(lat_lon.lon);
+ for (lon = first_lon; lon <= last_lon; lon += 360.0) {
+ AltosPointDouble pt = t.screen(lat, lon);
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+
+ if (0 <= state && state < AltosUIMap.stateColors.length)
+ g.setColor(AltosUIMap.stateColors[state]);
+ else
+ g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+
+ g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
+ g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
+ g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+
+ if (label != null) {
+ Rectangle2D bounds;
+ bounds = line_font.getStringBounds(label, g.getFontRenderContext());
+ float x = (float) pt.x;
+ float y = (float) pt.y + (float) bounds.getHeight() / 2.0f;
+
+ g.setFont(line_font);
+ g.setColor(Color.WHITE);
+ for (int dy = -2; dy <= 2; dy += 2)
+ for (int dx = -2; dx <= 2; dx += 2)
+ g.drawString(label, x + dx, y + dy);
+ if (0 <= state && state < AltosUIMap.stateColors.length)
+ g.setColor(AltosUIMap.stateColors[state]);
+ else
+ g.setColor(AltosUIMap.stateColors[AltosLib.ao_flight_invalid]);
+ g.drawString(label, x, y);
+ }
+ }
+ }
- g.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
- g.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
- g.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+ MapMark(double lat, double lon, int state, String label) {
+ super(lat, lon, state, label);
}
MapMark(double lat, double lon, int state) {
}
private boolean is_drag_event(MouseEvent e) {
- return e.getModifiers() == InputEvent.BUTTON1_MASK;
+ return e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK;
}
/* MouseMotionListener methods */
map.touch_continue(e.getPoint().x, e.getPoint().y, is_drag_event(e));
}
+ String pos(double p, String pos, String neg) {
+ if (p == AltosLib.MISSING)
+ return "";
+ String h = pos;
+ if (p < 0) {
+ h = neg;
+ p = -p;
+ }
+ int deg = (int) Math.floor(p);
+ double min = (p - Math.floor(p)) * 60.0;
+ return String.format("%s %4d° %9.6f'", h, deg, min);
+ }
+
+ String height(double h, String label) {
+ if (h == AltosLib.MISSING)
+ return "";
+ return String.format(" %s%s",
+ AltosConvert.height.show(6, h),
+ label);
+ }
+
+ String speed(double s, String label) {
+ if (s == AltosLib.MISSING)
+ return "";
+ return String.format(" %s%s",
+ AltosConvert.speed.show(6, s),
+ label);
+ }
+
public void mouseMoved(MouseEvent e) {
+ AltosMapPathPoint point = map.nearest(e.getPoint().x, e.getPoint().y);
+
+ if (point != null) {
+ if (nearest_mark == null)
+ nearest_mark = map.add_mark(point.gps.lat,
+ point.gps.lon,
+ point.state);
+ else {
+ nearest_mark.lat_lon.lat = point.gps.lat;
+ nearest_mark.lat_lon.lon = point.gps.lon;
+ nearest_mark.state = point.state;
+ }
+ nearest_label.setText(String.format("%9.2f sec %s%s%s%s",
+ point.time,
+ pos(point.gps.lat,
+ "N", "S"),
+ pos(point.gps.lon,
+ "E", "W"),
+ height(point.gps_height, ""),
+ speed(point.gps.ground_speed, "(h)"),
+ speed(point.gps.climb_rate, "(v)")));
+ } else {
+ nearest_label.setText("");
+ }
+ repaint();
}
/* MouseListener methods */
g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
for (AltosMapPathPoint point : points) {
- Point2D.Double cur = point2d(t.screen(point.lat_lon));
+ Point2D.Double cur = point2d(t.screen(point.gps.lat, point.gps.lon));
if (prev != null) {
Line2D.Double line = new Line2D.Double (prev, cur);
Rectangle bounds = line.getBounds();
if (image != null) {
g.drawImage(image, point.x, point.y, null);
+/*
+ * Useful when debugging map fetching problems
+ *
+ String message = String.format("%.6f %.6f", center.lat, center.lon);
+ g.setFont(tile_font);
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ Rectangle2D bounds = tile_font.getStringBounds(message, g.getFontRenderContext());
+
+ float x = px_size / 2.0f;
+ float y = px_size / 2.0f;
+ x = x - (float) bounds.getWidth() / 2.0f;
+ y = y + (float) bounds.getHeight() / 2.0f;
+ g.setColor(Color.RED);
+ g.drawString(message, (float) point_double.x + x, (float) point_double.y + y);
+*/
} else {
g.setColor(Color.GRAY);
g.fillRect(point.x, point.y, px_size, px_size);
message = "Internal error";
break;
case AltosMapTile.failed:
- message = "Network error, check connection";
+ message = "Network error";
break;
case AltosMapTile.forbidden:
- message = "Too many requests, try later";
+ message = "Outside of known launch areas";
break;
}
if (message != null && tile_font != null) {
return new MapMark(lat, lon, state);
}
+ public AltosMapMark new_mark(double lat, double lon, int state, String label) {
+ return new MapMark(lat, lon, state, label);
+ }
+
public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
return new MapTile(cache, upper_left, center, zoom, maptype, px_size, scale);
}
public void set_font() {
tile_font = AltosUILib.value_font;
line_font = AltosUILib.status_font;
+ if (nearest_label != null)
+ nearest_label.setFont(AltosUILib.value_font);
}
public void font_size_changed(int font_size) {
JLabel zoom_label;
+ JLabel nearest_label;
+
public void set_maptype(int type) {
+/*
map.set_maptype(type);
maptype_combo.setSelectedIndex(type);
+*/
}
/* AltosUIMapPreload functions */
map.add_mark(lat, lon, status);
}
+ public void add_mark(double lat, double lon, int status, String label) {
+ map.add_mark(lat, lon, status, label);
+ }
+
public void clear_marks() {
map.clear_marks();
}
map.show(state, listener_state);
}
- public void show(AltosGPS gps, int state) {
- map.show(gps, state);
+ public void show(AltosGPS gps, double time, int state, double gps_height) {
+ map.show(gps, time, state, gps_height);
}
public String getName() {
/* internal layout bits */
private GridBagLayout layout = new GridBagLayout();
+/*
JComboBox<String> maptype_combo;
+*/
MapView view;
c.weighty = 0;
add(zoom_out, c);
+
+ nearest_label = new JLabel("", JLabel.LEFT);
+ nearest_label.setFont(tile_font);
+
+ c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 0;
+ c.gridy = 11;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ add(nearest_label, c);
+/*
maptype_combo = new JComboBox<String>(map.maptype_labels);
maptype_combo.setEditable(false);
c.weightx = 0;
c.weighty = 0;
add(maptype_combo, c);
-
+*/
map = new AltosMap(this);
}
}