Ticket #5327: swiss.patch
File swiss.patch, 8.8 KB (added by , 14 years ago) |
---|
-
org/openstreetmap/josm/data/projection/SwissGrid.java
3 3 package org.openstreetmap.josm.data.projection; 4 4 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 7 6 import org.openstreetmap.josm.data.Bounds; 8 7 import org.openstreetmap.josm.data.coor.EastNorth; 9 8 import org.openstreetmap.josm.data.coor.LatLon; … … 14 13 * Calculations are based on formula from 15 14 * http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/switzerland.parsysrelated1.37696.downloadList.12749.DownloadFile.tmp/ch1903wgs84en.pdf 16 15 * 16 * August 2010 update to this formula (rigorous formulas) 17 * http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/switzerland.parsysrelated1.37696.downloadList.97912.DownloadFile.tmp/swissprojectionen.pdf 17 18 */ 18 19 public class SwissGrid implements Projection { 20 21 private static final double dX = 674.374; 22 private static final double dY = 15.056; 23 private static final double dZ = 405.346; 24 25 private static final double wgs84_a = 6378137.000; 26 private static final double wgs84_b = 6356752.314245; 27 // private static final double wgs84_f = (wgs84_a-wgs84_b)/wgs84_a; 28 private static final double wgs84_E2 = (Math.pow(wgs84_a, 2)-Math.pow(wgs84_b, 2))/Math.pow(wgs84_a, 2); 29 // private static final double wgs84_E = Math.sqrt(wgs84_E2); 30 31 32 private static final double a = 6377397.155; 33 private static final double b = 6356078.962822; 34 // private static final double f = (a-b)/a; 35 private static final double E2 = (Math.pow(a, 2)-Math.pow(b, 2))/Math.pow(a, 2); 36 private static final double E = Math.sqrt(E2); 37 private static final double phi0 = Math.toRadians(46.0 + 57.0 / 60 + 8.66 / 3600); 38 private static final double lambda0 = Math.toRadians(7.0 + 26.0 / 60 + 22.50 / 3600); 39 private static final double R = a * Math.sqrt(1 - E2) / (1 - (E2 * Math.pow(Math.sin(phi0), 2))); 40 private static final double alpha = Math.sqrt(1 + (E2 / (1 - E2) * Math.pow(Math.cos(phi0), 4))); 41 private static final double b0 = Math.asin(Math.sin(phi0) / alpha); 42 private static final double K = Math.log(Math.tan(Math.PI / 4 + b0 / 2)) - alpha 43 * Math.log(Math.tan(Math.PI / 4 + phi0 / 2)) + alpha * E / 2 44 * Math.log((1 + E * Math.sin(phi0)) / (1 - E * Math.sin(phi0))); 45 46 private static final double xTrans = 200000; 47 private static final double yTrans = 600000; 48 49 private LatLon correctETRS89toCH1903(LatLon coord) { 50 double phi = Math.toRadians(coord.lat()); 51 double lambda = Math.toRadians(coord.lon()); 52 53 double Rn = wgs84_a/Math.sqrt(1-wgs84_E2*Math.pow(Math.sin(phi), 2)); 54 double X = Rn*Math.cos(phi)*Math.cos(lambda); 55 double Y = Rn*Math.cos(phi)*Math.sin(lambda); 56 double Z = Rn*(1-wgs84_E2)*Math.sin(phi); 57 X -= dX; 58 Y -= dY; 59 Z -= dZ; 60 lambda = Math.atan(Y/X); 61 double sX2Ys = Math.sqrt(X*X+Y*Y); 62 phi = Math.atan((Z/sX2Ys)); 63 double h = 0; 64 65 for (int i = 0 ; i < 6 ; i++) { 66 Rn = a/Math.sqrt(1-E2*Math.pow(Math.sin(phi), 2)); 67 h = sX2Ys/Math.cos(phi)-Rn; 68 phi = Math.atan((Z/sX2Ys)/(1-Rn*E2/(Rn+h))); 69 } 70 71 return new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 72 } 73 74 private LatLon correctCH1903toETRS89(LatLon coord) { 75 double phi = Math.toRadians(coord.lat()); 76 double lambda = Math.toRadians(coord.lon()); 77 78 double Rn = a/Math.sqrt(1-E2*Math.pow(Math.sin(phi), 2)); 79 double X = Rn*Math.cos(phi)*Math.cos(lambda); 80 double Y = Rn*Math.cos(phi)*Math.sin(lambda); 81 double Z = Rn*(1-E2)*Math.sin(phi); 82 X += dX; 83 Y += dY; 84 Z += dZ; 85 lambda = Math.atan(Y/X); 86 double sX2Ys = Math.sqrt(X*X+Y*Y); 87 phi = Math.atan((Z/sX2Ys)); 88 double h = 0; 89 90 for (int i = 0 ; i < 5 ; i++) { 91 Rn = wgs84_a/Math.sqrt(1-wgs84_E2*Math.pow(Math.sin(phi), 2)); 92 h = sX2Ys/Math.cos(phi)-Rn; 93 phi = Math.atan((Z/sX2Ys)/(1-Rn*wgs84_E2/(Rn+h))); 94 } 95 96 return new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 97 } 98 19 99 /** 20 100 * @param wgs WGS84 lat/lon (ellipsoid GRS80) (in degree) 21 101 * @return eastnorth projection in Swiss National Grid (ellipsoid Bessel) 22 102 */ 23 103 public EastNorth latlon2eastNorth(LatLon wgs) { 24 double phi = 3600d * wgs.lat(); 25 double lambda = 3600d * wgs.lon(); 104 LatLon coord = correctETRS89toCH1903(wgs); 105 double phi = Math.toRadians(coord.lat()); 106 double lambda = Math.toRadians(coord.lon()); 26 107 27 double phiprime = (phi - 169028.66d) / 10000d; 28 double lambdaprime = (lambda - 26782.5d) / 10000d; 108 double S = alpha * Math.log(Math.tan(Math.PI / 4 + phi / 2)) - alpha * E / 2 109 * Math.log((1 + E * Math.sin(phi)) / (1 - E * Math.sin(phi))) + K; 110 double b = 2 * (Math.atan(Math.exp(S)) - Math.PI / 4); 111 double l = alpha * (lambda - lambda0); 29 112 30 // precompute squares for lambdaprime and phiprime 31 // 32 double lambdaprime_2 = Math.pow(lambdaprime,2); 33 double phiprime_2 = Math.pow(phiprime,2); 113 double lb = Math.atan(Math.sin(l) / (Math.sin(b0) * Math.tan(b) + Math.cos(b0) * Math.cos(l))); 114 double bb = Math.asin(Math.cos(b0) * Math.sin(b) - Math.sin(b0) * Math.cos(b) * Math.cos(l)); 34 115 35 double north = 36 200147.07d 37 + 308807.95d * phiprime 38 + 3745.25d * lambdaprime_2 39 + 76.63d * phiprime_2 40 - 194.56d * lambdaprime_2 * phiprime 41 + 119.79d * Math.pow(phiprime,3); 116 double y = R * lb; 117 double x = R / 2 * Math.log((1 + Math.sin(bb)) / (1 - Math.sin(bb))); 42 118 43 double east = 44 600072.37d 45 + 211455.93d * lambdaprime 46 - 10938.51d * lambdaprime * phiprime 47 - 0.36d * lambdaprime * phiprime_2 48 - 44.54d * Math.pow(lambdaprime,3); 49 50 return new EastNorth(east, north); 119 return new EastNorth(y + yTrans, x + xTrans); 51 120 } 52 121 53 122 /** 54 123 * @param xy SwissGrid east/north (in meters) 55 124 * @return LatLon WGS84 (in degree) 56 125 */ 57 58 126 public LatLon eastNorth2latlon(EastNorth xy) { 59 double yp = (xy.east() - 600000d) / 1000000d;60 double xp = (xy.north() - 200000d) / 1000000d;127 double x = xy.north() - xTrans; 128 double y = xy.east() - yTrans; 61 129 62 // precompute squares of xp and yp 63 // 64 double xp_2 = Math.pow(xp,2); 65 double yp_2 = Math.pow(yp,2); 130 double lb = y / R; 131 double bb = 2 * (Math.atan(Math.exp(x / R)) - Math.PI / 4); 66 132 67 // lambda = latitude, phi = longitude 68 double lmbp = 2.6779094d 69 + 4.728982d * yp 70 + 0.791484d * yp * xp 71 + 0.1306d * yp * xp_2 72 - 0.0436d * Math.pow(yp,3); 133 double b = Math.asin(Math.cos(b0) * Math.sin(bb) + Math.sin(b0) * Math.cos(bb) * Math.cos(lb)); 134 double l = Math.atan(Math.sin(lb) / (Math.cos(b0) * Math.cos(lb) - Math.sin(b0) * Math.tan(bb))); 73 135 74 double phip = 16.9023892d 75 + 3.238272d * xp 76 - 0.270978d * yp_2 77 - 0.002528d * xp_2 78 - 0.0447d * yp_2 * xp 79 - 0.0140d * Math.pow(xp,3); 136 double lambda = lambda0 + l / alpha; 137 double phi = b; 138 double S = 0; 80 139 81 double lmb = lmbp * 100.0d / 36.0d; 82 double phi = phip * 100.0d / 36.0d; 140 // 5 iteration to fins S and phi 141 for (int i = 0; i < 6; i++) { 142 S = 1 / alpha * (Math.log(Math.tan(Math.PI / 4 + b / 2)) - K) + E 143 * Math.log(Math.tan(Math.PI / 4 + Math.asin(E * Math.sin(phi)) / 2)); 144 phi = 2 * Math.atan(Math.exp(S)) - Math.PI / 2; 145 } 83 146 84 return new LatLon(phi,lmb); 147 LatLon coord = new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 148 return correctCH1903toETRS89(coord); 85 149 } 86 150 87 @Override public String toString() { 151 @Override 152 public String toString() { 88 153 return tr("Swiss Grid (Switzerland)"); 89 154 }