Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 1722)
@@ -250,4 +250,23 @@
         }
     };
+
+    static public void setProjection(String name)
+    {
+        Bounds b = (map != null && map.mapView != null) ? map.mapView.getRealBounds() : null;
+        Projection oldProj = Main.proj;
+        try {
+            Main.proj = (Projection)Class.forName(name).newInstance();
+        } catch (final Exception e) {
+            JOptionPane.showMessageDialog(null, tr("The projection {0} could not be activated. Using Mercator", name));
+            Main.proj = new Mercator();
+        }
+        if(!Main.proj.equals(oldProj))
+        {
+            if(b != null)
+                map.mapView.zoomTo(b);
+            /* TODO - remove layers with fixed projection */
+        }
+    }
+
     /**
      * Should be called before the main constructor to setup some parameter stuff
@@ -255,11 +274,5 @@
      */
     public static void preConstructorInit(Map<String, Collection<String>> args) {
-        try {
-            Main.proj = (Projection)Class.forName(Main.pref.get("projection")).newInstance();
-        } catch (final Exception e) {
-            e.printStackTrace();
-            JOptionPane.showMessageDialog(null, tr("The projection could not be read from preferences. Using Mercator"));
-            Main.proj = new Mercator();
-        }
+        setProjection(Main.pref.get("projection", Mercator.class.getName()));
 
         try {
Index: trunk/src/org/openstreetmap/josm/actions/MirrorAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/MirrorAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/MirrorAction.java	(revision 1722)
@@ -55,9 +55,10 @@
         }
 
-        double minEast = 200.0;
-        double maxEast = -200.0;
+        double minEast = 20000000000.0;
+        double maxEast = -20000000000.0;
         for (Node n : nodes) {
-            minEast = Math.min(minEast, n.eastNorth.east());
-            maxEast = Math.max(maxEast, n.eastNorth.east());
+            double east = n.getEastNorth().east();
+            minEast = Math.min(minEast, east);
+            maxEast = Math.max(maxEast, east);
         }
         double middle = (minEast + maxEast) / 2;
@@ -66,5 +67,5 @@
 
         for (Node n : nodes)
-            cmds.add(new MoveCommand(n, 2 * (middle - n.eastNorth.east()), 0.0));
+            cmds.add(new MoveCommand(n, 2 * (middle - n.getEastNorth().east()), 0.0));
 
         Main.main.undoRedo.add(new SequenceCommand(tr("Mirror"), cmds));
Index: trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 1722)
@@ -148,5 +148,5 @@
         if(e.getSource() instanceof JPanel) {
             MapView mv = Main.map.mapView;
-            n.setEastNorth(mv.getEastNorth(mv.lastMEvent.getX(), mv.lastMEvent.getY()));
+            n.setCoor(mv.getLatLon(mv.lastMEvent.getX(), mv.lastMEvent.getY()));
         }
 
Index: trunk/src/org/openstreetmap/josm/actions/ZoomInAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ZoomInAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/ZoomInAction.java	(revision 1722)
@@ -20,6 +20,5 @@
     public void actionPerformed(ActionEvent e) {
         if (Main.map == null) return;
-        double zoom = Main.map.mapView.getScale();
-        Main.map.mapView.zoomTo(Main.map.mapView.getCenter(), zoom * .9);
+        Main.map.mapView.zoomToFactor(0.9);
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/ZoomOutAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ZoomOutAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/ZoomOutAction.java	(revision 1722)
@@ -20,6 +20,5 @@
     public void actionPerformed(ActionEvent e) {
         if (Main.map == null) return;
-        double zoom = Main.map.mapView.getScale();
-        Main.map.mapView.zoomTo(Main.map.mapView.getCenter(), zoom /.9);
+        Main.map.mapView.zoomToFactor(1/0.9);
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 1722)
@@ -812,5 +812,5 @@
             double c = A.distanceSq(B);
             q = (a - b + c) / (2*c);
-            n.setEastNorth(B.east() + q * (A.east() - B.east()), B.north() + q * (A.north() - B.north()));
+            n.setEastNorth(new EastNorth(B.east() + q * (A.east() - B.east()), B.north() + q * (A.north() - B.north())));
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 1722)
@@ -57,9 +57,6 @@
      */
     public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
-        if (r.width >= 3 && r.height >= 3) {
-            double scale = mv.getScale() * r.getWidth()/mv.getWidth();
-            EastNorth newCenter = mv.getEastNorth(r.x+r.width/2, r.y+r.height/2);
-            mv.zoomTo(newCenter, scale);
-        }
+        if (r.width >= 3 && r.height >= 3)
+            mv.zoomToFactor(mv.getEastNorth(r.x+r.width/2, r.y+r.height/2), r.getWidth()/mv.getWidth());
     }
 
Index: trunk/src/org/openstreetmap/josm/command/MoveCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 1722)
@@ -48,5 +48,4 @@
     public static class OldState {
         LatLon latlon;
-        EastNorth eastNorth;
         boolean modified;
     }
@@ -70,5 +69,4 @@
         for (Node n : this.objects) {
             OldState os = new OldState();
-            os.eastNorth = n.getEastNorth();
             os.latlon = n.getCoor();
             os.modified = n.modified;
@@ -105,5 +103,5 @@
         for (Node n : objects) {
             OldState os = it.next();
-            n.setEastNorth(os.eastNorth);
+            n.setCoor(os.latlon);
             n.modified = os.modified;
         }
Index: trunk/src/org/openstreetmap/josm/command/RotateCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 1722)
@@ -14,4 +14,5 @@
 
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -37,4 +38,14 @@
 
     /**
+     * Small helper for holding the interesting part of the old data state of the
+     * objects.
+     */
+    public static class OldState {
+        LatLon latlon;
+        EastNorth eastNorth;
+        boolean modified;
+    }
+
+    /**
      * angle of rotation starting click to pivot
      */
@@ -49,5 +60,5 @@
      * List of all old states of the objects.
      */
-    private Map<Node, MoveCommand.OldState> oldState = new HashMap<Node, MoveCommand.OldState>();
+    private Map<Node, OldState> oldState = new HashMap<Node, OldState>();
 
     /**
@@ -63,7 +74,7 @@
 
         for (Node n : this.objects) {
-            MoveCommand.OldState os = new MoveCommand.OldState();
+            OldState os = new OldState();
+            os.latlon = n.getCoor();
             os.eastNorth = n.getEastNorth();
-            os.latlon = n.getCoor();
             os.modified = n.modified;
             oldState.put(n, os);
@@ -102,5 +113,5 @@
             double nx =  sinPhi * x + cosPhi * y + pivot.east();
             double ny = -cosPhi * x + sinPhi * y + pivot.north();
-            n.setEastNorth(nx, ny);
+            n.setEastNorth(new EastNorth(nx, ny));
             if (setModified)
                 n.modified = true;
@@ -115,6 +126,6 @@
     @Override public void undoCommand() {
         for (Node n : objects) {
-            MoveCommand.OldState os = oldState.get(n);
-            n.setEastNorth(os.eastNorth);
+            OldState os = oldState.get(n);
+            n.setCoor(os.latlon);
             n.modified = os.modified;
         }
Index: trunk/src/org/openstreetmap/josm/data/Bounds.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Bounds.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/Bounds.java	(revision 1722)
@@ -25,12 +25,4 @@
         this.min = min;
         this.max = max;
-    }
-
-    /**
-     * Construct bounds that span the whole world.
-     */
-    public Bounds() {
-        min = new LatLon(-Projection.MAX_LAT, -Projection.MAX_LON);
-        max = new LatLon(Projection.MAX_LAT, Projection.MAX_LON);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 1722)
@@ -352,5 +352,4 @@
         put("selectionlist.visible", true);
         put("commandstack.visible", true);
