Ignore:
Timestamp:
2017-07-22T14:25:19+02:00 (7 years ago)
Author:
bastiK
Message:

see #15013, see #14877 - remember projection when session is saved to a .jos/.joz file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/session/SessionReader.java

    r12279 r12486  
    1616import java.nio.charset.StandardCharsets;
    1717import java.util.ArrayList;
     18import java.util.Collection;
    1819import java.util.Collections;
    1920import java.util.Enumeration;
     
    4344import org.openstreetmap.josm.io.Compression;
    4445import org.openstreetmap.josm.io.IllegalDataException;
     46import org.openstreetmap.josm.tools.CheckParameterUtil;
    4547import org.openstreetmap.josm.tools.JosmRuntimeException;
    4648import org.openstreetmap.josm.tools.MultiMap;
     
    5860public class SessionReader {
    5961
     62    /**
     63     * Data class for projection saved in the session file.
     64     */
     65    public static class SessionProjectionChoiceData {
     66        private final String projectionChoiceId;
     67        private final Collection<String> subPreferences;
     68
     69        /**
     70         * Construct a new SessionProjectionChoiceData.
     71         * @param projectionChoiceId projection choice id
     72         * @param subPreferences parameters for the projection choice
     73         */
     74        public SessionProjectionChoiceData(String projectionChoiceId, Collection<String> subPreferences) {
     75            this.projectionChoiceId = projectionChoiceId;
     76            this.subPreferences = subPreferences;
     77        }
     78
     79        /**
     80         * Get the projection choice id.
     81         * @return the projection choice id
     82         */
     83        public String getProjectionChoiceId() {
     84            return projectionChoiceId;
     85        }
     86
     87        /**
     88         * Get the parameters for the projection choice
     89         * @return parameters for the projection choice
     90         */
     91        public Collection<String> getSubPreferences() {
     92            return subPreferences;
     93        }
     94    }
     95
     96    /**
     97     * Data class for viewport saved in the session file.
     98     */
     99    public static class SessionViewportData {
     100        private final LatLon center;
     101        private final double meterPerPixel;
     102
     103        /**
     104         * Construct a new SessionViewportData.
     105         * @param center the lat/lon coordinates of the screen center
     106         * @param meterPerPixel scale in meters per pixel
     107         */
     108        public SessionViewportData(LatLon center, double meterPerPixel) {
     109            CheckParameterUtil.ensureParameterNotNull(center);
     110            this.center = center;
     111            this.meterPerPixel = meterPerPixel;
     112        }
     113
     114        /**
     115         * Get the lat/lon coordinates of the screen center.
     116         * @return lat/lon coordinates of the screen center
     117         */
     118        public LatLon getCenter() {
     119            return center;
     120        }
     121
     122        /**
     123         * Get the scale in meters per pixel.
     124         * @return scale in meters per pixel
     125         */
     126        public double getScale() {
     127            return meterPerPixel;
     128        }
     129
     130        /**
     131         * Convert this viewport data to a {@link ViewportData} object (with projected coordinates).
     132         * @param proj the projection to convert from lat/lon to east/north
     133         * @return the corresponding ViewportData object
     134         */
     135        public ViewportData getEastNorthViewport(Projection proj) {
     136            EastNorth centerEN = proj.latlon2eastNorth(center);
     137            // Get a "typical" distance in east/north units that
     138            // corresponds to a couple of pixels. Shouldn't be too
     139            // large, to keep it within projection bounds and
     140            // not too small to avoid rounding errors.
     141            double dist = 0.01 * proj.getDefaultZoomInPPD();
     142            LatLon ll1 = proj.eastNorth2latlon(new EastNorth(centerEN.east() - dist, centerEN.north()));
     143            LatLon ll2 = proj.eastNorth2latlon(new EastNorth(centerEN.east() + dist, centerEN.north()));
     144            double meterPerEasting = ll1.greatCircleDistance(ll2) / dist / 2;
     145            double scale = meterPerPixel / meterPerEasting; // unit: easting per pixel
     146            return new ViewportData(centerEN, scale);
     147        }
     148    }
     149
    60150    private static final Map<String, Class<? extends SessionLayerImporter>> sessionLayerImporters = new HashMap<>();
    61151
     
    66156    private int active = -1;
    67157    private final List<Runnable> postLoadTasks = new ArrayList<>();
    68     private ViewportData viewport;
     158    private SessionViewportData viewport;
     159    private SessionProjectionChoiceData projectionChoice;
    69160
    70161    static {
     
    130221    /**
    131222     * Return the viewport (map position and scale).
    132      * @return The viewport. Can be null when no viewport info is found in the file.
    133      */
    134     public ViewportData getViewport() {
     223     * @return the viewport; can be null when no viewport info is found in the file
     224     */
     225    public SessionViewportData getViewport() {
    135226        return viewport;
     227    }
     228
     229    /**
     230     * Return the projection choice data.
     231     * @return the projection; can be null when no projection info is found in the file
     232     */
     233    public SessionProjectionChoiceData getProjectionChoice() {
     234        return projectionChoice;
    136235    }
    137236
     
    339438        }
    340439
    341         Element viewportEl = getElementByTagName(root, "viewport");
    342         if (viewportEl != null) {
    343             EastNorth center = null;
    344             Element centerEl = getElementByTagName(viewportEl, "center");
    345             if (centerEl != null && centerEl.hasAttribute("lat") && centerEl.hasAttribute("lon")) {
    346                 try {
    347                     LatLon centerLL = new LatLon(Double.parseDouble(centerEl.getAttribute("lat")),
    348                             Double.parseDouble(centerEl.getAttribute("lon")));
    349                     center = Projections.project(centerLL);
    350                 } catch (NumberFormatException ex) {
    351                     Main.warn(ex);
    352                 }
    353             }
    354             if (center != null) {
    355                 Element scaleEl = getElementByTagName(viewportEl, "scale");
    356                 if (scaleEl != null && scaleEl.hasAttribute("meter-per-pixel")) {
    357                     try {
    358                         double meterPerPixel = Double.parseDouble(scaleEl.getAttribute("meter-per-pixel"));
    359                         Projection proj = Main.getProjection();
    360                         // Get a "typical" distance in east/north units that
    361                         // corresponds to a couple of pixels. Shouldn't be too
    362                         // large, to keep it within projection bounds and
    363                         // not too small to avoid rounding errors.
    364                         double dist = 0.01 * proj.getDefaultZoomInPPD();
    365                         LatLon ll1 = proj.eastNorth2latlon(new EastNorth(center.east() - dist, center.north()));
    366                         LatLon ll2 = proj.eastNorth2latlon(new EastNorth(center.east() + dist, center.north()));
    367                         double meterPerEasting = ll1.greatCircleDistance(ll2) / dist / 2;
    368                         double scale = meterPerPixel / meterPerEasting; // unit: easting per pixel
    369                         viewport = new ViewportData(center, scale);
    370                     } catch (NumberFormatException ex) {
    371                         Main.warn(ex);
    372                     }
    373                 }
    374             }
    375         }
     440        viewport = readViewportData(root);
     441        projectionChoice = readProjectionChoiceData(root);
    376442
    377443        Element layersEl = getElementByTagName(root, "layers");
     
    550616    }
    551617
     618    private SessionViewportData readViewportData(Element root) {
     619        Element viewportEl = getElementByTagName(root, "viewport");
     620        if (viewportEl == null) return null;
     621        LatLon center = null;
     622        Element centerEl = getElementByTagName(viewportEl, "center");
     623        if (centerEl == null || !centerEl.hasAttribute("lat") || !centerEl.hasAttribute("lon")) return null;
     624        try {
     625            center = new LatLon(Double.parseDouble(centerEl.getAttribute("lat")),
     626                    Double.parseDouble(centerEl.getAttribute("lon")));
     627        } catch (NumberFormatException ex) {
     628            Main.warn(ex);
     629        }
     630        if (center == null) return null;
     631        Element scaleEl = getElementByTagName(viewportEl, "scale");
     632        if (scaleEl == null || !scaleEl.hasAttribute("meter-per-pixel")) return null;
     633        try {
     634            double scale = Double.parseDouble(scaleEl.getAttribute("meter-per-pixel"));
     635            return new SessionViewportData(center, scale);
     636        } catch (NumberFormatException ex) {
     637            Main.warn(ex);
     638            return null;
     639        }
     640    }
     641
     642    private SessionProjectionChoiceData readProjectionChoiceData(Element root) {
     643        Element projectionEl = getElementByTagName(root, "projection");
     644        if (projectionEl == null) return null;
     645        Element projectionChoiceEl = getElementByTagName(projectionEl, "projection-choice");
     646        if (projectionChoiceEl == null) return null;
     647        Element idEl = getElementByTagName(projectionChoiceEl, "id");
     648        if (idEl == null) return null;
     649        String id = idEl.getTextContent();
     650        Element parametersEl = getElementByTagName(projectionChoiceEl, "parameters");
     651        if (parametersEl == null) return null;
     652        Collection<String> parameters = new ArrayList<>();
     653        NodeList paramNl = parametersEl.getElementsByTagName("param");
     654        for (int i=0; i<paramNl.getLength(); i++) {
     655            Element paramEl = (Element) paramNl.item(i);
     656            parameters.add(paramEl.getTextContent());
     657        }
     658        return new SessionProjectionChoiceData(id, parameters);
     659    }
     660
    552661    /**
    553662     * Show Dialog when there is an error for one layer.
Note: See TracChangeset for help on using the changeset viewer.