Changeset 10805 in josm


Ignore:
Timestamp:
2016-08-15T14:45:38+02:00 (3 years ago)
Author:
Don-vip
Message:

fix #13287 - Projection updates to support multiple projections (patch by michael2402) - gsoc-core

Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/projection/AbstractProjection.java

    r10699 r10805  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.projection;
     3
     4import java.util.Collections;
     5import java.util.HashMap;
     6import java.util.Map;
     7import java.util.function.DoubleUnaryOperator;
    38
    49import org.openstreetmap.josm.data.Bounds;
     
    813import org.openstreetmap.josm.data.projection.datum.Datum;
    914import org.openstreetmap.josm.data.projection.proj.Proj;
     15import org.openstreetmap.josm.tools.Utils;
    1016
    1117/**
     
    116122    @Override
    117123    public LatLon eastNorth2latlon(EastNorth en) {
     124        return eastNorth2latlon(en, LatLon::normalizeLon);
     125    }
     126
     127    @Override
     128    public LatLon eastNorth2latlonClamped(EastNorth en) {
     129        LatLon ll = eastNorth2latlon(en, lon -> Utils.clamp(lon, -180, 180));
     130        Bounds bounds = getWorldBoundsLatLon();
     131        return new LatLon(Utils.clamp(ll.lat(), bounds.getMinLat(), bounds.getMaxLat()),
     132                Utils.clamp(ll.lon(), bounds.getMinLon(), bounds.getMaxLon()));
     133    }
     134
     135    private LatLon eastNorth2latlon(EastNorth en, DoubleUnaryOperator normalizeLon) {
    118136        double[] latlonRad = proj.invproject((en.east() * toMeter - x0) / ellps.a / k0, (en.north() * toMeter - y0) / ellps.a / k0);
    119         LatLon ll = new LatLon(Math.toDegrees(latlonRad[0]), LatLon.normalizeLon(Math.toDegrees(latlonRad[1]) + lon0 + pm));
     137        double lon = Math.toDegrees(latlonRad[1]) + lon0 + pm;
     138        LatLon ll = new LatLon(Math.toDegrees(latlonRad[0]), normalizeLon.applyAsDouble(lon));
    120139        return datum.toWGS84(ll);
     140    }
     141
     142    @Override
     143    public Map<ProjectionBounds, Projecting> getProjectingsForArea(ProjectionBounds area) {
     144        if (proj.lonIsLinearToEast()) {
     145            //FIXME: Respect datum?
     146            // wrap the wrold around
     147            Bounds bounds = getWorldBoundsLatLon();
     148            double minEast = latlon2eastNorth(bounds.getMin()).east();
     149            double maxEast = latlon2eastNorth(bounds.getMax()).east();
     150            double dEast = maxEast - minEast;
     151            if ((area.minEast < minEast || area.maxEast > maxEast) && dEast > 0) {
     152                // We could handle the dEast < 0 case but we don't need it atm.
     153                int minChunk = (int) Math.floor((area.minEast - minEast) / dEast);
     154                int maxChunk = (int) Math.floor((area.maxEast - minEast) / dEast);
     155                HashMap<ProjectionBounds, Projecting> ret = new HashMap<>();
     156                for (int chunk = minChunk; chunk <= maxChunk; chunk++) {
     157                    ret.put(new ProjectionBounds(Math.max(area.minEast, minEast + chunk * dEast), area.minNorth,
     158                            Math.min(area.maxEast, maxEast + chunk * dEast), area.maxNorth),
     159                            new ShiftedProjecting(this, new EastNorth(-chunk * dEast, 0)));
     160                }
     161                return ret;
     162            }
     163        }
     164
     165        return Collections.singletonMap(area, this);
    121166    }
    122167
     
    179224        return projectionBoundsBox;
    180225    }
     226
     227    @Override
     228    public Projection getBaseProjection() {
     229        return this;
     230    }
    181231}
  • trunk/src/org/openstreetmap/josm/data/projection/Projection.java

    r10381 r10805  
    1414 * factor and x/y offset.
    1515 */
    16 public interface Projection {
     16public interface Projection extends Projecting {
    1717    /**
    1818     * The default scale factor in east/north units per pixel
     
    2222     */
    2323    double getDefaultZoomInPPD();
    24 
    25     /**
    26      * Convert from lat/lon to easting/northing.
    27      *
    28      * @param ll the geographical point to convert (in WGS84 lat/lon)
    29      * @return the corresponding east/north coordinates
    30      */
    31     EastNorth latlon2eastNorth(LatLon ll);
    3224
    3325    /**
  • trunk/src/org/openstreetmap/josm/data/projection/proj/Mercator.java

    r10378 r10805  
    120120        return scaleFactor;
    121121    }
     122
     123    @Override
     124    public boolean lonIsLinearToEast() {
     125        return true;
     126    }
    122127}
  • trunk/src/org/openstreetmap/josm/data/projection/proj/Proj.java

    r10001 r10805  
    9191     */
    9292    boolean isGeographic();
     93
     94    /**
     95     * Checks wether the result of projecting a lon coordinate only has a linear relation to the east coordinate and
     96     * is not related to lat/north at all.
     97     * @return <code>true</code> if lon has a linear relationship to east only.
     98     * @since 10805
     99     */
     100    default boolean lonIsLinearToEast() {
     101        return false;
     102    }
    93103}
  • trunk/src/org/openstreetmap/josm/gui/MapViewState.java

    r10651 r10805  
    1717import org.openstreetmap.josm.data.coor.EastNorth;
    1818import org.openstreetmap.josm.data.coor.LatLon;
     19import org.openstreetmap.josm.data.projection.Projecting;
    1920import org.openstreetmap.josm.data.projection.Projection;
    2021import org.openstreetmap.josm.gui.download.DownloadDialog;
     
    2829public final class MapViewState {
    2930
    30     private final Projection projection;
     31    private final Projecting projecting;
    3132
    3233    private final int viewWidth;
     
    5152     * @param topLeft The top left corner in east/north space.
    5253     */
    53     private MapViewState(Projection projection, int viewWidth, int viewHeight, double scale, EastNorth topLeft) {
    54         this.projection = projection;
     54    private MapViewState(Projecting projection, int viewWidth, int viewHeight, double scale, EastNorth topLeft) {
     55        this.projecting = projection;
    5556        this.scale = scale;
    5657        this.topLeft = topLeft;
     
    6364
    6465    private MapViewState(EastNorth topLeft, MapViewState mapViewState) {
    65         this.projection = mapViewState.projection;
     66        this.projecting = mapViewState.projecting;
    6667        this.scale = mapViewState.scale;
    6768        this.topLeft = topLeft;
     
    7475
    7576    private MapViewState(double scale, MapViewState mapViewState) {
    76         this.projection = mapViewState.projection;
     77        this.projecting = mapViewState.projecting;
    7778        this.scale = scale;
    7879        this.topLeft = mapViewState.topLeft;
     
    8586
    8687    private MapViewState(JComponent position, MapViewState mapViewState) {
    87         this.projection = mapViewState.projection;
     88        this.projecting = mapViewState.projecting;
    8889        this.scale = mapViewState.scale;
    8990        this.topLeft = mapViewState.topLeft;
     
    106107    }
    107108
    108     private MapViewState(Projection projection, MapViewState mapViewState) {
    109         this.projection = projection;
     109    private MapViewState(Projecting projecting, MapViewState mapViewState) {
     110        this.projecting = projecting;
    110111        this.scale = mapViewState.scale;
    111112        this.topLeft = mapViewState.topLeft;
     
    201202     */
    202203    public Projection getProjection() {
    203         return projection;
     204        return projecting.getBaseProjection();
    204205    }
    205206
     
    269270     */
    270271    public MapViewState usingProjection(Projection projection) {
    271         if (projection.equals(this.projection)) {
     272        if (projection.equals(this.projecting)) {
    272273            return this;
    273274        } else {
     
    358359         * Gets the current position in LatLon coordinates according to the current projection.
    359360         * @return The positon as LatLon.
     361         * @see #getLatLonClamped()
    360362         */
    361363        public LatLon getLatLon() {
    362             return projection.eastNorth2latlon(getEastNorth());
     364            return projecting.getBaseProjection().eastNorth2latlon(getEastNorth());
     365        }
     366
     367        /**
     368         * Gets the latlon coordinate clamped to the current world area.
     369         * @return The lat/lon coordinate
     370         * @since 10805
     371         */
     372        public LatLon getLatLonClamped() {
     373            return projecting.eastNorth2latlonClamped(getEastNorth());
    363374        }
    364375
     
    474485         */
    475486        public Bounds getLatLonBoundsBox() {
    476             return projection.getLatLonBoundsBox(getProjectionBounds());
     487            // TODO @michael2402: Use hillclimb.
     488            return projecting.getBaseProjection().getLatLonBoundsBox(getProjectionBounds());
    477489        }
    478490
  • trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java

    r10757 r10805  
    231231
    232232    protected void initTileSource(T tileSource) {
    233         coordinateConverter = new TileCoordinateConverter(Main.map.mapView, getDisplaySettings());
     233        coordinateConverter = new TileCoordinateConverter(Main.map.mapView, tileSource, getDisplaySettings());
    234234        attribution.initialize(tileSource);
    235235
     
    368368     */
    369369    private double getScaleFactor(int zoom) {
    370         if (!Main.isDisplayingMapView()) return 1;
    371         MapView mv = Main.map.mapView;
    372         LatLon topLeft = mv.getLatLon(0, 0);
    373         LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
    374         TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom);
    375         TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom);
    376 
    377         int screenPixels = mv.getWidth()*mv.getHeight();
    378         double tilePixels = Math.abs((t2.getY()-t1.getY())*(t2.getX()-t1.getX())*tileSource.getTileSize()*tileSource.getTileSize());
    379         if (screenPixels == 0 || tilePixels == 0) return 1;
    380         return screenPixels/tilePixels;
     370        if (coordinateConverter != null) {
     371            return coordinateConverter.getScaleFactor(zoom);
     372        } else {
     373            return 1;
     374        }
    381375    }
    382376
     
    12461240
    12471241    private LatLon getShiftedLatLon(EastNorth en) {
    1248         return Main.getProjection().eastNorth2latlon(en.add(-getDisplaySettings().getDx(), -getDisplaySettings().getDy()));
     1242        return coordinateConverter.getProjecting().eastNorth2latlonClamped(en);
    12491243    }
    12501244
     
    15201514    @Override
    15211515    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
    1522         ProjectionBounds pb = mv.getState().getViewArea().getProjectionBounds();
    1523 
    1524         needRedraw = false;
    1525 
     1516        // old and unused.
     1517    }
     1518
     1519    private void drawInViewArea(Graphics2D g, MapView mv, ProjectionBounds pb) {
    15261520        int zoom = currentZoomLevel;
    15271521        if (getDisplaySettings().isAutoZoom()) {
     
    18981892            allocateCacheMemory();
    18991893            if (memory != null) {
    1900                 super.paint(graphics);
    1901             }
     1894                doPaint(graphics);
     1895            }
     1896        }
     1897
     1898        private void doPaint(MapViewGraphics graphics) {
     1899            ProjectionBounds pb = graphics.getClipBounds().getProjectionBounds();
     1900
     1901            needRedraw = false; // TEMPORARY
     1902
     1903            drawInViewArea(graphics.getDefaultGraphics(), graphics.getMapView(), pb);
    19021904        }
    19031905
  • trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileCoordinateConverter.java

    r10651 r10805  
    66
    77import org.openstreetmap.gui.jmapviewer.Tile;
     8import org.openstreetmap.gui.jmapviewer.TileXY;
    89import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
     10import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
    911import org.openstreetmap.josm.data.coor.LatLon;
     12import org.openstreetmap.josm.data.projection.Projecting;
     13import org.openstreetmap.josm.data.projection.ShiftedProjecting;
    1014import org.openstreetmap.josm.gui.MapView;
    1115import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
     
    1923    private MapView mapView;
    2024    private TileSourceDisplaySettings settings;
     25    private TileSource tileSource;
    2126
    2227    /**
    2328     * Create a new coordinate converter for the map view.
    2429     * @param mapView The map view.
     30     * @param tileSource The tile source to use when converting coordinates.
    2531     * @param settings displacement settings.
    2632     */
    27     public TileCoordinateConverter(MapView mapView, TileSourceDisplaySettings settings) {
     33    public TileCoordinateConverter(MapView mapView, TileSource tileSource, TileSourceDisplaySettings settings) {
    2834        this.mapView = mapView;
     35        this.tileSource = tileSource;
    2936        this.settings = settings;
    3037    }
     
    3239    private MapViewPoint pos(ICoordinate ll) {
    3340        return mapView.getState().getPointFor(new LatLon(ll)).add(settings.getDisplacement());
     41    }
     42
     43    /**
     44     * Gets the projecting instance to use to convert between latlon and eastnorth coordinates.
     45     * @return The {@link Projecting} instance.
     46     */
     47    public Projecting getProjecting() {
     48        return new ShiftedProjecting(mapView.getProjection(), settings.getDisplacement());
    3449    }
    3550
     
    5570        return pos(c1).rectTo(pos(c2)).getInView();
    5671    }
     72
     73    /**
     74     * Returns average number of screen pixels per tile pixel for current mapview
     75     * @param zoom zoom level
     76     * @return average number of screen pixels per tile pixel
     77     */
     78    public double getScaleFactor(int zoom) {
     79        LatLon topLeft = mapView.getLatLon(0, 0);
     80        LatLon botRight = mapView.getLatLon(mapView.getWidth(), mapView.getHeight());
     81        TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom);
     82        TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom);
     83
     84        int screenPixels = mapView.getWidth()*mapView.getHeight();
     85        double tilePixels = Math.abs((t2.getY()-t1.getY())*(t2.getX()-t1.getX())*tileSource.getTileSize()*tileSource.getTileSize());
     86        if (screenPixels == 0 || tilePixels == 0) return 1;
     87        return screenPixels/tilePixels;
     88    }
    5789}
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r10761 r10805  
    15521552        }
    15531553    }
     1554
     1555    /**
     1556     * Clamp a value to the given range
     1557     * @param val The value
     1558     * @param min minimum value
     1559     * @param max maximum value
     1560     * @return the value
     1561     * @since 10805
     1562     */
     1563    public static double clamp(double val, double min, double max) {
     1564        if (val < min) {
     1565            return min;
     1566        } else if (val > max) {
     1567            return max;
     1568        } else {
     1569            return val;
     1570        }
     1571    }
    15541572}
Note: See TracChangeset for help on using the changeset viewer.