Index: applications/editors/josm/plugins/agpifoj/build.xml
===================================================================
--- applications/editors/josm/plugins/agpifoj/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/agpifoj/build.xml	(revision 16294)
@@ -34,5 +34,5 @@
                 <attribute name="Plugin-Early" value="false"/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/AgPifoJ"/>
-                <attribute name="Plugin-Mainversion" value="1722"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java
===================================================================
--- applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java	(revision 16294)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.RenameLayerAction;
+import org.openstreetmap.josm.data.coor.CachedLatLon;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -53,5 +54,5 @@
 
     private int currentPhoto = -1;
-    
+
     // These are used by the auto-guess function to store the result,
     // so when the dialig is re-opened the users modifications don't
@@ -68,6 +69,5 @@
         Date time;
         LatLon exifCoor;
-        LatLon coor;
-        EastNorth pos;
+        CachedLatLon pos;
         /** Speed in kilometer per second */
         Double speed;
@@ -75,4 +75,8 @@
         Double elevation;
 
+        public void setCoor(LatLon latlon)
+        {
+            pos = new CachedLatLon(latlon);
+        }
         public int compareTo(ImageEntry image) {
             if (time != null && image.time != null) {
@@ -362,5 +366,5 @@
     public void visitBoundingBox(BoundingXYVisitor v) {
         for (ImageEntry e : data)
-            v.visit(e.pos);
+            v.visit(e.pos.getEastNorth());
     }
 
@@ -411,10 +415,8 @@
             // Store values
 
-            e.coor = new LatLon(lat, lon);
-            e.exifCoor = e.coor;
-            e.pos = Main.proj.latlon2eastNorth(e.coor);
+            e.setCoor(new LatLon(lat, lon));
+            e.exifCoor = e.pos;
 
         } catch (Exception p) {
-            e.coor = null;
             e.pos = null;
         }
Index: applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java
===================================================================
--- applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java	(revision 16290)
+++ applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java	(revision 16294)
@@ -765,5 +765,4 @@
                 // Reset previous position
                 for(ImageEntry x : autoImgs) {
-                    x.coor = null;
                     x.pos = null;
                 }
@@ -893,5 +892,4 @@
                 if (e.time != null) {
                     // Reset previous position
-                    e.coor = null;
                     e.pos = null;
                     dateImgLst.add(e);
@@ -908,5 +906,5 @@
         } else {
             for (ImageEntry e : yLayer.data) {
-                if (e.time != null && e.coor == null) {
+                if (e.time != null && e.pos == null) {
                     dateImgLst.add(e);
                 }
@@ -999,7 +997,6 @@
             while(i >= 0 && (dateImgLst.get(i).time.getTime()/1000) <= curDateWp
                         && (dateImgLst.get(i).time.getTime()/1000) >= (curDateWp - interval)) {
-                if(dateImgLst.get(i).coor == null) {
-                    dateImgLst.get(i).pos = curWp.eastNorth;
-                    dateImgLst.get(i).coor = Main.proj.eastNorth2latlon(dateImgLst.get(i).pos);
+                if(dateImgLst.get(i).pos == null) {
+                    dateImgLst.get(i).setCoor(curWp.getCoor());
                     dateImgLst.get(i).speed = speed;
                     dateImgLst.get(i).elevation = curElevation;
@@ -1016,16 +1013,13 @@
         while(i >= 0 && (imgDate = dateImgLst.get(i).time.getTime()/1000) >= prevDateWp) {
 
-            if(dateImgLst.get(i).coor == null) {
+            if(dateImgLst.get(i).pos == null) {
                 // The values of timeDiff are between 0 and 1, it is not seconds but a dimensionless
                 // variable
                 double timeDiff = (double)(imgDate - prevDateWp) / interval;
-                dateImgLst.get(i).pos = new EastNorth(
-                        interpolate(prevWp.eastNorth.east(),  curWp.eastNorth.east(),  timeDiff),
-                        interpolate(prevWp.eastNorth.north(), curWp.eastNorth.north(), timeDiff));
-                dateImgLst.get(i).coor = Main.proj.eastNorth2latlon(dateImgLst.get(i).pos);
+                dateImgLst.get(i).setCoor(prevWp.getCoor().interpolate(curWp.getCoor(), timeDiff));
                 dateImgLst.get(i).speed = speed;
 
                 if (curElevation != null && prevElevation != null)
-                    dateImgLst.get(i).elevation = interpolate(prevElevation, curElevation, timeDiff);
+                    dateImgLst.get(i).elevation = prevElevation + (curElevation - prevElevation) * timeDiff;
 
                 ret++;
@@ -1034,8 +1028,4 @@
         }
         return ret;
-    }
-
-    private double interpolate(double val1, double val2, double time) {
-        return val1 + (val2 - val1) * time;
     }
 
@@ -1168,8 +1158,8 @@
      * Formula and earth radius from : http://en.wikipedia.org/wiki/Great-circle_distance */
     public double getDistance(WayPoint p1, WayPoint p2) {
-        double p1Lat = p1.latlon.lat() * Math.PI / 180;
-        double p1Lon = p1.latlon.lon() * Math.PI / 180;
-        double p2Lat = p2.latlon.lat() * Math.PI / 180;
-        double p2Lon = p2.latlon.lon() * Math.PI / 180;
+        double p1Lat = p1.getCoor().lat() * Math.PI / 180;
+        double p1Lon = p1.getCoor().lon() * Math.PI / 180;
+        double p2Lat = p2.getCoor().lat() * Math.PI / 180;
+        double p2Lon = p2.getCoor().lon() * Math.PI / 180;
         double ret = Math.atan2(Math.sqrt(Math.pow(Math.cos(p2Lat) * Math.sin(p2Lon - p1Lon), 2)
                                           + Math.pow(Math.cos(p1Lat) * Math.sin(p2Lat)
Index: applications/editors/josm/plugins/editgpx/build.xml
===================================================================
--- applications/editors/josm/plugins/editgpx/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/editgpx/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="Allows the user to anonymize timestamps and delete parts of huge GPX tracks very fast." />
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/EditGpx" />
-                <attribute name="Plugin-Mainversion" value="1722" />
+                <attribute name="Plugin-Mainversion" value="1725" />
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
===================================================================
--- applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java	(revision 16294)
@@ -34,4 +34,5 @@
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.tools.DateUtils;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -167,7 +168,7 @@
                 WayPoint wpt = new WayPoint(n.getCoor());
                 if (anonTime) {
-                    wpt.attr.put("time", "1970-01-01T00:00:00");
+                    wpt.attr.put("time", "1970-01-01T00:00:00Z");
                 } else {
-                    wpt.attr.put("time", WayPoint.GPXTIMEFMT.format(tstamp));
+                    wpt.attr.put("time", DateUtils.fromDate(tstamp));
                 }
                 wpt.setTime();
@@ -185,7 +186,7 @@
             WayPoint wpt = new WayPoint(n.getCoor());
             if (anonTime) {
-                wpt.attr.put("time", "1970-01-01T00:00:00");
+                wpt.attr.put("time", "1970-01-01T00:00:00Z");
             } else {
-                wpt.attr.put("time", WayPoint.GPXTIMEFMT.format(tstamp));
+                wpt.attr.put("time", DateUtils.fromDate(tstamp));
             }
             wpt.setTime();
Index: applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
===================================================================
--- applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java	(revision 16290)
+++ applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java	(revision 16294)
@@ -68,5 +68,5 @@
             //go through nodes and mark the ones in the selection rect as deleted
             for (Node n: dataSet.nodes) {
-                Point p = Main.map.mapView.getPoint(n.getEastNorth());
+                Point p = Main.map.mapView.getPoint(n);
                 if (r.contains(p)) {
                     n.deleted = true; //only set as deleted. this makes reset to beginning possible
Index: applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
===================================================================
--- applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java	(revision 16290)
+++ applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java	(revision 16294)
@@ -115,11 +115,8 @@
                         Way w = new Way();
                         for (WayPoint p : segment) {
-                            Node n = new Node(p.latlon);
+                            Node n = new Node(p.getCoor());
                             String timestr = p.getString("time");
                             if(timestr != null)
-                            {
-                                timestr = timestr.replace("Z","+00:00");
                                 n.setTimestamp(DateUtils.fromString(timestr));
-                            }
                             dataSet.nodes.add(n);
                             w.nodes.add(n); //TODO what to do with these while deletion
Index: applications/editors/josm/plugins/grid/build.xml
===================================================================
--- applications/editors/josm/plugins/grid/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/grid/build.xml	(revision 16294)
@@ -25,4 +25,5 @@
                 <attribute name="Plugin-Description" value="Provide a background layer that displays a map grid" />
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
+                <attribute name="Plugin-MainVersion" value="1725"/>
             </manifest>
         </jar>
Index: applications/editors/josm/plugins/grid/src/grid/GridLayer.java
===================================================================
--- applications/editors/josm/plugins/grid/src/grid/GridLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/grid/src/grid/GridLayer.java	(revision 16294)
@@ -303,7 +303,7 @@
             lli = gridtoworld.transform(new LatLon(lat+latspacing,lon));
             llj = gridtoworld.transform(new LatLon(lat,lon+lonspacing));
-            Point p0=mv.getPoint(Main.proj.latlon2eastNorth(ll0));
-            Point pi=mv.getPoint(Main.proj.latlon2eastNorth(lli));
-            Point pj=mv.getPoint(Main.proj.latlon2eastNorth(llj));
+            Point p0=mv.getPoint(ll0);
+            Point pi=mv.getPoint(lli);
+            Point pj=mv.getPoint(llj);
 
             if(Math.round(lon/lonspacing)%lonmaj==0)
@@ -335,6 +335,6 @@
 
     private void drawGridLine(Graphics g, final MapView mv, LatLon ll0, LatLon ll1){
-        Point p0=mv.getPoint(Main.proj.latlon2eastNorth(ll0));
-        Point p1=mv.getPoint(Main.proj.latlon2eastNorth(ll1));
+        Point p0=mv.getPoint(ll0);
+        Point p1=mv.getPoint(ll1);
 
         if(Math.abs(ll0.lon()-ll1.lon())<180){
@@ -347,6 +347,6 @@
             if(lon1<0) lon1+=360;
             latm = ll0.lat() + (180-lon0)*(ll1.lat()-ll0.lat())/(lon1-lon0);
-            Point pm1 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(latm,180)));
-            Point pm2 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(latm,-180)));
+            Point pm1 = mv.getPoint(new LatLon(latm,180));
+            Point pm2 = mv.getPoint(new LatLon(latm,-180));
             if(lon0<=180){
                 g.drawLine(p0.x,p0.y,pm1.x,pm1.y);
Index: applications/editors/josm/plugins/imagewaypoint/build.xml
===================================================================
--- applications/editors/josm/plugins/imagewaypoint/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/imagewaypoint/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="Another plugin to match images to the waypoints in a GPX file. A match is made when the 'name', 'cmt' or 'desc' attribute of a waypoint tag matches the filename of an image."/>
                 <attribute name="Plugin-Early" value="false"/>
-                <attribute name="Plugin-Mainversion" value="1498"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageEntry.java
===================================================================
--- applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageEntry.java	(revision 16290)
+++ applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageEntry.java	(revision 16294)
@@ -151,5 +151,5 @@
         bounds = null;
     } else {
-        final Point point = mapView.getPoint(this.getWayPoint().eastNorth);
+        final Point point = mapView.getPoint(this.getWayPoint().getCoor());
         bounds = new Rectangle(point.x - ImageEntry.ICON_WIDTH,
         point.y - ImageEntry.ICON_HEIGHT,
Index: applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageWayPointLayer.java
===================================================================
--- applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageWayPointLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/imagewaypoint/src/org/insignificant/josm/plugins/imagewaypoint/ImageWayPointLayer.java	(revision 16294)
@@ -150,8 +150,6 @@
                 final ImageEntry imageEntry = images[index];
 
-                if (null != imageEntry.getWayPoint()
-                && null != imageEntry.getWayPoint().eastNorth) {
-                    visitor.visit(imageEntry.getWayPoint().eastNorth);
-                }
+                if (imageEntry.getWayPoint() != null)
+                    visitor.visit(imageEntry.getWayPoint().getCoor());
             }
         }
Index: applications/editors/josm/plugins/livegps/build.xml
===================================================================
--- applications/editors/josm/plugins/livegps/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/livegps/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="Support live GPS input (moving dot) through a connection to gpsd server."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/LiveGPS"/>
-                <attribute name="Plugin-Mainversion" value="1722"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Stage" value="50"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
Index: applications/editors/josm/plugins/livegps/src/livegps/LiveGpsLayer.java
===================================================================
--- applications/editors/josm/plugins/livegps/src/livegps/LiveGpsLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/livegps/src/livegps/LiveGpsLayer.java	(revision 16294)
@@ -74,5 +74,5 @@
     {
         if (lastPoint != null)
-            Main.map.mapView.zoomTo(lastPoint.eastNorth);
+            Main.map.mapView.zoomTo(lastPoint.getCoor());
     }
 
@@ -116,5 +116,5 @@
             if (lastPoint != null)
             {
-                Point screen = mv.getPoint(lastPoint.eastNorth);
+                Point screen = mv.getPoint(lastPoint.getCoor());
                 g.setColor(Main.pref.getColor(KEY_LIVEGPS_COLOR, Color.RED));
                 g.drawOval(screen.x-10, screen.y-10,20,20);
Index: applications/editors/josm/plugins/measurement/build.xml
===================================================================
--- applications/editors/josm/plugins/measurement/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/measurement/build.xml	(revision 16294)
@@ -25,5 +25,5 @@
                 <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
                 <attribute name="Plugin-Description" value="Provide a measurement dialog and a layer to measure length and angle of segments, area surrounded by a (simple) closed way and create measurement paths (which also can be imported from a gps layer)."/>
-                <attribute name="Plugin-Mainversion" value="1640"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java
===================================================================
--- applications/editors/josm/plugins/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/measurement/src/org/openstreetmap/josm/plugins/measurement/MeasurementLayer.java	(revision 16294)
@@ -75,6 +75,5 @@
         Point l = null;
         for(WayPoint p:points){
-            LatLon c = p.latlon;
-            Point pnt = Main.map.mapView.getPoint(Main.proj.latlon2eastNorth(c));
+            Point pnt = Main.map.mapView.getPoint(p.getCoor());
             if (l != null){
                 g.drawLine(l.x, l.y, pnt.x, pnt.y);
@@ -196,9 +195,9 @@
 
     public static double calcDistance(WayPoint p1, WayPoint p2){
-        return calcDistance(p1.latlon, p2.latlon);
+        return calcDistance(p1.getCoor(), p2.getCoor());
     }
 
     public static double angleBetween(WayPoint p1, WayPoint p2){
-        return angleBetween(p1.latlon, p2.latlon);
+        return angleBetween(p1.getCoor(), p2.getCoor());
     }
 
Index: applications/editors/josm/plugins/openstreetbugs/build.xml
===================================================================
--- applications/editors/josm/plugins/openstreetbugs/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/openstreetbugs/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="Imports issues from OpenStreetBugs"/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/OpenStreetBugs"/>
-                <attribute name="Plugin-Mainversion" value="1722"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/openstreetbugs/src/org/openstreetmap/josm/plugins/osb/OsbLayer.java
===================================================================
--- applications/editors/josm/plugins/openstreetbugs/src/org/openstreetmap/josm/plugins/osb/OsbLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/openstreetbugs/src/org/openstreetmap/josm/plugins/osb/OsbLayer.java	(revision 16294)
@@ -125,5 +125,5 @@
             }
 
-            Point p = mv.getPoint(node.getEastNorth());
+            Point p = mv.getPoint(node);
 
             ImageIcon icon = OsbPlugin.loadIcon("icon_error16.png");
@@ -200,5 +200,5 @@
             if (n.deleted || n.incomplete)
                 continue;
-            Point sp = Main.map.mapView.getPoint(n.getEastNorth());
+            Point sp = Main.map.mapView.getPoint(n);
             double dist = p.distanceSq(sp);
             if (minDistanceSq > dist && p.distance(sp) < snapDistance) {
Index: applications/editors/josm/plugins/routing/build.xml
===================================================================
--- applications/editors/josm/plugins/routing/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/routing/build.xml	(revision 16294)
@@ -44,5 +44,5 @@
                 <attribute name="Plugin-Description" value="Provides routing capabilities."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Routing"/>
-                <attribute name="Plugin-Mainversion" value="1722"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Stage" value="50"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
Index: applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java
===================================================================
--- applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java	(revision 16294)
@@ -139,5 +139,5 @@
                 if (n.deleted || n.incomplete) continue;
 
-                Point P = Main.map.mapView.getPoint(n.getEastNorth());
+                Point P = Main.map.mapView.getPoint(n);
                 double dist = p.distanceSq(P);
                 if (dist < NavigatableComponent.snapDistance) {
@@ -275,5 +275,5 @@
         // paint start icon
         Node node = nodes.get(0);
-        Point screen = mv.getPoint(node.getEastNorth());
+        Point screen = mv.getPoint(node);
         startIcon.paintIcon(mv, g, screen.x - startIcon.getIconWidth()/2,
                 screen.y - startIcon.getIconHeight());
@@ -282,5 +282,5 @@
         for(int index = 1; index < nodes.size() - 1; ++index) {
             node = nodes.get(index);
-            screen = mv.getPoint(node.getEastNorth());
+            screen = mv.getPoint(node);
             middleIcon.paintIcon(mv, g, screen.x - startIcon.getIconWidth()/2,
                     screen.y - middleIcon.getIconHeight());
@@ -289,5 +289,5 @@
         if(nodes.size() > 1) {
             node = nodes.get(nodes.size() - 1);
-            screen = mv.getPoint(node.getEastNorth());
+            screen = mv.getPoint(node);
             endIcon.paintIcon(mv, g, screen.x - startIcon.getIconWidth()/2,
                     screen.y - endIcon.getIconHeight());
Index: applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/MoveRouteNodeAction.java
===================================================================
--- applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/MoveRouteNodeAction.java	(revision 16290)
+++ applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/MoveRouteNodeAction.java	(revision 16294)
@@ -113,5 +113,5 @@
                 for (int i=0;i<nl.size();i++) {
                     Node node = nl.get(i);
-                    double d = Main.map.mapView.getPoint(node.getEastNorth()).distanceSq(e.getPoint());
+                    double d = Main.map.mapView.getPoint(node).distanceSq(e.getPoint());
                     if (d < dmax) {
                         dmax = d;
Index: applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/RemoveRouteNodeAction.java
===================================================================
--- applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/RemoveRouteNodeAction.java	(revision 16290)
+++ applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/actions/RemoveRouteNodeAction.java	(revision 16294)
@@ -102,5 +102,5 @@
                 for (int i=0;i<nl.size();i++) {
                     Node node = nl.get(i);
-                    double d = Main.map.mapView.getPoint(node.getEastNorth()).distanceSq(e.getPoint());
+                    double d = Main.map.mapView.getPoint(node).distanceSq(e.getPoint());
                     if (d < dmax) {
                         dmax = d;
Index: applications/editors/josm/plugins/slippymap/build.xml
===================================================================
--- applications/editors/josm/plugins/slippymap/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/slippymap/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="Displays a slippy map grid in JOSM. Can load tiles from slippy map as background and request updates."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/SlippyMap"/>
-                <attribute name="Plugin-Mainversion" value="1646"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
===================================================================
--- applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java	(revision 16294)
@@ -46,5 +46,5 @@
  * @author LuVar <lubomir.varga@freemap.sk>
  * @author Dave Hansen <dave@sr71.net>
- * 
+ *
  */
 public class SlippyMapLayer extends Layer implements ImageObserver,
@@ -131,15 +131,15 @@
                     }
                 }));
-        
+
         tileOptionMenu.add(new JMenuItem(
-        		new AbstractAction(tr("Flush Tile Cache")) {
-        			public void actionPerformed(ActionEvent ae) {
-        				System.out.print("flushing all tiles...");
-        				for (SlippyMapTile t : tileStorage.values()) {
-        					t.dropImage();
-        					}
-        				System.out.println("done");
-        				}
-        			}));
+                new AbstractAction(tr("Flush Tile Cache")) {
+                    public void actionPerformed(ActionEvent ae) {
+                        System.out.print("flushing all tiles...");
+                        for (SlippyMapTile t : tileStorage.values()) {
+                            t.dropImage();
+                            }
+                        System.out.println("done");
+                        }
+                    }));
         // end of adding menu commands
 
@@ -176,6 +176,6 @@
     /**
      * Zoom in, go closer to map.
-     * 
-     * @return	true, if zoom increasing was successfull, false othervise
+     *
+     * @return    true, if zoom increasing was successfull, false othervise
      */
     public boolean increaseZoomLevel() {
@@ -194,6 +194,6 @@
     /**
      * Zoom out from map.
-     * 
-     * @return	true, if zoom increasing was successfull, false othervise
+     *
+     * @return    true, if zoom increasing was successfull, false othervise
      */
     public boolean decreaseZoomLevel() {
@@ -271,29 +271,29 @@
 
     synchronized SlippyMapTile getTile(int x, int y, int zoom) {
-		SlippyMapKey key = new SlippyMapKey(x, y, zoom);
-		if (!key.valid) {
-			key = null;
-		}
-		return tileStorage.get(key);
-	}
-
-	synchronized SlippyMapTile putTile(SlippyMapTile tile, int x, int y, int zoom) {
-		SlippyMapKey key = new SlippyMapKey(x, y, zoom);
-		if (!key.valid) {
-			key = null;
-		}
-		return tileStorage.put(key, tile);
-	}
-
-	synchronized SlippyMapTile getOrCreateTile(int x, int y, int zoom) {
-		SlippyMapTile tile = getTile(x, y, zoom);
-		if (tile != null) {
-			return tile;
-		}
-		tile = new SlippyMapTile(x, y, zoom);
-		putTile(tile, x, y, zoom);
-		return tile;
-	}
-    
+        SlippyMapKey key = new SlippyMapKey(x, y, zoom);
+        if (!key.valid) {
+            key = null;
+        }
+        return tileStorage.get(key);
+    }
+
+    synchronized SlippyMapTile putTile(SlippyMapTile tile, int x, int y, int zoom) {
+        SlippyMapKey key = new SlippyMapKey(x, y, zoom);
+        if (!key.valid) {
+            key = null;
+        }
+        return tileStorage.put(key, tile);
+    }
+
+    synchronized SlippyMapTile getOrCreateTile(int x, int y, int zoom) {
+        SlippyMapTile tile = getTile(x, y, zoom);
+        if (tile != null) {
+            return tile;
+        }
+        tile = new SlippyMapTile(x, y, zoom);
+        putTile(tile, x, y, zoom);
+        return tile;
+    }
+
     void loadAllTiles() {
         MapView mv = Main.map.mapView;
@@ -302,55 +302,55 @@
 
         TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
-        
+
         // if there is more than 18 tiles on screen in any direction, do not
         // load all tiles!
         if (ts.tilesSpanned() > (18*18)) {
-        	System.out.println("Not downloading all tiles because there is more than 18 tiles on an axis!");
-        	return;
+            System.out.println("Not downloading all tiles because there is more than 18 tiles on an axis!");
+            return;
         }
 
         for (Tile t : ts.allTiles()) {
-        	SlippyMapTile tile = getOrCreateTile(t.x, t.y, currentZoomLevel);
-        	if (tile.getImage() == null) {
-        		this.loadSingleTile(tile);
-        	}
+            SlippyMapTile tile = getOrCreateTile(t.x, t.y, currentZoomLevel);
+            if (tile.getImage() == null) {
+                this.loadSingleTile(tile);
+            }
         }//end of for Tile t
     }
 
-	/*
-	 * Attempt to approximate how much the image is being scaled. For instance,
-	 * a 100x100 image being scaled to 50x50 would return 0.25.
-	 */
-	Image lastScaledImage = null;
-
-	double getImageScaling(Image img, Point p0, Point p1) {
-		int realWidth = img.getWidth(this);
-		int realHeight = img.getHeight(this);
-		if (realWidth == -1 || realHeight == -1) {
-			/*
-			 * We need a good image against which to work. If
-			 * the current one isn't loaded, then try the last one.
-			 * Should be good enough. If we've never seen one, then
-			 * guess.        
-			 */
-			if (lastScaledImage != null) {
-				return getImageScaling(lastScaledImage, p0, p1);
-			}
-			realWidth = 256;
-			realHeight = 256;
-		} else {
-			lastScaledImage = img;
-		}
-		/*
-		 * If the zoom scale gets really, really off, these can get into
-		 * the millions, so make this a double to prevent integer
-		 * overflows.        
-		 */
-		double drawWidth = p1.x - p0.x;
-		double drawHeight = p1.x - p0.x;
-		// stem.out.println("drawWidth: " + drawWidth + " drawHeight: " +
-		// drawHeight);
-
-		double drawArea = drawWidth * drawHeight;
+    /*
+     * Attempt to approximate how much the image is being scaled. For instance,
+     * a 100x100 image being scaled to 50x50 would return 0.25.
+     */
+    Image lastScaledImage = null;
+
+    double getImageScaling(Image img, Point p0, Point p1) {
+        int realWidth = img.getWidth(this);
+        int realHeight = img.getHeight(this);
+        if (realWidth == -1 || realHeight == -1) {
+            /*
+             * We need a good image against which to work. If
+             * the current one isn't loaded, then try the last one.
+             * Should be good enough. If we've never seen one, then
+             * guess.        
+             */
+            if (lastScaledImage != null) {
+                return getImageScaling(lastScaledImage, p0, p1);
+            }
+            realWidth = 256;
+            realHeight = 256;
+        } else {
+            lastScaledImage = img;
+        }
+        /*
+         * If the zoom scale gets really, really off, these can get into
+         * the millions, so make this a double to prevent integer
+         * overflows.        
+         */
+        double drawWidth = p1.x - p0.x;
+        double drawHeight = p1.x - p0.x;
+        // stem.out.println("drawWidth: " + drawWidth + " drawHeight: " +
+        // drawHeight);
+
+        double drawArea = drawWidth * drawHeight;
         double realArea = realWidth * realHeight;
 
@@ -358,157 +358,157 @@
     }
 
-	boolean imageLoaded(Image i) {
-		if (i == null)
-			return false;
-
-		int status = Toolkit.getDefaultToolkit().checkImage(i, -1, -1, this);
-		if ((status & ALLBITS) != 0)
-			return true;
-		return false;
-	}
-
-	Double paintTileImages(Graphics g, TileSet ts, int zoom) {
-		Double imageScale = null;
-		Image img = null;
-		for (Tile t : ts.allTiles()) {
-			SlippyMapTile tile = getTile(t.x, t.y, zoom);
-			if (tile == null) {
-				// Don't trigger tile loading if this isn't
-				// the exact zoom level we're looking for
-				if (zoom != currentZoomLevel)
-					continue;
-				tile = getOrCreateTile(t.x, t.y, zoom);
-				if (SlippyMapPreferences.getAutoloadTiles())
-					loadSingleTile(tile);
-			}
-			img = tile.getImage();
-			if (img == null)
-				continue;
-			if ((zoom != currentZoomLevel) && !tile.isDownloaded())
-				continue;
-			Point p = t.pixelPos(zoom);
-			/*
-			 * We need to get a box in which to draw, so advance by one tile in
-			 * each direction to find the other corner of the box
-			 */
-			Tile t2 = new Tile(t.x + 1, t.y + 1);
-			Point p2 = t2.pixelPos(zoom);
-
-			g.drawImage(img, p.x, p.y, p2.x - p.x, p2.y - p.y, this);
-			if (img == null)
-				continue;
-			if (imageScale == null && zoom == currentZoomLevel)
-				imageScale = new Double(getImageScaling(img, p, p2));
-			float fadeBackground = SlippyMapPreferences.getFadeBackground();
-			if (fadeBackground != 0f) {
-				// dimm by painting opaque rect...
-				g.setColor(new Color(1f, 1f, 1f, fadeBackground));
-				g.fillRect(p.x, p.y, p2.x - p.x, p2.y - p.y);
-			}
-		}// end of for
-		return imageScale;
-	}
-
-	void paintTileText(TileSet ts, Graphics g, MapView mv, int zoom, Tile t) {
-		int fontHeight = g.getFontMetrics().getHeight();
-
-		SlippyMapTile tile = getTile(t.x, t.y, zoom);
-		if (tile == null) {
-			return;
-		}
-		if (tile.getImage() == null) {
-			loadSingleTile(tile);
-		}
-		Point p = t.pixelPos(zoom);
-		int texty = p.y + 2 + fontHeight;
-
-		if (SlippyMapPreferences.getDrawDebug()) {
-			g.drawString("x=" + t.x + " y=" + t.y + " z=" + zoom + "", p.x + 2, texty);
-			texty += 1 + fontHeight;
-			if ((t.x % 32 == 0) && (t.y % 32 == 0)) {
-				g.drawString("x=" + t.x / 32 + " y=" + t.y / 32 + " z=7", p.x + 2, texty);
-				texty += 1 + fontHeight;
-			}
-		}// end of if draw debug
-
-		String md = tile.getMetadata();
-		if (md != null) {
-			g.drawString(md, p.x + 2, texty);
-			texty += 1 + fontHeight;
-		}
-
-		Image tileImage = tile.getImage();
-		if (tileImage == null) {
-			g.drawString(tr("image not loaded"), p.x + 2, texty);
-			texty += 1 + fontHeight;
-		}
-		if (!imageLoaded(tileImage)) {
-			g.drawString(tr("image loading..."), p.x + 2, texty);
-			needRedraw = true;
-			Main.map.repaint(100);
-			texty += 1 + fontHeight;
-		}
-
-		if (SlippyMapPreferences.getDrawDebug()) {
-			if (ts.leftTile(t)) {
-				if (t.y % 32 == 31) {
-					g.fillRect(0, p.y - 1, mv.getWidth(), 3);
-				} else {
-					g.drawLine(0, p.y, mv.getWidth(), p.y);
-				}
-			}
-		}// /end of if draw debug
-	}
-	
-	private class Tile {
-		public int x;
-		public int y;
-
-		Tile(int x, int y) {
-			this.x = x;
-			this.y = y;
-		}
-
-		public Point pixelPos(int zoom) {
-			double lon = tileXToLon(this.x, zoom);
-			LatLon tmpLL = new LatLon(tileYToLat(this.y, zoom), lon);
-			MapView mv = Main.map.mapView;
-			return mv.getPoint(Main.proj.latlon2eastNorth(tmpLL));
-		}
-	}
-
-	private class TileSet {
-		int z12x0, z12x1, z12y0, z12y1;
-		int zoom;
-
-		TileSet(LatLon topLeft, LatLon botRight, int zoom) {
-			this.zoom = zoom;
-			z12x0 = lonToTileX(topLeft.lon(), zoom);
-			z12x1 = lonToTileX(botRight.lon(), zoom);
-			z12y0 = latToTileY(topLeft.lat(), zoom);
-			z12y1 = latToTileY(botRight.lat(), zoom);
-			if (z12x0 > z12x1) {
-				int tmp = z12x0;
-				z12x0 = z12x1;
-				z12x1 = tmp;
-			}
-			if (z12y0 > z12y1) {
-				int tmp = z12y0;
-				z12y0 = z12y1;
-				z12y1 = tmp;
-			}
-		}
-
-		int tilesSpanned() {
-			int x_span = z12x1 - z12x0;
-			int y_span = z12y1 - z12y0;
-			return x_span * y_span;
-		}
-
-		/*
-		 * This is pretty silly. Should probably just be implemented as an
-		 * iterator to keep from having to instantiate all these tiles.
-		 */
-		List<Tile> allTiles()
+    boolean imageLoaded(Image i) {
+        if (i == null)
+            return false;
+
+        int status = Toolkit.getDefaultToolkit().checkImage(i, -1, -1, this);
+        if ((status & ALLBITS) != 0)
+            return true;
+        return false;
+    }
+
+    Double paintTileImages(Graphics g, TileSet ts, int zoom) {
+        Double imageScale = null;
+        Image img = null;
+        for (Tile t : ts.allTiles()) {
+            SlippyMapTile tile = getTile(t.x, t.y, zoom);
+            if (tile == null) {
+                // Don't trigger tile loading if this isn't
+                // the exact zoom level we're looking for
+                if (zoom != currentZoomLevel)
+                    continue;
+                tile = getOrCreateTile(t.x, t.y, zoom);
+                if (SlippyMapPreferences.getAutoloadTiles())
+                    loadSingleTile(tile);
+            }
+            img = tile.getImage();
+            if (img == null)
+                continue;
+            if ((zoom != currentZoomLevel) && !tile.isDownloaded())
+                continue;
+            Point p = t.pixelPos(zoom);
+            /*
+             * We need to get a box in which to draw, so advance by one tile in
+             * each direction to find the other corner of the box
+             */
+            Tile t2 = new Tile(t.x + 1, t.y + 1);
+            Point p2 = t2.pixelPos(zoom);
+
+            g.drawImage(img, p.x, p.y, p2.x - p.x, p2.y - p.y, this);
+            if (img == null)
+                continue;
+            if (imageScale == null && zoom == currentZoomLevel)
+                imageScale = new Double(getImageScaling(img, p, p2));
+            float fadeBackground = SlippyMapPreferences.getFadeBackground();
+            if (fadeBackground != 0f) {
+                // dimm by painting opaque rect...
+                g.setColor(new Color(1f, 1f, 1f, fadeBackground));
+                g.fillRect(p.x, p.y, p2.x - p.x, p2.y - p.y);
+            }
+        }// end of for
+        return imageScale;
+    }
+
+    void paintTileText(TileSet ts, Graphics g, MapView mv, int zoom, Tile t) {
+        int fontHeight = g.getFontMetrics().getHeight();
+
+        SlippyMapTile tile = getTile(t.x, t.y, zoom);
+        if (tile == null) {
+            return;
+        }
+        if (tile.getImage() == null) {
+            loadSingleTile(tile);
+        }
+        Point p = t.pixelPos(zoom);
+        int texty = p.y + 2 + fontHeight;
+
+        if (SlippyMapPreferences.getDrawDebug()) {
+            g.drawString("x=" + t.x + " y=" + t.y + " z=" + zoom + "", p.x + 2, texty);
+            texty += 1 + fontHeight;
+            if ((t.x % 32 == 0) && (t.y % 32 == 0)) {
+                g.drawString("x=" + t.x / 32 + " y=" + t.y / 32 + " z=7", p.x + 2, texty);
+                texty += 1 + fontHeight;
+            }
+        }// end of if draw debug
+
+        String md = tile.getMetadata();
+        if (md != null) {
+            g.drawString(md, p.x + 2, texty);
+            texty += 1 + fontHeight;
+        }
+
+        Image tileImage = tile.getImage();
+        if (tileImage == null) {
+            g.drawString(tr("image not loaded"), p.x + 2, texty);
+            texty += 1 + fontHeight;
+        }
+        if (!imageLoaded(tileImage)) {
+            g.drawString(tr("image loading..."), p.x + 2, texty);
+            needRedraw = true;
+            Main.map.repaint(100);
+            texty += 1 + fontHeight;
+        }
+
+        if (SlippyMapPreferences.getDrawDebug()) {
+            if (ts.leftTile(t)) {
+                if (t.y % 32 == 31) {
+                    g.fillRect(0, p.y - 1, mv.getWidth(), 3);
+                } else {
+                    g.drawLine(0, p.y, mv.getWidth(), p.y);
+                }
+            }
+        }// /end of if draw debug
+    }
+
+    private class Tile {
+        public int x;
+        public int y;
+
+        Tile(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        public Point pixelPos(int zoom) {
+            double lon = tileXToLon(this.x, zoom);
+            LatLon tmpLL = new LatLon(tileYToLat(this.y, zoom), lon);
+            MapView mv = Main.map.mapView;
+            return mv.getPoint(tmpLL);
+        }
+    }
+
+    private class TileSet {
+        int z12x0, z12x1, z12y0, z12y1;
+        int zoom;
+
+        TileSet(LatLon topLeft, LatLon botRight, int zoom) {
+            this.zoom = zoom;
+            z12x0 = lonToTileX(topLeft.lon(), zoom);
+            z12x1 = lonToTileX(botRight.lon(), zoom);
+            z12y0 = latToTileY(topLeft.lat(), zoom);
+            z12y1 = latToTileY(botRight.lat(), zoom);
+            if (z12x0 > z12x1) {
+                int tmp = z12x0;
+                z12x0 = z12x1;
+                z12x1 = tmp;
+            }
+            if (z12y0 > z12y1) {
+                int tmp = z12y0;
+                z12y0 = z12y1;
+                z12y1 = tmp;
+            }
+        }
+
+        int tilesSpanned() {
+            int x_span = z12x1 - z12x0;
+            int y_span = z12y1 - z12y0;
+            return x_span * y_span;
+        }
+
+        /*
+         * This is pretty silly. Should probably just be implemented as an
+         * iterator to keep from having to instantiate all these tiles.
+         */
+        List<Tile> allTiles()
         {
             List<Tile> ret = new ArrayList<Tile>();
@@ -526,134 +526,134 @@
         }
 
-		boolean topTile(Tile t) {
-			if (t.y == z12y0 - 1)
-				return true;
-			return false;
-		}
-
-		boolean leftTile(Tile t) {
-			if (t.x == z12x0 - 1)
-				return true;
-			return false;
-		}
-	}
-	
+        boolean topTile(Tile t) {
+            if (t.y == z12y0 - 1)
+                return true;
+            return false;
+        }
+
+        boolean leftTile(Tile t) {
+            if (t.x == z12x0 - 1)
+                return true;
+            return false;
+        }
+    }
+
     /**
      */
     @Override
     public void paint(Graphics g, MapView mv) {
-		long start = System.currentTimeMillis();
-		LatLon topLeft = mv.getLatLon(0, 0);
-		LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
-		Graphics oldg = g;
-
-		if (botRight.lon() == 0.0 || botRight.lat() == 0) {
-			// probably still initializing
-			return;
-		}
-		if (lastTopLeft != null && lastBotRight != null && topLeft.equalsEpsilon(lastTopLeft)
-				&& botRight.equalsEpsilon(lastBotRight) && bufferImage != null
-				&& mv.getWidth() == bufferImage.getWidth(null) && mv.getHeight() == bufferImage.getHeight(null)
-				&& !needRedraw) {
-
-			g.drawImage(bufferImage, 0, 0, null);
-			return;
-		}
-
-		needRedraw = false;
-		lastTopLeft = topLeft;
-		lastBotRight = botRight;
-		bufferImage = mv.createImage(mv.getWidth(), mv.getHeight());
-		g = bufferImage.getGraphics();
-
-		TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
-		int zoom = currentZoomLevel;
-
-		if (ts.tilesSpanned() > (18*18)) {
-			System.out.println("too many tiles, decreasing zoom from " + currentZoomLevel);
-			if (decreaseZoomLevel()) {
-				this.paint(oldg, mv);
-			}
-			return;
-		}//end of if more than 18*18
-		
-		if (ts.tilesSpanned() <= 0) {
-			System.out.println("doesn't even cover one tile, increasing zoom from " + currentZoomLevel);
-			if (increaseZoomLevel()) {
-				this.paint(oldg, mv);
-			}
-			return;
-		}
-
-		int fontHeight = g.getFontMetrics().getHeight();
-
-		g.setColor(Color.DARK_GRAY);
-
-		float fadeBackground = SlippyMapPreferences.getFadeBackground();
-
-		/*
-		  * Go looking for tiles in zoom levels *other* than the current
-		  * one.  Even if they might look bad, they look better than a
-		  *  blank tile.
-		  */
-		int otherZooms[] = {2, -2, 1, -1};
-		for (int zoomOff : otherZooms) {
-			int zoom2 = currentZoomLevel + zoomOff;
-			if ((zoom <= 0) || (zoom > SlippyMapPreferences.getMaxZoomLvl())) {
-				continue;
-			}
-			TileSet ts2 = new TileSet(topLeft, botRight, zoom2);
-			this.paintTileImages(g, ts2, zoom2);
-			}
-		/*
-		 * Save this for last since it will get painted over all the others
-		 */
-		Double imageScale = this.paintTileImages(g, ts, currentZoomLevel);
-		g.setColor(Color.red);
-		
-		for (Tile t : ts.allTiles()) {
-			// This draws the vertical lines for the entire
-			// column.  Only draw them for the top tile in
-			// the column.
-			if (ts.topTile(t)) {
-				Point p = t.pixelPos(currentZoomLevel);
-				if (SlippyMapPreferences.getDrawDebug()) {
-					if (t.x % 32 == 0) {
-						// level 7 tile boundary
-						g.fillRect(p.x - 1, 0, 3, mv.getHeight());
-					} else {
-						g.drawLine(p.x, 0, p.x, mv.getHeight());
-					}
-				}
-			}
-			this.paintTileText(ts, g, mv, currentZoomLevel, t);
-		}
-
-		oldg.drawImage(bufferImage, 0, 0, null);
-
-		if (imageScale != null) {
-			// If each source image pixel is being stretched into > 3
-			// drawn pixels, zoom in... getting too pixelated
-			if (imageScale > 3) {
-				if (SlippyMapPreferences.getAutozoom()) {
-					Main.debug("autozoom increase: scale: " + imageScale);
-					increaseZoomLevel();
-				}
-				this.paint(oldg, mv);
-			}
-
-			// If each source image pixel is being squished into > 0.32
-			// of a drawn pixels, zoom out.
-			if (imageScale < 0.32) {
-				if (SlippyMapPreferences.getAutozoom()) {
-					Main.debug("autozoom decrease: scale: " + imageScale);
-					decreaseZoomLevel();
-				}
-				this.paint(oldg, mv);
-			}
-		}
-		g.setColor(Color.black);
-		g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120);
-	}// end of paint method
+        long start = System.currentTimeMillis();
+        LatLon topLeft = mv.getLatLon(0, 0);
+        LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
+        Graphics oldg = g;
+
+        if (botRight.lon() == 0.0 || botRight.lat() == 0) {
+            // probably still initializing
+            return;
+        }
+        if (lastTopLeft != null && lastBotRight != null && topLeft.equalsEpsilon(lastTopLeft)
+                && botRight.equalsEpsilon(lastBotRight) && bufferImage != null
+                && mv.getWidth() == bufferImage.getWidth(null) && mv.getHeight() == bufferImage.getHeight(null)
+                && !needRedraw) {
+
+            g.drawImage(bufferImage, 0, 0, null);
+            return;
+        }
+
+        needRedraw = false;
+        lastTopLeft = topLeft;
+        lastBotRight = botRight;
+        bufferImage = mv.createImage(mv.getWidth(), mv.getHeight());
+        g = bufferImage.getGraphics();
+
+        TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
+        int zoom = currentZoomLevel;
+
+        if (ts.tilesSpanned() > (18*18)) {
+            System.out.println("too many tiles, decreasing zoom from " + currentZoomLevel);
+            if (decreaseZoomLevel()) {
+                this.paint(oldg, mv);
+            }
+            return;
+        }//end of if more than 18*18
+
+        if (ts.tilesSpanned() <= 0) {
+            System.out.println("doesn't even cover one tile, increasing zoom from " + currentZoomLevel);
+            if (increaseZoomLevel()) {
+                this.paint(oldg, mv);
+            }
+            return;
+        }
+
+        int fontHeight = g.getFontMetrics().getHeight();
+
+        g.setColor(Color.DARK_GRAY);
+
+        float fadeBackground = SlippyMapPreferences.getFadeBackground();
+
+        /*
+          * Go looking for tiles in zoom levels *other* than the current
+          * one.  Even if they might look bad, they look better than a
+          *  blank tile.
+          */
+        int otherZooms[] = {2, -2, 1, -1};
+        for (int zoomOff : otherZooms) {
+            int zoom2 = currentZoomLevel + zoomOff;
+            if ((zoom <= 0) || (zoom > SlippyMapPreferences.getMaxZoomLvl())) {
+                continue;
+            }
+            TileSet ts2 = new TileSet(topLeft, botRight, zoom2);
+            this.paintTileImages(g, ts2, zoom2);
+            }
+        /*
+         * Save this for last since it will get painted over all the others
+         */
+        Double imageScale = this.paintTileImages(g, ts, currentZoomLevel);
+        g.setColor(Color.red);
+
+        for (Tile t : ts.allTiles()) {
+            // This draws the vertical lines for the entire
+            // column.  Only draw them for the top tile in
+            // the column.
+            if (ts.topTile(t)) {
+                Point p = t.pixelPos(currentZoomLevel);
+                if (SlippyMapPreferences.getDrawDebug()) {
+                    if (t.x % 32 == 0) {
+                        // level 7 tile boundary
+                        g.fillRect(p.x - 1, 0, 3, mv.getHeight());
+                    } else {
+                        g.drawLine(p.x, 0, p.x, mv.getHeight());
+                    }
+                }
+            }
+            this.paintTileText(ts, g, mv, currentZoomLevel, t);
+        }
+
+        oldg.drawImage(bufferImage, 0, 0, null);
+
+        if (imageScale != null) {
+            // If each source image pixel is being stretched into > 3
+            // drawn pixels, zoom in... getting too pixelated
+            if (imageScale > 3) {
+                if (SlippyMapPreferences.getAutozoom()) {
+                    Main.debug("autozoom increase: scale: " + imageScale);
+                    increaseZoomLevel();
+                }
+                this.paint(oldg, mv);
+            }
+
+            // If each source image pixel is being squished into > 0.32
+            // of a drawn pixels, zoom out.
+            if (imageScale < 0.32) {
+                if (SlippyMapPreferences.getAutozoom()) {
+                    Main.debug("autozoom decrease: scale: " + imageScale);
+                    decreaseZoomLevel();
+                }
+                this.paint(oldg, mv);
+            }
+        }
+        g.setColor(Color.black);
+        g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120);
+    }// end of paint method
 
     /**
@@ -662,12 +662,12 @@
      */
     SlippyMapTile getTileForPixelpos(int px, int py) {
-    	MapView mv = Main.map.mapView;
-    	Point clicked = new Point(px, py);
-    	LatLon topLeft = mv.getLatLon(0, 0);
-    	LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
-    	TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
-    	int z = currentZoomLevel;
-    	
-    	Tile clickedTile = null;
+        MapView mv = Main.map.mapView;
+        Point clicked = new Point(px, py);
+        LatLon topLeft = mv.getLatLon(0, 0);
+        LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
+        TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
+        int z = currentZoomLevel;
+
+        Tile clickedTile = null;
         for (Tile t1 : ts.allTiles()) {
             Tile t2 = new Tile(t1.x+1, t1.y+1);
@@ -735,67 +735,67 @@
 
     private int lonToTileX(double lon, int zoom) {
-    	return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0);
+        return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0);
     }
 
     private double tileYToLat(int y, int zoom) {
         return Math.atan(Math.sinh(Math.PI
-        		- (Math.PI * y / Math.pow(2.0, zoom - 1))))
+                - (Math.PI * y / Math.pow(2.0, zoom - 1))))
                 * 180 / Math.PI;
     }
 
     private double tileXToLon(int x, int zoom) {
-    	return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
+        return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
     }
 
     private SlippyMapTile imgToTile(Image img) {
-		// we use the enumeration to avoid ConcurrentUpdateExceptions
-		// with other users of the tileStorage
-		Enumeration<SlippyMapTile> e = tileStorage.elements();
-		while (e.hasMoreElements()) {
-			SlippyMapTile t = e.nextElement();
-			if (t.getImageNoTimestamp() != img) {
-				continue;
-			}
-			return t;
-		}
-		return null;
-	}
-    
+        // we use the enumeration to avoid ConcurrentUpdateExceptions
+        // with other users of the tileStorage
+        Enumeration<SlippyMapTile> e = tileStorage.elements();
+        while (e.hasMoreElements()) {
+            SlippyMapTile t = e.nextElement();
+            if (t.getImageNoTimestamp() != img) {
+                continue;
+            }
+            return t;
+        }
+        return null;
+    }
+
     private static int nr_loaded = 0;
     private static int at_zoom = -1;
-    
+
     public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
-		boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
-		SlippyMapTile imageTile = imgToTile(img);
-		if (imageTile == null) {
-			return false;
-		}
-
-		if ((infoflags & ERROR) != 0) {
-			String url; // = "unknown";
-			url = imageTile.getImageURL().toString();
-			System.err.println("imageUpdate(" + img + ") error " + url + ")");
-		}
-		if (((infoflags & ALLBITS) != 0)) {
-			int z = imageTile.getZoom();
-			if (z == at_zoom) {
-				nr_loaded++;
-			} else {
-				System.out.println("downloaded " + nr_loaded + " at: " + at_zoom + " now going to " + z);
-				nr_loaded = 0;
-				at_zoom = z;
-			}
-			imageTile.markAsDownloaded();
-		}
-		if ((infoflags & SOMEBITS) != 0) {
-			// if (y%100 == 0)
-			//System.out.println("imageUpdate("+img+") SOMEBITS ("+x+","+y+")");
-		}
-		// Repaint immediately if we are done, otherwise batch up
-		// repaint requests every 100 milliseconds
-		needRedraw = true;
-		Main.map.repaint(done ? 0 : 100);
-		return !done;
-	}
+        boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
+        SlippyMapTile imageTile = imgToTile(img);
+        if (imageTile == null) {
+            return false;
+        }
+
+        if ((infoflags & ERROR) != 0) {
+            String url; // = "unknown";
+            url = imageTile.getImageURL().toString();
+            System.err.println("imageUpdate(" + img + ") error " + url + ")");
+        }
+        if (((infoflags & ALLBITS) != 0)) {
+            int z = imageTile.getZoom();
+            if (z == at_zoom) {
+                nr_loaded++;
+            } else {
+                System.out.println("downloaded " + nr_loaded + " at: " + at_zoom + " now going to " + z);
+                nr_loaded = 0;
+                at_zoom = z;
+            }
+            imageTile.markAsDownloaded();
+        }
+        if ((infoflags & SOMEBITS) != 0) {
+            // if (y%100 == 0)
+            //System.out.println("imageUpdate("+img+") SOMEBITS ("+x+","+y+")");
+        }
+        // Repaint immediately if we are done, otherwise batch up
+        // repaint requests every 100 milliseconds
+        needRedraw = true;
+        Main.map.repaint(done ? 0 : 100);
+        return !done;
+    }
 
     /*
Index: applications/editors/josm/plugins/validator/build.xml
===================================================================
--- applications/editors/josm/plugins/validator/build.xml	(revision 16290)
+++ applications/editors/josm/plugins/validator/build.xml	(revision 16294)
@@ -26,5 +26,5 @@
                 <attribute name="Plugin-Description" value="An OSM data validator. It checks for problems in data, and provides fixes for the common ones. Spellcheck integrated for tag names."/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Validator"/>
-                <attribute name="Plugin-Mainversion" value="1722"/>
+                <attribute name="Plugin-Mainversion" value="1725"/>
                 <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
             </manifest>
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java	(revision 16290)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java	(revision 16294)
@@ -23,5 +23,5 @@
 /**
  * A debug layer for testing the grid cells a way crosses.
- * 
+ *
  * @author frsantos
  */
@@ -29,8 +29,8 @@
 {
     /**
-     * Constructor 
+     * Constructor
      * @param name
      */
-    public GridLayer(String name) 
+    public GridLayer(String name)
     {
         super(name);
@@ -47,10 +47,10 @@
      * Draw the grid and highlight all cells acuppied by any selected primitive.
      */
-    @Override 
-    public void paint(final Graphics g, final MapView mv) 
+    @Override
+    public void paint(final Graphics g, final MapView mv)
     {
         if( !Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
             return;
-        
+
         int gridWidth = Integer.parseInt(Main.pref.get(PreferenceEditor.PREF_DEBUG + ".grid") );
         int width = mv.getWidth();
@@ -67,13 +67,13 @@
         for(OsmPrimitive p : Main.ds.getSelected() )
             p.visit(visitor);
-        
+
         long x0 = (long)Math.floor(origin.east()  * gridWidth);
         long x1 = (long)Math.floor(border.east()  * gridWidth);
         long y0 = (long)Math.floor(origin.north() * gridWidth) + 1;
-        long y1 = (long)Math.floor(border.north() * gridWidth) + 1;        
+        long y1 = (long)Math.floor(border.north() * gridWidth) + 1;
         long aux;
         if( x0 > x1 ) { aux = x0; x0 = x1; x1 = aux; }
         if( y0 > y1 ) { aux = y0; y0 = y1; y1 = aux; }
-        
+
         g.setColor(Color.RED.brighter().brighter());
         for( double x = x0; x <= x1; x++)
@@ -90,29 +90,29 @@
     }
 
-    @Override 
-    public String getToolTipText() 
+    @Override
+    public String getToolTipText()
     {
         return null;
     }
 
-    @Override 
+    @Override
     public void mergeFrom(Layer from) {}
 
-    @Override 
+    @Override
     public boolean isMergable(Layer other) {
         return false;
     }
 
-    @Override 
+    @Override
     public void visitBoundingBox(BoundingXYVisitor v) {}
 
-    @Override 
-    public Object getInfoComponent() 
+    @Override
+    public Object getInfoComponent()
     {
         return getToolTipText();
     }
 
-    @Override 
-    public Component[] getMenuEntries() 
+    @Override
+    public Component[] getMenuEntries()
     {
         return new Component[]{
@@ -126,5 +126,5 @@
 
     @Override public void destroy() { }
-    
+
     /**
      * Visitor that highlights all cells the selected primitives go through
@@ -152,5 +152,5 @@
             this.mv = mv;
             this.gridDetail = gridDetail;
-            
+
             Point p = mv.getPoint( new EastNorth(0, 0) );
             Point p2 = mv.getPoint( new EastNorth(1d/gridDetail, 1d/gridDetail) );
@@ -158,5 +158,5 @@
         }
 
-        public void visit(Node n) 
+        public void visit(Node n)
         {
             double x = n.getEastNorth().east() * gridDetail;
@@ -166,5 +166,5 @@
         }
 
-        public void visit(Way w) 
+        public void visit(Way w)
         {
             Node lastN = null;
@@ -182,6 +182,6 @@
 
         public void visit(Relation r) {}
-        
-        /** 
+
+        /**
          * Draws a solid cell at the (x,y) location
          * @param x
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 16290)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 16294)
@@ -280,5 +280,5 @@
          */
         public void drawNode(Node n, Color color) {
-            Point p = mv.getPoint(n.getEastNorth());
+            Point p = mv.getPoint(n);
             g.setColor(color);
             if (selected) {
@@ -295,6 +295,6 @@
          */
         public void drawSegment(Node n1, Node n2, Color color) {
-            Point p1 = mv.getPoint(n1.getEastNorth());
-            Point p2 = mv.getPoint(n2.getEastNorth());
+            Point p1 = mv.getPoint(n1);
+            Point p2 = mv.getPoint(n2);
             g.setColor(color);
 
@@ -365,5 +365,5 @@
          */
         protected boolean isNodeVisible(Node n) {
-            Point p = mv.getPoint(n.getEastNorth());
+            Point p = mv.getPoint(n);
             return !((p.x < 0) || (p.y < 0) || (p.x > mv.getWidth()) || (p.y > mv.getHeight()));
         }
@@ -377,6 +377,6 @@
          */
         protected boolean isSegmentVisible(Node n1, Node n2) {
-            Point p1 = mv.getPoint(n1.getEastNorth());
-            Point p2 = mv.getPoint(n2.getEastNorth());
+            Point p1 = mv.getPoint(n1);
+            Point p2 = mv.getPoint(n2);
             if ((p1.x < 0) && (p2.x < 0))
                 return false;
