Index: /trunk/data_nodist/projection/josm-epsg
===================================================================
--- /trunk/data_nodist/projection/josm-epsg	(revision 9564)
+++ /trunk/data_nodist/projection/josm-epsg	(revision 9565)
@@ -53,6 +53,6 @@
 # Belgian Lambert 2008
 <3812> +proj=lcc +lat_0=50d47'52.134" +lat_1=49d50'0" +lat_2=51d10'0" +lon_0=4d21'33.177" +x_0=649328 +y_0=665262 +ellps=GRS80 +nadgrids=null +units=m +bounds=2.54,49.51,6.4,51.5  <>
-# Pseudo-Mercator
-<3857> +proj=josm:smerc +datum=WGS84 +units=m +bounds=-180,-85.05112877980659,180,85.05112877980659  <>
+# WGS 84 / Pseudo-Mercator
+<3857> +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +bounds=-180,-85.05112877980659,180,85.05112877980659 <>
 # Lambert CC9 (France) Zone 42
 <3942> +proj=lcc +lat_0=42 +lat_1=41.25 +lat_2=42.75 +lon_0=3 +x_0=1700000 +y_0=1200000 +ellps=GRS80 +nadgrids=null +units=m +bounds=-5.5,41,10.2,44.5  <>
Index: /trunk/data_nodist/projection/projection-regression-test-data
===================================================================
--- /trunk/data_nodist/projection/projection-regression-test-data	(revision 9564)
+++ /trunk/data_nodist/projection/projection-regression-test-data	(revision 9565)
@@ -5945,4 +5945,16 @@
   en  -193969.4282884883 8469842.549172236
   ll2 -13.760992483199203 38.60194124510362
+EPSG:3000
+  ll  31.910053601835273 18.106211343257215
+  en  -6298607.693804365 4617158.822506971
+  ll2 31.910053822996915 18.10621242764793
+EPSG:3001
+  ll  35.517579866263844 152.3184248561901
+  en  8596711.674334003 5097011.9228557665
+  ll2 35.51757975669143 152.31842469563856
+EPSG:3002
+  ll  11.457376033055027 163.93490862689723
+  en  9885642.748954434 2171556.0805702494
+  ll2 11.457376033600664 163.9349086202522
 EPSG:3003
   ll  38.09725651416973 7.4345625019044315
@@ -9541,4 +9553,8 @@
   en  6480276.344184 1151844.8226038879
   ll2 10.291404319051509 41.91402761717174
+EPSG:3388
+  ll  -73.24907273227738 126.72589597701531
+  en  6273844.747247949 -9063422.188490324
+  ll2 -73.24907270081529 126.72589592872397
 EPSG:3389
   ll  -14.438886660384838 173.46408675562256
@@ -9565,4 +9581,8 @@
   en  4744317.466116981 -1532445.4287352874
   ll2 5.39523547581824 71.65431390978326
+EPSG:3395
+  ll  -55.07366715935213 -39.25832129180364
+  en  -4370216.3356023105 -7341116.553800662
+  ll2 -55.073667159347856 -39.25832129180364
 EPSG:3396
   ll  85.94787390828097 5.998729693776394
@@ -11173,4 +11193,8 @@
   en  578839.8963415996 9495341.810721355
   ll2 85.4401286193869 132.0129193956132
+EPSG:3832
+  ll  73.69237557115602 34.57071836335369
+  en  -1.284952885442483E7 1.23513911708691E7
+  ll2 73.69237557115602 34.57071836335369
 EPSG:3833
   ll  -40.122015589116714 8.310180221924293
@@ -11461,4 +11485,8 @@
   en  4313912.928101179 3313513.266237703
   ll2 41.9479651127952 -20.193469561386244
+EPSG:3994
+  ll  -50.71638723313427 160.46719257754955
+  en  5087418.440840361 -4941555.3324789135
+  ll2 -50.716387233124316 160.46719257754955
 EPSG:3995
   ll  -58.51924034223759 170.25401704511552
@@ -14405,4 +14433,16 @@
   en  3110069.5559353866 -4317519.519979515
   ll2 25.078168139707362 -7.402209063825693
