source: josm/trunk/src/org/openstreetmap/josm/data/projection/proj/Mercator.java@ 13600

Last change on this file since 13600 was 12013, checked in by bastiK, 7 years ago

see #11889 - backport improved version of Math.toDegrees and Math.toRadians from Java 9

  • Property svn:eol-style set to native
File size: 4.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.projection.proj;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import org.openstreetmap.josm.data.Bounds;
7import org.openstreetmap.josm.data.projection.ProjectionConfigurationException;
8import org.openstreetmap.josm.tools.Utils;
9
10/**
11 * Mercator Cylindrical Projection. The parallels and the meridians are straight lines and
12 * cross at right angles; this projection thus produces rectangular charts. The scale is true
13 * along the equator (by default) or along two parallels equidistant of the equator (if a scale
14 * factor other than 1 is used). This projection is used to represent areas close to the equator.
15 * It is also often used for maritime navigation because all the straight lines on the chart are
16 * <em>loxodrome</em> lines, i.e. a ship following this line would keep a constant azimuth on its
17 * compass.
18 * <p>
19 * This implementation handles both the 1 and 2 stardard parallel cases.
20 * For 1 SP (EPSG code 9804), the line of contact is the equator.
21 * For 2 SP (EPSG code 9805) lines of contact are symmetrical
22 * about the equator.
23 * <p>
24 * This class has been derived from the implementation of the Geotools project;
25 * git 8cbf52d, org.geotools.referencing.operation.projection.Mercator
26 * at the time of migration.
27 * <p>
28 * <b>References:</b>
29 * <ul>
30 * <li>John P. Snyder (Map Projections - A Working Manual,<br>
31 * U.S. Geological Survey Professional Paper 1395, 1987)</li>
32 * <li>"Coordinate Conversions and Transformations including Formulas",<br>
33 * EPSG Guidence Note Number 7, Version 19.</li>
34 * </ul>
35 *
36 * @author André Gosselin
37 * @author Martin Desruisseaux (PMO, IRD)
38 * @author Rueben Schulz
39 * @author Simone Giannecchini
40 *
41 * @see <A HREF="http://mathworld.wolfram.com/MercatorProjection.html">Mercator projection on MathWorld</A>
42 * @see <A HREF="http://www.remotesensing.org/geotiff/proj_list/mercator_1sp.html">"mercator_1sp" on RemoteSensing.org</A>
43 * @see <A HREF="http://www.remotesensing.org/geotiff/proj_list/mercator_2sp.html">"mercator_2sp" on RemoteSensing.org</A>
44 */
45public class Mercator extends AbstractProj implements IScaleFactorProvider {
46 /**
47 * Maximum difference allowed when comparing real numbers.
48 */
49 private static final double EPSILON = 1E-6;
50
51 protected double scaleFactor;
52
53 @Override
54 public String getName() {
55 return tr("Mercator");
56 }
57
58 @Override
59 public String getProj4Id() {
60 return "merc";
61 }
62
63 @Override
64 public void initialize(ProjParameters params) throws ProjectionConfigurationException {
65 super.initialize(params);
66 scaleFactor = 1;
67 if (params.lat_ts != null) {
68 /*
69 * scaleFactor is not a parameter in the 2 SP case and is computed from
70 * the standard parallel.
71 */
72 double standardParallel = Utils.toRadians(params.lat_ts);
73 if (spherical) {
74 scaleFactor *= Math.cos(standardParallel);
75 } else {
76 scaleFactor *= msfn(Math.sin(standardParallel), Math.cos(standardParallel));
77 }
78 }
79 /*
80 * A correction that allows us to employs a latitude of origin that is not
81 * correspondent to the equator. See Snyder and al. for reference, page 47.
82 */
83 if (params.lat0 != null) {
84 final double lat0 = Utils.toRadians(params.lat0);
85 final double sinPhi = Math.sin(lat0);
86 scaleFactor *= (Math.cos(lat0) / (Math.sqrt(1 - e2 * sinPhi * sinPhi)));
87 }
88 }
89
90 @Override
91 public double[] project(double y, double x) {
92 if (Math.abs(y) > (Math.PI/2 - EPSILON)) {
93 return new double[] {0, 0}; // this is an error and should be handled somehow
94 }
95 if (spherical) {
96 y = Math.log(Math.tan(Math.PI/4 + 0.5*y));
97 } else {
98 y = -Math.log(tsfn(y, Math.sin(y)));
99 }
100 return new double[] {x, y};
101 }
102
103 @Override
104 public double[] invproject(double x, double y) {
105 if (spherical) {
106 y = Math.PI/2 - 2.0*Math.atan(Math.exp(-y));
107 } else {
108 y = Math.exp(-y);
109 y = cphi2(y);
110 }
111 return new double[] {y, x};
112 }
113
114 @Override
115 public Bounds getAlgorithmBounds() {
116 return new Bounds(-89, -180, 89, 180, false);
117 }
118
119 @Override
120 public double getScaleFactor() {
121 return scaleFactor;
122 }
123
124 @Override
125 public boolean lonIsLinearToEast() {
126 return true;
127 }
128}
Note: See TracBrowser for help on using the repository browser.