altosuilib: Add distance measuring line to site map.
authorKeith Packard <keithp@keithp.com>
Tue, 27 May 2014 22:39:13 +0000 (15:39 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 27 May 2014 22:39:13 +0000 (15:39 -0700)
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 <keithp@keithp.com>
altosuilib/AltosSiteMap.java
altosuilib/AltosSiteMapCache.java
altosuilib/AltosSiteMapTile.java
altosuilib/GrabNDrag.java

index f4143fe2433d84fbdcfeb072daee35f19772381e..f22d9531848acd4d87be60ae4b5ed06946e7d155 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.lang.Math;
 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.*;
 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
        // 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<Point,AltosSiteMapTile> mapTiles = new ConcurrentHashMap<Point,AltosSiteMapTile>();
        Point2D.Double centre;
 
        ConcurrentHashMap<Point,AltosSiteMapTile> mapTiles = new ConcurrentHashMap<Point,AltosSiteMapTile>();
        Point2D.Double centre;
 
@@ -307,16 +311,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                base_location_set = false;
                circle_set = false;
                points = new LinkedList<MapPoint>();
                base_location_set = false;
                circle_set = false;
                points = new LinkedList<MapPoint>();
-               for (AltosSiteMapTile tile : mapTiles.values())
-                       tile.clearMap();
+               line_start = line_end = null;
        }
 
        public void setBaseLocation(double lat, double lng) {
        }
 
        public void setBaseLocation(double lat, double lng) {
+               for (AltosSiteMapTile tile : mapTiles.values())
+                       tile.clearMap();
                this.lat = lat;
                this.lon = lng;
                base_location_set = true;
                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));
 
                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 (circle_set)
                        draw_circle(circle_lat, circle_lon);
+               if (line_start != null)
+                       set_line();
        }
 
        public void show(final AltosState state, final AltosListenerState listener_state) {
        }
 
        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();
 
        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;
 
        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);
                GrabNDrag scroller = new GrabNDrag(comp);
 
                comp.setLayout(layout);
index acc84ab081a115f7ed47e8eefe4db8222c074451..42914debf78412d6cb8a8d4ef811450e7a944d9b 100644 (file)
@@ -91,7 +91,7 @@ public class AltosSiteMapCache {
        static final int        bad_request = 3;
        static final int        forbidden = 4;
 
        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();
        }
 
                return file.exists();
        }
 
@@ -182,7 +182,7 @@ public class AltosSiteMapCache {
 
        static long                     used;
 
 
        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;
                int             oldest = -1;
                long            age = used;
                AltosCacheImage image;
index 9610b248c994e5856dc5cb446e8fb41b6913e49a..09f184a37869cf121f19e3f556b535f10ca7e4ea 100644 (file)
@@ -44,6 +44,9 @@ public class AltosSiteMapTile extends JComponent {
 
        Point2D.Double  boost;
        Point2D.Double  landed;
 
        Point2D.Double  boost;
        Point2D.Double  landed;
+       Line2D.Double   line;
+       double          line_course;
+       double          line_dist;
 
        LinkedList<AltosPoint>  points;
 
 
        LinkedList<AltosPoint>  points;
 
@@ -81,6 +84,7 @@ public class AltosSiteMapTile extends JComponent {
                file = null;
                status = AltosSiteMapCache.success;
                queue_repaint();
                file = null;
                status = AltosSiteMapCache.success;
                queue_repaint();
+               line = null;
        }
 
        static Color stateColors[] = {
        }
 
        static Color stateColors[] = {
@@ -106,6 +110,47 @@ public class AltosSiteMapTile extends JComponent {
                queue_repaint();
        }
 
                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;
        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;
                                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);
                        }
                                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);
                }
                        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)
        }
 
        public synchronized void show(int state, Point2D.Double last_pt, Point2D.Double pt)
index 5e5fdd5297b1930955c217f883ae7d1102b08087..4426f7a3de35fe436ae2d9211c4af350ed4c6ebe 100644 (file)
@@ -33,16 +33,23 @@ class GrabNDrag extends MouseInputAdapter {
                scroll.setAutoscrolls(true);
        }
 
                scroll.setAutoscrolls(true);
        }
 
+       public static boolean grab_n_drag(MouseEvent e) {
+               return e.getModifiers() == InputEvent.BUTTON1_MASK;
+       }
+
        public void mousePressed(MouseEvent e) {
        public void mousePressed(MouseEvent e) {
-               startPt.setLocation(e.getPoint());
+               if (grab_n_drag(e))
+                       startPt.setLocation(e.getPoint());
        }
        public void mouseDragged(MouseEvent e) {
        }
        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);
+               }
        }
 }
        }
 }