+EPSG:5329
+  ll  -23.170901896645304 -57.605842799307936
+  en  -1.4699694275369853E7 -1727381.2603731817
+  ll2 -23.170902573741188 -57.605842740240085
+EPSG:5330
+  ll  12.9779121381478 142.08163488900027
+  en  7460496.874071628 2343321.8977075103
+  ll2 12.977912125247077 142.08163486687238
+EPSG:5331
+  ll  -4.523931631753413 -57.62016766238983
+  en  -1.4701037559979454E7 400716.72736424254
+  ll2 -4.523931469991159 -57.620168125269096
 EPSG:5337
   ll  -0.4402497156128504 -35.57669067759142
@@ -14769,4 +14809,8 @@
   en  4181126.435413616 2483990.525243229
   ll2 49.02916195063009 12.564236704801566
+EPSG:5641
+  ll  -49.93383931217301 40.41312972718575
+  en  1.4279888478912478E7 3601767.464654859
+  ll2 -49.933839312161766 40.413129727185755
 EPSG:5643
   ll  41.66055483285982 31.866237633592732
Index: /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 9565)
@@ -27,4 +27,5 @@
 import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
 import org.openstreetmap.josm.data.projection.proj.ICentralMeridianProvider;
+import org.openstreetmap.josm.data.projection.proj.IScaleFactorProvider;
 import org.openstreetmap.josm.data.projection.proj.Mercator;
 import org.openstreetmap.josm.data.projection.proj.Proj;
@@ -274,4 +275,7 @@
                 this.k0 = parseDouble(s, Param.k_0.key);
             }
+            if (proj instanceof IScaleFactorProvider) {
+                this.k0 *= ((IScaleFactorProvider) proj).getScaleFactor();
+            }
             s = parameters.get(Param.bounds.key);
             if (s != null) {
Index: /trunk/src/org/openstreetmap/josm/data/projection/Ellipsoid.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Ellipsoid.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/Ellipsoid.java	(revision 9565)
@@ -132,4 +132,10 @@
 
     /**
+     * if ellipsoid is spherical, i.e.&nbsp;the major and minor semiaxis are
+     * the same
+     */
+    public final boolean spherical;
+
+    /**
      * private constructur - use one of the create_* methods
      *
@@ -139,6 +145,7 @@
      * @param e2 first eccentricity squared
      * @param eb2 square of the second eccentricity
-     */
-    private Ellipsoid(double a, double b, double e, double e2, double eb2) {
+     * @param sperical if the ellipsoid is sphere
+     */
+    private Ellipsoid(double a, double b, double e, double e2, double eb2, boolean sperical) {
         this.a = a;
         this.b = b;
@@ -146,4 +153,5 @@
         this.e2 = e2;
         this.eb2 = eb2;
+        this.spherical = sperical;
     }
 
@@ -159,5 +167,5 @@
         double e = Math.sqrt(e2);
         double eb2 = e2 / (1.0 - e2);
-        return new Ellipsoid(a, b, e, e2, eb2);
+        return new Ellipsoid(a, b, e, e2, eb2, a == b);
     }
 
@@ -173,5 +181,5 @@
         double e = Math.sqrt(es);
         double eb2 = es / (1.0 - es);
-        return new Ellipsoid(a, b, e, es, eb2);
+        return new Ellipsoid(a, b, e, es, eb2, es == 0);
     }
 
@@ -188,5 +196,5 @@
         double e = Math.sqrt(e2);
         double eb2 = e2 / (1.0 - e2);
-        return new Ellipsoid(a, b, e, e2, eb2);
+        return new Ellipsoid(a, b, e, e2, eb2, f == 0);
     }
 
@@ -334,5 +342,5 @@
         return new LatLon(Math.toDegrees(lt), Math.toDegrees(lg));
     }