-        put("projection", Mercator.class.getName());
         if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") == -1) {
             put("laf", "javax.swing.plaf.metal.MetalLookAndFeel");
Index: trunk/src/org/openstreetmap/josm/data/ProjectionBounds.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/ProjectionBounds.java	(revision 1722)
+++ trunk/src/org/openstreetmap/josm/data/ProjectionBounds.java	(revision 1722)
@@ -0,0 +1,42 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.data;
+
+import java.awt.geom.Rectangle2D;
+
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+/**
+ * This is a simple data class for "rectangular" areas of the world, given in
+ * lat/lon min/max values.
+ *
+ * @author imi
+ */
+public class ProjectionBounds {
+    /**
+     * The minimum and maximum coordinates.
+     */
+    public EastNorth min, max;
+
+    /**
+     * Construct bounds out of two points
+     */
+    public ProjectionBounds(EastNorth min, EastNorth max) {
+        this.min = min;
+        this.max = max;
+    }
+    public ProjectionBounds(EastNorth center, double east, double north) {
+        this.min = new EastNorth(center.east()-east/2.0, center.north()-north/2.0);
+        this.max = new EastNorth(center.east()+east/2.0, center.north()+north/2.0);
+    }
+    public void extend(EastNorth e)
+    {
+        if (e.east() < min.east() || e.north() < min.north())
+            min = e;
+        else if (e.east() > max.east() || e.north() > max.north())
+            max = e;
+    }
+    public EastNorth getCenter()
+    {
+        return  new EastNorth(min.east()/2+max.east()/2, min.north()/2+max.north()/2);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/data/coor/LatLon.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/coor/LatLon.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/coor/LatLon.java	(revision 1722)
@@ -7,4 +7,5 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.Main;
 
 import java.text.DecimalFormat;
@@ -87,6 +88,7 @@
      */
     public boolean isOutSideWorld() {
-        return lat() < -Projection.MAX_LAT || lat() > Projection.MAX_LAT ||
-            lon() < -Projection.MAX_LON || lon() > Projection.MAX_LON;
+        Bounds b = Main.proj.getWorldBoundsLatLon();
+        return lat() < b.min.lat() || lat() > b.max.lat() ||
+            lon() < b.min.lon() || lon() > b.max.lon();
     }
 
Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 1722)
@@ -40,6 +40,4 @@
     public Collection<WayPoint> waypoints = new LinkedList<WayPoint>();
 
-    public Bounds bounds;
-
     public void mergeFrom(GpxData other) {
         if (storageFile == null && other.storageFile != null) {
@@ -82,6 +80,6 @@
 
     // FIXME might perhaps use visitor pattern?
-    public void recalculateBounds() {
-        bounds = null;
+    public Bounds recalculateBounds() {
+        Bounds bounds = null;
         for (WayPoint wpt : waypoints) {
             if (bounds == null) {
@@ -111,7 +109,5 @@
             }
         }
-        if (bounds == null) {
-            bounds = new Bounds();
-        }
+        return bounds;
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 1722)
@@ -8,5 +8,7 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.coor.LatLon.CoordinateFormat;
+import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
+import org.openstreetmap.josm.data.osm.Node;
 
 
@@ -18,10 +20,13 @@
 public final class Node extends OsmPrimitive {
 
-    public LatLon coor;
-    public volatile EastNorth eastNorth;
+    private LatLon coor;
+
+    private EastNorth eastNorth;
+    private Projection proj;
+
 
     public final void setCoor(LatLon coor) {
         this.coor = coor;
-        this.eastNorth = Main.proj.latlon2eastNorth(coor);
+        proj = null;
     }
 
@@ -31,13 +36,15 @@
 
     public final void setEastNorth(EastNorth eastNorth) {
-        this.eastNorth = eastNorth;
-        this.coor = Main.proj.eastNorth2latlon(eastNorth);
-    }
-
-    public final void setEastNorth(double east, double north) {
-        this.setEastNorth(new EastNorth(east, north));
+        proj = Main.proj;
+        eastNorth = eastNorth;
+        this.coor = proj.eastNorth2latlon(eastNorth);
     }
 
     public final EastNorth getEastNorth() {
+        if(proj != Main.proj)
+        {
+            proj = Main.proj;
+            eastNorth = proj.latlon2eastNorth(coor);
+        }
         return eastNorth;
     }
@@ -45,10 +52,20 @@
     private static CoordinateFormat mCord;
 
-    static {
+    static public CoordinateFormat getCoordinateFormat()
+    {
+        return mCord;
+    }
+
+    static public void setCoordinateFormat()
+    {
         try {
             mCord = LatLon.CoordinateFormat.valueOf(Main.pref.get("coordinates"));
         } catch (IllegalArgumentException iae) {
-            mCord =LatLon.CoordinateFormat.DECIMAL_DEGREES;
+            mCord = LatLon.CoordinateFormat.DECIMAL_DEGREES;
         }
+    }
+
+    static {
+        setCoordinateFormat();
     }
 
@@ -72,4 +89,8 @@
     }
 
+    public Node(EastNorth eastNorth) {
+        setEastNorth(eastNorth);
+    }
+
     @Override public void visit(Visitor visitor) {
         visitor.visit(this);
@@ -78,6 +99,5 @@
     @Override public void cloneFrom(OsmPrimitive osm) {
         super.cloneFrom(osm);
-        coor = ((Node)osm).coor;
-        eastNorth = ((Node)osm).eastNorth;
+        setCoor(((Node)osm).coor);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java	(revision 1722)
@@ -4,4 +4,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -19,5 +20,5 @@
 public class BoundingXYVisitor extends AbstractVisitor {
 
-    public EastNorth min, max;
+    private ProjectionBounds bounds = null;
 
     public void visit(Node n) {
@@ -38,16 +39,29 @@
     }
 
+    public void visit(Bounds b) {
+        if(b != null)
+        {
+            visit(Main.proj.latlon2eastNorth(b.min));
+            visit(Main.proj.latlon2eastNorth(b.max));
+        }
+    }
+
+    public void visit(ProjectionBounds b) {
+        if(b != null)
+            bounds = new ProjectionBounds(b.min, b.max);
+    }
+
     public void visit(EastNorth eastNorth) {
         if (eastNorth != null) {
-            if (min == null)
-                min = eastNorth;
-            else if (eastNorth.east() < min.east() || eastNorth.north() < min.north())
-                min = new EastNorth(Math.min(min.east(), eastNorth.east()), Math.min(min.north(), eastNorth.north()));
+            if (bounds == null)
+                bounds = new ProjectionBounds(eastNorth, eastNorth);
+            else
+                bounds.extend(eastNorth);
+        }
+    }
 
-            if (max == null)
-                max = eastNorth;
-            else if (eastNorth.east() > max.east() || eastNorth.north() > max.north())
-                max = new EastNorth(Math.max(max.east(), eastNorth.east()), Math.max(max.north(), eastNorth.north()));
-        }
+    public boolean hasExtend()
+    {
+        return bounds != null && !bounds.min.equals(bounds.max);
     }
 
@@ -55,8 +69,6 @@
      * @return The bounding box or <code>null</code> if no coordinates have passed
      */
-    public Bounds getBounds() {
-        if (min == null || max == null)
-            return null;
-        return new Bounds(Main.proj.eastNorth2latlon(min), Main.proj.eastNorth2latlon(max));
+    public ProjectionBounds getBounds() {
+        return bounds;
     }
 
@@ -78,10 +90,11 @@
      */
     public void enlargeBoundingBox(double enlargeDegree) {
-        if (min == null || max == null)
+        if (bounds == null)
             return;
-        LatLon minLatlon = Main.proj.eastNorth2latlon(min);
-        min = Main.proj.latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree));
-        LatLon maxLatlon = Main.proj.eastNorth2latlon(max);
-        max = Main.proj.latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree));
+        LatLon minLatlon = Main.proj.eastNorth2latlon(bounds.min);
+        LatLon maxLatlon = Main.proj.eastNorth2latlon(bounds.max);
+        bounds = new ProjectionBounds(
+        Main.proj.latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree)),
+        Main.proj.latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree)));
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1722)
@@ -1274,5 +1274,5 @@
         useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth",false);
         zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",false);
