Ticket #6421: 0001-Combined-commits-from-cached-lat-lon-patch-against-J.patch

File 0001-Combined-commits-from-cached-lat-lon-patch-against-J.patch, 114.3 KB (added by anonymous, 15 years ago)

Updated patch against JOSM 4115, includes suggestions from this ticket

  • src/org/openstreetmap/josm/Main.java

    From 77f5b2b45b8c07f1b32922d324148a7452c30e43 Mon Sep 17 00:00:00 2001
    From: Gubaer <karl.gugisberg@guggis.ch>
    Date: Sun, 5 Jun 2011 11:01:23 +0200
    Subject: [PATCH] Combined commits from cached-lat-lon, patch against JOSM 4115
    
    ---
     src/org/openstreetmap/josm/Main.java               |  116 ++++++++++++++++++-
     .../josm/actions/CreateCircleAction.java           |    4 +-
     .../josm/actions/ImageryAdjustAction.java          |    4 +-
     .../josm/actions/OrthogonalizeAction.java          |    2 +-
     .../josm/actions/mapmode/ExtrudeAction.java        |   10 +-
     .../openstreetmap/josm/command/MoveCommand.java    |    4 +-
     .../openstreetmap/josm/data/coor/CachedLatLon.java |   88 ++++++++++-----
     src/org/openstreetmap/josm/data/coor/LatLon.java   |    9 +-
     src/org/openstreetmap/josm/data/gpx/GpxTrack.java  |    1 -
     .../josm/data/gpx/ImmutableGpxTrackSegment.java    |    1 -
     src/org/openstreetmap/josm/data/gpx/WayPoint.java  |   73 +++++++++++-
     .../josm/data/imagery/OffsetBookmark.java          |    6 +-
     src/org/openstreetmap/josm/data/osm/DataSet.java   |   67 +++++++++++-
     src/org/openstreetmap/josm/data/osm/INode.java     |    3 +-
     src/org/openstreetmap/josm/data/osm/Node.java      |  119 +++++++++++++++----
     src/org/openstreetmap/josm/data/osm/NodeData.java  |   38 ++++--
     .../josm/data/osm/visitor/BoundingXYVisitor.java   |   18 +--
     .../data/projection/ProjectionChangeListener.java  |    6 +
     .../josm/data/projection/Projections.java          |   44 +++++---
     .../josm/data/validation/OsmValidator.java         |   57 +++++-----
     src/org/openstreetmap/josm/gui/MapView.java        |    4 +-
     .../josm/gui/NavigatableComponent.java             |   44 +++-----
     src/org/openstreetmap/josm/gui/layer/GpxLayer.java |   36 ++++++-
     .../openstreetmap/josm/gui/layer/ImageryLayer.java |    2 +-
     src/org/openstreetmap/josm/gui/layer/Layer.java    |   12 ++-
     .../openstreetmap/josm/gui/layer/OsmDataLayer.java |   12 ++-
     .../openstreetmap/josm/gui/layer/RawGpsLayer.java  |    2 +-
     src/org/openstreetmap/josm/gui/layer/TMSLayer.java |    4 +-
     .../josm/gui/layer/geoimage/ImageEntry.java        |   10 +-
     .../josm/gui/layer/markerlayer/Marker.java         |   92 +++++++--------
     .../josm/gui/preferences/ImageryPreference.java    |    2 +-
     .../josm/gui/preferences/ProjectionPreference.java |   46 +------
     src/org/openstreetmap/josm/io/imagery/Grabber.java |    2 +-
     .../openstreetmap/josm/io/imagery/HTMLGrabber.java |    2 +-
     .../josm/io/imagery/OsmosnimkiOffsetServer.java    |    4 +-
     .../openstreetmap/josm/io/imagery/WMSGrabber.java  |   18 ++--
     src/org/openstreetmap/josm/tools/Geometry.java     |    8 +-
     .../openstreetmap/josm/fixtures/JOSMFixture.java   |    2 +-
     .../pair/properties/PropertiesMergerTest.java      |    2 +-
     .../josm/gui/history/HistoryBrowserTest.java       |    2 +-
     .../josm/io/MultiFetchServerObjectReaderTest.java  |    2 +-
     .../josm/io/OsmServerBackreferenceReaderTest.java  |    2 +-
     .../data/osm/MapPaintVisitorPerformanceTest.java   |    2 +-
     .../josm/data/osm/DataSetMergerTest.java           |    2 +-
     .../openstreetmap/josm/data/osm/FilterTest.java    |    2 +-
     .../josm/data/osm/NodeProjectionTest.java          |   72 ++++++++++++
     .../josm/data/osm/OsmPrimitiveTest.java            |    2 +-
     .../josm/data/osm/QuadBucketsTest.java             |    4 +-
     .../openstreetmap/josm/data/osm/RelationTest.java  |    2 +-
     .../visitor/MergeSourceBuildingVisitorTest.java    |    2 +-
     .../josm/data/projection/SwissGridTest.java        |  122 +++++++++++++-------
     .../properties/PropertiesMergeModelTest.java       |    2 +-
     52 files changed, 826 insertions(+), 366 deletions(-)
     create mode 100644 src/org/openstreetmap/josm/data/projection/ProjectionChangeListener.java
     create mode 100644 test/unit/org/openstreetmap/josm/data/osm/NodeProjectionTest.java
    
    diff --git a/src/org/openstreetmap/josm/Main.java b/src/org/openstreetmap/josm/Main.java
    index c25d00b..4ddd9e0 100644
    a b import java.awt.event.KeyEvent;  
    1515import java.awt.event.WindowAdapter;
    1616import java.awt.event.WindowEvent;
    1717import java.io.File;
     18import java.lang.ref.WeakReference;
    1819import java.net.URI;
    1920import java.net.URISyntaxException;
    2021import java.util.ArrayList;
    2122import java.util.Collection;
     23import java.util.Iterator;
    2224import java.util.List;
    2325import java.util.Map;
    2426import java.util.StringTokenizer;
    import org.openstreetmap.josm.data.coor.LatLon;  
    5557import org.openstreetmap.josm.data.osm.DataSet;
    5658import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy;
    5759import org.openstreetmap.josm.data.projection.Projection;
     60import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
    5861import org.openstreetmap.josm.data.validation.OsmValidator;
    5962import org.openstreetmap.josm.gui.GettingStarted;
    6063import org.openstreetmap.josm.gui.MainMenu;
    import org.openstreetmap.josm.gui.preferences.TaggingPresetPreference;  
    7275import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
    7376import org.openstreetmap.josm.io.OsmApi;
    7477import org.openstreetmap.josm.plugins.PluginHandler;
     78import org.openstreetmap.josm.tools.CheckParameterUtil;
    7579import org.openstreetmap.josm.tools.I18n;
    7680import org.openstreetmap.josm.tools.ImageProvider;
    7781import org.openstreetmap.josm.tools.OsmUrlToBounds;
    abstract public class Main {  
    118122     */
    119123    public static PrimitiveDeepCopy pasteBuffer = new PrimitiveDeepCopy();
    120124    public static Layer pasteSource;
    121     /**
    122      * The projection method used.
    123      */
    124     public static Projection proj;
     125
     126
    125127    /**
    126128     * The MapFrame. Use setMapFrame to set or clear it.
    127129     */
    abstract public class Main {  
    212214        isOpenjdk = System.getProperty("java.vm.name").toUpperCase().indexOf("OPENJDK") != -1;
    213215        platform.startupHook();
    214216
    215         // We try to establish an API connection early, so that any API 
     217        // We try to establish an API connection early, so that any API
    216218        // capabilities are already known to the editor instance. However
    217219        // if it goes wrong that's not critical at this stage.
    218220        try {
    abstract public class Main {  
    767769        }
    768770        System.err.println("Error: Could not recognize Java Version: "+version);
    769771    }
     772
     773    /* ----------------------------------------------------------------------------------------- */
     774    /* projection handling  - Main is a registry for a single, global projection instance        */
     775    /*                                                                                           */
     776    /* TODO: For historical reasons the registry is implemented by Main. An alternative approach */
     777    /* would be a singleton org.openstreetmap.josm.data.projection.ProjectionRegistry class.     */
     778    /* ----------------------------------------------------------------------------------------- */
     779    /**
     780     * The projection method used.
     781     * @deprecated use {@link #getProjection()} and {@link #setProjection(Projection)} instead.
     782     * For the time being still publicly available, but avoid/migrate write access to it. Use
     783     * {@link #setProjection(Projection)} in order to trigger a projection change event.
     784     */
     785    @Deprecated
     786    public static Projection proj;
     787
     788    /**
     789     * Replies the current projection.
     790     *
     791     * @return
     792     */
     793    public static Projection getProjection() {
     794        return proj;
     795    }
     796
     797    /**
     798     * Sets the current projection
     799     *
     800     * @param p the projection
     801     */
     802    public static void setProjection(Projection p) {
     803        CheckParameterUtil.ensureParameterNotNull(p);
     804        Projection oldValue = proj;
     805        proj = p;
     806        fireProjectionChanged(oldValue, proj);
     807    }
     808
     809    /*
     810     * Keep WeakReferences to the listeners. This relieves clients from the burden of
     811     * explicitly removing the listeners and allows us to transparently register every
     812     * created dataset as projection change listener.
     813     */
     814    private static final ArrayList<WeakReference<ProjectionChangeListener>> listeners = new ArrayList<WeakReference<ProjectionChangeListener>>();
     815
     816    private static void fireProjectionChanged(Projection oldValue, Projection newValue) {
     817        if (newValue == null ^ oldValue == null
     818                || (newValue != null && oldValue != null && !newValue.getClass().getName().equals(oldValue.getClass().getName()))) {
     819
     820            synchronized(Main.class) {
     821                Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
     822                while(it.hasNext()){
     823                    WeakReference<ProjectionChangeListener> wr = it.next();
     824                    if (wr.get() == null) {
     825                        it.remove();
     826                        continue;
     827                    }
     828                    wr.get().projectionChanged(oldValue, newValue);
     829                }
     830            }
     831            if (newValue != null) {
     832                Bounds b = (Main.map != null && Main.map.mapView != null) ? Main.map.mapView.getRealBounds() : null;
     833                if (b != null){
     834                    Main.map.mapView.zoomTo(b);
     835                }
     836            }
     837            /* TODO - remove layers with fixed projection */
     838        }
     839    }
     840
     841    /**
     842     * Register a projection change listener
     843     *
     844     * @param listener the listener. Ignored if null.
     845     */
     846    public static void addProjectionChangeListener(ProjectionChangeListener listener) {
     847        if (listener == null) return;
     848        synchronized (Main.class) {
     849            for (WeakReference<ProjectionChangeListener> wr : listeners) {
     850                // already registered ? => abort
     851                if (wr.get() == listener) return;
     852            }
     853        }
     854        listeners.add(new WeakReference<ProjectionChangeListener>(listener));
     855    }
     856
     857    /**
     858     * Removes a projection change listener
     859     *
     860     * @param listener the listener. Ignored if null.
     861     */
     862    public static void removeProjectionChangeListener(ProjectionChangeListener listener) {
     863        if (listener == null) return;
     864        synchronized(Main.class){
     865            Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
     866            while(it.hasNext()){
     867                WeakReference<ProjectionChangeListener> wr = it.next();
     868                // remove the listener - and any other listener which god garbage
     869                // collected in the meantime
     870                if (wr.get() == null || wr.get() == listener) {
     871                    it.remove();
     872                }
     873            }
     874        }
     875    }
    770876}
  • src/org/openstreetmap/josm/actions/CreateCircleAction.java

    diff --git a/src/org/openstreetmap/josm/actions/CreateCircleAction.java b/src/org/openstreetmap/josm/actions/CreateCircleAction.java
    index ebf7666..1afea76 100644
    a b public final class CreateCircleAction extends JosmAction {  
    152152                    // get the position of the new node and insert it
    153153                    double x = xc + r*Math.cos(a);
    154154                    double y = yc + r*Math.sin(a);
    155                     Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
     155                    Node n = new Node(Main.getProjection().eastNorth2latlon(new EastNorth(x,y)));
    156156                    wayToAdd.add(n);
    157157                    cmds.add(new AddCommand(n));
    158158                }
    public final class CreateCircleAction extends JosmAction {  
    244244                // get the position of the new node and insert it
    245245                double x = xc + r*Math.cos(a);
    246246                double y = yc + r*Math.sin(a);
    247                 Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
     247                Node n = new Node(Main.getProjection().eastNorth2latlon(new EastNorth(x,y)));
    248248                wayToAdd.add(n);
    249249                cmds.add(new AddCommand(n));
    250250            }
  • src/org/openstreetmap/josm/actions/ImageryAdjustAction.java

    diff --git a/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java b/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java
    index 9380fc1..3d5b844 100644
    a b public class ImageryAdjustAction extends MapMode implements MouseListener, Mouse  
    161161            JPanel pnl = new JPanel(new GridBagLayout());
    162162            pnl.add(new JMultilineLabel(tr("Use arrow keys or drag the imagery layer with mouse to adjust the imagery offset.\n" +
    163163                    "You can also enter east and north offset in the {0} coordinates.\n" +
    164                     "If you want to save the offset as bookmark, enter the bookmark name below",Main.proj.toString())), GBC.eop());
     164                    "If you want to save the offset as bookmark, enter the bookmark name below",Main.getProjection().toString())), GBC.eop());
    165165            pnl.add(new JLabel(tr("Offset: ")),GBC.std());
    166166            pnl.add(tOffset,GBC.eol().fill(GBC.HORIZONTAL).insets(0,0,0,5));
    167167            pnl.add(new JLabel(tr("Bookmark name: ")),GBC.std());
    public class ImageryAdjustAction extends MapMode implements MouseListener, Mouse  
    210210
    211211        public void updateOffsetIntl() {
    212212            // Support projections with very small numbers (e.g. 4326)
    213             int precision = Main.proj.getDefaultZoomInPPD() >= 1.0 ? 2 : 7;
     213            int precision = Main.getProjection().getDefaultZoomInPPD() >= 1.0 ? 2 : 7;
    214214            // US locale to force decimal separator to be '.'
    215215            tOffset.setText(new java.util.Formatter(java.util.Locale.US).format(
    216216                    "%1." + precision + "f; %1." + precision + "f",
  • src/org/openstreetmap/josm/actions/OrthogonalizeAction.java

    diff --git a/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java b/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java
    index d4b7714..a7df4da 100644
    a b public final class OrthogonalizeAction extends JosmAction {  
    116116    public void actionPerformed(ActionEvent e) {
    117117        if (!isEnabled())
    118118            return;
    119         if ("EPSG:4326".equals(Main.proj.toString())) {
     119        if ("EPSG:4326".equals(Main.getProjection().toString())) {
    120120            String msg = tr("<html>You are using the EPSG:4326 projection which might lead<br>" +
    121121                    "to undesirable results when doing rectangular alignments.<br>" +
    122122                    "Change your projection to get rid of this warning.<br>" +
  • src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java

    diff --git a/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java b/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
    index 252852c..63c8960 100644
    a b public class ExtrudeAction extends MapMode implements MapViewPaintable {  
    254254            newN2en = new EastNorth(initialN2en.getX() + bestMovement.getX(), initialN2en.getY() + bestMovement.getY());
    255255
    256256            // find out the movement distance, in metres
    257             double distance = Main.proj.eastNorth2latlon(initialN1en).greatCircleDistance(Main.proj.eastNorth2latlon(newN1en));
     257            double distance = Main.getProjection().eastNorth2latlon(initialN1en).greatCircleDistance(Main.getProjection().eastNorth2latlon(newN1en));
    258258            Main.map.statusLine.setDist(distance);
    259259            updateStatusLine();
    260260
    public class ExtrudeAction extends MapMode implements MapViewPaintable {  
    308308                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    309309                        //move existing node
    310310                        Node n1Old = selectedSegment.getFirstNode();
    311                         cmds.add(new MoveCommand(n1Old, Main.proj.eastNorth2latlon(newN1en)));
     311                        cmds.add(new MoveCommand(n1Old, Main.getProjection().eastNorth2latlon(newN1en)));
    312312                    } else {
    313313                        //introduce new node
    314                         Node n1New = new Node(Main.proj.eastNorth2latlon(newN1en));
     314                        Node n1New = new Node(Main.getProjection().eastNorth2latlon(newN1en));
    315315                        wnew.addNode(insertionPoint, n1New);
    316316                        insertionPoint ++;
    317317                        cmds.add(new AddCommand(n1New));
    public class ExtrudeAction extends MapMode implements MapViewPaintable {  
    325325                    if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) {
    326326                        //move existing node
    327327                        Node n2Old = selectedSegment.getSecondNode();
    328                         cmds.add(new MoveCommand(n2Old, Main.proj.eastNorth2latlon(newN2en)));
     328                        cmds.add(new MoveCommand(n2Old, Main.getProjection().eastNorth2latlon(newN2en)));
    329329                    } else {
    330330                        //introduce new node
    331                         Node n2New = new Node(Main.proj.eastNorth2latlon(newN2en));
     331                        Node n2New = new Node(Main.getProjection().eastNorth2latlon(newN2en));
    332332                        wnew.addNode(insertionPoint, n2New);
    333333                        insertionPoint ++;
    334334                        cmds.add(new AddCommand(n2New));
  • src/org/openstreetmap/josm/command/MoveCommand.java

    diff --git a/src/org/openstreetmap/josm/command/MoveCommand.java b/src/org/openstreetmap/josm/command/MoveCommand.java
    index b7b5d25..ba43d5d 100644
    a b import java.util.List;  
    1111
    1212import javax.swing.JLabel;
    1313
    14 import org.openstreetmap.josm.data.coor.CachedLatLon;
    1514import org.openstreetmap.josm.data.coor.EastNorth;
    1615import org.openstreetmap.josm.data.coor.LatLon;
    1716import org.openstreetmap.josm.data.osm.Node;
    1817import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1918import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
     19import org.openstreetmap.josm.data.projection.Projections;
    2020import org.openstreetmap.josm.tools.ImageProvider;
    2121
    2222/**
    public class MoveCommand extends Command {  
    5858    }
    5959
    6060    public MoveCommand(Node node, LatLon position) {
    61         this(Collections.singleton((OsmPrimitive) node), node.getEastNorth().sub(new CachedLatLon(position).getEastNorth()));
     61        this(Collections.singleton((OsmPrimitive) node), node.getEastNorth().sub(Projections.project(position)));
    6262    }
    6363
    6464    public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) {
  • src/org/openstreetmap/josm/data/coor/CachedLatLon.java

    diff --git a/src/org/openstreetmap/josm/data/coor/CachedLatLon.java b/src/org/openstreetmap/josm/data/coor/CachedLatLon.java
    index 6858705..f40c264 100644
    a b  
    22package org.openstreetmap.josm.data.coor;
    33
    44import org.openstreetmap.josm.Main;
     5import org.openstreetmap.josm.data.gpx.WayPoint;
    56import org.openstreetmap.josm.data.projection.Projection;
    67
     8/**
     9 * <p>Maintains an internal cache of the projected lat/lon coordinates.</p>
     10 *
     11 * <p><strong>Caveat:</strong> instances do not listen to {@link ProjectionChangeEvents}s. Clients have to make
     12 * sure that they invalidate the internal cache if the {@link Main#getProjection() global projection} changes.</p>
     13 *
     14 * @deprecated Don't use anymore. If necessary, maintain a cache of projected coordinates elsewhere. See {@link Node} and {@link WayPoint} for examples.
     15 *
     16 */
     17@Deprecated
    718public class CachedLatLon extends LatLon {
    8     private EastNorth eastNorth;
    9     private Projection proj;
    1019
     20    private double east = java.lang.Double.NaN;
     21    private double north = java.lang.Double.NaN;
     22
     23    /**
     24     * Constructor
     25     *
     26     * @param lat latitude
     27     * @param lon longitude
     28     */
    1129    public CachedLatLon(double lat, double lon) {
    12         super(lat, lon);
     30        this(new LatLon(lat,lon));
    1331    }
    1432
     33    /**
     34     * Constructor
     35     *
     36     * @param coor lat/lon pair. If null, assumes lat/lon pair (0,0)
     37     */
    1538    public CachedLatLon(LatLon coor) {
    16         super(coor.lat(), coor.lon());
    17         proj = null;
     39        super(coor == null ? new LatLon(0,0) : coor);
    1840    }
    1941
     42    /**
     43     * Constructor
     44     *
     45     * Inversely projects {@code eastNorth} using {@link Main#getProjection() the current projection}. Throws
     46     * an assertion exception, if this projection isn't set.
     47     *
     48     * @param eastNorth  the projected east/north coordinates. Assumes (0/0) if null.
     49     */
    2050    public CachedLatLon(EastNorth eastNorth) {
    21         super(Main.proj.eastNorth2latlon(eastNorth));
    22         proj = Main.proj;
    23         this.eastNorth = eastNorth;
     51        super(Main.getProjection().eastNorth2latlon(eastNorth = eastNorth == null ? new EastNorth(0, 0) : eastNorth));
     52        this.east = eastNorth.east();
     53        this.north = eastNorth.north();
    2454    }
    2555
    26     public final void setCoor(LatLon coor) {
    27         setLocation(coor.lon(), coor.lat());
    28         proj = null;
     56    /**
     57     * Replies the projected east/north coordinates.
     58     *
     59     * @return the internally cached east/north coordinates. null, if the globally defined projection is null
     60     */
     61    public final EastNorth getEastNorth() {
     62        if (east == java.lang.Double.NaN && north == java.lang.Double.NaN) {
     63            Projection p = Main.getProjection();
     64            if (p == null) return null;
     65            EastNorth en = p.latlon2eastNorth(this);
     66            this.east = en.east();
     67            this.north = en.north();
     68            return en;
     69        } else
     70            return new EastNorth(east, north);
    2971    }
    3072
    31     public final void setEastNorth(EastNorth eastNorth) {
    32         proj = Main.proj;
    33         this.eastNorth = eastNorth;
    34         LatLon l = proj.eastNorth2latlon(eastNorth);
    35         setLocation(l.lon(), l.lat());
     73    /**
     74     * Invalidate the internal cache for east/north coordinates
     75     */
     76    public void invalidateEastNorthCache() {
     77        this.east = java.lang.Double.NaN;
     78        this.north = java.lang.Double.NaN;
    3679    }
    3780
    38     public final EastNorth getEastNorth() {
    39         if(proj != Main.proj)
    40         {
    41             proj = Main.proj;
    42             eastNorth = proj.latlon2eastNorth(this);
    43         }
    44         return eastNorth;
    45     }
    4681    @Override public String toString() {
    4782        return "CachedLatLon[lat="+lat()+",lon="+lon()+"]";
    4883    }
    49 
    50     // Only for Node.get3892DebugInfo()
    51     public Projection getProjection() {
    52         return proj;
    53     }
    5484}
  • src/org/openstreetmap/josm/data/coor/LatLon.java

    diff --git a/src/org/openstreetmap/josm/data/coor/LatLon.java b/src/org/openstreetmap/josm/data/coor/LatLon.java
    index 63ffdb5..084bc9c 100644
    a b  
    11// License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.data.coor;
    33
    4 import static org.openstreetmap.josm.tools.I18n.trc;
    5 
    64import static java.lang.Math.PI;
    75import static java.lang.Math.asin;
    86import static java.lang.Math.cos;
    97import static java.lang.Math.sin;
    108import static java.lang.Math.sqrt;
    119import static java.lang.Math.toRadians;
     10import static org.openstreetmap.josm.tools.I18n.trc;
    1211
    1312import java.text.DecimalFormat;
    1413import java.text.NumberFormat;
    public class LatLon extends Coordinate {  
    105104        case DECIMAL_DEGREES: return cDdFormatter.format(y);
    106105        case DEGREES_MINUTES_SECONDS: return dms(y) + ((y < 0) ? SOUTH : NORTH);
    107106        case NAUTICAL: return dm(y) + ((y < 0) ? SOUTH : NORTH);
    108         case EAST_NORTH: return cDdFormatter.format(Main.proj.latlon2eastNorth(this).north());
     107        case EAST_NORTH: return cDdFormatter.format(Main.getProjection().latlon2eastNorth(this).north());
    109108        default: return "ERR";
    110109        }
    111110    }
    public class LatLon extends Coordinate {  
    121120        case DECIMAL_DEGREES: return cDdFormatter.format(x);
    122121        case DEGREES_MINUTES_SECONDS: return dms(x) + ((x < 0) ? WEST : EAST);
    123122        case NAUTICAL: return dm(x) + ((x < 0) ? WEST : EAST);
    124         case EAST_NORTH: return cDdFormatter.format(Main.proj.latlon2eastNorth(this).east());
     123        case EAST_NORTH: return cDdFormatter.format(Main.getProjection().latlon2eastNorth(this).east());
    125124        default: return "ERR";
    126125        }
    127126    }
    public class LatLon extends Coordinate {  
    141140     * by using lat/lon.
    142141     */
    143142    public boolean isOutSideWorld() {
    144         Bounds b = Main.proj.getWorldBoundsLatLon();
     143        Bounds b = Main.getProjection().getWorldBoundsLatLon();
    145144        return lat() < b.getMin().lat() || lat() > b.getMax().lat() ||
    146145        lon() < b.getMin().lon() || lon() > b.getMax().lon();
    147146    }
  • src/org/openstreetmap/josm/data/gpx/GpxTrack.java

    diff --git a/src/org/openstreetmap/josm/data/gpx/GpxTrack.java b/src/org/openstreetmap/josm/data/gpx/GpxTrack.java
    index db7c57d..ce837aa 100644
    a b public interface GpxTrack {  
    2525     * @return Number of times this track has been changed. Always 0 for read-only tracks
    2626     */
    2727    int getUpdateCount();
    28 
    2928}
  • src/org/openstreetmap/josm/data/gpx/ImmutableGpxTrackSegment.java

    diff --git a/src/org/openstreetmap/josm/data/gpx/ImmutableGpxTrackSegment.java b/src/org/openstreetmap/josm/data/gpx/ImmutableGpxTrackSegment.java
    index 5a6eff6..6e76bf3 100644
    a b public class ImmutableGpxTrackSegment implements GpxTrackSegment {  
    6464    public int getUpdateCount() {
    6565        return 0;
    6666    }
    67 
    6867}
  • src/org/openstreetmap/josm/data/gpx/WayPoint.java

    diff --git a/src/org/openstreetmap/josm/data/gpx/WayPoint.java b/src/org/openstreetmap/josm/data/gpx/WayPoint.java
    index 94b41c6..3ec724d 100644
    a b package org.openstreetmap.josm.data.gpx;  
    66import java.awt.Color;
    77import java.util.Date;
    88
    9 import org.openstreetmap.josm.data.coor.CachedLatLon;
     9import org.openstreetmap.josm.Main;
    1010import org.openstreetmap.josm.data.coor.EastNorth;
    1111import org.openstreetmap.josm.data.coor.LatLon;
     12import org.openstreetmap.josm.data.projection.Projection;
    1213import org.openstreetmap.josm.tools.PrimaryDateParser;
    1314
    1415public class WayPoint extends WithAttributes implements Comparable<WayPoint> {
    public class WayPoint extends WithAttributes implements Comparable<WayPoint> {  
    2526    public int dir;
    2627
    2728    public WayPoint(LatLon ll) {
    28         coor = new CachedLatLon(ll);
     29        lat = ll.lat();
     30        lon = ll.lon();
    2931    }
    3032
    31     private final CachedLatLon coor;
     33    /*
     34     * We "inline" lat/lon, rather than usinga LatLon internally => reduces memory overhead. Relevant
     35     * because a lot of GPX waypoints are created when GPS tracks are downloaded from the OSM server.
     36     */
     37    private double lat = 0;
     38    private double lon = 0;
     39
     40    /*
     41     * internal cache of projected coordinates
     42     */
     43    private double east = Double.NaN;
     44    private double north = Double.NaN;
     45
     46    private boolean isAlreadyProjected() {
     47        return ! Double.isNaN(east) && ! Double.isNaN(north);
     48    }
     49
     50    /**
     51     * <p>Reproject the coordinates and refresh  the internal cache of the projected coordinates.</p>
     52     */
     53    public void reproject() {
     54        Projection p = Main.getProjection();
     55        if (p == null){
     56            east = Double.NaN;
     57            north = Double.NaN;
     58            return;
     59        }
     60        EastNorth en = p.latlon2eastNorth(getCoor());
     61        east = en.east();
     62        north = en.north();
     63    }
     64
     65    /**
     66     * Invalidate the internal cache of east/north coordinates.
     67     */
     68    public void invalidateEastNorthCache() {
     69        this.east = Double.NaN;
     70        this.north = Double.NaN;
     71    }
    3272
    3373    public final LatLon getCoor() {
    34         return coor;
     74        return new LatLon(lat,lon);
    3575    }
    3676
     77
     78    /**
     79     * <p>Replies the projected east/north coordinates.</p>
     80     *
     81     * <p>Uses the {@link Main#getProjection() global projection} to project the lan/lon-coordinates.
     82     * Internally caches the projected coordinates.</p>
     83     *
     84     * <p><strong>Caveat:</strong> doesn't listen to projection changes. Clients must
     85     * {@link #reproject() trigger a reprojection} or {@link #invalidateEastNorthCache() invalidate the internal cache}.</p>
     86     *
     87     * <p>Replies {@code null}, if no global projection is defined.</p>
     88     *
     89     * @return the east north coordinates or {@code null}
     90     * @see #reproject()
     91     * @see #invalidateEastNorthCache()
     92     *
     93     */
    3794    public final EastNorth getEastNorth() {
    38         return coor.getEastNorth();
     95        if (isAlreadyProjected())
     96            return new EastNorth(east, north);
     97        reproject();
     98        if (!isAlreadyProjected()) return null;
     99        return new EastNorth(east, north);
    39100    }
    40101
    41102    @Override
    42103    public String toString() {
    43         return "WayPoint (" + (attr.containsKey("name") ? attr.get("name") + ", " :"") + coor.toString() + ", " + attr + ")";
     104        return "WayPoint (" + (attr.containsKey("name") ? attr.get("name") + ", " :"") + getCoor().toString() + ", " + attr + ")";
    44105    }
    45106
    46107    /**
  • src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java

    diff --git a/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java b/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java
    index d6d8c6c..838542a 100644
    a b public class OffsetBookmark {  
    2929
    3030    public boolean isUsable(ImageryLayer layer) {
    3131        if (proj == null) return false;
    32         if (!Main.proj.toCode().equals(proj.toCode())) return false;
     32        if (!Main.getProjection().toCode().equals(proj.toCode())) return false;
    3333        return layer.getInfo().getName().equals(layerName);
    3434    }
    3535
    public class OffsetBookmark {  
    121121    public static void bookmarkOffset(String name, ImageryLayer layer) {
    122122        LatLon center;
    123123        if (Main.map != null && Main.map.mapView != null) {
    124             center = Main.proj.eastNorth2latlon(Main.map.mapView.getCenter());
     124            center = Main.getProjection().eastNorth2latlon(Main.map.mapView.getCenter());
    125125        } else {
    126126            center = new LatLon(0,0);
    127127        }
    128128        OffsetBookmark nb = new OffsetBookmark(
    129                 Main.proj, layer.getInfo().getName(),
     129                Main.getProjection(), layer.getInfo().getName(),
    130130                name, layer.getDx(), layer.getDy(), center.lon(), center.lat());
    131131        for (ListIterator<OffsetBookmark> it = allBookmarks.listIterator();it.hasNext();) {
    132132            OffsetBookmark b = it.next();
  • src/org/openstreetmap/josm/data/osm/DataSet.java

    diff --git a/src/org/openstreetmap/josm/data/osm/DataSet.java b/src/org/openstreetmap/josm/data/osm/DataSet.java
    index 0cde797..dae4fac 100644
    a b import java.util.concurrent.locks.Lock;  
    1919import java.util.concurrent.locks.ReadWriteLock;
    2020import java.util.concurrent.locks.ReentrantReadWriteLock;
    2121
     22import org.openstreetmap.josm.Main;
    2223import org.openstreetmap.josm.data.Bounds;
    2324import org.openstreetmap.josm.data.SelectionChangedListener;
    2425import org.openstreetmap.josm.data.coor.EastNorth;
    import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;  
    3334import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
    3435import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
    3536import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
     37import org.openstreetmap.josm.data.projection.Projection;
     38import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
    3639import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
    3740import org.openstreetmap.josm.tools.FilteredCollection;
    3841import org.openstreetmap.josm.tools.Predicate;
    import org.openstreetmap.josm.tools.SubclassFilteredCollection;  
    8285 *
    8386 * @author imi
    8487 */
    85 public class DataSet implements Cloneable {
     88public class DataSet implements Cloneable, ProjectionChangeListener {
    8689
    8790    /**
    8891     * Maximum number of events that can be fired between beginUpdate/endUpdate to be send as single events (ie without DatasetChangedEvent)
    public class DataSet implements Cloneable {  
    120123    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    121124    private final Object selectionLock = new Object();
    122125
     126    public DataSet() {
     127        /*
     128         * Transparently register as projection change lister. No need to explicitly remove the
     129         * the listener, projection change listeners are managed as WeakReferences.
     130         */
     131        Main.addProjectionChangeListener(this);
     132    }
     133
    123134    public Lock getReadLock() {
    124135        return lock.readLock();
    125136    }
    public class DataSet implements Cloneable {  
    974985        highlightUpdateCount++;
    975986    }
    976987
     988
     989    /**
     990     * Triggers a refresh of cached projected coordinates.
     991     *
     992     * This method can be invoked after the globally configured projection method
     993     * changed.
     994     */
     995    public void reproject() {
     996        if (Main.getProjection() == null) return; // sanity check
     997        try {
     998            beginUpdate();
     999            for (OsmPrimitive p: allPrimitives) {
     1000                if ( ! (p instanceof Node)) {
     1001                    continue;
     1002                }
     1003                Node n = (Node)p;
     1004                n.reproject();
     1005            }
     1006        } finally {
     1007            endUpdate();
     1008        }
     1009    }
     1010
     1011    /**
     1012     * Invalidates the internal cache of projected east/north coordinates.
     1013     *
     1014     * This method can be invoked after the globally configured projection method
     1015     * changed. In contrast to {@link DataSet#reproject()} it only invalidates the
     1016     * cache and doesn't reproject the coordinates.
     1017     */
     1018    public void invalidateEastNorthCache() {
     1019        if (Main.getProjection() == null) return; // sanity check
     1020        try {
     1021            beginUpdate();
     1022            for (OsmPrimitive p: allPrimitives) {
     1023                if ( ! (p instanceof Node)) {
     1024                    continue;
     1025                }
     1026                Node n = (Node)p;
     1027                n.invalidateEastNorthCache();
     1028            }
     1029        } finally {
     1030            endUpdate();
     1031        }
     1032    }
     1033
    9771034    public void cleanupDeletedPrimitives() {
    9781035        beginUpdate();
    9791036        try {
    public class DataSet implements Cloneable {  
    10631120        }
    10641121        return ret;
    10651122    }
     1123
     1124    /* --------------------------------------------------------------------------------- */
     1125    /* interface ProjectionChangeListner                                                 */
     1126    /* --------------------------------------------------------------------------------- */
     1127    @Override
     1128    public void projectionChanged(Projection oldValue, Projection newValue) {
     1129        invalidateEastNorthCache();
     1130    }
    10661131}
  • src/org/openstreetmap/josm/data/osm/INode.java

    diff --git a/src/org/openstreetmap/josm/data/osm/INode.java b/src/org/openstreetmap/josm/data/osm/INode.java
    index 68eb01d..40d6cc1 100644
    a b import org.openstreetmap.josm.data.coor.EastNorth;  
    55import org.openstreetmap.josm.data.coor.LatLon;
    66
    77public interface INode extends IPrimitive {
    8    
     8
    99    LatLon getCoor();
    1010    void setCoor(LatLon coor);
    1111    EastNorth getEastNorth();
    1212    void setEastNorth(EastNorth eastNorth);
    13 
    1413}
  • src/org/openstreetmap/josm/data/osm/Node.java

    diff --git a/src/org/openstreetmap/josm/data/osm/Node.java b/src/org/openstreetmap/josm/data/osm/Node.java
    index d11bc81..155f61e 100644
    a b  
    11// License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.data.osm;
    33
    4 import org.openstreetmap.josm.data.coor.CachedLatLon;
     4import org.openstreetmap.josm.Main;
    55import org.openstreetmap.josm.data.coor.EastNorth;
    66import org.openstreetmap.josm.data.coor.LatLon;
    77import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
    88import org.openstreetmap.josm.data.osm.visitor.Visitor;
    9 
     9import org.openstreetmap.josm.data.projection.Projection;
     10import org.openstreetmap.josm.data.projection.Projections;
    1011/**
    1112 * One node data, consisting of one world coordinate waypoint.
    1213 *
    import org.openstreetmap.josm.data.osm.visitor.Visitor;  
    1415 */
    1516public final class Node extends OsmPrimitive implements INode {
    1617
    17     private CachedLatLon coor;
     18    /*
     19     * We "inline" lat/lon rather than using a LatLon-object => reduces memory footprint
     20     */
     21    static private final double COORDINATE_NOT_DEFINED = Double.NaN;
     22    private double lat = COORDINATE_NOT_DEFINED;
     23    private double lon = COORDINATE_NOT_DEFINED;
     24
     25
     26    private boolean isLatLonKnown() {
     27        return lat != COORDINATE_NOT_DEFINED && lon != COORDINATE_NOT_DEFINED;
     28    }
    1829
    1930    @Override
    2031    public final void setCoor(LatLon coor) {
    public final class Node extends OsmPrimitive implements INode {  
    4556
    4657    @Override
    4758    public final LatLon getCoor() {
    48         return coor;
     59        if (!isLatLonKnown()) return null;
     60        return new LatLon(lat,lon);
    4961    }
    5062
     63    /**
     64     * <p>Replies the projected east/north coordinates.</p>
     65     *
     66     * <p>Uses the {@link Main#getProjection() global projection} to project the lan/lon-coordinates.
     67     * Internally caches the projected coordinates.</p>
     68     *
     69     * <p><strong>Caveat:</strong> doesn't listen to projection changes. Clients must
     70     * {@link #reproject() trigger a reprojection} or {@link #invalidateEastNorthCache() invalidate the internal cache}.</p>
     71     *
     72     * <p>Replies {@code null} if this node doesn't know lat/lon-coordinates, i.e. because it is an incomplete node. Also
     73     * replies {@code null}, if no global projection is defined.</p>
     74     *
     75     * @return the east north coordinates or {@code null}
     76     * @see #reproject()
     77     * @see #invalidateEastNorthCache()
     78     *
     79     */
    5180    @Override
    5281    public final EastNorth getEastNorth() {
    53         return coor != null ? coor.getEastNorth() : null;
     82        if (!isLatLonKnown()) return null;
     83        Projection p = Main.getProjection();
     84        if (p == null) return null;
     85        if (!isAlreadyProjected()) {
     86            reproject();
     87        }
     88        return new EastNorth(east, north);
    5489    }
    5590
    5691    /**
    5792     * To be used only by Dataset.reindexNode
    5893     */
    5994    protected void setCoorInternal(LatLon coor, EastNorth eastNorth) {
    60         if(this.coor == null) {
    61             if (eastNorth == null) {
    62                 this.coor = new CachedLatLon(coor);
    63             } else {
    64                 this.coor = new CachedLatLon(eastNorth);
    65             }
    66         } else {
    67             if (eastNorth == null) {
    68                 this.coor.setCoor(coor);
    69             } else {
    70                 this.coor.setEastNorth(eastNorth);
    71             }
     95        if (coor != null){
     96            this.lat = coor.lat();
     97            this.lon = coor.lon();
     98            invalidateEastNorthCache();
     99        } else if (eastNorth != null) {
     100            LatLon ll = Projections.inverseProject(eastNorth);
     101            this.lat = ll.lat();
     102            this.lon = ll.lon();
     103            this.east = eastNorth.east();
     104            this.north = eastNorth.north();
    72105        }
    73106    }
    74107
    public final class Node extends OsmPrimitive implements INode {  
    149182        boolean locked = writeLock();
    150183        try {
    151184            super.cloneFrom(osm);
    152             setCoor(((Node)osm).coor);
     185            setCoor(((Node)osm).getCoor());
    153186        } finally {
    154187            writeUnlock(locked);
    155188        }
    public final class Node extends OsmPrimitive implements INode {  
    172205        try {
    173206            super.mergeFrom(other);
    174207            if (!other.isIncomplete()) {
    175                 setCoor(new LatLon(((Node)other).coor));
     208                setCoor(new LatLon(((Node)other).getCoor()));
    176209            }
    177210        } finally {
    178211            writeUnlock(locked);
    public final class Node extends OsmPrimitive implements INode {  
    199232    }
    200233
    201234    @Override public String toString() {
     235        LatLon coor = getCoor();
    202236        String coorDesc = coor == null?"":"lat="+coor.lat()+",lon="+coor.lon();
    203237        return "{Node id=" + getUniqueId() + " version=" + getVersion() + " " + getFlagsAsString() + " "  + coorDesc+"}";
    204238    }
    public final class Node extends OsmPrimitive implements INode {  
    210244        if (! super.hasEqualSemanticAttributes(other))
    211245            return false;
    212246        Node n = (Node)other;
    213         if (coor == null && n.coor == null)
     247        LatLon coor = getCoor();
     248        LatLon otherCoor = n.getCoor();
     249        if (coor == null && otherCoor == null)
    214250            return true;
    215         else if (coor != null && n.coor != null)
    216             return coor.equalsEpsilon(n.coor);
     251        else if (coor != null && otherCoor != null)
     252            return coor.equalsEpsilon(otherCoor);
    217253        else
    218254            return false;
    219255    }
    public final class Node extends OsmPrimitive implements INode {  
    240276
    241277    @Override
    242278    public void updatePosition() {
    243         // TODO: replace CachedLatLon with simple doubles and update precalculated EastNorth value here
    244279    }
    245280
    246281    public boolean isConnectionNode() {
    public final class Node extends OsmPrimitive implements INode {  
    252287        builder.append("Unexpected error. Please report it to http://josm.openstreetmap.de/ticket/3892\n");
    253288        builder.append(toString());
    254289        builder.append("\n");
    255         if (coor == null) {
     290        if (isLatLonKnown()) {
    256291            builder.append("Coor is null\n");
    257292        } else {
    258             builder.append(String.format("EastNorth: %s\n", coor.getEastNorth()));
    259             builder.append(coor.getProjection());
     293            builder.append(String.format("EastNorth: %s\n", getEastNorth()));
     294            builder.append(Main.getProjection());
    260295            builder.append("\n");
    261296        }
    262297
    263298        return builder.toString();
    264299    }
     300
     301    /*
     302     * the cached projected coordinates
     303     */
     304    private double east = Double.NaN;
     305    private double north = Double.NaN;
     306
     307    private boolean isAlreadyProjected() {
     308        return !Double.isNaN(east) && !Double.isNaN(north);
     309    }
     310
     311    /**
     312     * <p>Refresh the internal cache of the projected node coordinates.</p>
     313     *
     314     * <p>Should be invoked after having switched to a new projection.</p>
     315     */
     316    public void reproject() {
     317        if (!isLatLonKnown()) return;
     318        EastNorth en = Projections.project(getCoor());
     319        this.east = en.east();
     320        this.north = en.north();
     321    }
     322
     323    /**
     324     * Invoke to invalidate the internal cache of projected east/north coordinates.
     325     * Coordinates are reprojected on demand when the {@link #getEastNorth()} is invoked
     326     * next time.
     327     */
     328    public void invalidateEastNorthCache() {
     329        this.east = Double.NaN;
     330        this.north = Double.NaN;
     331    }
    265332}
  • src/org/openstreetmap/josm/data/osm/NodeData.java

    diff --git a/src/org/openstreetmap/josm/data/osm/NodeData.java b/src/org/openstreetmap/josm/data/osm/NodeData.java
    index 16d7f81..73abbb8 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
    33
    4 import org.openstreetmap.josm.data.coor.CachedLatLon;
    54import org.openstreetmap.josm.data.coor.EastNorth;
    65import org.openstreetmap.josm.data.coor.LatLon;
    76import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
     7import org.openstreetmap.josm.data.projection.Projections;
    88
    99public class NodeData extends PrimitiveData implements INode {
    1010
    11     private final CachedLatLon coor = new CachedLatLon(0, 0);
     11    /*
     12     * we "inline" lat/lon coordinates instead of using a LatLon => reduces memory footprint
     13     */
     14    private double lat = 0;
     15    private double lon = 0;
    1216
    13     public NodeData() {
    14 
    15     }
     17    public NodeData() {}
    1618
    1719    public NodeData(NodeData data) {
    1820        super(data);
    public class NodeData extends PrimitiveData implements INode {  
    2123
    2224    @Override
    2325    public LatLon getCoor() {
    24         return coor;
     26        return new LatLon(lat,lon);
    2527    }
    2628
    2729    @Override
    2830    public void setCoor(LatLon coor) {
    29         this.coor.setCoor(coor);
     31        if (coor == null) {
     32            this.lat = 0;
     33            this.lon = 0;
     34        } else {
     35            this.lat = coor.lat();
     36            this.lon = coor.lon();
     37        }
    3038    }
    3139
    3240    @Override
    3341    public EastNorth getEastNorth() {
    34         return this.coor.getEastNorth();
     42        /*
     43         * No internal caching of projected coordinates needed. In contrast to getEastNorth()
     44         * on Node, this method is rarely used. Caching would be overkill.
     45         */
     46        return Projections.project(getCoor());
    3547    }
    3648
    3749    @Override
    3850    public void setEastNorth(EastNorth eastNorth) {
    39         this.coor.setEastNorth(eastNorth);
     51        LatLon ll = Projections.inverseProject(eastNorth);
     52        setCoor(ll);
    4053    }
    4154
    4255    @Override
    public class NodeData extends PrimitiveData implements INode {  
    4659
    4760    @Override
    4861    public String toString() {
    49         return super.toString() + " NODE " + coor;
     62        return super.toString() + " NODE " + getCoor();
    5063    }
    5164
    5265    @Override
    5366    public OsmPrimitiveType getType() {
    5467        return OsmPrimitiveType.NODE;
    5568    }
    56    
    57     @Override 
     69
     70    @Override
    5871    public void visit(PrimitiveVisitor visitor) {
    5972        visitor.visit(this);
    6073    }
    public class NodeData extends PrimitiveData implements INode {  
    6376    public String getDisplayName(NameFormatter formatter) {
    6477        return formatter.format(this);
    6578    }
    66 
    6779}
  • src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java

    diff --git a/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java b/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java
    index 2c29454..63f8903 100644
    a b import java.util.Collection;  
    66import org.openstreetmap.josm.Main;
    77import org.openstreetmap.josm.data.Bounds;
    88import org.openstreetmap.josm.data.ProjectionBounds;
    9 import org.openstreetmap.josm.data.coor.CachedLatLon;
    109import org.openstreetmap.josm.data.coor.EastNorth;
    1110import org.openstreetmap.josm.data.coor.LatLon;
    1211import org.openstreetmap.josm.data.osm.Node;
    public class BoundingXYVisitor extends AbstractVisitor {  
    6160    }
    6261
    6362    public void visit(LatLon latlon) {
    64         if(latlon != null)
    65         {
    66             if(latlon instanceof CachedLatLon) {
    67                 visit(((CachedLatLon)latlon).getEastNorth());
    68             } else {
    69                 visit(Main.proj.latlon2eastNorth(latlon));
    70             }
     63        if(latlon != null){
     64            visit(Main.getProjection().latlon2eastNorth(latlon));
    7165        }
    7266    }
    7367
    public class BoundingXYVisitor extends AbstractVisitor {  
    112106    public void enlargeBoundingBox(double enlargeDegree) {
    113107        if (bounds == null)
    114108            return;
    115         LatLon minLatlon = Main.proj.eastNorth2latlon(bounds.getMin());
    116         LatLon maxLatlon = Main.proj.eastNorth2latlon(bounds.getMax());
     109        LatLon minLatlon = Main.getProjection().eastNorth2latlon(bounds.getMin());
     110        LatLon maxLatlon = Main.getProjection().eastNorth2latlon(bounds.getMax());
    117111        bounds = new ProjectionBounds(
    118                 Main.proj.latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree)),
    119                 Main.proj.latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree)));
     112                Main.getProjection().latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree)),
     113                Main.getProjection().latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree)));
    120114    }
    121115
    122116    @Override public String toString() {
  • new file src/org/openstreetmap/josm/data/projection/ProjectionChangeListener.java

    diff --git a/src/org/openstreetmap/josm/data/projection/ProjectionChangeListener.java b/src/org/openstreetmap/josm/data/projection/ProjectionChangeListener.java
    new file mode 100644
    index 0000000..f5accfc
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.projection;
     3
     4public interface ProjectionChangeListener {
     5    void projectionChanged(Projection oldValue, Projection newValue);
     6}
  • src/org/openstreetmap/josm/data/projection/Projections.java

    diff --git a/src/org/openstreetmap/josm/data/projection/Projections.java b/src/org/openstreetmap/josm/data/projection/Projections.java
    index f31f7a9..10d0a2d 100644
    a b  
    11// License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.data.projection;
    33
    4 import java.util.Arrays;
    54import java.util.ArrayList;
     5import java.util.Arrays;
     6
     7import org.openstreetmap.josm.Main;
     8import org.openstreetmap.josm.data.coor.EastNorth;
     9import org.openstreetmap.josm.data.coor.LatLon;
    610
    711/**
    812 * Class to handle projections
    public class Projections {  
    1317     * List of all available projections.
    1418     */
    1519    private static ArrayList<Projection> allProjections =
    16     new ArrayList<Projection>(Arrays.asList(new Projection[] {
    17         // global projections
    18         new Epsg4326(),
    19         new Mercator(),
    20         new UTM(),
    21         // regional - alphabetical order by country name
    22         new LambertEST(), // Still needs proper default zoom
    23         new Lambert(),    // Still needs proper default zoom
    24         new LambertCC9Zones(),    // Still needs proper default zoom
    25         new UTM_France_DOM(),
    26         new TransverseMercatorLV(),
    27         new Puwg(),
    28         new Epsg3008(), // SWEREF99 13 30
    29         new SwissGrid(),
    30     }));
     20        new ArrayList<Projection>(Arrays.asList(new Projection[] {
     21                // global projections
     22                new Epsg4326(),
     23                new Mercator(),
     24                new UTM(),
     25                // regional - alphabetical order by country name
     26                new LambertEST(), // Still needs proper default zoom
     27                new Lambert(),    // Still needs proper default zoom
     28                new LambertCC9Zones(),    // Still needs proper default zoom
     29                new UTM_France_DOM(),
     30                new TransverseMercatorLV(),
     31                new Puwg(),
     32                new Epsg3008(), // SWEREF99 13 30
     33                new SwissGrid(),
     34        }));
    3135
    3236    public static ArrayList<Projection> getProjections() {
    3337        return allProjections;
    public class Projections {  
    4246    public static void addProjection(Projection proj) {
    4347        allProjections.add(proj);
    4448    }
     49
     50    static public EastNorth project(LatLon ll) {
     51        return Main.getProjection().latlon2eastNorth(ll);
     52    }
     53
     54    static public LatLon inverseProject(EastNorth en) {
     55        return Main.getProjection().eastNorth2latlon(en);
     56    }
    4557}
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

    diff --git a/src/org/openstreetmap/josm/data/validation/OsmValidator.java b/src/org/openstreetmap/josm/data/validation/OsmValidator.java
    index ce77780..7817efe 100644
    a b import javax.swing.JOptionPane;  
    2222
    2323import org.openstreetmap.josm.Main;
    2424import org.openstreetmap.josm.actions.ValidateAction;
    25 import org.openstreetmap.josm.actions.upload.ValidateUploadHook;
    2625import org.openstreetmap.josm.data.projection.Epsg4326;
    2726import org.openstreetmap.josm.data.projection.Lambert;
    2827import org.openstreetmap.josm.data.projection.Mercator;
    2928import org.openstreetmap.josm.data.validation.tests.Coastlines;
    3029import org.openstreetmap.josm.data.validation.tests.CrossingWays;
    3130import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
    32 import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
    3331import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
     32import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
    3433import org.openstreetmap.josm.data.validation.tests.DuplicatedWayNodes;
    3534import org.openstreetmap.josm.data.validation.tests.MultipolygonTest;
    3635import org.openstreetmap.josm.data.validation.tests.NameMismatch;
    import org.openstreetmap.josm.data.validation.tests.UntaggedNode;  
    4746import org.openstreetmap.josm.data.validation.tests.UntaggedWay;
    4847import org.openstreetmap.josm.data.validation.tests.WronglyOrderedWays;
    4948import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
    50 import org.openstreetmap.josm.gui.layer.ValidatorLayer;
    5149import org.openstreetmap.josm.gui.layer.Layer;
    5250import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     51import org.openstreetmap.josm.gui.layer.ValidatorLayer;
    5352import org.openstreetmap.josm.gui.preferences.ValidatorPreference;
    5453
    5554/**
    public class OsmValidator implements LayerChangeListener {  
    7675     */
    7776    @SuppressWarnings("unchecked")
    7877    public static Class<Test>[] allAvailableTests = new Class[] {
    79             DuplicateNode.class, // ID    1 ..   99
    80             OverlappingWays.class, // ID  101 ..  199
    81             UntaggedNode.class, // ID  201 ..  299
    82             UntaggedWay.class, // ID  301 ..  399
    83             SelfIntersectingWay.class, // ID  401 ..  499
    84             DuplicatedWayNodes.class, // ID  501 ..  599
    85             CrossingWays.class, // ID  601 ..  699
    86             SimilarNamedWays.class, // ID  701 ..  799
    87             NodesWithSameName.class, // ID  801 ..  899
    88             Coastlines.class, // ID  901 ..  999
    89             WronglyOrderedWays.class, // ID 1001 .. 1099
    90             UnclosedWays.class, // ID 1101 .. 1199
    91             TagChecker.class, // ID 1201 .. 1299
    92             UnconnectedWays.class, // ID 1301 .. 1399
    93             DuplicateWay.class, // ID 1401 .. 1499
    94             NameMismatch.class, // ID  1501 ..  1599
    95             MultipolygonTest.class, // ID  1601 ..  1699
    96             RelationChecker.class, // ID  1701 ..  1799
    97             TurnrestrictionTest.class, // ID  1801 ..  1899
    98             DuplicateRelation.class, // ID 1901 .. 1999
     78        DuplicateNode.class, // ID    1 ..   99
     79        OverlappingWays.class, // ID  101 ..  199
     80        UntaggedNode.class, // ID  201 ..  299
     81        UntaggedWay.class, // ID  301 ..  399
     82        SelfIntersectingWay.class, // ID  401 ..  499
     83        DuplicatedWayNodes.class, // ID  501 ..  599
     84        CrossingWays.class, // ID  601 ..  699
     85        SimilarNamedWays.class, // ID  701 ..  799
     86        NodesWithSameName.class, // ID  801 ..  899
     87        Coastlines.class, // ID  901 ..  999
     88        WronglyOrderedWays.class, // ID 1001 .. 1099
     89        UnclosedWays.class, // ID 1101 .. 1199
     90        TagChecker.class, // ID 1201 .. 1299
     91        UnconnectedWays.class, // ID 1301 .. 1399
     92        DuplicateWay.class, // ID 1401 .. 1499
     93        NameMismatch.class, // ID  1501 ..  1599
     94        MultipolygonTest.class, // ID  1601 ..  1699
     95        RelationChecker.class, // ID  1701 ..  1799
     96        TurnrestrictionTest.class, // ID  1801 ..  1899
     97        DuplicateRelation.class, // ID 1901 .. 1999
    9998    };
    10099
    101100    public OsmValidator() {
    public class OsmValidator implements LayerChangeListener {  
    241240     * until most bugs were discovered while keeping the processing time reasonable)
    242241     */
    243242    public void initializeGridDetail() {
    244         if (Main.proj.toString().equals(new Epsg4326().toString())) {
     243        if (Main.getProjection().toString().equals(new Epsg4326().toString())) {
    245244            OsmValidator.griddetail = 10000;
    246         } else if (Main.proj.toString().equals(new Mercator().toString())) {
     245        } else if (Main.getProjection().toString().equals(new Mercator().toString())) {
    247246            OsmValidator.griddetail = 0.01;
    248         } else if (Main.proj.toString().equals(new Lambert().toString())) {
     247        } else if (Main.getProjection().toString().equals(new Lambert().toString())) {
    249248            OsmValidator.griddetail = 0.1;
    250249        }
    251250    }
    public class OsmValidator implements LayerChangeListener {  
    264263                e.printStackTrace();
    265264                JOptionPane.showMessageDialog(Main.parent,
    266265                        tr("Error initializing test {0}:\n {1}", test.getClass()
    267                         .getSimpleName(), e),
    268                         tr("Error"),
    269                         JOptionPane.ERROR_MESSAGE);
     266                                .getSimpleName(), e),
     267                                tr("Error"),
     268                                JOptionPane.ERROR_MESSAGE);
    270269            }
    271270        }
    272271    }
  • src/org/openstreetmap/josm/gui/MapView.java

    diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
    index e4fe0db..0507b20 100644
    a b public class MapView extends NavigatableComponent implements PropertyChangeListe  
    117117     * Adds an edit layer change listener
    118118     *
    119119     * @param listener the listener. Ignored if null or already registered.
    120      * @param initialFire Fire an edit-layer-changed-event right after adding 
     120     * @param initialFire Fire an edit-layer-changed-event right after adding
    121121     * the listener in case there is an edit layer present
    122122     */
    123123    public static void addEditLayerChangeListener(EditLayerChangeListener listener, boolean initialFire) {
    public class MapView extends NavigatableComponent implements PropertyChangeListe  
    284284            setActiveLayer(layer);
    285285        }
    286286        layer.addPropertyChangeListener(this);
     287        Main.addProjectionChangeListener(layer);
    287288        AudioPlayer.reset();
    288289        repaint();
    289290    }
    public class MapView extends NavigatableComponent implements PropertyChangeListe  
    358359        }
    359360
    360361        layers.remove(layer);
     362        Main.removeProjectionChangeListener(layer);
    361363        fireLayerRemoved(layer);
    362364        layer.removePropertyChangeListener(this);
    363365        layer.destroy();
  • src/org/openstreetmap/josm/gui/NavigatableComponent.java

    diff --git a/src/org/openstreetmap/josm/gui/NavigatableComponent.java b/src/org/openstreetmap/josm/gui/NavigatableComponent.java
    index 32484c4..a1a6328 100644
    a b import javax.swing.JComponent;  
    2727import org.openstreetmap.josm.Main;
    2828import org.openstreetmap.josm.data.Bounds;
    2929import org.openstreetmap.josm.data.ProjectionBounds;
    30 import org.openstreetmap.josm.data.coor.CachedLatLon;
    3130import org.openstreetmap.josm.data.coor.EastNorth;
    3231import org.openstreetmap.josm.data.coor.LatLon;
    3332import org.openstreetmap.josm.data.osm.BBox;
    import org.openstreetmap.josm.data.osm.Way;  
    3837import org.openstreetmap.josm.data.osm.WaySegment;
    3938import org.openstreetmap.josm.data.preferences.IntegerProperty;
    4039import org.openstreetmap.josm.data.projection.Projection;
     40import org.openstreetmap.josm.data.projection.Projections;
    4141import org.openstreetmap.josm.gui.help.Helpful;
    4242import org.openstreetmap.josm.gui.preferences.ProjectionPreference;
    4343import org.openstreetmap.josm.tools.Predicate;
    public class NavigatableComponent extends JComponent implements Helpful {  
    9595     * every physical pixel on screen are 10 x or 10 y units in the
    9696     * northing/easting space of the projection.
    9797     */
    98     private double scale = Main.proj.getDefaultZoomInPPD();
     98    private double scale = Main.getProjection().getDefaultZoomInPPD();
    9999    /**
    100100     * Center n/e coordinate of the desired screen center.
    101101     */
    public class NavigatableComponent extends JComponent implements Helpful {  
    110110    }
    111111
    112112    private EastNorth calculateDefaultCenter() {
    113         Bounds b = Main.proj.getWorldBoundsLatLon();
     113        Bounds b = Main.getProjection().getWorldBoundsLatLon();
    114114        double lat = (b.getMax().lat() + b.getMin().lat())/2;
    115115        double lon = (b.getMax().lon() + b.getMin().lon())/2;
    116116
    117         return Main.proj.latlon2eastNorth(new LatLon(lat, lon));
     117        return Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));
    118118    }
    119119
    120120    public static String getDistText(double dist) {
    public class NavigatableComponent extends JComponent implements Helpful {  
    208208        EastNorth p1 = getEastNorth(r.x, r.y);
    209209        EastNorth p2 = getEastNorth(r.x + r.width, r.y + r.height);
    210210
    211         Bounds result = new Bounds(Main.proj.eastNorth2latlon(p1));
     211        Bounds result = new Bounds(Main.getProjection().eastNorth2latlon(p1));
    212212
    213213        double eastMin = Math.min(p1.east(), p2.east());
    214214        double eastMax = Math.max(p1.east(), p2.east());
    public class NavigatableComponent extends JComponent implements Helpful {  
    218218        double deltaNorth = (northMax - northMin) / 10;
    219219
    220220        for (int i=0; i < 10; i++) {
    221             result.extend(Main.proj.eastNorth2latlon(new EastNorth(eastMin + i * deltaEast, northMin)));
    222             result.extend(Main.proj.eastNorth2latlon(new EastNorth(eastMin + i * deltaEast, northMax)));
    223             result.extend(Main.proj.eastNorth2latlon(new EastNorth(eastMin, northMin  + i * deltaNorth)));
    224             result.extend(Main.proj.eastNorth2latlon(new EastNorth(eastMax, northMin  + i * deltaNorth)));
     221            result.extend(Main.getProjection().eastNorth2latlon(new EastNorth(eastMin + i * deltaEast, northMin)));
     222            result.extend(Main.getProjection().eastNorth2latlon(new EastNorth(eastMin + i * deltaEast, northMax)));
     223            result.extend(Main.getProjection().eastNorth2latlon(new EastNorth(eastMin, northMin  + i * deltaNorth)));
     224            result.extend(Main.getProjection().eastNorth2latlon(new EastNorth(eastMax, northMin  + i * deltaNorth)));
    225225        }
    226226
    227227        return result;
    public class NavigatableComponent extends JComponent implements Helpful {  
    244244    public Point2D getPoint2D(LatLon latlon) {
    245245        if (latlon == null)
    246246            return new Point();
    247         else if (latlon instanceof CachedLatLon)
    248             return getPoint2D(((CachedLatLon)latlon).getEastNorth());
    249         else
    250             return getPoint2D(getProjection().latlon2eastNorth(latlon));
     247        return getPoint2D(Projections.project(latlon));
    251248    }
     249
    252250    public Point2D getPoint2D(Node n) {
    253251        return getPoint2D(n.getEastNorth());
    254252    }
    public class NavigatableComponent extends JComponent implements Helpful {  
    281279     */
    282280    public void zoomTo(EastNorth newCenter, double newScale) {
    283281        Bounds b = getProjection().getWorldBoundsLatLon();
    284         CachedLatLon cl = new CachedLatLon(newCenter);
     282        LatLon cl = Projections.inverseProject(newCenter);
    285283        boolean changed = false;
    286284        double lat = cl.lat();
    287285        double lon = cl.lon();
    public class NavigatableComponent extends JComponent implements Helpful {  
    290288        if(lon < b.getMin().lon()) {changed = true; lon = b.getMin().lon(); }
    291289        else if(lon > b.getMax().lon()) {changed = true; lon = b.getMax().lon(); }
    292290        if(changed) {
    293             newCenter = new CachedLatLon(lat, lon).getEastNorth();
     291            newCenter = Projections.project(new LatLon(lat,lon));
    294292        }
    295293        int width = getWidth()/2;
    296294        int height = getHeight()/2;
    public class NavigatableComponent extends JComponent implements Helpful {  
    349347    }
    350348
    351349    public void zoomTo(LatLon newCenter) {
    352         if(newCenter instanceof CachedLatLon) {
    353             zoomTo(((CachedLatLon)newCenter).getEastNorth(), scale);
    354         } else {
    355             zoomTo(getProjection().latlon2eastNorth(newCenter), scale);
    356         }
     350        zoomTo(Projections.project(newCenter));
    357351    }
    358352
    359353    public void smoothScrollTo(LatLon newCenter) {
    360         if (newCenter instanceof CachedLatLon) {
    361             smoothScrollTo(((CachedLatLon)newCenter).getEastNorth());
    362         } else {
    363             smoothScrollTo(getProjection().latlon2eastNorth(newCenter));
    364         }
     354        smoothScrollTo(Projections.project(newCenter));
    365355    }
    366356
    367357    /**
    public class NavigatableComponent extends JComponent implements Helpful {  
    440430        double scale;
    441431
    442432        public ZoomData(EastNorth center, double scale) {
    443             this.center = new CachedLatLon(center);
     433            this.center = Projections.inverseProject(center);
    444434            this.scale = scale;
    445435        }
    446436
    public class NavigatableComponent extends JComponent implements Helpful {  
    11441134     * @return The projection to be used in calculating stuff.
    11451135     */
    11461136    public Projection getProjection() {
    1147         return Main.proj;
     1137        return Main.getProjection();
    11481138    }
    11491139
    11501140    public String helpTopic() {
  • src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/GpxLayer.java b/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
    index 83e9df8..e734736 100644
    a b import org.openstreetmap.josm.data.Bounds;  
    5151import org.openstreetmap.josm.data.coor.EastNorth;
    5252import org.openstreetmap.josm.data.coor.LatLon;
    5353import org.openstreetmap.josm.data.gpx.GpxData;
     54import org.openstreetmap.josm.data.gpx.GpxRoute;
    5455import org.openstreetmap.josm.data.gpx.GpxTrack;
    5556import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
    5657import org.openstreetmap.josm.data.gpx.WayPoint;
    import org.openstreetmap.josm.data.osm.DataSet;  
    5859import org.openstreetmap.josm.data.osm.Node;
    5960import org.openstreetmap.josm.data.osm.Way;
    6061import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     62import org.openstreetmap.josm.data.projection.Projection;
    6163import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    6264import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    6365import org.openstreetmap.josm.gui.MapView;
    public class GpxLayer extends Layer {  
    329331        lastTracks.addAll(data.tracks);
    330332
    331333        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    332         Main.pref.getBoolean("mappaint.gpx.use-antialiasing", false) ?
    333                 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
     334                Main.pref.getBoolean("mappaint.gpx.use-antialiasing", false) ?
     335                        RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
    334336
    335337        /****************************************************************
    336338         ********** STEP 1 - GET CONFIG VALUES **************************
    public class GpxLayer extends Layer {  
    12301232        }
    12311233        if (bestEN == null)
    12321234            return null;
    1233         WayPoint best = new WayPoint(Main.proj.eastNorth2latlon(bestEN));
     1235        WayPoint best = new WayPoint(Main.getProjection().eastNorth2latlon(bestEN));
    12341236        best.time = bestTime;
    12351237        return best;
    12361238    }
    public class GpxLayer extends Layer {  
    14891491            addRecursiveFiles(files, sel);
    14901492            importer.importDataHandleExceptions(files, NullProgressMonitor.INSTANCE);
    14911493        }
     1494    }
    14921495
     1496    @Override
     1497    public void projectionChanged(Projection oldValue, Projection newValue) {
     1498        if (newValue == null) return;
     1499        if (data.waypoints != null) {
     1500            for (WayPoint wp : data.waypoints){
     1501                wp.invalidateEastNorthCache();
     1502            }
     1503        }
     1504        if (data.tracks != null){
     1505            for (GpxTrack track: data.tracks) {
     1506                for (GpxTrackSegment segment: track.getSegments()) {
     1507                    for (WayPoint wp: segment.getWayPoints()) {
     1508                        wp.invalidateEastNorthCache();
     1509                    }
     1510                }
     1511            }
     1512        }
     1513        if (data.routes != null) {
     1514            for (GpxRoute route: data.routes) {
     1515                if (route.routePoints == null) {
     1516                    continue;
     1517                }
     1518                for (WayPoint wp: route.routePoints) {
     1519                    wp.invalidateEastNorthCache();
     1520                }
     1521            }
     1522        }
    14931523    }
    14941524}
     1525 No newline at end of file
  • src/org/openstreetmap/josm/gui/layer/ImageryLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java b/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
    index 6520532..497cff9 100644
    a b public abstract class ImageryLayer extends Layer {  
    8282    }
    8383
    8484    public double getPPD(){
    85         if (Main.map == null || Main.map.mapView == null) return Main.proj.getDefaultZoomInPPD();
     85        if (Main.map == null || Main.map.mapView == null) return Main.getProjection().getDefaultZoomInPPD();
    8686        ProjectionBounds bounds = Main.map.mapView.getProjectionBounds();
    8787        return Main.map.mapView.getWidth() / (bounds.maxEast - bounds.minEast);
    8888    }
  • src/org/openstreetmap/josm/gui/layer/Layer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/Layer.java b/src/org/openstreetmap/josm/gui/layer/Layer.java
    index f6ee43c..0bf99a0 100644
    a b import org.openstreetmap.josm.actions.SaveAction;  
    2222import org.openstreetmap.josm.actions.SaveAsAction;
    2323import org.openstreetmap.josm.data.Bounds;
    2424import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     25import org.openstreetmap.josm.data.projection.Projection;
     26import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
    2527import org.openstreetmap.josm.gui.MapView;
    2628import org.openstreetmap.josm.tools.Destroyable;
    2729import org.openstreetmap.josm.tools.ImageProvider;
    import org.openstreetmap.josm.tools.ImageProvider;  
    4143 *
    4244 * @author imi
    4345 */
    44 abstract public class Layer implements Destroyable, MapViewPaintable {
     46abstract public class Layer implements Destroyable, MapViewPaintable, ProjectionChangeListener {
    4547
    4648    public interface LayerAction {
    4749        boolean supportLayers(List<Layer> layers);
    abstract public class Layer implements Destroyable, MapViewPaintable {  
    361363            new GpxExportAction().export(layer);
    362364        }
    363365    }
     366
     367    /* --------------------------------------------------------------------------------- */
     368    /* interface ProjectionChangeListener                                                */
     369    /* --------------------------------------------------------------------------------- */
     370    @Override
     371    public void projectionChanged(Projection oldValue, Projection newValue) {
     372        // default implementation does nothing - override in subclasses
     373    }
    364374}
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
    index 32fda21..7725a92 100644
    a b import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;  
    6161import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    6262import org.openstreetmap.josm.data.osm.visitor.paint.MapRendererFactory;
    6363import org.openstreetmap.josm.data.osm.visitor.paint.Rendering;
     64import org.openstreetmap.josm.data.projection.Projection;
    6465import org.openstreetmap.josm.data.validation.TestError;
    6566import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    6667import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
    import org.openstreetmap.josm.tools.ImageProvider;  
    7980 * @author imi
    8081 */
    8182public class OsmDataLayer extends Layer implements Listener, SelectionChangedListener {
     83    // static private final Logger logger = Logger.getLogger(OsmDataLayer.class.getName());
     84
    8285    static public final String REQUIRES_SAVE_TO_DISK_PROP = OsmDataLayer.class.getName() + ".requiresSaveToDisk";
    8386    static public final String REQUIRES_UPLOAD_TO_SERVER_PROP = OsmDataLayer.class.getName() + ".requiresUploadToServer";
    8487
    public class OsmDataLayer extends Layer implements Listener, SelectionChangedLis  
    657660                JOptionPane.showMessageDialog(Main.parent, p, tr("Warning"), JOptionPane.WARNING_MESSAGE);
    658661            }
    659662        }
    660 
    661663    }
    662664
    663665    @Override
    public class OsmDataLayer extends Layer implements Listener, SelectionChangedLis  
    674676    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
    675677        isChanged = true;
    676678    }
     679
     680    @Override
     681    public void projectionChanged(Projection oldValue, Projection newValue) {
     682        /*
     683         * No reprojection required. The dataset itself is registered as projection
     684         * change listener and already got notified.
     685         */
     686    }
    677687}
  • src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java b/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java
    index bb41ddc..4acce3f 100644
    a b public class RawGpsLayer extends Layer implements PreferenceChangedListener {  
    9494        public final String time;
    9595        public GpsPoint(LatLon ll, String t) {
    9696            latlon = ll;
    97             eastNorth = Main.proj.latlon2eastNorth(ll);
     97            eastNorth = Main.getProjection().latlon2eastNorth(ll);
    9898            time = t;
    9999        }
    100100    }
  • src/org/openstreetmap/josm/gui/layer/TMSLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/TMSLayer.java b/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
    index 360a6fc..3423be1 100644
    a b public class TMSLayer extends ImageryLayer implements ImageObserver, TileLoaderL  
    870870    }
    871871
    872872    private Point pixelPos(LatLon ll) {
    873         return Main.map.mapView.getPoint(Main.proj.latlon2eastNorth(ll).add(getDx(), getDy()));
     873        return Main.map.mapView.getPoint(Main.getProjection().latlon2eastNorth(ll).add(getDx(), getDy()));
    874874    }
    875875    private Point pixelPos(Tile t) {
    876876        double lon = tileSource.tileXToLon(t.getXtile(), t.getZoom());
    public class TMSLayer extends ImageryLayer implements ImageObserver, TileLoaderL  
    878878        return pixelPos(tmpLL);
    879879    }
    880880    private LatLon getShiftedLatLon(EastNorth en) {
    881         return Main.proj.eastNorth2latlon(en.add(-getDx(), -getDy()));
     881        return Main.getProjection().eastNorth2latlon(en.add(-getDx(), -getDy()));
    882882    }
    883883    private Coordinate getShiftedCoord(EastNorth en) {
    884884        LatLon ll = getShiftedLatLon(en);
  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageEntry.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageEntry.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageEntry.java
    index 5731554..9de7e28 100644
    a b import java.awt.Image;  
    99import java.io.File;
    1010import java.util.Date;
    1111
    12 import org.openstreetmap.josm.data.coor.CachedLatLon;
    1312import org.openstreetmap.josm.data.coor.LatLon;
    1413
    1514/*
    final public class ImageEntry implements Comparable<ImageEntry>, Cloneable {  
    2423    Image thumbnail;
    2524
    2625    /** The following values are computed from the correlation with the gpx track */
    27     private CachedLatLon pos;
     26    private LatLon pos;
    2827    /** Speed in kilometer per second */
    2928    private Double speed;
    3029    /** Elevation (altitude) in meters */
    final public class ImageEntry implements Comparable<ImageEntry>, Cloneable {  
    4544    /**
    4645     * getter methods that refer to the temporary value
    4746     */
    48     public CachedLatLon getPos() {
     47    public LatLon getPos() {
    4948        if (tmp != null)
    5049            return tmp.pos;
    5150        return pos;
    final public class ImageEntry implements Comparable<ImageEntry>, Cloneable {  
    8584    /**
    8685     * setter methods
    8786     */
    88     public void setPos(CachedLatLon pos) {
    89         this.pos = pos;
    90     }
    9187    public void setPos(LatLon pos) {
    92         this.pos = new CachedLatLon(pos);
     88        this.pos = pos;
    9389    }
    9490    public void setSpeed(Double speed) {
    9591        this.speed = speed;
  • src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java b/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java
    index 6236ea3..e35a75d 100644
    a b import java.util.Map;  
    1515
    1616import javax.swing.Icon;
    1717
    18 import org.openstreetmap.josm.data.coor.CachedLatLon;
    1918import org.openstreetmap.josm.data.coor.EastNorth;
    2019import org.openstreetmap.josm.data.coor.LatLon;
    2120import org.openstreetmap.josm.data.gpx.GpxData;
    2221import org.openstreetmap.josm.data.gpx.GpxLink;
    2322import org.openstreetmap.josm.data.gpx.WayPoint;
    2423import org.openstreetmap.josm.data.preferences.IntegerProperty;
     24import org.openstreetmap.josm.data.projection.Projections;
    2525import org.openstreetmap.josm.gui.MapView;
    2626import org.openstreetmap.josm.tools.ImageProvider;
    2727
    public class Marker implements ActionListener {  
    6969    public double offset; /* time offset in seconds from the gpx point from which it was derived,
    7070                             may be adjusted later to sync with other data, so not final */
    7171
    72     private CachedLatLon coor;
     72    private LatLon coor;
    7373
    7474    public final void setCoor(LatLon coor) {
    75         if(this.coor == null) {
    76             this.coor = new CachedLatLon(coor);
    77         } else {
    78             this.coor.setCoor(coor);
    79         }
     75        this.coor = new LatLon(coor);
    8076    }
    8177
    8278    public final LatLon getCoor() {
    public class Marker implements ActionListener {  
    8480    }
    8581
    8682    public final void setEastNorth(EastNorth eastNorth) {
    87         coor.setEastNorth(eastNorth);
     83        this.coor = Projections.inverseProject(eastNorth);
    8884    }
    8985
    9086    public final EastNorth getEastNorth() {
    91         return coor.getEastNorth();
     87        return Projections.project(this.coor);
    9288    }
    9389
    9490    /**
    public class Marker implements ActionListener {  
    263259     * @return Text
    264260     */
    265261    public String getText() {
    266         if (this.text != null ) {
     262        if (this.text != null )
    267263            return this.text;
    268         }
    269         else {
     264        else
    270265            return getText(this.textMap);
    271         }
    272266    }
    273267
    274268    /**
    public class Marker implements ActionListener {  
    284278        if (textMap != null && !textMap.isEmpty()) {
    285279            switch(PROP_LABEL.get())
    286280            {
    287                 // name
    288                 case 1:
    289                 {
    290                     if (textMap.containsKey("name")) {
    291                         text = textMap.get("name");
    292                     }
    293                     break;
     281            // name
     282            case 1:
     283            {
     284                if (textMap.containsKey("name")) {
     285                    text = textMap.get("name");
    294286                }
     287                break;
     288            }
    295289
    296                 // desc
    297                 case 2:
    298                 {
    299                     if (textMap.containsKey("desc")) {
    300                         text = textMap.get("desc");
    301                     }
    302                     break;
     290            // desc
     291            case 2:
     292            {
     293                if (textMap.containsKey("desc")) {
     294                    text = textMap.get("desc");
    303295                }
     296                break;
     297            }
    304298
    305                 // auto
    306                 case 0:
     299            // auto
     300            case 0:
    307301                // both
    308                 case 3:
    309                 {
    310                     if (textMap.containsKey("name")) {
    311                         text = textMap.get("name");
    312 
    313                         if (textMap.containsKey("desc")) {
    314                             if (PROP_LABEL.get() != 0 || !text.equals(textMap.get("desc"))) {
    315                                 text += " - " + textMap.get("desc");
    316                             }
     302            case 3:
     303            {
     304                if (textMap.containsKey("name")) {
     305                    text = textMap.get("name");
     306
     307                    if (textMap.containsKey("desc")) {
     308                        if (PROP_LABEL.get() != 0 || !text.equals(textMap.get("desc"))) {
     309                            text += " - " + textMap.get("desc");
    317310                        }
    318311                    }
    319                     else if (textMap.containsKey("desc")) {
    320                         text = textMap.get("desc");
    321                     }
    322                     break;
    323312                }
    324 
    325                 // none
    326                 case 4:
    327                 default:
    328                 {
    329                     text = "";
    330                     break;
     313                else if (textMap.containsKey("desc")) {
     314                    text = textMap.get("desc");
    331315                }
     316                break;
     317            }
     318
     319            // none
     320            case 4:
     321            default:
     322            {
     323                text = "";
     324                break;
     325            }
    332326            }
    333327        }
    334328
  • src/org/openstreetmap/josm/gui/preferences/ImageryPreference.java

    diff --git a/src/org/openstreetmap/josm/gui/preferences/ImageryPreference.java b/src/org/openstreetmap/josm/gui/preferences/ImageryPreference.java
    index e5fa737..60502e7 100644
    a b public class ImageryPreference implements PreferenceSetting {  
    733733            add.addActionListener(new ActionListener() {
    734734                @Override
    735735                public void actionPerformed(ActionEvent e) {
    736                     OffsetBookmark b = new OffsetBookmark(Main.proj,"","",0,0);
     736                    OffsetBookmark b = new OffsetBookmark(Main.getProjection(),"","",0,0);
    737737                    model.addRow(b);
    738738                }
    739739            });
  • src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java

    diff --git a/src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java b/src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java
    index 9d0b41e..b834a77 100644
    a b import java.awt.event.ActionEvent;  
    88import java.awt.event.ActionListener;
    99import java.util.ArrayList;
    1010import java.util.Collection;
    11 import java.util.concurrent.CopyOnWriteArrayList;
    1211
    1312import javax.swing.BorderFactory;
    1413import javax.swing.JComboBox;
    import org.openstreetmap.josm.data.preferences.ParametrizedCollectionProperty;  
    2625import org.openstreetmap.josm.data.preferences.StringProperty;
    2726import org.openstreetmap.josm.data.projection.Mercator;
    2827import org.openstreetmap.josm.data.projection.Projection;
    29 import org.openstreetmap.josm.data.projection.Projections;
    3028import org.openstreetmap.josm.data.projection.ProjectionSubPrefs;
     29import org.openstreetmap.josm.data.projection.Projections;
    3130import org.openstreetmap.josm.gui.NavigatableComponent;
    3231import org.openstreetmap.josm.plugins.PluginHandler;
    3332import org.openstreetmap.josm.tools.GBC;
    public class ProjectionPreference implements PreferenceSetting {  
    4039        }
    4140    }
    4241
    43     public interface ProjectionChangedListener {
    44         void projectionChanged();
    45     }
    46 
    4742    private static final StringProperty PROP_PROJECTION = new StringProperty("projection", Mercator.class.getName());
    4843    private static final StringProperty PROP_COORDINATES = new StringProperty("coordinates", null);
    4944    private static final CollectionProperty PROP_SUB_PROJECTION = new CollectionProperty("projection.sub", null);
    public class ProjectionPreference implements PreferenceSetting {  
    6459        }
    6560    }
    6661
    67     //TODO This is not nice place for a listener code but probably only Dataset will want to listen for projection changes so it's acceptable
    68     private static CopyOnWriteArrayList<ProjectionChangedListener> listeners = new CopyOnWriteArrayList<ProjectionChangedListener>();
    69 
    70     public static void addProjectionChangedListener(ProjectionChangedListener listener) {
    71         listeners.addIfAbsent(listener);
    72     }
    73 
    74     public static void removeProjectionChangedListener(ProjectionChangedListener listener) {
    75         listeners.remove(listener);
    76     }
    77 
    78     private static void fireProjectionChanged() {
    79         for (ProjectionChangedListener listener: listeners) {
    80             listener.projectionChanged();
    81         }
    82     }
    83 
    84 
    8562    /**
    8663     * Combobox with all projections available
    8764     */
    public class ProjectionPreference implements PreferenceSetting {  
    160137        JScrollPane scrollpane = new JScrollPane(projPanel);
    161138        gui.mapcontent.addTab(tr("Map Projection"), scrollpane);
    162139
    163         updateMeta(Main.proj);
     140        updateMeta(Main.getProjection());
    164141    }
    165142
    166143    private void updateMeta(Projection proj)
    public class ProjectionPreference implements PreferenceSetting {  
    200177
    201178    static public void setProjection(String name, Collection<String> coll)
    202179    {
    203         Bounds b = (Main.map != null && Main.map.mapView != null) ? Main.map.mapView.getRealBounds() : null;
    204         Projection oldProj = Main.proj;
    205 
    206180        Projection p = null;
    207181        for (ClassLoader cl : PluginHandler.getResourceClassLoaders()) {
    208182            try {
    public class ProjectionPreference implements PreferenceSetting {  
    210184            } catch (final Exception e) {
    211185            }
    212186            if (p != null) {
    213                 Main.proj = p;
    214187                break;
    215188            }
    216189        }
    public class ProjectionPreference implements PreferenceSetting {  
    222195                    JOptionPane.ERROR_MESSAGE
    223196            );
    224197            coll = null;
    225             Main.proj = new Mercator();
    226             name = Main.proj.getClass().getName();
     198            p = new Mercator();
     199            name = Main.getProjection().getClass().getName();
    227200        }
    228201        PROP_SUB_PROJECTION.put(coll);
    229202        PROP_PROJECTION_SUBPROJECTION.put(coll, name);
    230         if(Main.proj instanceof ProjectionSubPrefs) {
    231             ((ProjectionSubPrefs) Main.proj).setPreferences(coll);
    232         }
    233         fireProjectionChanged(); // This should be probably called from the if bellow, but hashCode condition doesn't look sure enough
    234         if(b != null && (!Main.proj.getClass().getName().equals(oldProj.getClass().getName()) || Main.proj.hashCode() != oldProj.hashCode()))
    235         {
    236             Main.map.mapView.zoomTo(b);
    237             /* TODO - remove layers with fixed projection */
     203        if(Main.getProjection() instanceof ProjectionSubPrefs) {
     204            ((ProjectionSubPrefs) Main.getProjection()).setPreferences(coll);
    238205        }
     206        Main.setProjection(p);
    239207    }
    240208
    241209    private class SBPanel extends JPanel implements ActionListener
  • src/org/openstreetmap/josm/io/imagery/Grabber.java

    diff --git a/src/org/openstreetmap/josm/io/imagery/Grabber.java b/src/org/openstreetmap/josm/io/imagery/Grabber.java
    index 648cb8b..5a49fc3 100644
    a b abstract public class Grabber implements Runnable {  
    4040                            b.maxNorth + northCoef * northSize));
    4141        }
    4242
    43         this.proj = Main.proj;
     43        this.proj = Main.getProjection();
    4444        this.pixelPerDegree = request.getPixelPerDegree();
    4545        this.request = request;
    4646    }
  • src/org/openstreetmap/josm/io/imagery/HTMLGrabber.java

    diff --git a/src/org/openstreetmap/josm/io/imagery/HTMLGrabber.java b/src/org/openstreetmap/josm/io/imagery/HTMLGrabber.java
    index d12619d..40aac55 100644
    a b public class HTMLGrabber extends WMSGrabber {  
    5151        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    5252        BufferedImage img = layer.normalizeImage(ImageIO.read(bais));
    5353        bais.reset();
    54         layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.proj, pixelPerDegree, b.minEast, b.minNorth);
     54        layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
    5555
    5656        return img;
    5757    }
  • src/org/openstreetmap/josm/io/imagery/OsmosnimkiOffsetServer.java

    diff --git a/src/org/openstreetmap/josm/io/imagery/OsmosnimkiOffsetServer.java b/src/org/openstreetmap/josm/io/imagery/OsmosnimkiOffsetServer.java
    index 02d9ee5..fc31932 100644
    a b public class OsmosnimkiOffsetServer implements OffsetServer {  
    3939
    4040    @Override
    4141    public EastNorth getOffset(ImageryInfo info, EastNorth en) {
    42         LatLon ll = Main.proj.eastNorth2latlon(en);
     42        LatLon ll = Main.getProjection().eastNorth2latlon(en);
    4343        try {
    4444            URL url = new URL(this.url + "action=GetOffsetForPoint&lat=" + ll.lat() + "&lon=" + ll.lon() + "&id=" + URLEncoder.encode(info.getFullUrl(), "UTF-8"));
    4545            System.out.println(tr("Querying offset: {0}", url.toString()));
    public class OsmosnimkiOffsetServer implements OffsetServer {  
    4949            if (i == -1) return null;
    5050            String sLon = s.substring(1,i);
    5151            String sLat = s.substring(i+1,s.length()-1);
    52             return Main.proj.latlon2eastNorth(new LatLon(Double.valueOf(sLat),Double.valueOf(sLon))).sub(en);
     52            return Main.getProjection().latlon2eastNorth(new LatLon(Double.valueOf(sLat),Double.valueOf(sLon))).sub(en);
    5353        } catch (Exception e) {
    5454            e.printStackTrace();
    5555            return null;
  • src/org/openstreetmap/josm/io/imagery/WMSGrabber.java

    diff --git a/src/org/openstreetmap/josm/io/imagery/WMSGrabber.java b/src/org/openstreetmap/josm/io/imagery/WMSGrabber.java
    index 048370e..d13bfa3 100644
    a b public class WMSGrabber extends Grabber {  
    7171
    7272    protected URL getURL(double w, double s,double e,double n,
    7373            int wi, int ht) throws MalformedURLException {
    74         String myProj = Main.proj.toCode();
    75         if(Main.proj instanceof Mercator) // don't use mercator code directly
     74        String myProj = Main.getProjection().toCode();
     75        if(Main.getProjection() instanceof Mercator) // don't use mercator code directly
    7676        {
    77             LatLon sw = Main.proj.eastNorth2latlon(new EastNorth(w, s));
    78             LatLon ne = Main.proj.eastNorth2latlon(new EastNorth(e, n));
     77            LatLon sw = Main.getProjection().eastNorth2latlon(new EastNorth(w, s));
     78            LatLon ne = Main.getProjection().eastNorth2latlon(new EastNorth(e, n));
    7979            myProj = "EPSG:4326";
    8080            s = sw.lat();
    8181            w = sw.lon();
    public class WMSGrabber extends Grabber {  
    113113
    114114    static public String getProjection(String baseURL, Boolean warn)
    115115    {
    116         String projname = Main.proj.toCode();
    117         if(Main.proj instanceof Mercator) {
     116        String projname = Main.getProjection().toCode();
     117        if(Main.getProjection() instanceof Mercator) {
    118118            projname = "EPSG:4326";
    119119        }
    120120        String res = "";
    public class WMSGrabber extends Grabber {  
    145145
    146146    @Override
    147147    public boolean loadFromCache(WMSRequest request) {
    148         BufferedImage cached = layer.cache.getExactMatch(Main.proj, pixelPerDegree, b.minEast, b.minNorth);
     148        BufferedImage cached = layer.cache.getExactMatch(Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
    149149
    150150        if (cached != null) {
    151151            request.finish(State.IMAGE, cached);
    152152            return true;
    153153        } else if (request.isAllowPartialCacheMatch()) {
    154             BufferedImage partialMatch = layer.cache.getPartialMatch(Main.proj, pixelPerDegree, b.minEast, b.minNorth);
     154            BufferedImage partialMatch = layer.cache.getPartialMatch(Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
    155155            if (partialMatch != null) {
    156156                request.finish(State.PARTLY_IN_CACHE, partialMatch);
    157157                return true;
    public class WMSGrabber extends Grabber {  
    193193        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    194194        BufferedImage img = layer.normalizeImage(ImageIO.read(bais));
    195195        bais.reset();
    196         layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.proj, pixelPerDegree, b.minEast, b.minNorth);
     196        layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), pixelPerDegree, b.minEast, b.minNorth);
    197197        return img;
    198198    }
    199199
  • src/org/openstreetmap/josm/tools/Geometry.java

    diff --git a/src/org/openstreetmap/josm/tools/Geometry.java b/src/org/openstreetmap/josm/tools/Geometry.java
    index ade8359..210f6d4 100644
    a b public class Geometry {  
    111111                                    return intersectionNodes;
    112112                                }
    113113
    114                                 Node newNode = new Node(Main.proj.eastNorth2latlon(intersection));
     114                                Node newNode = new Node(Main.getProjection().eastNorth2latlon(intersection));
    115115                                Node intNode = newNode;
    116116                                boolean insertInSeg1 = false;
    117117                                boolean insertInSeg2 = false;
    public class Geometry {  
    457457
    458458        return inside;
    459459    }
    460    
     460
    461461    /**
    462462     * returns area of a closed way in square meters
    463463     * (approximate(?), but should be OK for small areas)
    public class Geometry {  
    477477        }
    478478        return Math.abs(area/2);
    479479    }
    480    
     480
    481481    protected static double calcX(Node p1){
    482482        double lat1, lon1, lat2, lon2;
    483483        double dlon, dlat;
    public class Geometry {  
    494494        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    495495        return 6367000 * c;
    496496    }
    497    
     497
    498498    protected static double calcY(Node p1){
    499499        double lat1, lon1, lat2, lon2;
    500500        double dlon, dlat;
  • test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java

    diff --git a/test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java b/test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java
    index e976723..adadcbd 100644
    a b public class JOSMFixture {  
    6767        Main.pref.init(false);
    6868
    6969        // init projection
    70         Main.proj = new Mercator();
     70        Main.setProjection(new Mercator());
    7171
    7272        // make sure we don't upload to or test against production
    7373        //
  • test/functional/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergerTest.java

    diff --git a/test/functional/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergerTest.java b/test/functional/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergerTest.java
    index f7ac131..09146d4 100644
    a b public class PropertiesMergerTest extends JFrame{  
    1717    private PropertiesMerger merger;
    1818
    1919    protected void build() {
    20         Main.proj = new Epsg4326();
     20        Main.setProjection(new Epsg4326());
    2121
    2222        setLayout(new BorderLayout());
    2323        add(merger = new PropertiesMerger(), BorderLayout.CENTER);
  • test/functional/org/openstreetmap/josm/gui/history/HistoryBrowserTest.java

    diff --git a/test/functional/org/openstreetmap/josm/gui/history/HistoryBrowserTest.java b/test/functional/org/openstreetmap/josm/gui/history/HistoryBrowserTest.java
    index e343a20..020b8c1 100644
    a b public class HistoryBrowserTest extends JFrame {  
    5757        Main.pref.init(false);
    5858
    5959        // init projection
    60         Main.proj = new Mercator();
     60        Main.setProjection(new Mercator());
    6161    }
    6262
    6363    private HistoryBrowser browser;
  • test/functional/org/openstreetmap/josm/io/MultiFetchServerObjectReaderTest.java

    diff --git a/test/functional/org/openstreetmap/josm/io/MultiFetchServerObjectReaderTest.java b/test/functional/org/openstreetmap/josm/io/MultiFetchServerObjectReaderTest.java
    index cba8559..9a71296 100644
    a b public class MultiFetchServerObjectReaderTest {  
    175175        // don't use atomic upload, the test API server can't cope with large diff uploads
    176176        //
    177177        Main.pref.put("osm-server.atomic-upload", false);
    178         Main.proj = new Mercator();
     178        Main.setProjection(new Mercator());
    179179
    180180        File dataSetCacheOutputFile = new File(tempOutputDir, MultiFetchServerObjectReaderTest.class.getName() + ".dataset");
    181181
  • test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java

    diff --git a/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java b/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java
    index 354af96..92d206c 100644
    a b public class OsmServerBackreferenceReaderTest {  
    182182        // don't use atomic upload, the test API server can't cope with large diff uploads
    183183        //
    184184        Main.pref.put("osm-server.atomic-upload", false);
    185         Main.proj = new Mercator();
     185        Main.setProjection(new Mercator());
    186186
    187187        File dataSetCacheOutputFile = new File(tempOutputDir, MultiFetchServerObjectReaderTest.class.getName() + ".dataset");
    188188
  • test/performance/org/openstreetmap/josm/data/osm/MapPaintVisitorPerformanceTest.java

    diff --git a/test/performance/org/openstreetmap/josm/data/osm/MapPaintVisitorPerformanceTest.java b/test/performance/org/openstreetmap/josm/data/osm/MapPaintVisitorPerformanceTest.java
    index bb702e2..d74cce7 100644
    a b public class MapPaintVisitorPerformanceTest {  
    3131
    3232    @BeforeClass
    3333    public static void load() throws Exception {
    34         Main.proj = new Mercator();
     34        Main.setProjection(new Mercator());
    3535        img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_3BYTE_BGR);
    3636        g = (Graphics2D)img.getGraphics();
    3737        nc = new NavigatableComponent();
  • test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java b/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java
    index e40437e..58a1a7b 100644
    a b public class DataSetMergerTest {  
    7575        my.setVersion("0.6");
    7676        their = new DataSet();
    7777        their.setVersion("0.6");
    78         Main.proj = new Mercator();
     78        Main.setProjection(new Mercator());
    7979    }
    8080
    8181    private void runConsistencyTests(DataSet ds) throws Exception {
  • test/unit/org/openstreetmap/josm/data/osm/FilterTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/FilterTest.java b/test/unit/org/openstreetmap/josm/data/osm/FilterTest.java
    index 596ccb5..9317599 100644
    a b public class FilterTest {  
    2828
    2929    @BeforeClass
    3030    public static void setUp() {
    31         Main.proj = new Mercator();
     31        Main.setProjection(new Mercator());
    3232        Main.pref = new Preferences();
    3333    }
    3434
  • new file test/unit/org/openstreetmap/josm/data/osm/NodeProjectionTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/NodeProjectionTest.java b/test/unit/org/openstreetmap/josm/data/osm/NodeProjectionTest.java
    new file mode 100644
    index 0000000..a1e4186
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.osm;
     3
     4import static org.junit.Assert.assertEquals;
     5
     6import org.junit.Before;
     7import org.junit.Test;
     8import org.openstreetmap.josm.Main;
     9import org.openstreetmap.josm.data.Preferences;
     10import org.openstreetmap.josm.data.coor.EastNorth;
     11import org.openstreetmap.josm.data.coor.LatLon;
     12import org.openstreetmap.josm.data.projection.Epsg4326;
     13import org.openstreetmap.josm.data.projection.Mercator;
     14public class NodeProjectionTest {
     15
     16
     17    @Before
     18    public void setUp(){
     19        Main.pref  = new Preferences();
     20        Main.setProjection(new Mercator());
     21    }
     22
     23    /**
     24     * If a node is isolated (i.e. if it isn't part of a data set), {@link Node#getEastNorth()} should always
     25     * reply projected east/north coordinates compliant with the global projection given
     26     * by {@link Main#getProjection()}.
     27     */
     28    @Test
     29    public void projectIsolatedNode() {
     30        Node n = new Node(1,1);
     31        n.setCoor(new LatLon(0,0));
     32        EastNorth en = Main.getProjection().latlon2eastNorth(new LatLon(0,0));
     33        assertEquals(en, n.getEastNorth());
     34
     35        /* change the projection ... */
     36        Main.setProjection(new Epsg4326());
     37        en = Main.getProjection().latlon2eastNorth(new LatLon(0,0));
     38
     39        /* n should now reply east/north coordinates for this projection
     40         * although it is isolated (neither added to a dataset, nor to  - indirectly -
     41         * a layer).
     42         */
     43        assertEquals(en, n.getEastNorth());
     44    }
     45
     46    /**
     47     * If a node isn't isolated (i.e. if it *is* part of a data set), {@link Node#getEastNorth()} should always
     48     * reply projected east/north coordinates compliant with the global projection given
     49     * by {@link Main#getProjection()}, *although* it internally caches the projected
     50     * coordinates. In other words: it should refresh the internal cache if the projection
     51     * changes.
     52     */
     53
     54    @Test
     55    public void projectNodeBelongingToAnIsolatedDataSet() {
     56        DataSet ds  = new DataSet();
     57        Node n = new Node(1,1);
     58        ds.addPrimitive(n);
     59        n.setCoor(new LatLon(0,0));
     60        EastNorth en = Main.getProjection().latlon2eastNorth(new LatLon(0,0));
     61        assertEquals(en, n.getEastNorth());
     62
     63        /* change the projection ... */
     64        Main.setProjection(new Epsg4326());
     65        en = Main.getProjection().latlon2eastNorth(new LatLon(0,0));
     66
     67        /* n should now reply east/north coordinates for this projection
     68         * although it is part of a dataset which isn't connected to a layer
     69         */
     70        assertEquals(en, n.getEastNorth());
     71    }
     72}
  • test/unit/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java b/test/unit/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java
    index 9a2bc7b..5172817 100644
    a b public class OsmPrimitiveTest {  
    2828
    2929    @BeforeClass
    3030    public static void setUp() {
    31         Main.proj = new Mercator();
     31        Main.setProjection(new Mercator());
    3232    }
    3333
    3434    @Test
  • test/unit/org/openstreetmap/josm/data/osm/QuadBucketsTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/QuadBucketsTest.java b/test/unit/org/openstreetmap/josm/data/osm/QuadBucketsTest.java
    index c0d9597..9f1fc44 100644
    a b public class QuadBucketsTest {  
    6565
    6666    @Test
    6767    public void testRemove() throws Exception {
    68         Main.proj = new Mercator();
     68        Main.setProjection(new Mercator());
    6969        DataSet ds = OsmReader.parseDataSet(new FileInputStream("data_nodist/restriction.osm"), NullProgressMonitor.INSTANCE);
    7070        removeAllTest(ds);
    7171    }
    7272
    7373    @Test
    7474    public void testMove() throws Exception {
    75         Main.proj = new Mercator();
     75        Main.setProjection(new Mercator());
    7676        DataSet ds = OsmReader.parseDataSet(new FileInputStream("data_nodist/restriction.osm"), NullProgressMonitor.INSTANCE);
    7777
    7878        for (Node n: ds.getNodes()) {
  • test/unit/org/openstreetmap/josm/data/osm/RelationTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/RelationTest.java b/test/unit/org/openstreetmap/josm/data/osm/RelationTest.java
    index 2687fd8..1bf7122 100644
    a b public class RelationTest {  
    1515
    1616    @BeforeClass
    1717    public static void setUp() {
    18         Main.proj = new Mercator();
     18        Main.setProjection(new Mercator());
    1919        Main.pref = new Preferences();
    2020    }
    2121
  • test/unit/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitorTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitorTest.java b/test/unit/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitorTest.java
    index 7b9aee8..fef5177 100644
    a b public class MergeSourceBuildingVisitorTest {  
    3636
    3737    @BeforeClass
    3838    public static void setUp() {
    39         Main.proj = new Mercator();
     39        Main.setProjection(new Mercator());
    4040        Main.pref = new Preferences();
    4141    }
    4242
  • test/unit/org/openstreetmap/josm/data/projection/SwissGridTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/projection/SwissGridTest.java b/test/unit/org/openstreetmap/josm/data/projection/SwissGridTest.java
    index 4b44434..e369652 100644
    a b public class SwissGridTest {  
    1414
    1515    @BeforeClass
    1616    public static void setUp() {
    17         Main.proj = new SwissGrid();
     17        Main.setProjection(new SwissGrid());
    1818    }
    1919
    2020    /**
    public class SwissGridTest {  
    6161    public void a_latlon2eastNorth_test() {
    6262        {
    6363            LatLon ll = new LatLon(46.518, 6.567);
    64             EastNorth en = Main.proj.latlon2eastNorth(ll);
    65             if (debug) System.out.println(en);
     64            EastNorth en = Main.getProjection().latlon2eastNorth(ll);
     65            if (debug) {
     66                System.out.println(en);
     67            }
    6668            assertTrue("Lausanne", Math.abs(en.east() - 533111.69) < 0.1);
    6769            assertTrue("Lausanne", Math.abs(en.north() - 152227.85) < 0.1);
    6870        }
    6971
    7072        {
    7173            LatLon ll = new LatLon(47.78, 8.58);
    72             EastNorth en = Main.proj.latlon2eastNorth(ll);
    73             if (debug) System.out.println(en);
     74            EastNorth en = Main.getProjection().latlon2eastNorth(ll);
     75            if (debug) {
     76                System.out.println(en);
     77            }
    7478            assertTrue("Schafouse", Math.abs(en.east() - 685544.16) < 0.1);
    7579            assertTrue("Schafouse", Math.abs(en.north() - 292782.91) < 0.1);
    7680        }
    7781
    7882        {
    7983            LatLon ll = new LatLon(46.58, 10.48);
    80             EastNorth en = Main.proj.latlon2eastNorth(ll);
    81             if (debug) System.out.println(en);
     84            EastNorth en = Main.getProjection().latlon2eastNorth(ll);
     85            if (debug) {
     86                System.out.println(en);
     87            }
    8288            assertTrue("Grinson", Math.abs(en.east() - 833068.04) < 0.1);
    8389            assertTrue("Grinson", Math.abs(en.north() - 163265.39) < 0.1);
    8490        }
    8591
    8692        {
    8793            LatLon ll = new LatLon(46.0 + 57.0 / 60 + 3.89813884505 / 3600, 7.0 + 26.0 / 60 + 19.076595154147 / 3600);
    88             EastNorth en = Main.proj.latlon2eastNorth(ll);
    89             if (debug) System.out.println(en);
     94            EastNorth en = Main.getProjection().latlon2eastNorth(ll);
     95            if (debug) {
     96                System.out.println(en);
     97            }
    9098            assertTrue("Berne", Math.abs(en.east() - 600000.0) < 0.1);
    9199            assertTrue("Berne", Math.abs(en.north() - 200000.0) < 0.1);
    92100        }
    93101        {
    94102            LatLon ll = new LatLon(46.0 + 2.0 / 60 + 38.87 / 3600, 8.0 + 43.0 / 60 + 49.79 / 3600);
    95             EastNorth en = Main.proj.latlon2eastNorth(ll);
    96             if (debug) System.out.println(en);
     103            EastNorth en = Main.getProjection().latlon2eastNorth(ll);
     104            if (debug) {
     105                System.out.println(en);
     106            }
    97107            assertTrue("Ref", Math.abs(en.east() - 700000.0) < 0.1);
    98108            assertTrue("Ref", Math.abs(en.north() - 100000.0) < 0.1);
    99109        }
    public class SwissGridTest {  
    104114    public void b_eastNorth2latlon_test() {
    105115        {
    106116            EastNorth en = new EastNorth(533111.69, 152227.85);
    107             LatLon ll = Main.proj.eastNorth2latlon(en);
    108             if (debug) System.out.println(ll);
     117            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     118            if (debug) {
     119                System.out.println(ll);
     120            }
    109121            assertTrue("Lausanne", Math.abs(ll.lat() - 46.518) < 0.00001);
    110122            assertTrue("Lausanne", Math.abs(ll.lon() - 6.567) < 0.00001);
    111123        }
    112124
    113125        {
    114126            EastNorth en = new EastNorth(685544.16, 292782.91);
    115             LatLon ll = Main.proj.eastNorth2latlon(en);
    116             if (debug) System.out.println(ll);
     127            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     128            if (debug) {
     129                System.out.println(ll);
     130            }
    117131            assertTrue("Schafouse", Math.abs(ll.lat() - 47.78) < 0.00001);
    118132            assertTrue("Schafouse", Math.abs(ll.lon() - 8.58) < 0.00001);
    119133        }
    120134
    121135        {
    122136            EastNorth en = new EastNorth(833068.04, 163265.39);
    123             LatLon ll = Main.proj.eastNorth2latlon(en);
    124             if (debug) System.out.println(ll);
     137            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     138            if (debug) {
     139                System.out.println(ll);
     140            }
    125141            assertTrue("Grinson", Math.abs(ll.lat() - 46.58) < 0.00001);
    126142            assertTrue("Grinson", Math.abs(ll.lon() - 10.48) < 0.00001);
    127143        }
    128144
    129145        {
    130146            EastNorth en = new EastNorth(600000.0, 200000.0);
    131             LatLon ll = Main.proj.eastNorth2latlon(en);
    132             if (debug) System.out.println(ll);
     147            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     148            if (debug) {
     149                System.out.println(ll);
     150            }
    133151            assertTrue("Berne", Math.abs(ll.lat() - (46.0 + 57.0 / 60 + 3.89813884505 / 3600)) < 0.00001);
    134152            assertTrue("Berne", Math.abs(ll.lon() - (7.0 + 26.0 / 60 + 19.076595154147 / 3600)) < 0.00001);
    135153        }
    136154
    137155        {
    138156            EastNorth en = new EastNorth(700000.0, 100000.0);
    139             LatLon ll = Main.proj.eastNorth2latlon(en);
    140             if (debug) System.out.println(ll);
     157            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     158            if (debug) {
     159                System.out.println(ll);
     160            }
    141161            assertTrue("Ref", Math.abs(ll.lat() - (46.0 + 2.0 / 60 + 38.87 / 3600)) < 0.00001);
    142162            assertTrue("Ref", Math.abs(ll.lon() - (8.0 + 43.0 / 60 + 49.79 / 3600)) < 0.00001);
    143163        }
    public class SwissGridTest {  
    151171    public void c_sendandreturn_test() {
    152172        {
    153173            EastNorth en = new EastNorth(533111.69, 152227.85);
    154             LatLon ll = Main.proj.eastNorth2latlon(en);
    155             EastNorth en2 = Main.proj.latlon2eastNorth(ll);
    156             if (debug) System.out.println(en.east() - en2.east());
    157             if (debug) System.out.println(en.north() - en2.north());
     174            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     175            EastNorth en2 = Main.getProjection().latlon2eastNorth(ll);
     176            if (debug) {
     177                System.out.println(en.east() - en2.east());
     178            }
     179            if (debug) {
     180                System.out.println(en.north() - en2.north());
     181            }
    158182            assertTrue("Lausanne", Math.abs(en.east() - en2.east()) < 0.002);
    159183            assertTrue("Lausanne", Math.abs(en.north() - en2.north()) < 0.002);
    160184        }
    161185
    162186        {
    163187            EastNorth en = new EastNorth(685544.16, 292782.91);
    164             LatLon ll = Main.proj.eastNorth2latlon(en);
    165             EastNorth en2 = Main.proj.latlon2eastNorth(ll);
    166             if (debug) System.out.println(en.east() - en2.east());
    167             if (debug) System.out.println(en.north() - en2.north());
     188            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     189            EastNorth en2 = Main.getProjection().latlon2eastNorth(ll);
     190            if (debug) {
     191                System.out.println(en.east() - en2.east());
     192            }
     193            if (debug) {
     194                System.out.println(en.north() - en2.north());
     195            }
    168196            assertTrue("Schafouse", Math.abs(en.east() - en2.east()) < 0.002);
    169197            assertTrue("Schafouse", Math.abs(en.north() - en2.north()) < 0.002);
    170198        }
    171199
    172200        {
    173201            EastNorth en = new EastNorth(833068.04, 163265.39);
    174             LatLon ll = Main.proj.eastNorth2latlon(en);
    175             EastNorth en2 = Main.proj.latlon2eastNorth(ll);
    176             if (debug) System.out.println(en.east() - en2.east());
    177             if (debug) System.out.println(en.north() - en2.north());
     202            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     203            EastNorth en2 = Main.getProjection().latlon2eastNorth(ll);
     204            if (debug) {
     205                System.out.println(en.east() - en2.east());
     206            }
     207            if (debug) {
     208                System.out.println(en.north() - en2.north());
     209            }
    178210            assertTrue("Grinson", Math.abs(en.east() - en2.east()) < 0.002);
    179211            assertTrue("Grinson", Math.abs(en.north() - en2.north()) < 0.002);
    180212        }
    181213
    182214        {
    183215            EastNorth en = new EastNorth(600000.0, 200000.0);
    184             LatLon ll = Main.proj.eastNorth2latlon(en);
    185             EastNorth en2 = Main.proj.latlon2eastNorth(ll);
    186             if (debug) System.out.println(en.east() - en2.east());
    187             if (debug) System.out.println(en.north() - en2.north());
     216            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     217            EastNorth en2 = Main.getProjection().latlon2eastNorth(ll);
     218            if (debug) {
     219                System.out.println(en.east() - en2.east());
     220            }
     221            if (debug) {
     222                System.out.println(en.north() - en2.north());
     223            }
    188224            assertTrue("Berne", Math.abs(en.east() - en2.east()) < 0.002);
    189225            assertTrue("Berne", Math.abs(en.north() - en2.north()) < 0.002);
    190226        }
    191227
    192228        {
    193229            EastNorth en = new EastNorth(700000.0, 100000.0);
    194             LatLon ll = Main.proj.eastNorth2latlon(en);
    195             EastNorth en2 = Main.proj.latlon2eastNorth(ll);
    196             if (debug) System.out.println(en.east() - en2.east());
    197             if (debug) System.out.println(en.north() - en2.north());
     230            LatLon ll = Main.getProjection().eastNorth2latlon(en);
     231            EastNorth en2 = Main.getProjection().latlon2eastNorth(ll);
     232            if (debug) {
     233                System.out.println(en.east() - en2.east());
     234            }
     235            if (debug) {
     236                System.out.println(en.north() - en2.north());
     237            }
    198238            assertTrue("Ref", Math.abs(en.east() - en2.east()) < 0.002);
    199239            assertTrue("Ref", Math.abs(en.north() - en2.north()) < 0.002);
    200240        }
  • test/unit/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModelTest.java

    diff --git a/test/unit/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModelTest.java b/test/unit/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModelTest.java
    index 7e9ad9b..7f9ffae 100644
    a b public class PropertiesMergeModelTest {  
    4646
    4747    @BeforeClass
    4848    public static void init() {
    49         Main.proj = new Epsg4326();
     49        Main.setProjection(new Epsg4326());
    5050        Main.pref = new Preferences();
    5151    }
    5252