-    
+
     /**
      * convert ellipsoidal coordinates to cartesian coordinates
Index: /trunk/src/org/openstreetmap/josm/data/projection/Projections.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 9565)
@@ -89,8 +89,8 @@
         registerBaseProjection("aea", AlbersEqualArea.class, "core");
         registerBaseProjection("cass", CassiniSoldner.class, "core");
-        registerBaseProjection("josm:smerc", Mercator.class, "core");
         registerBaseProjection("laea", LambertAzimuthalEqualArea.class, "core");
         registerBaseProjection("lcc", LambertConformalConic.class, "core");
         registerBaseProjection("lonlat", LonLat.class, "core");
+        registerBaseProjection("merc", Mercator.class, "core");
         registerBaseProjection("omerc", ObliqueMercator.class, "core");
         registerBaseProjection("somerc", SwissObliqueMercator.class, "core");
Index: /trunk/src/org/openstreetmap/josm/data/projection/proj/AbstractProj.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/proj/AbstractProj.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/proj/AbstractProj.java	(revision 9565)
@@ -74,4 +74,10 @@
      */
     protected double e2;
+    
+    /**
+     * is ellipsoid spherical?
+     * @see Ellisoid.spherical
+     */
+    protected boolean spherical;
 
     @Override
@@ -79,4 +85,5 @@
         e2 = params.ellps.e2;
         e = params.ellps.e;
+        spherical = params.ellps.spherical;
         //  Compute constants for the mlfn
         double t;
Index: /trunk/src/org/openstreetmap/josm/data/projection/proj/IScaleFactorProvider.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/proj/IScaleFactorProvider.java	(revision 9565)
+++ /trunk/src/org/openstreetmap/josm/data/projection/proj/IScaleFactorProvider.java	(revision 9565)
@@ -0,0 +1,21 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.projection.proj;
+
+/**
+ * A {@link Proj} implements this interface, if it derives the scale factor
+ * value from it's other input parameters.
+ *
+ * (Normally the scale factor is projection input parameter and the Proj
+ * class does not deal with it.)
+ *
+ * @see Proj
+ */
+public interface IScaleFactorProvider {
+    /**
+     * Get the scale factor.
+     * Will be multiplied by the scale factor parameter, if supplied by the user
+     * explicitly.
+     * @return the scale factor
+     */
+    double getScaleFactor();
+}
Index: /trunk/src/org/openstreetmap/josm/data/projection/proj/Mercator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/proj/Mercator.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/proj/Mercator.java	(revision 9565)
@@ -2,9 +2,4 @@
 package org.openstreetmap.josm.data.projection.proj;
 
-import static java.lang.Math.PI;
-import static java.lang.Math.atan;
-import static java.lang.Math.log;
-import static java.lang.Math.sinh;
-import static java.lang.Math.tan;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
@@ -13,7 +8,45 @@
 
 /**
- * Mercator Projection.
+ * Mercator Cylindrical Projection. The parallels and the meridians are straight lines and
+ * cross at right angles; this projection thus produces rectangular charts. The scale is true
+ * along the equator (by default) or along two parallels equidistant of the equator (if a scale
+ * factor other than 1 is used). This projection is used to represent areas close to the equator.
+ * It is also often used for maritime navigation because all the straight lines on the chart are
+ * <em>loxodrome</em> lines, i.e. a ship following this line would keep a constant azimuth on its
+ * compass.
+ * <p>
+ * This implementation handles both the 1 and 2 stardard parallel cases.
+ * For 1 SP (EPSG code 9804), the line of contact is the equator.
+ * For 2 SP (EPSG code 9805) lines of contact are symmetrical
+ * about the equator.
+ * <p>
+ * This class has been derived from the implementation of the Geotools project;
+ * git 8cbf52d, org.geotools.referencing.operation.projection.CassiniSoldner
+ * at the time of migration.
+ * <p>
+ * <b>References:</b>
+ * <ul>
+ *   <li>John P. Snyder (Map Projections - A Working Manual,<br>
+ *       U.S. Geological Survey Professional Paper 1395, 1987)</li>
+ *   <li>"Coordinate Conversions and Transformations including Formulas",<br>
+ *       EPSG Guidence Note Number 7, Version 19.</li>
+ * </ul>
+ *
+ * @see <A HREF="http://mathworld.wolfram.com/MercatorProjection.html">Mercator projection on MathWorld</A>
+ * @see <A HREF="http://www.remotesensing.org/geotiff/proj_list/mercator_1sp.html">"mercator_1sp" on RemoteSensing.org</A>
+ * @see <A HREF="http://www.remotesensing.org/geotiff/proj_list/mercator_2sp.html">"mercator_2sp" on RemoteSensing.org</A>
+ *
+ * @author André Gosselin
+ * @author Martin Desruisseaux (PMO, IRD)
+ * @author Rueben Schulz
+ * @author Simone Giannecchini
  */