-        circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; /* circumference of the earth in meter */
+        circum = Main.map.mapView.getMapScale();
         styles = MapPaintStyles.getStyles().getStyleSet();
         drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon",true);
Index: trunk/src/org/openstreetmap/josm/data/projection/Epsg4326.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/Epsg4326.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/Epsg4326.java	(revision 1722)
@@ -1,7 +1,11 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.data.projection;
+
 import static org.openstreetmap.josm.tools.I18n.tr;
+
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 /**
@@ -32,14 +36,19 @@
     }
 
-    public double scaleFactor() {
-        return 1.0/360;
-    }
-
     @Override public boolean equals(Object o) {
         return o instanceof Epsg4326;
     }
 
-    @Override public int hashCode() {
-        return Epsg4326.class.hashCode();
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(-90.0, -180.0),
+        new LatLon(90.0, 180.0));
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/Lambert.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/Lambert.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/Lambert.java	(revision 1722)
@@ -12,4 +12,6 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 public class Lambert implements Projection {
@@ -104,15 +106,4 @@
         } else {
             outOfLambertZones = true; // possible when MAX_LAT is used
-            if (p.lat() != 0 && Math.abs(p.lat()) != Projection.MAX_LAT
-                    && p.lon() != 0 && Math.abs(p.lon()) != Projection.MAX_LON
-                    && dontDisplayErrors == false) {
-                JOptionPane.showMessageDialog(Main.parent,
-                        tr("The projection \"{0}\" is designed for\n"
-                        + "latitudes between 46.1\u00b0 and 57\u00b0 only.\n"
-                        + "Use another projection system if you are not using\n"
-                        + "a French WMS server.\n"
-                        + "Do not upload any data after this message.", this.toString()));
-                dontDisplayErrors = true;
-            }
         }
         if (!outOfLambertZones) {
@@ -167,16 +158,7 @@
     }
 
-    public double scaleFactor() {
-        return 1.0 / 360;
-    }
-
     @Override
     public boolean equals(Object o) {
         return o instanceof Lambert;
-    }
-
-    @Override
-    public int hashCode() {
-        return Lambert.class.hashCode();
     }
 
@@ -300,3 +282,15 @@
     }
 
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(-90.0, -180.0),
+        new LatLon(90.0, 180.0));
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/LambertEST.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/LambertEST.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/LambertEST.java	(revision 1722)
@@ -9,4 +9,6 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 public class LambertEST implements Projection {
@@ -105,8 +107,4 @@
     }
 
-    public double scaleFactor() {
-        return 1.0 / 360;
-    }
-
     @Override
     public boolean equals(Object o) {
@@ -114,7 +112,15 @@
     }
 
-    @Override
-    public int hashCode() {
-        return LambertEST.class.hashCode();
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(-90.0, -180.0),
+        new LatLon(90.0, 180.0));
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/Mercator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 1722)
@@ -6,4 +6,6 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 /**
@@ -45,14 +47,19 @@
     }
 
-    public double scaleFactor() {
-        return 1/Math.PI/2;
-    }
-
     @Override public boolean equals(Object o) {
         return o instanceof Mercator;
     }
 
-    @Override public int hashCode() {
-        return Mercator.class.hashCode();
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(-85.05112877980659, -180.0),
+        new LatLon(85.05112877980659, 180.0));
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/Projection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 1722)
@@ -4,4 +4,6 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 /**
@@ -12,15 +14,4 @@
  */
 public interface Projection {
-
-    /**
-     * Maximum latitude representable.
-     */
-    public static final double MAX_LAT = 85.05112877980659; // Mercator squares the world
-
-    /**
-     * Maximum longditude representable.
-     */
-    public static final double MAX_LON = 180;
-
     /**
      * Minimum difference in location to not be represented as the same position.
@@ -36,5 +27,6 @@
         new Lambert(),
         new LambertEST(),
-        new SwissGrid()
+        new SwissGrid(),
+        new UTM()
     };
 
@@ -69,7 +61,7 @@
 
     /**
-     * The factor to multiply with an easting coordinate to get from "easting
-     * units per pixel" to "meters per pixel"
+     * Get the bounds of the world
      */
-    double scaleFactor();
+    ProjectionBounds getWorldBounds();
+    Bounds getWorldBoundsLatLon();
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/SwissGrid.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/SwissGrid.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/data/projection/SwissGrid.java	(revision 1722)
@@ -5,9 +5,9 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import javax.swing.JOptionPane;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 
 /**
@@ -19,40 +19,4 @@
  */
 public class SwissGrid implements Projection {
-    private boolean doAlertOnCoordinatesOufOfRange = true;
-
-    /**
-     * replies true if if wgs is in or reasonably close to Switzerland. False otherwise.
-     *
-     * @param wgs  lat/lon in WGS89
-     * @return
-     */
-    protected boolean latlonInAcceptableRange(LatLon wgs) {
-        // coordinate transformation is invoked for boundary values regardless
-        // of current data set.
-        //
-        if (Math.abs(wgs.lon()) == Projection.MAX_LON && Math.abs(wgs.lat()) == Projection.MAX_LAT) {
-            return true;
-        }
-        return   wgs.lon() >= 5.7 && wgs.lon() <= 10.6
-               && wgs.lat() >= 45.7 && wgs.lat() <= 47.9;
-    }
-
-    /**
-     * displays an alert if lat/lon are not reasonably close to Switzerland.
-     */
-    protected void alertCoordinatesOutOfRange() {
-        JOptionPane.showMessageDialog(Main.parent,
-                tr("The projection \"{0}\" is designed for\n"
-                + "latitudes between 45.7\u00b0 and 47.9\u00b0\n"
-                + "and longitutes between 5.7\u00b0 and 10.6\u00b0 only.\n"
-                + "Use another projection system if you are not working\n"
-                + "on a data set of Switzerland or Liechtenstein.\n"
-                + "Do not upload any data after this message.", this.toString()),
-                "Current projection not suitable",
-                JOptionPane.WARNING_MESSAGE
-        );
-        doAlertOnCoordinatesOufOfRange = false;
-    }
-
     /**
      * @param wgs  WGS84 lat/lon (ellipsoid GRS80) (in degree)
@@ -60,10 +24,4 @@
      */
     public EastNorth latlon2eastNorth(LatLon wgs) {
-            if (!latlonInAcceptableRange(wgs)) {
-                if (doAlertOnCoordinatesOufOfRange) {
-                    alertCoordinatesOutOfRange();
-                }
-            }
-
             double phi = 3600d * wgs.lat();
             double lambda = 3600d * wgs.lon();
@@ -131,8 +89,4 @@
     }
 
-    public double scaleFactor() {
-        return 1.0;
-    }
-
     @Override public String toString() {
         return tr("Swiss Grid (Switzerland)");
@@ -152,7 +106,15 @@
     }
 
-    @Override
-    public int hashCode() {
-        return SwissGrid.class.hashCode();
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(45.7, 5.7),
+        new LatLon(47.9, 10.6));
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/UTM.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/UTM.java	(revision 1722)
+++ trunk/src/org/openstreetmap/josm/data/projection/UTM.java	(revision 1722)
@@ -0,0 +1,363 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.data.projection;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
+
+/**
+ * Directly use latitude / longitude values as x/y.
+ *
+ * @author Dirk Stöcker
+ * code based on JavaScript from Chuck Taylor
+ */
+public class UTM implements Projection {
+
+    final private double UTMScaleFactor = 0.9996;
+
+    /* Ellipsoid model constants (WGS84) - TODO Use Elliposid class here too */
+    final private double sm_EccSquared = 6.69437999013e-03;
+
+    /*
+    * ArcLengthOfMeridian
+    *
+    * Computes the ellipsoidal distance from the equator to a point at a
+    * given latitude.
+    *
+    * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
+    * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
+    *
+    * Inputs:
+    *     phi - Latitude of the point, in radians.
+    *
+    * Globals:
+    *     Ellipsoid.GRS80.a - Ellipsoid model major axis.
+    *     Ellipsoid.GRS80.b - Ellipsoid model minor axis.
+    *
+    * Returns:
+    *     The ellipsoidal distance of the point from the equator, in meters.
+    *
+    */
+    private double ArcLengthOfMeridian(double phi)
+    {
+        /* Precalculate n */
+        double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
+
+        /* Precalculate alpha */
+        double alpha = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
+           * (1.0 + (Math.pow (n, 2.0) / 4.0) + (Math.pow (n, 4.0) / 64.0));
+
+        /* Precalculate beta */
+        double beta = (-3.0 * n / 2.0) + (9.0 * Math.pow (n, 3.0) / 16.0)
+           + (-3.0 * Math.pow (n, 5.0) / 32.0);
+
+        /* Precalculate gamma */
+        double gamma = (15.0 * Math.pow (n, 2.0) / 16.0)
+            + (-15.0 * Math.pow (n, 4.0) / 32.0);
+
+        /* Precalculate delta */
+        double delta = (-35.0 * Math.pow (n, 3.0) / 48.0)
+            + (105.0 * Math.pow (n, 5.0) / 256.0);
+
+        /* Precalculate epsilon */
+        double epsilon = (315.0 * Math.pow (n, 4.0) / 512.0);
+
+        /* Now calculate the sum of the series and return */
+        return alpha
+        * (phi + (beta * Math.sin (2.0 * phi))
+            + (gamma * Math.sin (4.0 * phi))
+            + (delta * Math.sin (6.0 * phi))
+            + (epsilon * Math.sin (8.0 * phi)));
+    }
+
+    /*
+    * UTMCentralMeridian
+    *
+    * Determines the central meridian for the given UTM zone.
+    *
+    * Inputs:
+    *     zone - An integer value designating the UTM zone, range [1,60].
+    *
+    * Returns:
+    *   The central meridian for the given UTM zone, in radians, or zero
+    *   if the UTM zone parameter is outside the range [1,60].
+    *   Range of the central meridian is the radian equivalent of [-177,+177].
+    *
+    */
+    private double UTMCentralMeridian(int zone)
+    {
+        return Math.toRadians(-183.0 + (zone * 6.0));
+    }
+
+    /*
+    * FootpointLatitude
+    *
+    * Computes the footpoint latitude for use in converting transverse
+    * Mercator coordinates to ellipsoidal coordinates.
+    *
+    * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
+    *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
+    *
+    * Inputs:
+    *   y - The UTM northing coordinate, in meters.
+    *
+    * Returns:
+    *   The footpoint latitude, in radians.
+    *
+    */
+    private double FootpointLatitude(double y)
+    {
+        /* Precalculate n (Eq. 10.18) */
+        double n = (Ellipsoid.GRS80.a - Ellipsoid.GRS80.b) / (Ellipsoid.GRS80.a + Ellipsoid.GRS80.b);
+
+        /* Precalculate alpha_ (Eq. 10.22) */
+        /* (Same as alpha in Eq. 10.17) */
+        double alpha_ = ((Ellipsoid.GRS80.a + Ellipsoid.GRS80.b) / 2.0)
+            * (1 + (Math.pow (n, 2.0) / 4) + (Math.pow (n, 4.0) / 64));
+
+        /* Precalculate y_ (Eq. 10.23) */
+        double y_ = y / alpha_;
+
+        /* Precalculate beta_ (Eq. 10.22) */
+        double beta_ = (3.0 * n / 2.0) + (-27.0 * Math.pow (n, 3.0) / 32.0)
+            + (269.0 * Math.pow (n, 5.0) / 512.0);
+
+        /* Precalculate gamma_ (Eq. 10.22) */
+        double gamma_ = (21.0 * Math.pow (n, 2.0) / 16.0)
+            + (-55.0 * Math.pow (n, 4.0) / 32.0);
+
+        /* Precalculate delta_ (Eq. 10.22) */
+        double delta_ = (151.0 * Math.pow (n, 3.0) / 96.0)
+            + (-417.0 * Math.pow (n, 5.0) / 128.0);
+
+        /* Precalculate epsilon_ (Eq. 10.22) */
+        double epsilon_ = (1097.0 * Math.pow (n, 4.0) / 512.0);
+
+        /* Now calculate the sum of the series (Eq. 10.21) */
+        return y_ + (beta_ * Math.sin (2.0 * y_))
+            + (gamma_ * Math.sin (4.0 * y_))
+            + (delta_ * Math.sin (6.0 * y_))
+            + (epsilon_ * Math.sin (8.0 * y_));
+    }
+
+    /*
+    * MapLatLonToXY
+    *
+    * Converts a latitude/longitude pair to x and y coordinates in the
+    * Transverse Mercator projection.  Note that Transverse Mercator is not
+    * the same as UTM; a scale factor is required to convert between them.
+    *
+    * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
+    * GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
+    *
+    * Inputs:
+    *    phi - Latitude of the point, in radians.
+    *    lambda - Longitude of the point, in radians.
+    *    lambda0 - Longitude of the central meridian to be used, in radians.
+    *
+    * Outputs:
+    *    xy - A 2-element array containing the x and y coordinates
+    *         of the computed point.
+    *
+    * Returns:
+    *    The function does not return a value.
+    *
+    */
+    public EastNorth MapLatLonToXY(double phi, double lambda, double lambda0)
+    {
+        /* Precalculate ep2 */
+        double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0)) / Math.pow (Ellipsoid.GRS80.b, 2.0);
+
+        /* Precalculate nu2 */
+        double nu2 = ep2 * Math.pow (Math.cos (phi), 2.0);
+
+        /* Precalculate N */
+        double N = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nu2));
+
+        /* Precalculate t */
+        double t = Math.tan (phi);
+        double t2 = t * t;
+        double tmp = (t2 * t2 * t2) - Math.pow (t, 6.0);
+
+        /* Precalculate l */
+        double l = lambda - lambda0;
+
+        /* Precalculate coefficients for l**n in the equations below
+           so a normal human being can read the expressions for easting
+           and northing
+           -- l**1 and l**2 have coefficients of 1.0 */
+        double l3coef = 1.0 - t2 + nu2;
+
+        double l4coef = 5.0 - t2 + 9 * nu2 + 4.0 * (nu2 * nu2);
+
+        double l5coef = 5.0 - 18.0 * t2 + (t2 * t2) + 14.0 * nu2
+            - 58.0 * t2 * nu2;
+
+        double l6coef = 61.0 - 58.0 * t2 + (t2 * t2) + 270.0 * nu2
+            - 330.0 * t2 * nu2;
+
+        double l7coef = 61.0 - 479.0 * t2 + 179.0 * (t2 * t2) - (t2 * t2 * t2);
+
+        double l8coef = 1385.0 - 3111.0 * t2 + 543.0 * (t2 * t2) - (t2 * t2 * t2);
+
+        return new EastNorth(
+        /* Calculate easting (x) */
+        N * Math.cos (phi) * l
+            + (N / 6.0 * Math.pow (Math.cos (phi), 3.0) * l3coef * Math.pow (l, 3.0))
+            + (N / 120.0 * Math.pow (Math.cos (phi), 5.0) * l5coef * Math.pow (l, 5.0))
+            + (N / 5040.0 * Math.pow (Math.cos (phi), 7.0) * l7coef * Math.pow (l, 7.0)),
+        /* Calculate northing (y) */
+        ArcLengthOfMeridian (phi)
+            + (t / 2.0 * N * Math.pow (Math.cos (phi), 2.0) * Math.pow (l, 2.0))
+            + (t / 24.0 * N * Math.pow (Math.cos (phi), 4.0) * l4coef * Math.pow (l, 4.0))
+            + (t / 720.0 * N * Math.pow (Math.cos (phi), 6.0) * l6coef * Math.pow (l, 6.0))
+            + (t / 40320.0 * N * Math.pow (Math.cos (phi), 8.0) * l8coef * Math.pow (l, 8.0)));
+    }
+
+    /*
+    * MapXYToLatLon
+    *
+    * Converts x and y coordinates in the Transverse Mercator projection to
+    * a latitude/longitude pair.  Note that Transverse Mercator is not
+    * the same as UTM; a scale factor is required to convert between them.
+    *
+    * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
+    *   GPS: Theory and Practice, 3rd ed.  New York: Springer-Verlag Wien, 1994.
+    *
+    * Inputs:
+    *   x - The easting of the point, in meters.
+    *   y - The northing of the point, in meters.
+    *   lambda0 - Longitude of the central meridian to be used, in radians.
+    *
+    * Outputs:
+    *   philambda - A 2-element containing the latitude and longitude
+    *               in radians.
+    *
+    * Returns:
+    *   The function does not return a value.
+    *
+    * Remarks:
+    *   The local variables Nf, nuf2, tf, and tf2 serve the same purpose as
+    *   N, nu2, t, and t2 in MapLatLonToXY, but they are computed with respect
+    *   to the footpoint latitude phif.
+    *
+    *   x1frac, x2frac, x2poly, x3poly, etc. are to enhance readability and
+    *   to optimize computations.
+    *
+    */
+    public LatLon MapXYToLatLon(double x, double y, double lambda0)
+    {
+        /* Get the value of phif, the footpoint latitude. */
+        double phif = FootpointLatitude (y);
+
+        /* Precalculate ep2 */
+        double ep2 = (Math.pow (Ellipsoid.GRS80.a, 2.0) - Math.pow (Ellipsoid.GRS80.b, 2.0))
+              / Math.pow (Ellipsoid.GRS80.b, 2.0);
+
+        /* Precalculate cos (phif) */
+        double cf = Math.cos (phif);
+
+        /* Precalculate nuf2 */
+        double nuf2 = ep2 * Math.pow (cf, 2.0);
+
+        /* Precalculate Nf and initialize Nfpow */
+        double Nf = Math.pow (Ellipsoid.GRS80.a, 2.0) / (Ellipsoid.GRS80.b * Math.sqrt (1 + nuf2));
+        double Nfpow = Nf;
+
+        /* Precalculate tf */
+        double tf = Math.tan (phif);
+        double tf2 = tf * tf;
+        double tf4 = tf2 * tf2;
+
+        /* Precalculate fractional coefficients for x**n in the equations
+           below to simplify the expressions for latitude and longitude. */
+        double x1frac = 1.0 / (Nfpow * cf);
+
+        Nfpow *= Nf;   /* now equals Nf**2) */
+        double x2frac = tf / (2.0 * Nfpow);
+
+        Nfpow *= Nf;   /* now equals Nf**3) */
+        double x3frac = 1.0 / (6.0 * Nfpow * cf);
+
+        Nfpow *= Nf;   /* now equals Nf**4) */
+        double x4frac = tf / (24.0 * Nfpow);
+
+        Nfpow *= Nf;   /* now equals Nf**5) */
+        double x5frac = 1.0 / (120.0 * Nfpow * cf);
+
+        Nfpow *= Nf;   /* now equals Nf**6) */
+        double x6frac = tf / (720.0 * Nfpow);
+
+        Nfpow *= Nf;   /* now equals Nf**7) */
+        double x7frac = 1.0 / (5040.0 * Nfpow * cf);
+
+        Nfpow *= Nf;   /* now equals Nf**8) */
+        double x8frac = tf / (40320.0 * Nfpow);
+
+        /* Precalculate polynomial coefficients for x**n.
+           -- x**1 does not have a polynomial coefficient. */
+        double x2poly = -1.0 - nuf2;
+        double x3poly = -1.0 - 2 * tf2 - nuf2;
+        double x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 *nuf2) - 9.0 * tf2 * (nuf2 * nuf2);
+        double x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2;
+        double x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2;
+        double x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2);
+        double x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2);
+
+        return new LatLon(
+        /* Calculate latitude */
+        Math.toDegrees(
+        phif + x2frac * x2poly * (x * x)
+        + x4frac * x4poly * Math.pow (x, 4.0)
+        + x6frac * x6poly * Math.pow (x, 6.0)
+        + x8frac * x8poly * Math.pow (x, 8.0)),
+        Math.toDegrees(
+        /* Calculate longitude */
+        lambda0 + x1frac * x
+        + x3frac * x3poly * Math.pow (x, 3.0)
+        + x5frac * x5poly * Math.pow (x, 5.0)
+        + x7frac * x7poly * Math.pow (x, 7.0)));
+    }
+
+    public EastNorth latlon2eastNorth(LatLon p) {
+        EastNorth a = MapLatLonToXY(Math.toRadians(p.lat()), Math.toRadians(p.lon()), UTMCentralMeridian(33));
+        return new EastNorth(a.east() * UTMScaleFactor + 3500000.0, a.north() * UTMScaleFactor);
+    }
+
+    public LatLon eastNorth2latlon(EastNorth p) {
+        return MapXYToLatLon((p.east()-3500000.0)/UTMScaleFactor, p.north()/UTMScaleFactor, UTMCentralMeridian(33));
+    }
+
+    /* TODO - support all UTM's not only zone 33 */
+    @Override public String toString() {
+        return tr("UTM Zone {0}", 33);
+    }
+
+    public String toCode() {
+        return "EPSG:325833";
+    }
+
+    public String getCacheDirectoryName() {
+        return "epsg325833";
+    }
+
+    @Override public boolean equals(Object o) {
+        return o instanceof UTM;
+    }
+
+    public ProjectionBounds getWorldBounds()
+    {
+        Bounds b = getWorldBoundsLatLon();
+        return new ProjectionBounds(latlon2eastNorth(b.min), latlon2eastNorth(b.max));
+    }
+
+    public Bounds getWorldBoundsLatLon()
+    {
+        return new Bounds(
+        new LatLon(-90.0, 14.0),
+        new LatLon(90.0, 22.0));
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 1722)
@@ -44,11 +44,11 @@
                 EastNorth newcenter = nc.getEastNorth(nc.getWidth()/2+nc.getWidth()/5, nc.getHeight()/2+nc.getHeight()/5);
                 if (action.equals("left"))
