Ticket #6834: patchV2.diff

File patchV2.diff, 39.3 KB (added by Don-vip, 15 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
     
    539556    }
    540557
    541558    /**
     559     * Paint a single rectangle.
     560     */
     561    protected void paintRectangle(Graphics g, MapRectangle rectangle) {
     562        Coordinate topLeft = rectangle.getTopLeft();
     563        Coordinate bottomRight = rectangle.getBottomRight();
     564        if (topLeft != null && bottomRight != null) {
     565            Point pTopLeft = getMapPosition(topLeft, false);
     566            Point pBottomRight = getMapPosition(bottomRight, false);
     567            if (pTopLeft != null && pBottomRight != null) {
     568                rectangle.paint(g, pTopLeft, pBottomRight);
     569            }
     570        }
     571    }
     572
     573    /**
     574     * Paint a single polygon.
     575     */
     576    protected void paintPolygon(Graphics g, MapPolygon polygon) {
     577        List<Coordinate> coords = polygon.getPoints();
     578        if (coords != null && coords.size() >= 3) {
     579            List<Point> points = new LinkedList<Point>();
     580            for (Coordinate c : coords) {
     581                Point p = getMapPosition(c, false);
     582                if (p == null) {
     583                    return;
     584                }
     585                points.add(p);
     586            }
     587            polygon.paint(g, points);
     588        }
     589    }
     590   
     591    /**
    542592     * Moves the visible map pane.
    543593     *
    544594     * @param x
     
    660710        return mapRectangleList;
    661711    }
    662712
     713    public void setMapPolygonList(List<MapPolygon> mapPolygonList) {
     714        this.mapPolygonList = mapPolygonList;
     715        repaint();
     716    }
     717
     718    public List<MapPolygon> getMapPolygonList() {
     719        return mapPolygonList;
     720    }
     721
    663722    public void addMapMarker(MapMarker marker) {
    664723        mapMarkerList.add(marker);
    665724        repaint();
     
    690749        repaint();
    691750    }
    692751
     752    public void addMapPolygon(MapPolygon polygon) {
     753        mapPolygonList.add(polygon);
     754        repaint();
     755    }
     756
     757    public void removeMapPolygon(MapPolygon polygon) {
     758        mapPolygonList.remove(polygon);
     759        repaint();
     760    }
     761
     762    public void removeAllMapPolygons() {
     763        mapPolygonList.clear();
     764        repaint();
     765    }
     766   
    693767    public void setZoomContolsVisible(boolean visible) {
    694768        zoomSlider.setVisible(visible);
    695769        zoomInButton.setVisible(visible);
     
    735809    /**
    736810     * Enables or disables painting of the {@link MapRectangle}
    737811     *
    738      * @param mapMarkersVisible
     812     * @param mapRectanglesVisible
    739813     * @see #addMapRectangle(MapRectangle)
    740814     * @see #getMapRectangleList()
    741815     */
     
    744818        repaint();
    745819    }
    746820
     821    public boolean isMapPolygonsVisible() {
     822        return mapPolygonsVisible;
     823    }
     824
     825    /**
     826     * Enables or disables painting of the {@link MapPolygon}
     827     *
     828     * @param mapPolygonsVisible
     829     * @see #addMapPolygon(MapPolygon)
     830     * @see #getMapPolygonList()
     831     */
     832    public void setMapPolygonsVisible(boolean mapPolygonsVisible) {
     833        this.mapPolygonsVisible = mapPolygonsVisible;
     834        repaint();
     835    }
     836
    747837    /*
    748838     * (non-Javadoc)
    749839     *
  • 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

     
    4040            return urlString;
    4141        }
    4242    }
     43   
     44    public static class ImageryBounds extends Bounds {
     45        public ImageryBounds(String asString, String separator) {
     46            super(asString, separator);
     47        }
     48
     49        private List<Shape> shapes = new ArrayList<Shape>();
     50       
     51        public void addShape(Shape shape) {
     52            this.shapes.add(shape);
     53        }
     54
     55        public void setShapes(List<Shape> shapes) {
     56            this.shapes = shapes;
     57        }
     58
     59        public List<Shape> getShapes() {
     60            return shapes;
     61        }
     62    }
    4363
    4464    private String name;
    4565    private String url = null;
     
    5171    private int maxZoom = 0;
    5272    private int defaultMaxZoom = 0;
    5373    private int defaultMinZoom = 0;
    54     private Bounds bounds = null;
     74    private ImageryBounds bounds = null;
    5575    private List<String> serverProjections;
    5676    private String attributionText;
    5777    private String attributionImage;
     
    106126        res.add(attributionLinkURL);
    107127        res.add(attributionImage);
    108128        res.add(termsOfUseURL);
     129        // Shapes
     130        String shapesString = "";
     131        for (Shape s : bounds.getShapes()) {
     132            if (!shapesString.isEmpty()) {
     133                shapesString += ";";
     134            }
     135            shapesString += s.encodeAsString(",");
     136        }
     137        res.add(shapesString.isEmpty() ? null : shapesString);
    109138        return res;
    110139    }
    111140
     
    127156        }
    128157        if(array.size() >= 5 && !array.get(4).isEmpty()) {
    129158            try {
    130                 bounds = new Bounds(array.get(4), ",");
     159                bounds = new ImageryBounds(array.get(4), ",");
    131160            } catch (IllegalArgumentException e) {
    132161                Main.warn(e.toString());
    133162            }
     
    144173        if(array.size() >= 9 && !array.get(8).isEmpty()) {
    145174            setTermsOfUseURL(array.get(8));
    146175        }
     176        if(bounds != null && array.size() >= 10 && !array.get(9).isEmpty()) {
     177            try {
     178                for (String s : array.get(9).split(";")) {
     179                    bounds.addShape(new Shape(s, ","));
     180                }
     181            } catch (IllegalArgumentException e) {
     182                Main.warn(e.toString());
     183            }
     184        }
    147185    }
    148186
    149187    public ImageryInfo(ImageryInfo i) {
     
    200238        this.maxZoom = maxZoom;
    201239    }
    202240
    203     public void setBounds(Bounds b) {
     241    public void setBounds(ImageryBounds b) {
    204242        this.bounds = b;
    205243    }
    206244
    207     public Bounds getBounds() {
     245    public ImageryBounds getBounds() {
    208246        return bounds;
    209247    }
    210248
    211249    public void setAttributionText(String text) {
    212          attributionText = text;
     250        attributionText = text;
    213251    }
    214252
    215253    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;
    56 import org.openstreetmap.josm.data.Bounds;
    5759import org.openstreetmap.josm.data.imagery.ImageryInfo;
     60import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
    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
     466            // The current drawn rectangles and polygons
    463467            private final Map<Integer, MapRectangle> mapRectangles;
     468            private final Map<Integer, List<MapPolygon>> mapPolygons;
    464469
    465470            private DefListSelectionListener() {
    466471                this.mapRectangles = new HashMap<Integer, 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                        updateBoundsAndShapes(i);
     487                    }
     488                    // If needed, adjust map to show all map rectangles and polygons
     489                    if (!mapRectangles.isEmpty() || !mapPolygons.isEmpty()) {
     490                        map.setDisplayToFitMapElements(false, true, true);
     491                        map.zoomOut();
     492                    }
     493                }
     494            }
     495           
     496            private void updateBoundsAndShapes(int i) {
     497                ImageryBounds bounds = modeldef.getRow(i).getBounds();
     498                if (bounds != null) {
     499                    List<Shape> shapes = bounds.getShapes();
     500                    if (shapes != null && !shapes.isEmpty()) {
     501                        if (listdef.getSelectionModel().isSelectedIndex(i)) {
     502                            if (!mapPolygons.containsKey(i)) {
     503                                List<MapPolygon> list = new ArrayList<MapPolygon>();
     504                                mapPolygons.put(i, list);
     505                                // Add new map polygons
     506                                for (Shape shape : shapes) {
     507                                    MapPolygon polygon = new MapPolygonImpl(shape.getPoints());
     508                                    list.add(polygon);
     509                                    map.addMapPolygon(polygon);
    486510                                }
    487                             } else if (mapRectangles.containsKey(i)) {
    488                                 // Remove previousliy drawn map rectangle
    489                                 map.removeMapRectangle(mapRectangles.get(i));
    490                                 mapRectangles.remove(i);
    491511                            }
     512                        } else if (mapPolygons.containsKey(i)) {
     513                            // Remove previously drawn map polygons
     514                            for (MapPolygon polygon : mapPolygons.get(i)) {
     515                                map.removeMapPolygon(polygon);
     516                            }
     517                            mapPolygons.remove(i);
    492518                        }
    493                     }
    494                     // If needed, adjust map to show all map rectangles
    495                     if (!mapRectangles.isEmpty()) {
    496                         map.setDisplayToFitMapRectangle();
    497                         map.zoomOut();
     519                     // Only display bounds when no polygons (shapes) are defined for this provider
     520                    } else {
     521                        if (listdef.getSelectionModel().isSelectedIndex(i)) {
     522                            if (!mapRectangles.containsKey(i)) {
     523                                // Add new map rectangle
     524                                MapRectangle rectangle = new MapRectangleImpl(bounds);
     525                                mapRectangles.put(i, rectangle);
     526                                map.addMapRectangle(rectangle);
     527                            }
     528                        } else if (mapRectangles.containsKey(i)) {
     529                            // Remove previously drawn map rectangle
     530                            map.removeMapRectangle(mapRectangles.get(i));
     531                            mapRectangles.remove(i);
     532                        }
    498533                    }
    499534                }
    500535            }
  • src/org/openstreetmap/josm/io/imagery/ImageryReader.java

     
    1818import javax.xml.parsers.SAXParserFactory;
    1919
    2020import org.openstreetmap.josm.Main;
    21 import org.openstreetmap.josm.data.Bounds;
    2221import org.openstreetmap.josm.data.imagery.ImageryInfo;
     22import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
    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;
     
    4041        ENTRY_ATTRIBUTE,    // note we are inside an entry attribute to collect the character data
    4142        SUPPORTED_PROJECTIONS,
    4243        PR,
     44        SHAPE,
     45        SHAPE_POINT,
    4346        UNKNOWN,            // element is not recognized in the current context
    4447    }
    4548
    46     public ImageryReader(String source) throws IOException {
     49    public ImageryReader(String source) {
    4750        this.source = source;
    4851    }
    4952
     
    142145                        if (val.length >= 5 && !val[4].isEmpty()) {
    143146                            // 5th parameter optional for bounds
    144147                            try {
    145                                 info.setBounds(new Bounds(val[4], ","));
     148                                info.setBounds(new ImageryBounds(val[4], ","));
    146149                            } catch (IllegalArgumentException e) {
    147150                                Main.warn(e.toString());
    148151                            }
     
    189192        boolean skipEntry;
    190193
    191194        ImageryInfo entry;
    192         Bounds bounds;
     195        ImageryBounds bounds;
     196        Shape shape;
    193197        List<String> supported_srs;
    194198
    195199        @Override public void startDocument() {
     
    240244                        newState = State.ENTRY_ATTRIBUTE;
    241245                    } else if (qName.equals("bounds")) {
    242246                        try {
    243                             bounds = new Bounds(
     247                            bounds = new ImageryBounds(
    244248                                    atts.getValue("min-lat") + "," +
    245249                                    atts.getValue("min-lon") + "," +
    246250                                    atts.getValue("max-lat") + "," +
     
    254258                        newState = State.SUPPORTED_PROJECTIONS;
    255259                    }
    256260                    break;
     261                case ENTRY_ATTRIBUTE:
     262                    if (qName.equals("shape")) {
     263                        shape = new Shape();
     264                        newState = State.SHAPE;
     265                    }
     266                    break;
     267                case SHAPE:
     268                    if (qName.equals("point")) {
     269                        try {
     270                            shape.addPoint(atts.getValue("lat"), atts.getValue("lon"));
     271                        } catch (IllegalArgumentException e) {
     272                            break;
     273                        }
     274                        newState = State.SHAPE_POINT;
     275                    }
     276                    break;
    257277                case SUPPORTED_PROJECTIONS:
    258278                    if (qName.equals("pr")) {
    259279                        newState = State.PR;
     
    358378                    } else {
    359379                    }
    360380                    break;
     381                case SHAPE:
     382                    bounds.addShape(shape);
     383                    shape = null;
     384                    break;
    361385                case PR:
    362386                    supported_srs.add(accumulator.toString());
    363387                    break;