Ticket #6834: patch.diff

File patch.diff, 39.5 KB (added by Don-vip, 14 years ago)
  • src/org/openstreetmap/gui/jmapviewer/JMapViewer.java

     
    2727import javax.swing.event.ChangeListener;
    2828
    2929import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
     30import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
    3031import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
    3132import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
    3233import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
     
    5657
    5758    protected List<MapMarker> mapMarkerList;
    5859    protected List<MapRectangle> mapRectangleList;
     60    protected List<MapPolygon> mapPolygonList;
    5961
    6062    protected boolean mapMarkersVisible;
    6163    protected boolean mapRectanglesVisible;
     64    protected boolean mapPolygonsVisible;
    6265
    6366    protected boolean tileGridVisible;
    6467
     
    115118        tileController = new TileController(tileSource, tileCache, this);
    116119        mapMarkerList = new LinkedList<MapMarker>();
    117120        mapRectangleList = new LinkedList<MapRectangle>();
     121        mapPolygonList = new LinkedList<MapPolygon>();
    118122        mapMarkersVisible = true;
    119123        mapRectanglesVisible = true;
     124        mapPolygonsVisible = true;
    120125        tileGridVisible = false;
    121126        setLayout(null);
    122127        initializeZoomSlider();
     
    246251    }
    247252
    248253    /**
    249      * Sets the displayed map pane and zoom level so that all map markers are
     254     * Sets the displayed map pane and zoom level so that all chosen map elements are
    250255     * visible.
    251256     */
    252     public void setDisplayToFitMapMarkers() {
    253         if (mapMarkerList == null || mapMarkerList.size() == 0)
     257    public void setDisplayToFitMapElements(boolean markers, boolean rectangles, boolean polygons) {
     258        int nbElemToCheck = 0;
     259        if (markers && mapMarkerList != null)
     260            nbElemToCheck += mapMarkerList.size();
     261        if (rectangles && mapRectangleList != null)
     262            nbElemToCheck += mapRectangleList.size();
     263        if (polygons && mapPolygonList != null)
     264            nbElemToCheck += mapPolygonList.size();
     265        if (nbElemToCheck == 0)
    254266            return;
     267       
    255268        int x_min = Integer.MAX_VALUE;
    256269        int y_min = Integer.MAX_VALUE;
    257270        int x_max = Integer.MIN_VALUE;
    258271        int y_max = Integer.MIN_VALUE;
    259272        int mapZoomMax = tileController.getTileSource().getMaxZoom();
    260         for (MapMarker marker : mapMarkerList) {
    261             int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
    262             int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
    263             x_max = Math.max(x_max, x);
    264             y_max = Math.max(y_max, y);
    265             x_min = Math.min(x_min, x);
    266             y_min = Math.min(y_min, y);
     273       
     274        if (markers) {
     275            for (MapMarker marker : mapMarkerList) {
     276                int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
     277                int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
     278                x_max = Math.max(x_max, x);
     279                y_max = Math.max(y_max, y);
     280                x_min = Math.min(x_min, x);
     281                y_min = Math.min(y_min, y);
     282            }
    267283        }
     284       
     285        if (rectangles) {
     286            for (MapRectangle rectangle : mapRectangleList) {
     287                x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
     288                y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
     289                x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
     290                y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
     291            }
     292        }
     293       
     294        if (polygons) {
     295            for (MapPolygon polygon : mapPolygonList) {
     296                for (Coordinate c : polygon.getPoints()) {
     297                    int x = OsmMercator.LonToX(c.getLon(), mapZoomMax);
     298                    int y = OsmMercator.LatToY(c.getLat(), mapZoomMax);
     299                    x_max = Math.max(x_max, x);
     300                    y_max = Math.max(y_max, y);
     301                    x_min = Math.min(x_min, x);
     302                    y_min = Math.min(y_min, y);
     303                }
     304            }
     305        }
     306       
    268307        int height = Math.max(0, getHeight());
    269308        int width = Math.max(0, getWidth());
    270         // System.out.println(x_min + " < x < " + x_max);
    271         // System.out.println(y_min + " < y < " + y_max);
    272         // System.out.println("tiles: " + width + " " + height);
    273309        int newZoom = mapZoomMax;
    274310        int x = x_max - x_min;
    275311        int y = y_max - y_min;
    276312        while (x > width || y > height) {
    277             // System.out.println("zoom: " + zoom + " -> " + x + " " + y);
    278313            newZoom--;
    279314            x >>= 1;
    280315            y >>= 1;
     
    286321        y /= z;
    287322        setDisplayPosition(x, y, newZoom);
    288323    }
    289 
     324   
    290325    /**
    291326     * Sets the displayed map pane and zoom level so that all map markers are
    292327     * visible.
    293328     */
    294     public void setDisplayToFitMapRectangle() {
    295         if (mapRectangleList == null || mapRectangleList.size() == 0)
    296             return;
    297         int x_min = Integer.MAX_VALUE;
    298         int y_min = Integer.MAX_VALUE;
    299         int x_max = Integer.MIN_VALUE;
    300         int y_max = Integer.MIN_VALUE;
    301         int mapZoomMax = tileController.getTileSource().getMaxZoom();
    302         for (MapRectangle rectangle : mapRectangleList) {
    303             x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
    304             y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
    305             x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
    306             y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
    307         }
    308         int height = Math.max(0, getHeight());
    309         int width = Math.max(0, getWidth());
    310         // System.out.println(x_min + " < x < " + x_max);
    311         // System.out.println(y_min + " < y < " + y_max);
    312         // System.out.println("tiles: " + width + " " + height);
    313         int newZoom = mapZoomMax;
    314         int x = x_max - x_min;
    315         int y = y_max - y_min;
    316         while (x > width || y > height) {
    317             // System.out.println("zoom: " + zoom + " -> " + x + " " + y);
    318             newZoom--;
    319             x >>= 1;
    320             y >>= 1;
    321         }
    322         x = x_min + (x_max - x_min) / 2;
    323         y = y_min + (y_max - y_min) / 2;
    324         int z = 1 << (mapZoomMax - newZoom);
    325         x /= z;
    326         y /= z;
    327         setDisplayPosition(x, y, newZoom);
     329    public void setDisplayToFitMapMarkers() {
     330        setDisplayToFitMapElements(true, false, false);
    328331    }
    329332
    330333    /**
     334     * Sets the displayed map pane and zoom level so that all map rectangles are
     335     * visible.
     336     */
     337    public void setDisplayToFitMapRectangles() {
     338        setDisplayToFitMapElements(false, true, false);
     339    }
     340   
     341    /**
     342     * Sets the displayed map pane and zoom level so that all map polygons are
     343     * visible.
     344     */
     345    public void setDisplayToFitMapPolygons() {
     346        setDisplayToFitMapElements(false, false, true);
     347    }
     348
     349    /**
    331350     * Calculates the latitude/longitude coordinate of the center of the
    332351     * currently displayed map area.
    333352     *
     
    506525
    507526        // g.drawString("Tiles in cache: " + tileCache.getTileCount(), 50, 20);
    508527
     528        if (mapPolygonsVisible && mapPolygonList != null) {
     529            for (MapPolygon polygon : mapPolygonList) {
     530                paintPolygon(g, polygon);
     531            }
     532        }
     533
    509534        if (mapRectanglesVisible && mapRectangleList != null) {
    510535            for (MapRectangle rectangle : mapRectangleList) {
    511                 Coordinate topLeft = rectangle.getTopLeft();
    512                 Coordinate bottomRight = rectangle.getBottomRight();
    513                 if (topLeft != null && bottomRight != null) {
    514                     Point pTopLeft = getMapPosition(topLeft.getLat(), topLeft.getLon(), false);
    515                     Point pBottomRight = getMapPosition(bottomRight.getLat(), bottomRight.getLon(), false);
    516                     if (pTopLeft != null && pBottomRight != null) {
    517                         rectangle.paint(g, pTopLeft, pBottomRight);
    518                     }
    519                 }
     536                paintRectangle(g, rectangle);
    520537            }
    521538        }
    522539
     
    525542                paintMarker(g, marker);
    526543            }
    527544        }
     545       
    528546        paintAttribution(g);
    529547    }
    530548
     
    539557    }
    540558
    541559    /**
     560     * Paint a single rectangle.
     561     */
     562    protected void paintRectangle(Graphics g, MapRectangle rectangle) {
     563        Coordinate topLeft = rectangle.getTopLeft();
     564        Coordinate bottomRight = rectangle.getBottomRight();
     565        if (topLeft != null && bottomRight != null) {
     566            Point pTopLeft = getMapPosition(topLeft, false);
     567            Point pBottomRight = getMapPosition(bottomRight, false);
     568            if (pTopLeft != null && pBottomRight != null) {
     569                rectangle.paint(g, pTopLeft, pBottomRight);
     570            }
     571        }
     572    }
     573
     574    /**
     575     * Paint a single polygon.
     576     */
     577    protected void paintPolygon(Graphics g, MapPolygon polygon) {
     578        List<Coordinate> coords = polygon.getPoints();
     579        if (coords != null && coords.size() >= 3) {
     580            List<Point> points = new LinkedList<Point>();
     581            for (Coordinate c : coords) {
     582                Point p = getMapPosition(c, false);
     583                if (p == null) {
     584                    return;
     585                }
     586                points.add(p);
     587            }
     588            polygon.paint(g, points);
     589        }
     590    }
     591   
     592    /**
    542593     * Moves the visible map pane.
    543594     *
    544595     * @param x
     
    660711        return mapRectangleList;
    661712    }
    662713
     714    public void setMapPolygonList(List<MapPolygon> mapPolygonList) {
     715        this.mapPolygonList = mapPolygonList;
     716        repaint();
     717    }
     718
     719    public List<MapPolygon> getMapPolygonList() {
     720        return mapPolygonList;
     721    }
     722
    663723    public void addMapMarker(MapMarker marker) {
    664724        mapMarkerList.add(marker);
    665725        repaint();
     
    690750        repaint();
    691751    }
    692752
     753    public void addMapPolygon(MapPolygon polygon) {
     754        mapPolygonList.add(polygon);
     755        repaint();
     756    }
     757
     758    public void removeMapPolygon(MapPolygon polygon) {
     759        mapPolygonList.remove(polygon);
     760        repaint();
     761    }
     762
     763    public void removeAllMapPolygons() {
     764        mapPolygonList.clear();
     765        repaint();
     766    }
     767   
    693768    public void setZoomContolsVisible(boolean visible) {
    694769        zoomSlider.setVisible(visible);
    695770        zoomInButton.setVisible(visible);
     
    735810    /**
    736811     * Enables or disables painting of the {@link MapRectangle}
    737812     *
    738      * @param mapMarkersVisible
     813     * @param mapRectanglesVisible
    739814     * @see #addMapRectangle(MapRectangle)
    740815     * @see #getMapRectangleList()
    741816     */
     
    744819        repaint();
    745820    }
    746821
     822    public boolean isMapPolygonsVisible() {
     823        return mapPolygonsVisible;
     824    }
     825
     826    /**
     827     * Enables or disables painting of the {@link MapPolygon}
     828     *
     829     * @param mapPolygonsVisible
     830     * @see #addMapPolygon(MapPolygon)
     831     * @see #getMapPolygonList()
     832     */
     833    public void setMapPolygonsVisible(boolean mapPolygonsVisible) {
     834        this.mapPolygonsVisible = mapPolygonsVisible;
     835        repaint();
     836    }
     837
    747838    /*
    748839     * (non-Javadoc)
    749840     *
  • src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.gui.jmapviewer;
     3
     4import java.awt.BasicStroke;
     5import java.awt.Color;
     6import java.awt.Graphics;
     7import java.awt.Graphics2D;
     8import java.awt.Point;
     9import java.awt.Polygon;
     10import java.awt.Stroke;
     11import java.util.List;
     12
     13import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
     14
     15/**
     16 * @author Vincent
     17 *
     18 */
     19public class MapPolygonImpl implements MapPolygon {
     20
     21    private List<Coordinate> points;
     22    private Color color;
     23    private Stroke stroke;
     24
     25    public MapPolygonImpl(List<Coordinate> points) {
     26        this(points, Color.BLUE, new BasicStroke(2));
     27    }
     28
     29    public MapPolygonImpl(List<Coordinate> points, Color color, Stroke stroke) {
     30        this.points = points;
     31        this.color = color;
     32        this.stroke = stroke;
     33    }
     34
     35    /* (non-Javadoc)
     36     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#getPoints()
     37     */
     38    @Override
     39    public List<Coordinate> getPoints() {
     40        return this.points;
     41    }
     42
     43    /* (non-Javadoc)
     44     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.util.List)
     45     */
     46    @Override
     47    public void paint(Graphics g, List<Point> points) {
     48        Polygon polygon = new Polygon();
     49        for (Point p : points) {
     50            polygon.addPoint(p.x, p.y);
     51        }
     52        paint(g, polygon);
     53    }
     54
     55    /* (non-Javadoc)
     56     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.awt.Polygon)
     57     */
     58    @Override
     59    public void paint(Graphics g, Polygon polygon) {
     60        // Prepare graphics
     61        Color oldColor = g.getColor();
     62        g.setColor(color);
     63        Stroke oldStroke = null;
     64        if (g instanceof Graphics2D) {
     65            Graphics2D g2 = (Graphics2D) g;
     66            oldStroke = g2.getStroke();
     67            g2.setStroke(stroke);
     68        }
     69        // Draw
     70        g.drawPolygon(polygon);
     71        // Restore graphics
     72        g.setColor(oldColor);
     73        if (g instanceof Graphics2D) {
     74            ((Graphics2D) g).setStroke(oldStroke);
     75        }
     76    }
     77
     78    /* (non-Javadoc)
     79     * @see java.lang.Object#toString()
     80     */
     81    @Override
     82    public String toString() {
     83        return "MapPolygon [points=" + points + "]";
     84    }
     85}
  • src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.gui.jmapviewer;
    33
     4import java.awt.BasicStroke;
    45import java.awt.Color;
    56import java.awt.Graphics;
     7import java.awt.Graphics2D;
    68import java.awt.Point;
     9import java.awt.Stroke;
    710
    811import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
    912import org.openstreetmap.josm.data.Bounds;
     
    1619
    1720    private Coordinate topLeft;
    1821    private Coordinate bottomRight;
    19     Color color;
     22    private Color color;
     23    private Stroke stroke;
    2024
    2125    public MapRectangleImpl(Bounds bounds) {
    22         this(bounds, Color.BLUE);
     26        this(bounds, Color.BLUE, new BasicStroke(2));
    2327    }
    2428
    25     public MapRectangleImpl(Bounds bounds, Color color) {
     29    public MapRectangleImpl(Bounds bounds, Color color, Stroke stroke) {
    2630        this.topLeft = new Coordinate(bounds.getMax().lat(), bounds.getMin().lon());
    2731        this.bottomRight = new Coordinate(bounds.getMin().lat(), bounds.getMax().lon());
    2832        this.color = color;
     33        this.stroke = stroke;
    2934    }
    3035
    3136    /* (non-Javadoc)
     
    4954     */
    5055    @Override
    5156    public void paint(Graphics g, Point topLeft, Point bottomRight) {
     57        // Prepare graphics
     58        Color oldColor = g.getColor();
    5259        g.setColor(color);
     60        Stroke oldStroke = null;
     61        if (g instanceof Graphics2D) {
     62            Graphics2D g2 = (Graphics2D) g;
     63            oldStroke = g2.getStroke();
     64            g2.setStroke(stroke);
     65        }
     66        // Draw
    5367        g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
     68        // Restore graphics
     69        g.setColor(oldColor);
     70        if (g instanceof Graphics2D) {
     71            ((Graphics2D) g).setStroke(oldStroke);
     72        }
    5473    }
    5574
    5675    @Override
  • src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.gui.jmapviewer.interfaces;
     3
     4import java.awt.Graphics;
     5import java.awt.Point;
     6import java.awt.Polygon;
     7import java.util.List;
     8
     9import org.openstreetmap.gui.jmapviewer.Coordinate;
     10
     11/**
     12 * Interface to be implemented by polygons that can be displayed on the map.
     13 *
     14 * @author Vincent
     15 */
     16public interface MapPolygon {
     17
     18    /**
     19     * @return Latitude/Longitude of each point of polygon
     20     */
     21    public List<Coordinate> getPoints();
     22
     23    /**
     24     * Paints the map rectangle on the map. The <code>points</code>
     25     * are specifying the coordinates within <code>g</code>
     26     *
     27     * @param g
     28     * @param points
     29     */
     30    public void paint(Graphics g, List<Point> points);
     31
     32    /**
     33     * Paints the map rectangle on the map. The <code>polygon</code>
     34     * is specifying the coordinates within <code>g</code>
     35     *
     36     * @param g
     37     * @param polygon
     38     */
     39    public void paint(Graphics g, Polygon polygon);
     40}
  • src/org/openstreetmap/josm/data/Bounds.java

     
    4242    }
    4343
    4444    public Bounds(double minlat, double minlon, double maxlat, double maxlon) {
    45         this.minLat = roundToOsmPrecision(minlat);
    46         this.minLon = roundToOsmPrecision(minlon);
    47         this.maxLat = roundToOsmPrecision(maxlat);
    48         this.maxLon = roundToOsmPrecision(maxlon);
     45        this.minLat = LatLon.roundToOsmPrecision(minlat);
     46        this.minLon = LatLon.roundToOsmPrecision(minlon);
     47        this.maxLat = LatLon.roundToOsmPrecision(maxlat);
     48        this.maxLon = LatLon.roundToOsmPrecision(maxlon);
    4949    }
    5050
    5151    public Bounds(double [] coords) {
    5252        CheckParameterUtil.ensureParameterNotNull(coords, "coords");
    5353        if (coords.length != 4)
    5454            throw new IllegalArgumentException(MessageFormat.format("Expected array of length 4, got {0}", coords.length));
    55         this.minLat = roundToOsmPrecision(coords[0]);
    56         this.minLon = roundToOsmPrecision(coords[1]);
    57         this.maxLat = roundToOsmPrecision(coords[2]);
    58         this.maxLon = roundToOsmPrecision(coords[3]);
     55        this.minLat = LatLon.roundToOsmPrecision(coords[0]);
     56        this.minLon = LatLon.roundToOsmPrecision(coords[1]);
     57        this.maxLat = LatLon.roundToOsmPrecision(coords[2]);
     58        this.maxLon = LatLon.roundToOsmPrecision(coords[3]);
    5959    }
    6060
    6161    public Bounds(String asString, String separator) throws IllegalArgumentException {
     
    8080        if (!LatLon.isValidLon(values[3]))
    8181            throw new IllegalArgumentException(tr("Illegal latitude value ''{0}''", values[3]));
    8282
    83         this.minLat = roundToOsmPrecision(values[0]);
    84         this.minLon = roundToOsmPrecision(values[1]);
    85         this.maxLat = roundToOsmPrecision(values[2]);
    86         this.maxLon = roundToOsmPrecision(values[3]);
     83        this.minLat = LatLon.roundToOsmPrecision(values[0]);
     84        this.minLon = LatLon.roundToOsmPrecision(values[1]);
     85        this.maxLat = LatLon.roundToOsmPrecision(values[2]);
     86        this.maxLon = LatLon.roundToOsmPrecision(values[3]);
    8787    }
    8888
    8989    public Bounds(Bounds other) {
     
    113113        if (lonExtent <= 0.0)
    114114            throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0.0 exptected, got {1}", "lonExtent", lonExtent));
    115115
    116         this.minLat = roundToOsmPrecision(center.lat() - latExtent / 2);
    117         this.minLon = roundToOsmPrecision(center.lon() - lonExtent / 2);
    118         this.maxLat = roundToOsmPrecision(center.lat() + latExtent / 2);
    119         this.maxLon = roundToOsmPrecision(center.lon() + lonExtent / 2);
     116        this.minLat = LatLon.roundToOsmPrecision(center.lat() - latExtent / 2);
     117        this.minLon = LatLon.roundToOsmPrecision(center.lon() - lonExtent / 2);
     118        this.maxLat = LatLon.roundToOsmPrecision(center.lat() + latExtent / 2);
     119        this.maxLon = LatLon.roundToOsmPrecision(center.lon() + lonExtent / 2);
    120120    }
    121121
    122122    @Override public String toString() {
     
    144144     */
    145145    public void extend(LatLon ll) {
    146146        if (ll.lat() < minLat) {
    147             minLat = roundToOsmPrecision(ll.lat());
     147            minLat = LatLon.roundToOsmPrecision(ll.lat());
    148148        }
    149149        if (ll.lon() < minLon) {
    150             minLon = roundToOsmPrecision(ll.lon());
     150            minLon = LatLon.roundToOsmPrecision(ll.lon());
    151151        }
    152152        if (ll.lat() > maxLat) {
    153             maxLat = roundToOsmPrecision(ll.lat());
     153            maxLat = LatLon.roundToOsmPrecision(ll.lat());
    154154        }
    155155        if (ll.lon() > maxLon) {
    156             maxLon = roundToOsmPrecision(ll.lon());
     156            maxLon = LatLon.roundToOsmPrecision(ll.lon());
    157157        }
    158158    }
    159159
     
    283283            return false;
    284284        return true;
    285285    }
    286 
    287     /**
    288      * Returns the value rounded to OSM precisions, i.e. to
    289      * LatLon.MAX_SERVER_PRECISION
    290      *
    291      * @return rounded value
    292      */
    293     private double roundToOsmPrecision(double value) {
    294         return Math.round(value / LatLon.MAX_SERVER_PRECISION) * LatLon.MAX_SERVER_PRECISION;
    295     }
    296286}
  • src/org/openstreetmap/josm/data/coor/LatLon.java

     
    222222    @Override public String toString() {
    223223        return "LatLon[lat="+lat()+",lon="+lon()+"]";
    224224    }
    225 
     225   
     226    /**
     227     * Returns the value rounded to OSM precisions, i.e. to
     228     * LatLon.MAX_SERVER_PRECISION
     229     *
     230     * @return rounded value
     231     */
     232    public static double roundToOsmPrecision(double value) {
     233        return Math.round(value / MAX_SERVER_PRECISION) * MAX_SERVER_PRECISION;
     234    }
     235   
    226236    /**
    227237     * Replies a clone of this lat LatLon, rounded to OSM precisions, i.e. to
    228238     * MAX_SERVER_PRECISION
     
    231241     */
    232242    public LatLon getRoundedToOsmPrecision() {
    233243        return new LatLon(
    234                 Math.round(lat() / MAX_SERVER_PRECISION) * MAX_SERVER_PRECISION,
    235                 Math.round(lon() / MAX_SERVER_PRECISION) * MAX_SERVER_PRECISION
     244                roundToOsmPrecision(lat()),
     245                roundToOsmPrecision(lon())
    236246        );
    237247    }
    238248
  • src/org/openstreetmap/josm/data/imagery/ImageryInfo.java

     
    5151    private int maxZoom = 0;
    5252    private int defaultMaxZoom = 0;
    5353    private int defaultMinZoom = 0;
    54     private Bounds bounds = null;
     54    private List<Bounds> bounds = new ArrayList<Bounds>();
     55    private List<Shape> shapes = new ArrayList<Shape>();
    5556    private List<String> serverProjections;
    5657    private String attributionText;
    5758    private String attributionImage;
     
    101102        } else {
    102103            res.add(maxZoom != 0 ? String.valueOf(maxZoom) : null);
    103104        }
    104         res.add(bounds != null ? bounds.encodeAsString(",") : null);
     105        // Bounds
     106        String boundsString = "";
     107        for (Bounds b : bounds) {
     108            if (!boundsString.isEmpty()) {
     109                boundsString += ";";
     110            }
     111            boundsString += b.encodeAsString(",");
     112        }
     113        res.add(boundsString.isEmpty() ? null : boundsString);
     114        // Attribution, terms of use
    105115        res.add(attributionText);
    106116        res.add(attributionLinkURL);
    107117        res.add(attributionImage);
    108118        res.add(termsOfUseURL);
     119        // Shapes
     120        String shapesString = "";
     121        for (Shape s : shapes) {
     122            if (!shapesString.isEmpty()) {
     123                shapesString += ";";
     124            }
     125            shapesString += s.encodeAsString(",");
     126        }
     127        res.add(shapesString.isEmpty() ? null : shapesString);
    109128        return res;
    110129    }
    111130
     
    127146        }
    128147        if(array.size() >= 5 && !array.get(4).isEmpty()) {
    129148            try {
    130                 bounds = new Bounds(array.get(4), ",");
     149                for (String s : array.get(4).split(";")) {
     150                    addBounds(new Bounds(s, ","));
     151                }
    131152            } catch (IllegalArgumentException e) {
    132153                Main.warn(e.toString());
    133154            }
     
    144165        if(array.size() >= 9 && !array.get(8).isEmpty()) {
    145166            setTermsOfUseURL(array.get(8));
    146167        }
     168        if(array.size() >= 10 && !array.get(9).isEmpty()) {
     169            try {
     170                for (String s : array.get(9).split(";")) {
     171                    addShape(new Shape(s, ","));
     172                }
     173            } catch (IllegalArgumentException e) {
     174                Main.warn(e.toString());
     175            }
     176        }
    147177    }
    148178
    149179    public ImageryInfo(ImageryInfo i) {
     
    157187        this.pixelPerDegree=i.pixelPerDegree;
    158188        this.eulaAcceptanceRequired = null;
    159189        this.bounds = i.bounds;
     190        this.shapes = i.shapes;
    160191        this.attributionImage = i.attributionImage;
    161192        this.attributionLinkURL = i.attributionLinkURL;
    162193        this.attributionText = i.attributionText;
     
    200231        this.maxZoom = maxZoom;
    201232    }
    202233
    203     public void setBounds(Bounds b) {
    204         this.bounds = b;
     234    public void addBounds(Bounds b) {
     235        this.bounds.add(b);
    205236    }
    206237
    207     public Bounds getBounds() {
     238    public void setBounds(List<Bounds> list) {
     239        this.bounds = list;
     240    }
     241
     242    public List<Bounds> getBounds() {
    208243        return bounds;
    209244    }
    210245
     246    public void addShape(Shape s) {
     247        this.shapes.add(s);
     248    }
     249
     250    public void setShapes(List<Shape> list) {
     251        this.shapes = list;
     252    }
     253
     254    public List<Shape> getShapes() {
     255        return shapes;
     256    }
     257
    211258    public void setAttributionText(String text) {
    212          attributionText = text;
     259        attributionText = text;
    213260    }
    214261
    215262    public void setAttributionImage(String text) {
  • src/org/openstreetmap/josm/data/imagery/Shape.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.imagery;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.text.MessageFormat;
     7import java.util.ArrayList;
     8import java.util.List;
     9
     10import org.openstreetmap.gui.jmapviewer.Coordinate;
     11import org.openstreetmap.josm.data.coor.LatLon;
     12import org.openstreetmap.josm.tools.CheckParameterUtil;
     13
     14/**
     15 * @author Vincent
     16 *
     17 */
     18public class Shape {
     19
     20    private List<Coordinate> coords = new ArrayList<Coordinate>();
     21   
     22    public Shape(String asString, String separator) throws IllegalArgumentException {
     23        CheckParameterUtil.ensureParameterNotNull(asString, "asString");
     24        String[] components = asString.split(separator);
     25        if (components.length % 2 != 0)
     26            throw new IllegalArgumentException(MessageFormat.format("Even number of doubles excpected in string, got {0}: {1}", components.length, asString));
     27        for (int i=0; i<components.length; i+=2) {
     28            addPoint(components[i], components[i+1]);
     29        }
     30    }
     31
     32    public Shape() {
     33    }
     34
     35    public String encodeAsString(String separator) {
     36        StringBuffer sb = new StringBuffer();
     37        for (Coordinate c : coords) {
     38            if (sb.length() != 0) {
     39                sb.append(separator);
     40            }
     41            sb.append(c.getLat()).append(separator).append(c.getLon());
     42        }
     43        return sb.toString();
     44    }
     45
     46    public List<Coordinate> getPoints() {
     47        return coords;
     48    }
     49
     50    public void addPoint(String sLat, String sLon) throws IllegalArgumentException {
     51        CheckParameterUtil.ensureParameterNotNull(sLat, "sLat");
     52        CheckParameterUtil.ensureParameterNotNull(sLon, "sLon");
     53
     54        double lat, lon;
     55       
     56        try {
     57            lat = Double.parseDouble(sLat);
     58            if (!LatLon.isValidLat(lat))
     59                throw new IllegalArgumentException(tr("Illegal latitude value ''{0}''", lat));
     60        } catch (NumberFormatException e) {
     61            throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLat));
     62        }
     63
     64        try {
     65            lon = Double.parseDouble(sLon);
     66            if (!LatLon.isValidLon(lon))
     67                throw new IllegalArgumentException(tr("Illegal longitude value ''{0}''", lon));
     68        } catch (NumberFormatException e) {
     69            throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", sLon));
     70        }
     71       
     72        coords.add(new Coordinate(LatLon.roundToOsmPrecision(lat), LatLon.roundToOsmPrecision(lon)));
     73    }
     74}
  • src/org/openstreetmap/josm/gui/preferences/ImageryPreference.java

     
    1717import java.io.IOException;
    1818import java.net.MalformedURLException;
    1919import java.net.URL;
     20import java.util.ArrayList;
    2021import java.util.HashMap;
    2122import java.util.List;
    2223import java.util.Locale;
     
    5051import javax.swing.table.TableColumnModel;
    5152
    5253import org.openstreetmap.gui.jmapviewer.JMapViewer;
     54import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
    5355import org.openstreetmap.gui.jmapviewer.MapRectangleImpl;
     56import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
    5457import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
    5558import org.openstreetmap.josm.Main;
    5659import org.openstreetmap.josm.data.Bounds;
     
    5861import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
    5962import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
    6063import org.openstreetmap.josm.data.imagery.OffsetBookmark;
     64import org.openstreetmap.josm.data.imagery.Shape;
    6165import org.openstreetmap.josm.gui.layer.ImageryLayer;
    6266import org.openstreetmap.josm.gui.layer.TMSLayer;
    6367import org.openstreetmap.josm.gui.layer.WMSLayer;
     
    459463
    460464        // Listener of default providers list selection
    461465        private final class DefListSelectionListener implements ListSelectionListener {
    462             // The current drawn rectangles
    463             private final Map<Integer, MapRectangle> mapRectangles;
     466            // The current drawn rectangles and polygons
     467            private final Map<Integer, List<MapRectangle>> mapRectangles;
     468            private final Map<Integer, List<MapPolygon>> mapPolygons;
    464469
    465470            private DefListSelectionListener() {
    466                 this.mapRectangles = new HashMap<Integer, MapRectangle>();
     471                this.mapRectangles = new HashMap<Integer, List<MapRectangle>>();
     472                this.mapPolygons = new HashMap<Integer, List<MapPolygon>>();
    467473            }
    468474
    469475            @Override
    470476            public void valueChanged(ListSelectionEvent e) {
    471                 // First index is set to -1 when the list is refreshed, so discard all map rectangles
     477                // First index is set to -1 when the list is refreshed, so discard all map rectangles and polygons
    472478                if (e.getFirstIndex() == -1) {
    473479                    map.removeAllMapRectangles();
     480                    map.removeAllMapPolygons();
    474481                    mapRectangles.clear();
     482                    mapPolygons.clear();
    475483                    // Only process complete (final) selection events
    476484                } else if (!e.getValueIsAdjusting()) {
    477485                    for (int i = e.getFirstIndex(); i<=e.getLastIndex(); i++) {
    478                         Bounds bounds = modeldef.getRow(i).getBounds();
    479                         if (bounds != null) {
    480                             if (listdef.getSelectionModel().isSelectedIndex(i)) {
    481                                 if (!mapRectangles.containsKey(i)) {
    482                                     // Add new map rectangle
    483                                     MapRectangle rectangle = new MapRectangleImpl(bounds);
    484                                     mapRectangles.put(i, rectangle);
    485                                     map.addMapRectangle(rectangle);
    486                                 }
    487                             } else if (mapRectangles.containsKey(i)) {
    488                                 // Remove previousliy drawn map rectangle
    489                                 map.removeMapRectangle(mapRectangles.get(i));
    490                                 mapRectangles.remove(i);
     486                        updateBounds(i);
     487                        updateShapes(i);
     488                    }
     489                    // If needed, adjust map to show all map rectangles and polygons
     490                    if (!mapRectangles.isEmpty() || !mapPolygons.isEmpty()) {
     491                        map.setDisplayToFitMapElements(false, true, true);
     492                        map.zoomOut();
     493                    }
     494                }
     495            }
     496           
     497            private void updateBounds(int i) {
     498                List<Bounds> bounds = modeldef.getRow(i).getBounds();
     499                if (bounds != null && !bounds.isEmpty()) {
     500                    if (listdef.getSelectionModel().isSelectedIndex(i)) {
     501                        if (!mapRectangles.containsKey(i)) {
     502                            List<MapRectangle> list = new ArrayList<MapRectangle>();
     503                            mapRectangles.put(i, list);
     504                            // Add new map rectangles
     505                            for (Bounds b : bounds) {
     506                                MapRectangle rectangle = new MapRectangleImpl(b);
     507                                list.add(rectangle);
     508                                map.addMapRectangle(rectangle);
    491509                            }
    492510                        }
     511                    } else if (mapRectangles.containsKey(i)) {
     512                        // Remove previously drawn map rectangles
     513                        for (MapRectangle rectangle : mapRectangles.get(i)) {
     514                            map.removeMapRectangle(rectangle);
     515                        }
     516                        mapRectangles.remove(i);
    493517                    }
    494                     // If needed, adjust map to show all map rectangles
    495                     if (!mapRectangles.isEmpty()) {
    496                         map.setDisplayToFitMapRectangle();
    497                         map.zoomOut();
     518                }
     519            }
     520
     521            private void updateShapes(int i) {
     522                List<Shape> shapes = modeldef.getRow(i).getShapes();
     523                if (shapes != null && !shapes.isEmpty()) {
     524                    if (listdef.getSelectionModel().isSelectedIndex(i)) {
     525                        if (!mapPolygons.containsKey(i)) {
     526                            List<MapPolygon> list = new ArrayList<MapPolygon>();
     527                            mapPolygons.put(i, list);
     528                            // Add new map polygons
     529                            for (Shape shape : shapes) {
     530                                MapPolygon polygon = new MapPolygonImpl(shape.getPoints());
     531                                list.add(polygon);
     532                                map.addMapPolygon(polygon);
     533                            }
     534                        }
     535                    } else if (mapPolygons.containsKey(i)) {
     536                        // Remove previously drawn map polygons
     537                        for (MapPolygon polygon : mapPolygons.get(i)) {
     538                            map.removeMapPolygon(polygon);
     539                        }
     540                        mapPolygons.remove(i);
    498541                    }
    499542                }
    500543            }
  • src/org/openstreetmap/josm/io/imagery/ImageryReader.java

     
    2121import org.openstreetmap.josm.data.Bounds;
    2222import org.openstreetmap.josm.data.imagery.ImageryInfo;
    2323import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
     24import org.openstreetmap.josm.data.imagery.Shape;
    2425import org.openstreetmap.josm.io.MirroredInputStream;
    2526import org.openstreetmap.josm.io.UTFInputStreamReader;
    2627import org.openstreetmap.josm.tools.Utils;
     
    142143                        if (val.length >= 5 && !val[4].isEmpty()) {
    143144                            // 5th parameter optional for bounds
    144145                            try {
    145                                 info.setBounds(new Bounds(val[4], ","));
     146                                info.addBounds(new Bounds(val[4], ","));
    146147                            } catch (IllegalArgumentException e) {
    147148                                Main.warn(e.toString());
    148149                            }
     
    190191
    191192        ImageryInfo entry;
    192193        Bounds bounds;
     194        Shape shape;
    193195        List<String> supported_srs;
    194196
    195197        @Override public void startDocument() {
     
    249251                            break;
    250252                        }
    251253                        newState = State.ENTRY_ATTRIBUTE;
     254                    } else if (qName.equals("shape")) {
     255                        shape = new Shape();
     256                        newState = State.ENTRY_ATTRIBUTE;
    252257                    } else if (qName.equals("supported-projections")) {
    253258                        supported_srs = new ArrayList<String>();
    254259                        newState = State.SUPPORTED_PROJECTIONS;
    255260                    }
    256261                    break;
     262                case ENTRY_ATTRIBUTE:
     263                    if (qName.equals("point")) {
     264                        shape.addPoint(atts.getValue("lat"), atts.getValue("lon"));
     265                    }
     266                    break;
    257267                case SUPPORTED_PROJECTIONS:
    258268                    if (qName.equals("pr")) {
    259269                        newState = State.PR;
     
    339349                            }
    340350                        }
    341351                    } else if (qName.equals("bounds")) {
    342                         entry.setBounds(bounds);
     352                        entry.addBounds(bounds);
    343353                        bounds = null;
     354                    } else if (qName.equals("shape")) {
     355                        entry.addShape(shape);
     356                        shape = null;
    344357                    } else if (qName.equals("attribution-text")) {
    345358                        entry.setAttributionText(accumulator.toString());
    346359                    } else if (qName.equals("attribution-url")) {