-                    nc.zoomTo(new EastNorth(2*center.east()-newcenter.east(), center.north()), nc.getScale());
+                    nc.zoomTo(new EastNorth(2*center.east()-newcenter.east(), center.north()));
                 else if (action.equals("right"))
-                    nc.zoomTo(new EastNorth(newcenter.east(), center.north()), nc.getScale());
+                    nc.zoomTo(new EastNorth(newcenter.east(), center.north()));
                 else if (action.equals("up"))
-                    nc.zoomTo(new EastNorth(center.east(), 2*center.north()-newcenter.north()), nc.getScale());
+                    nc.zoomTo(new EastNorth(center.east(), 2*center.north()-newcenter.north()));
                 else if (action.equals("down"))
-                    nc.zoomTo(new EastNorth(center.east(), newcenter.north()), nc.getScale());
+                    nc.zoomTo(new EastNorth(center.east(), newcenter.north()));
             }
         }
@@ -123,8 +123,7 @@
             EastNorth center = nc.getCenter();
             EastNorth mouseCenter = nc.getEastNorth(e.getX(), e.getY());
-            EastNorth p = new EastNorth(
+            nc.zoomTo(new EastNorth(
                     mousePosMove.east() + center.east() - mouseCenter.east(),
-                    mousePosMove.north() + center.north() - mouseCenter.north());
-            nc.zoomTo(p, nc.getScale());
+                    mousePosMove.north() + center.north() - mouseCenter.north()));
         } else
             endMovement();
@@ -182,12 +181,5 @@
      */
     public void mouseWheelMoved(MouseWheelEvent e) {
-        double newScale = nc.getScale() * Math.pow(0.8, - e.getWheelRotation());
-
-        // New center position so that point under the mouse pointer stays the same place as it was before zooming
-        // You will get the formula by simplifying this expression: newCenter = oldCenter + mouseCoordinatesInNewZoom - mouseCoordinatesInOldZoom
-        double newX = nc.center.east() - (e.getX() - nc.getWidth()/2.0) * (newScale - nc.scale);
-        double newY = nc.center.north() + (e.getY() - nc.getHeight()/2.0) * (newScale - nc.scale);
-
-        nc.zoomTo(new EastNorth(newX, newY), newScale);
+        nc.zoomToFactor(e.getX(), e.getY(), Math.pow(0.8, - e.getWheelRotation()));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/MapScaler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapScaler.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/MapScaler.java	(revision 1722)
@@ -14,10 +14,9 @@
 import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.projection.Projection;
 
 public class MapScaler extends JComponent implements Helpful {
 
     private final NavigatableComponent mv;
-    public MapScaler(NavigatableComponent mv, Projection proj) {
+    public MapScaler(NavigatableComponent mv) {
         this.mv = mv;
         setSize(100,30);
@@ -26,7 +25,5 @@
 
     @Override public void paint(Graphics g) {
-        LatLon ll1 = mv.getLatLon(0,0);
-        LatLon ll2 = mv.getLatLon(100,0);
-        double dist = ll1.greatCircleDistance(ll2);
+        double dist = mv.getDist100Pixel();
         String text = dist >= 2000 ? Math.round(dist/100)/10 +" km" : (dist >= 1
         ? Math.round(dist*10)/10 +" m" : "< 1 m");
Index: trunk/src/org/openstreetmap/josm/gui/MapSlider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapSlider.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/MapSlider.java	(revision 1722)
@@ -11,4 +11,6 @@
 import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.ProjectionBounds;
+import org.openstreetmap.josm.Main;
 
 class MapSlider extends JSlider implements PropertyChangeListener, ChangeListener, Helpful {
@@ -28,25 +30,34 @@
         if (getModel().getValueIsAdjusting()) return;
 
-        double sizex = this.mv.scale * this.mv.getWidth();
-        double sizey = this.mv.scale * this.mv.getHeight();
-        for (int zoom = 0; zoom <= 150; zoom++, sizex *= 1.1, sizey *= 1.1) {
-            if (sizex > MapView.world.east() || sizey > MapView.world.north()) {
-                preventChange=true;
-                setValue(zoom);
-                preventChange=false;
+        ProjectionBounds world = Main.proj.getWorldBounds();
+        ProjectionBounds current = this.mv.getProjectionBounds();
+
+        double cur_e = current.max.east()-current.min.east();
+        double cur_n = current.max.north()-current.min.north();
+        double e = world.max.east()-world.min.east();
+        double n = world.max.north()-world.min.north();
+        int zoom = 0;
+
+        while(zoom <= 150) {
+            e /= 1.1;
+            n /= 1.1;
+            if(e < cur_e && n < cur_n)
                 break;
-            }
+            ++zoom;
         }
+        preventChange=true;
+        setValue(zoom);
+        preventChange=false;
     }
 
     public void stateChanged(ChangeEvent e) {
         if (preventChange) return;
-        EastNorth pos = MapView.world;
-        for (int zoom = 0; zoom < getValue(); zoom++)
-            pos = new EastNorth(pos.east()/1.1, pos.north()/1.1);
-        if (this.mv.getWidth() < this.mv.getHeight())
-            this.mv.zoomTo(this.mv.center, pos.east()/(this.mv.getWidth()-20));
-        else
-            this.mv.zoomTo(this.mv.center, pos.north()/(this.mv.getHeight()-20));
+
+        ProjectionBounds world = Main.proj.getWorldBounds();
+        double fact = Math.pow(1.1, getValue());
+        double es = world.max.east()-world.min.east();
+        double n = world.max.north()-world.min.north();
+
+        this.mv.zoomTo(new ProjectionBounds(this.mv.getCenter(), es/fact, n/fact));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 1722)
@@ -38,6 +38,8 @@
 import org.openstreetmap.josm.actions.HelpAction.Helpful;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.LatLon.CoordinateFormat;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -89,6 +91,4 @@
         }
     }
-
-    LatLon.CoordinateFormat mCord;
 
     ImageLabel lonText = new ImageLabel("lon", tr("The geographic longitude at the mouse pointer."), 11);
@@ -263,9 +263,4 @@
         this.mv = mapFrame.mapView;
 
-        try {
-            mCord = LatLon.CoordinateFormat.valueOf(Main.pref.get("coordinates"));
-        } catch (IllegalArgumentException iae) {
-            mCord =LatLon.CoordinateFormat.DECIMAL_DEGREES;
-        }
         // Listen for mouse movements and set the position text field
         mv.addMouseMotionListener(new MouseMotionListener(){
@@ -278,4 +273,5 @@
                 // Do not update the view if ctrl is pressed.
                 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == 0) {
+                    CoordinateFormat mCord = Node.getCoordinateFormat();
                     LatLon p = mv.getLatLon(e.getX(),e.getY());
                     latText.setText(p.latToString(mCord));
Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 1722)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.actions.MoveAction;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -95,5 +96,5 @@
                 zoomSlider.setBounds(3, 0, 114, 30);
 
-                MapScaler scaler = new MapScaler(MapView.this, Main.proj);
+                MapScaler scaler = new MapScaler(MapView.this);
                 add(scaler);
                 scaler.setLocation(10,30);
@@ -197,5 +198,4 @@
     }
 
-
     /**
      * Remove the layer from the mapview. If the layer was in the list before,
@@ -289,7 +289,7 @@
         // draw world borders
         tempG.setColor(Color.WHITE);
-        Bounds b = new Bounds();
-        Point min = getPoint(getProjection().latlon2eastNorth(b.min));
-        Point max = getPoint(getProjection().latlon2eastNorth(b.max));
+        ProjectionBounds b = getProjection().getWorldBounds();
+        Point min = getPoint(b.min);
+        Point max = getPoint(b.max);
         int x1 = Math.min(min.x, max.x);
         int y1 = Math.min(min.y, max.y);
@@ -307,40 +307,15 @@
 
     /**
-     * Set the new dimension to the projection class. Also adjust the components
-     * scale, if in autoScale mode.
+     * Set the new dimension to the view.
      */
     public void recalculateCenterScale(BoundingXYVisitor box) {
-        // -20 to leave some border
-        int w = getWidth()-20;
-        if (w < 20)
-            w = 20;
-        int h = getHeight()-20;
-        if (h < 20)
-            h = 20;
-
-        EastNorth oldCenter = center;
-        double oldScale = this.scale;
-
-        if (box == null || box.min == null || box.max == null) {
-            // no bounds means whole world
-            center = getProjection().latlon2eastNorth(new LatLon(0,0));
-            EastNorth world = getProjection().latlon2eastNorth(new LatLon(Projection.MAX_LAT,Projection.MAX_LON));
-            double scaleX = world.east()*2/w;
-            double scaleY = world.north()*2/h;
-            scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
-        } else {
-            if(box.min.equals(box.max))
-                box.enlargeBoundingBox();
-            center = new EastNorth(box.min.east()/2+box.max.east()/2, box.min.north()/2+box.max.north()/2);
-            double scaleX = (box.max.east()-box.min.east())/w;
-            double scaleY = (box.max.north()-box.min.north())/h;
-            scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
-        }
-
-        if (!center.equals(oldCenter))
-            firePropertyChange("center", oldCenter, center);
-        if (oldScale != scale)
-            firePropertyChange("scale", oldScale, scale);
-        repaint();
+        if(box == null)
+            box = new BoundingXYVisitor();
+        if(box.getBounds() == null)
+            box.visit(getProjection().getWorldBounds());
+        if(!box.hasExtend())
+             box.enlargeBoundingBox();
+
+        zoomTo(box.getBounds());
     }
 
@@ -392,18 +367,4 @@
 
     /**
-     * In addition to the base class funcitonality, this keep trak of the autoscale
-     * feature.
-     */
-    @Override public void zoomTo(EastNorth newCenter, double scale) {
-        EastNorth oldCenter = center;
-        double oldScale = this.scale;
-        super.zoomTo(newCenter, scale);
-        if ((oldCenter == null && center != null) || !oldCenter.equals(center))
-            firePropertyChange("center", oldCenter, center);
-        if (oldScale != scale)
-            firePropertyChange("scale", oldScale, scale);
-    }
-
-    /**
      * Tries to zoom to the download boundingbox[es] of the current edit layer
      * (aka {@link OsmDataLayer}). If the edit layer has multiple download bounding
@@ -420,9 +381,6 @@
         BoundingXYVisitor bbox = new BoundingXYVisitor();
         for (DataSource ds : dataSources) {
-            if (ds.bounds != null) {
-                bbox.visit(Main.proj.latlon2eastNorth(ds.bounds.max));
-                bbox.visit(Main.proj.latlon2eastNorth(ds.bounds.min));
-            }
-            if (bbox.max != null && bbox.min != null && !bbox.max.equals(bbox.min)) {
+            bbox.visit(ds.bounds);
+            if (bbox.hasExtend()) {
                 // ... we zoom to it's bounding box
                 recalculateCenterScale(bbox);
Index: trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 1722)
@@ -16,4 +16,6 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.HelpAction.Helpful;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -24,4 +26,5 @@
 import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.data.projection.Mercator;
 
 /**
@@ -33,5 +36,4 @@
 public class NavigatableComponent extends JComponent implements Helpful {
 
-    public static final EastNorth world = Main.proj.latlon2eastNorth(new LatLon(Projection.MAX_LAT, Projection.MAX_LON));
     public static final int snapDistance = sqr(Main.pref.getInteger("node.snap-distance", 10));
 
@@ -42,5 +44,5 @@
      * northing/easting space of the projection.
      */
-    protected double scale;
+    private double scale;
     /**
      * Center n/e coordinate of the desired screen center.
@@ -58,16 +60,4 @@
 
     /**
-     * Return the OSM-conform zoom factor (0 for whole world, 1 for half, 2 for quarter...)
-     */
-    public int zoom() {
-        double sizex = scale * getWidth();
-        double sizey = scale * getHeight();
-        for (int zoom = 0; zoom <= 32; zoom++, sizex *= 2, sizey *= 2)
-            if (sizex > world.east() || sizey > world.north())
-                return zoom;
-        return 32;
-    }
-
-    /**
      * Return a ID which is unique as long as viewport dimensions are the same
      */
@@ -75,5 +65,5 @@
     {
         String x = center.east() + "_" + center.north() + "_" + scale + "_" +
-        getWidth() + "_" + getHeight();
+        getWidth() + "_" + getHeight() + "_" + getProjection().toString();
         java.util.zip.CRC32 id = new java.util.zip.CRC32();
         id.update(x.getBytes());
@@ -81,10 +71,14 @@
     }
 
-    /**
-     * Return the current scale value.
-     * @return The scale value currently used in display
-     */
-    public double getScale() {
-        return scale;
+    public double getMapScale() {
+        /* TODO: we assume a pixel is 0.025mm */
+        return getDist100Pixel()/(0.00025*100);
+    }
+
+    public double getDist100Pixel()
+    {
+        LatLon ll1 = getLatLon(0,0);
+        LatLon ll2 = getLatLon(100,0);
+        return ll1.greatCircleDistance(ll2);
     }
 
@@ -110,4 +104,24 @@
     }
 
+    public ProjectionBounds getProjectionBounds() {
+        return new ProjectionBounds(
+        new EastNorth(
+                center.east() - getWidth()/2.0*scale,
+                center.north() - getHeight()/2.0*scale),
+        new EastNorth(
+                center.east() + getWidth()/2.0*scale,
+                center.north() + getHeight()/2.0*scale));
+    };
+
+    public Bounds getRealBounds() {
+        return new Bounds(
+        getProjection().eastNorth2latlon(new EastNorth(
+                center.east() - getWidth()/2.0*scale,
+                center.north() - getHeight()/2.0*scale)),
+        getProjection().eastNorth2latlon(new EastNorth(
+                center.east() + getWidth()/2.0*scale,
+                center.north() + getHeight()/2.0*scale)));
+    };
+
     /**
      * @param x X-Pixelposition to get coordinate from
@@ -118,5 +132,4 @@
      */
     public LatLon getLatLon(int x, int y) {
-
         return getProjection().eastNorth2latlon(getEastNorth(x, y));
     }
@@ -141,9 +154,66 @@
      * @param scale The scale to use.
      */
-    public void zoomTo(EastNorth newCenter, double scale) {
-        center = newCenter;
-        getProjection().eastNorth2latlon(center);
-        this.scale = scale;
-        repaint();
+    private void zoomTo(EastNorth newCenter, double newScale) {
+/* TODO: check that newCenter is really inside visible world and that scale is correct, don't allow zooming out to much */
+        boolean rep = false;
+        if(!newCenter.equals(center))
+        {
+            EastNorth oldCenter = center;
+            center = newCenter;
+            rep = true;
+            firePropertyChange("center", oldCenter, newCenter);
+        }
+        if(scale != newScale)
+        {
+            double oldScale = scale;
+            scale = newScale;
+            rep = true;
+            firePropertyChange("scale", oldScale, newScale);
+        }
+        if(rep)
+            repaint();
+    }
+
+    public void zoomTo(EastNorth newCenter) {
+        zoomTo(newCenter, scale);
+    }
+
+    public void zoomToFactor(double x, double y, double factor) {
+        double newScale = scale*factor;
+        // New center position so that point under the mouse pointer stays the same place as it was before zooming
+        // You will get the formula by simplifying this expression: newCenter = oldCenter + mouseCoordinatesInNewZoom - mouseCoordinatesInOldZoom
+        zoomTo(new EastNorth(
+        center.east() - (x - getWidth()/2.0) * (newScale - scale),
+        center.north() + (y - getHeight()/2.0) * (newScale - scale)),
+        newScale);
+    }
+
+    public void zoomToFactor(EastNorth newCenter, double factor) {
+        zoomTo(newCenter, scale*factor);
+    }
+
+    public void zoomToFactor(double factor) {
+        zoomTo(center, scale*factor);
+    }
+
+    public void zoomTo(ProjectionBounds box) {
+        // -20 to leave some border
+        int w = getWidth()-20;
+        if (w < 20)
+            w = 20;
+        int h = getHeight()-20;
+        if (h < 20)
+            h = 20;
+
+        double scaleX = (box.max.east()-box.min.east())/w;
+        double scaleY = (box.max.north()-box.min.north())/h;
+        double newScale = Math.max(scaleX, scaleY);
+
+        zoomTo(box.getCenter(), newScale);
+    }
+
+    public void zoomTo(Bounds box) {
+        zoomTo(new ProjectionBounds(getProjection().latlon2eastNorth(box.min),
+        getProjection().latlon2eastNorth(box.max)));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 1722)
@@ -207,5 +207,5 @@
                 ((OsmPrimitive) o).visit(box);
         }
-        if (box.max == null || box.min == null)
+        if (box.getBounds() == null)
             return;
         box.enlargeBoundingBox();
Index: trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java	(revision 1722)
@@ -21,4 +21,5 @@
 
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.OsmUrlToBounds;
@@ -162,24 +163,6 @@
 
     private void updateUrl(DownloadDialog gui) {
-        double lat = (gui.minlat + gui.maxlat)/2;
-        double lon = (gui.minlon + gui.maxlon)/2;
-        // convert to mercator (for calculation of zoom only)
-        double latMin = Math.log(Math.tan(Math.PI/4.0+gui.minlat/180.0*Math.PI/2.0))*180.0/Math.PI;
-        double latMax = Math.log(Math.tan(Math.PI/4.0+gui.maxlat/180.0*Math.PI/2.0))*180.0/Math.PI;
-        double size = Math.max(Math.abs(latMax-latMin), Math.abs(gui.maxlon-gui.minlon));
-        int zoom = 0;
-        while (zoom <= 20) {
-            if (size >= 180)
-                break;
-            size *= 2;
-            zoom++;
-        }
-        // Truncate lat and lon to something more sensible
-        int decimals = (int) Math.pow(10, (zoom / 3));
-        lat = Math.round(lat * decimals);
-        lat /= decimals;
-        lon = Math.round(lon * decimals);
-        lon /= decimals;
-        showUrl.setText("http://www.openstreetmap.org/?lat="+lat+"&lon="+lon+"&zoom="+zoom);
+        showUrl.setText(OsmUrlToBounds.getURL(new Bounds(
+        new LatLon(gui.minlat, gui.minlon), new LatLon(gui.maxlat, gui.maxlon))));
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 1722)
@@ -536,5 +536,5 @@
 
             if (centerToggle.getModel().isSelected())
-                Main.map.mapView.zoomTo(currentImageEntry.pos, Main.map.mapView.getScale());
+                Main.map.mapView.zoomTo(currentImageEntry.pos);
 
             dlg.setTitle(currentImageEntry.image +
Index: trunk/src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/ProjectionPreference.java	(revision 1722)
@@ -13,6 +13,8 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.projection.Mercator;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.coor.LatLon.CoordinateFormat;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.tools.GBC;
 
@@ -28,5 +30,5 @@
 
         for (int i = 0; i < projectionCombo.getItemCount(); ++i) {
-            if (projectionCombo.getItemAt(i).getClass().getName().equals(Main.pref.get("projection"))) {
+            if (projectionCombo.getItemAt(i).getClass().getName().equals(Main.pref.get("projection", Mercator.class.getName()))) {
                 projectionCombo.setSelectedIndex(i);
                 break;
@@ -54,10 +56,11 @@
 
     public boolean ok() {
-        boolean restart = Main.pref.put("projection",
-        projectionCombo.getSelectedItem().getClass().getName());
+        String projname = projectionCombo.getSelectedItem().getClass().getName();
+        if(Main.pref.put("projection", projname))
+            Main.setProjection(projname);
         if(Main.pref.put("coordinates",
         ((CoordinateFormat)coordinatesCombo.getSelectedItem()).name()))
-            restart = true;
-        return restart;
+            Node.setCoordinateFormat();
+        return false;
     }
 }
Index: trunk/src/org/openstreetmap/josm/io/GpxWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/GpxWriter.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/io/GpxWriter.java	(revision 1722)
@@ -121,9 +121,11 @@
         if (attr.containsKey(GpxData.META_KEYWORDS)) simpleTag("keywords", (String)attr.get(GpxData.META_KEYWORDS));
 
-        data.recalculateBounds();
-        Bounds bounds = data.bounds;
-        String b = "minlat=\"" + bounds.min.lat() + "\" minlon=\"" + bounds.min.lon() +
-            "\" maxlat=\"" + bounds.max.lat() + "\" maxlon=\"" + bounds.max.lon() + "\"" ;
-        inline("bounds", b);
+        Bounds bounds = data.recalculateBounds();
+        if(bounds != null)
+        {
+            String b = "minlat=\"" + bounds.min.lat() + "\" minlon=\"" + bounds.min.lon() +
+                "\" maxlat=\"" + bounds.max.lat() + "\" maxlon=\"" + bounds.max.lon() + "\"" ;
+            inline("bounds", b);
+        }
 
         closeln("metadata");
Index: trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java	(revision 1721)
+++ trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java	(revision 1722)
@@ -55,3 +55,33 @@
         return Double.parseDouble(map.get("m"+key));
     }
+
+    static public int getZoom(Bounds b)
+    {
+        // convert to mercator (for calculation of zoom only)
+        double latMin = Math.log(Math.tan(Math.PI/4.0+b.min.lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
+        double latMax = Math.log(Math.tan(Math.PI/4.0+b.max.lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
+        double size = Math.max(Math.abs(latMax-latMin), Math.abs(b.max.lon()-b.min.lon()));
+        int zoom = 0;
+        while (zoom <= 20) {
+            if (size >= 180)
+                break;
+            size *= 2;
+            zoom++;
+        }
+        return zoom;
+    }
+
+    static public String getURL(Bounds b)
+    {
+        return getURL(b.center(), getZoom(b));
+    }
+
+    static public String getURL(LatLon pos, int zoom)
+    {
+        // Truncate lat and lon to something more sensible
+        int decimals = (int) Math.pow(10, (zoom / 3));
+        double lat = (Math.round(pos.lat() * decimals))/decimals;
+        double lon = (Math.round(pos.lon() * decimals))/decimals;
+        return new String("http://www.openstreetmap.org/?lat="+lat+"&lon="+lon+"&zoom="+zoom);
+    }
 }