-public class Mercator implements Proj {
+public class Mercator extends AbstractProj implements IScaleFactorProvider {
+    /**
+     * Maximum difference allowed when comparing real numbers.
+     */
+    private static final double EPSILON = 1E-6;
+
+    protected double scaleFactor;
 
     @Override
@@ -24,19 +57,56 @@
     @Override
     public String getProj4Id() {
-        return "josm:smerc"; // "merc" is ellipsoidal Mercator projection in PROJ.4
+        return "merc";
     }
 
     @Override
     public void initialize(ProjParameters params) throws ProjectionConfigurationException {
+        super.initialize(params);
+        scaleFactor = 1;
+        if (params.lat_ts != null) {
+            /*
+             * scaleFactor is not a parameter in the 2 SP case and is computed from
+             * the standard parallel.
+             */
+            double standardParallel = Math.toRadians(params.lat_ts);
+            if (spherical) {
+                scaleFactor *= Math.cos(standardParallel);
+            }  else {
+                scaleFactor *= msfn(Math.sin(standardParallel), Math.cos(standardParallel));
+            }
+        }
+        /*
+         * A correction that allows us to employs a latitude of origin that is not
+         * correspondent to the equator. See Snyder and al. for reference, page 47.
+         */
+        if (params.lat0 != null) {
+            final double lat0 = Math.toRadians(params.lat0);
+            final double sinPhi = Math.sin(lat0);
+            scaleFactor *= (Math.cos(lat0) / (Math.sqrt(1 - e2 * sinPhi * sinPhi)));
+        }
     }
 
     @Override
-    public double[] project(double lat_rad, double lon_rad) {
-        return new double[] {lon_rad, log(tan(PI/4 + lat_rad/2))};
+    public double[] project(double y, double x) {
+        if (Math.abs(y) > (Math.PI/2 - EPSILON)) {
+            return new double[] {0, 0}; // this is an error and should be handled somehow
+        }
+        if (spherical) {
+            y = Math.log(Math.tan(Math.PI/4 + 0.5*y));
+        } else {
+            y = -Math.log(tsfn(y, Math.sin(y)));
+        }
+        return new double[] {x, y};
     }
 
     @Override
-    public double[] invproject(double east, double north) {
-        return new double[] {atan(sinh(north)), east};
+    public double[] invproject(double x, double y) {
+        if (spherical) {
+            y = Math.PI/2 - 2.0*Math.atan(Math.exp(-y));
+        } else {
+            y = Math.exp(-y);
+            y = cphi2(y);
+        }
+        return new double[] {y, x};
     }
 
@@ -45,3 +115,8 @@
         return new Bounds(-89, -180, 89, 180, false);
     }
+
+    @Override
+    public double getScaleFactor() {
+        return scaleFactor;
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/data/projection/proj/ProjParameters.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/proj/ProjParameters.java	(revision 9564)
+++ /trunk/src/org/openstreetmap/josm/data/projection/proj/ProjParameters.java	(revision 9565)
@@ -15,5 +15,5 @@
     public Double lat2;
 
-    // Polar Stereographic
+    // Polar Stereographic and Mercator
     public Double lat_ts;
 
Index: /trunk/test/unit/org/openstreetmap/josm/data/projection/ProjectionTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/projection/ProjectionTest.java	(revision 9564)
+++ /trunk/test/unit/org/openstreetmap/josm/data/projection/ProjectionTest.java	(revision 9565)
@@ -112,5 +112,4 @@
         final double EPS = 1e-6;
         testProj("lonlat", EPS, "");
-        testProj("josm:smerc", EPS, "");
         testProj("lcc", EPS, "+lat_0=34");
         testProj("lcc", EPS, "+lat_1=87 +lat_2=83.6 +lat_0=85.43");
@@ -125,4 +124,5 @@
         testProj("cass", 1e-3, "+lat_0=11 +bounds=-1.0,-89,1.0,89");
         testProj("laea", 3e-3, "+lat_0=34");
+        testProj("merc", 1e-5, "");
 
         if (error2) {
