From: Keith Packard Date: Tue, 27 May 2014 22:39:13 +0000 (-0700) Subject: altosuilib: Add distance measuring line to site map. X-Git-Tag: 1.3.2.2~66 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=8e44580cbe978f1570d4d2ac13d3dd7cd470ecf7;ds=sidebyside altosuilib: Add distance measuring line to site map. Use any modifier or button other than the left one to draw a line on the map. The length of the line is shown at the start of the line. Signed-off-by: Keith Packard --- diff --git a/altosuilib/AltosSiteMap.java b/altosuilib/AltosSiteMap.java index f4143fe2..f22d9531 100644 --- a/altosuilib/AltosSiteMap.java +++ b/altosuilib/AltosSiteMap.java @@ -22,7 +22,7 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.lang.Math; -import java.awt.geom.Point2D; +import java.awt.geom.*; import java.util.*; import java.util.concurrent.*; import org.altusmetrum.altoslib_4.*; @@ -50,7 +50,7 @@ class MapPoint { } } -public class AltosSiteMap extends JComponent implements AltosFlightDisplay { +public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener { // preferred vertical step in a tile in naut. miles // will actually choose a step size between x and 2x, where this // is 1.5x @@ -160,6 +160,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } */ + private LatLng latlng(Point pt) { + return latlng(new Point2D.Double(pt.x, pt.y), scale_x, scale_y); + } + ConcurrentHashMap mapTiles = new ConcurrentHashMap(); Point2D.Double centre; @@ -307,16 +311,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { base_location_set = false; circle_set = false; points = new LinkedList(); - for (AltosSiteMapTile tile : mapTiles.values()) - tile.clearMap(); + line_start = line_end = null; } public void setBaseLocation(double lat, double lng) { + for (AltosSiteMapTile tile : mapTiles.values()) + tile.clearMap(); this.lat = lat; this.lon = lng; base_location_set = true; - for (AltosSiteMapTile tile : mapTiles.values()) - tile.clearMap(); centre = getBaseLocation(lat, lng); scrollRocketToVisible(pt(lat,lng)); @@ -442,6 +445,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } if (circle_set) draw_circle(circle_lat, circle_lon); + if (line_start != null) + set_line(); } public void show(final AltosState state, final AltosListenerState listener_state) { @@ -598,14 +603,85 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } } - JComponent comp = new JComponent() { }; + JComponent comp; + private GridBagLayout layout = new GridBagLayout(); + LatLng line_start, line_end; + + private void set_line() { + if (line_start != null && line_end != null) { + Point2D.Double start = pt(line_start.lat, line_start.lng); + Point2D.Double end = pt(line_end.lat, line_end.lng); + AltosGreatCircle g = new AltosGreatCircle(line_start.lat, line_start.lng, + line_end.lat, line_end.lng); + + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double s, e; + s = translatePoint(start, tileCoordOffset(offset)); + e = translatePoint(end, tileCoordOffset(offset)); + tile.set_line(new Line2D.Double(s.x, s.y, e.x, e.y), g.distance); + } + } else { + for (AltosSiteMapTile tile : mapTiles.values()) + tile.set_line(null, 0); + } + } + + LatLng latlng(MouseEvent e) { + if (!base_location_set) + return null; + + Rectangle zerozero = mapTiles.get(new Point(0, 0)).getBounds(); + + return latlng(-centre.x + e.getPoint().x - zerozero.x, -centre.y + e.getPoint().y - zerozero.y); + } + + /* MouseMotionListener methods */ + public void mouseDragged(MouseEvent e) { + if (!GrabNDrag.grab_n_drag(e)) { + LatLng loc = latlng(e); + line_end = loc; + set_line(); + } + } + + public void mouseMoved(MouseEvent e) { + } + + /* MouseListener methods */ + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + if (!GrabNDrag.grab_n_drag(e)) { + LatLng loc = latlng(e); + line_start = loc; + line_end = null; + set_line(); + } + } + + public void mouseReleased(MouseEvent e) { + } + JScrollPane pane = new JScrollPane(); public AltosSiteMap(int in_radius) { radius = in_radius; + comp = new JComponent() { }; + + comp.addMouseMotionListener(this); + comp.addMouseListener(this); + GrabNDrag scroller = new GrabNDrag(comp); comp.setLayout(layout); diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index acc84ab0..42914deb 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -91,7 +91,7 @@ public class AltosSiteMapCache { static final int bad_request = 3; static final int forbidden = 4; - public static synchronized boolean has_map(File file, String url) { + public static boolean has_map(File file, String url) { return file.exists(); } @@ -182,7 +182,7 @@ public class AltosSiteMapCache { static long used; - public static synchronized Image get_image(Component component, File file, int width, int height) { + public static Image get_image(Component component, File file, int width, int height) { int oldest = -1; long age = used; AltosCacheImage image; diff --git a/altosuilib/AltosSiteMapTile.java b/altosuilib/AltosSiteMapTile.java index 9610b248..09f184a3 100644 --- a/altosuilib/AltosSiteMapTile.java +++ b/altosuilib/AltosSiteMapTile.java @@ -44,6 +44,9 @@ public class AltosSiteMapTile extends JComponent { Point2D.Double boost; Point2D.Double landed; + Line2D.Double line; + double line_course; + double line_dist; LinkedList points; @@ -81,6 +84,7 @@ public class AltosSiteMapTile extends JComponent { file = null; status = AltosSiteMapCache.success; queue_repaint(); + line = null; } static Color stateColors[] = { @@ -106,6 +110,47 @@ public class AltosSiteMapTile extends JComponent { queue_repaint(); } + public void set_line(Line2D.Double line, double distance) { + this.line = line; + line_dist = distance; + queue_repaint(); + } + + private String line_dist() { + String format; + double distance = line_dist; + + if (AltosConvert.imperial_units) { + distance = AltosConvert.meters_to_feet(distance); + if (distance < 10000) { + format = "%4.0fft"; + } else { + distance /= 5280; + if (distance < 10) + format = "%5.3fmi"; + else if (distance < 100) + format = "%5.2fmi"; + else if (distance < 1000) + format = "%5.1fmi"; + else + format = "%5.0fmi"; + } + } else { + if (distance < 10000) { + format = "%4.0fm"; + } else { + distance /= 1000; + if (distance < 100) + format = "%5.2fkm"; + else if (distance < 1000) + format = "%5.1fkm"; + else + format = "%5.0fkm"; + } + } + return String.format(format, distance); + } + public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; AltosPoint prev = null; @@ -143,7 +188,7 @@ public class AltosSiteMapTile extends JComponent { float x = getWidth() / 2.0f; float y = getHeight() / 2.0f; x = x - (float) bounds.getWidth() / 2.0f; - y = y - (float) bounds.getHeight() / 2.0f; + y = y + (float) bounds.getHeight() / 2.0f; g2d.setColor(Color.BLACK); g2d.drawString(message, x, y); } @@ -171,6 +216,27 @@ public class AltosSiteMapTile extends JComponent { g2d.setColor(Color.BLACK); draw_circle(g2d, landed); } + + if (line != null) { + g2d.setColor(Color.BLUE); + g2d.draw(line); + + String message = line_dist(); + g2d.setFont(font); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + Rectangle2D bounds; + bounds = font.getStringBounds(message, g2d.getFontRenderContext()); + + float x = (float) line.x1; + float y = (float) line.y1 + (float) bounds.getHeight() / 2.0f; + + if (line.x1 < line.x2) { + x -= (float) bounds.getWidth() + 2.0f; + } else { + x += 2.0f; + } + g2d.drawString(message, x, y); + } } public synchronized void show(int state, Point2D.Double last_pt, Point2D.Double pt) diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java index 5e5fdd52..4426f7a3 100644 --- a/altosuilib/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -33,16 +33,23 @@ class GrabNDrag extends MouseInputAdapter { scroll.setAutoscrolls(true); } + public static boolean grab_n_drag(MouseEvent e) { + return e.getModifiers() == InputEvent.BUTTON1_MASK; + } + public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); + if (grab_n_drag(e)) + startPt.setLocation(e.getPoint()); } public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; + if (grab_n_drag(e)) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } } }