Ticket #5327: new.patch
| File new.patch, 15.0 KB (added by , 15 years ago) |
|---|
-
test/unit/org/openstreetmap/josm/data/projection/SwissGridTest.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.projection; 3 4 import static org.junit.Assert.assertTrue; 5 6 import org.junit.BeforeClass; 7 import org.junit.Test; 8 import org.openstreetmap.josm.Main; 9 import org.openstreetmap.josm.data.coor.EastNorth; 10 import org.openstreetmap.josm.data.coor.LatLon; 11 12 public class SwissGridTest { 13 @BeforeClass 14 public static void setUp() { 15 Main.proj = new SwissGrid(); 16 } 17 18 @Test 19 public void a_latlon2eastNorth_test() { 20 { 21 LatLon ll = new LatLon(46.518, 6.567); 22 EastNorth en = Main.proj.latlon2eastNorth(ll); 23 System.out.println(en); 24 assertTrue("Lausanne", Math.abs(en.east() - 533111.69) < 0.1); 25 assertTrue("Lausanne", Math.abs(en.north() - 152227.85) < 0.1); 26 } 27 28 { 29 LatLon ll = new LatLon(47.78, 8.58); 30 EastNorth en = Main.proj.latlon2eastNorth(ll); 31 System.out.println(en); 32 assertTrue("Schafouse", Math.abs(en.east() - 685544.16) < 0.1); 33 assertTrue("Schafouse", Math.abs(en.north() - 292782.91) < 0.1); 34 } 35 36 { 37 LatLon ll = new LatLon(46.58, 10.48); 38 EastNorth en = Main.proj.latlon2eastNorth(ll); 39 System.out.println(en); 40 assertTrue("Grinson", Math.abs(en.east() - 833068.04) < 0.1); 41 assertTrue("Grinson", Math.abs(en.north() - 163265.39) < 0.1); 42 } 43 { 44 LatLon ll = new LatLon(46.0 + 57.0 / 60 + 3.89813884505 / 3600, 7.0 + 26.0 / 60 + 19.076595154147 / 3600); 45 EastNorth en = Main.proj.latlon2eastNorth(ll); 46 System.out.println(en); 47 assertTrue("Berne", Math.abs(en.east() - 600000.0) < 0.1); 48 assertTrue("Berne", Math.abs(en.north() - 200000.0) < 0.1); 49 } 50 { 51 LatLon ll = new LatLon(46.044130, 8.730497); 52 EastNorth en = Main.proj.latlon2eastNorth(ll); 53 System.out.println(en); 54 assertTrue("Ref", Math.abs(en.east() - 700000.0) < 0.1); 55 assertTrue("Ref", Math.abs(en.north() - 100000.0) < 0.1); 56 } 57 } 58 59 @Test 60 public void b_eastNorth2latlon_test() { 61 { 62 EastNorth en = new EastNorth(533111.69, 152227.85); 63 LatLon ll = Main.proj.eastNorth2latlon(en); 64 System.out.println(ll); 65 assertTrue("Lausanne", Math.abs(ll.lat() - 46.518) < 0.00001); 66 assertTrue("Lausanne", Math.abs(ll.lon() - 6.567) < 0.00001); 67 } 68 69 { 70 EastNorth en = new EastNorth(685544.16, 292782.91); 71 LatLon ll = Main.proj.eastNorth2latlon(en); 72 System.out.println(ll); 73 assertTrue("Schafouse", Math.abs(ll.lat() - 47.78) < 0.00001); 74 assertTrue("Schafouse", Math.abs(ll.lon() - 8.58) < 0.00001); 75 } 76 77 { 78 EastNorth en = new EastNorth(833068.04, 163265.39); 79 LatLon ll = Main.proj.eastNorth2latlon(en); 80 System.out.println(ll); 81 assertTrue("Ref", Math.abs(ll.lat() - 46.58) < 0.00001); 82 assertTrue("Ref", Math.abs(ll.lon() -10.48) < 0.00001); 83 } 84 85 { 86 EastNorth en = new EastNorth(600000.0, 200000.0); 87 LatLon ll = Main.proj.eastNorth2latlon(en); 88 System.out.println(ll); 89 assertTrue("Berne", Math.abs(ll.lat() - (46.0 + 57.0 / 60 + 3.89813884505 / 3600)) < 0.00001); 90 assertTrue("Berne", Math.abs(ll.lon() - (7.0 + 26.0 / 60 + 19.076595154147 / 3600)) < 0.00001); 91 } 92 93 { 94 EastNorth en = new EastNorth(700000.0, 100000.0); 95 LatLon ll = Main.proj.eastNorth2latlon(en); 96 System.out.println(ll); 97 assertTrue("Ref", Math.abs(ll.lat() - 46.044130) < 0.00001); 98 assertTrue("Ref", Math.abs(ll.lon() - 8.730497) < 0.00001); 99 } 100 101 } 102 } -
src/org/openstreetmap/josm/data/projection/SwissGrid.java
14 14 * Calculations are based on formula from 15 15 * http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/switzerland.parsysrelated1.37696.downloadList.12749.DownloadFile.tmp/ch1903wgs84en.pdf 16 16 * 17 * August 2010 update to this formula (rigorous formulas) 18 * http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/switzerland.parsysrelated1.37696.downloadList.97912.DownloadFile.tmp/swissprojectionen.pdf 17 19 */ 18 20 public class SwissGrid implements Projection { 21 22 public static void main(String[] args) { 23 SwissGrid proj = new SwissGrid(); 24 { 25 EastNorth en = new EastNorth(700000.0, 100000.0); 26 LatLon ll = proj.eastNorth2latlon(en); 27 System.out.println(ll); 28 } 29 { 30 EastNorth en = new EastNorth(700000.1, 100000.1); 31 LatLon ll = proj.eastNorth2latlon(en); 32 System.out.println(ll); 33 } 34 35 { 36 LatLon ll = new LatLon(46.518, 6.567); 37 EastNorth en = proj.latlon2eastNorth(ll); 38 System.out.println(en); 39 } 40 41 { 42 LatLon ll = new LatLon(47.78, 8.58); 43 EastNorth en = proj.latlon2eastNorth(ll); 44 System.err.println(en); 45 } 46 47 { 48 LatLon ll = new LatLon(46.58, 10.48); 49 EastNorth en = proj.latlon2eastNorth(ll); 50 System.out.println(en); 51 } 52 53 { 54 LatLon ll = new LatLon(46.0 + 57.0 / 60 + 3.89813884505 / 3600, 7.0 + 26.0 / 60 + 19.076595154147 / 3600); 55 EastNorth en = proj.latlon2eastNorth(ll); 56 System.out.println(en); 57 } 58 { 59 LatLon ll = new LatLon(46.0 + 2.0 / 60 + 38.87 / 3600, 8.0 + 43.0 / 60 + 49.79 / 3600); 60 EastNorth en = proj.latlon2eastNorth(ll); 61 System.out.println(en); 62 } 63 } 64 65 private static final double dX = 674.374; 66 private static final double dY = 15.056; 67 private static final double dZ = 405.346; 68 69 private static final double wgs84_a = 6378137.000; 70 private static final double wgs84_b = 6356752.314245; 71 // private static final double wgs84_f = (wgs84_a-wgs84_b)/wgs84_a; 72 private static final double wgs84_E2 = (Math.pow(wgs84_a, 2) - Math.pow(wgs84_b, 2)) / Math.pow(wgs84_a, 2); 73 // private static final double wgs84_E = Math.sqrt(wgs84_E2); 74 75 private static final double a = 6377397.155; 76 private static final double b = 6356078.962822; 77 // private static final double f = (a-b)/a; 78 private static final double E2 = (Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(a, 2); 79 private static final double E = Math.sqrt(E2); 80 private static final double phi0 = Math.toRadians(46.0 + 57.0 / 60 + 8.66 / 3600); 81 private static final double lambda0 = Math.toRadians(7.0 + 26.0 / 60 + 22.50 / 3600); 82 private static final double R = a * Math.sqrt(1 - E2) / (1 - (E2 * Math.pow(Math.sin(phi0), 2))); 83 private static final double alpha = Math.sqrt(1 + (E2 / (1 - E2) * Math.pow(Math.cos(phi0), 4))); 84 private static final double b0 = Math.asin(Math.sin(phi0) / alpha); 85 private static final double K = Math.log(Math.tan(Math.PI / 4 + b0 / 2)) - alpha 86 * Math.log(Math.tan(Math.PI / 4 + phi0 / 2)) + alpha * E / 2 87 * Math.log((1 + E * Math.sin(phi0)) / (1 - E * Math.sin(phi0))); 88 89 private static final double xTrans = 200000; 90 private static final double yTrans = 600000; 91 92 private LatLon correctETRS89toCH1903(LatLon coord) { 93 double phi = Math.toRadians(coord.lat()); 94 double lambda = Math.toRadians(coord.lon()); 95 96 double Rn = wgs84_a / Math.sqrt(1 - wgs84_E2 * Math.pow(Math.sin(phi), 2)); 97 double X = Rn * Math.cos(phi) * Math.cos(lambda); 98 double Y = Rn * Math.cos(phi) * Math.sin(lambda); 99 double Z = Rn * (1 - wgs84_E2) * Math.sin(phi); 100 X -= dX; 101 Y -= dY; 102 Z -= dZ; 103 lambda = Math.atan2(Y, X); 104 double sX2Ys = Math.sqrt(X * X + Y * Y); 105 phi = Math.atan2(Z, sX2Ys); 106 double h = 0; 107 double prevPhi = -1000; 108 int iteration = 0; 109 while (Math.abs(phi - prevPhi) > 0.0000001) { 110 if (++iteration > 20) { 111 throw new RuntimeException("Two many iterations"); 112 } 113 Rn = a / Math.sqrt(1 - E2 * Math.pow(Math.sin(phi), 2)); 114 h = sX2Ys / Math.cos(phi) - Rn; 115 prevPhi = phi; 116 phi = Math.atan2(Z / sX2Ys, 1 - Rn * E2 / (Rn + h)); 117 } 118 119 return new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 120 } 121 122 private LatLon correctCH1903toETRS89(LatLon coord) { 123 double phi = Math.toRadians(coord.lat()); 124 double lambda = Math.toRadians(coord.lon()); 125 126 double Rn = a / Math.sqrt(1 - E2 * Math.pow(Math.sin(phi), 2)); 127 double X = Rn * Math.cos(phi) * Math.cos(lambda); 128 double Y = Rn * Math.cos(phi) * Math.sin(lambda); 129 double Z = Rn * (1 - E2) * Math.sin(phi); 130 X += dX; 131 Y += dY; 132 Z += dZ; 133 lambda = Math.atan2(Y, X); 134 double sX2Ys = Math.sqrt(X * X + Y * Y); 135 phi = Math.atan((Z / sX2Ys)); 136 double h = 0; 137 138 double prevPhi = -1000; 139 int iteration = 0; 140 while (Math.abs(phi - prevPhi) > 0.0000001) { 141 if (++iteration > 20) { 142 throw new RuntimeException("Two many iterations"); 143 } 144 Rn = wgs84_a / Math.sqrt(1 - wgs84_E2 * Math.pow(Math.sin(phi), 2)); 145 h = sX2Ys / Math.cos(phi) - Rn; 146 prevPhi = phi; 147 phi = Math.atan2(Z / sX2Ys, 1 - Rn * wgs84_E2 / (Rn + h)); 148 } 149 150 return new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 151 } 152 19 153 /** 20 154 * @param wgs WGS84 lat/lon (ellipsoid GRS80) (in degree) 21 155 * @return eastnorth projection in Swiss National Grid (ellipsoid Bessel) 22 156 */ 23 157 public EastNorth latlon2eastNorth(LatLon wgs) { 24 double phi = 3600d * wgs.lat(); 25 double lambda = 3600d * wgs.lon(); 158 LatLon coord = correctETRS89toCH1903(wgs); 159 double phi = Math.toRadians(coord.lat()); 160 double lambda = Math.toRadians(coord.lon()); 26 161 27 double phiprime = (phi - 169028.66d) / 10000d; 28 double lambdaprime = (lambda - 26782.5d) / 10000d; 162 double S = alpha * Math.log(Math.tan(Math.PI / 4 + phi / 2)) - alpha * E / 2 163 * Math.log((1 + E * Math.sin(phi)) / (1 - E * Math.sin(phi))) + K; 164 double b = 2 * (Math.atan(Math.exp(S)) - Math.PI / 4); 165 double l = alpha * (lambda - lambda0); 29 166 30 // precompute squares for lambdaprime and phiprime 31 // 32 double lambdaprime_2 = Math.pow(lambdaprime,2); 33 double phiprime_2 = Math.pow(phiprime,2); 167 double lb = Math.atan2(Math.sin(l), Math.sin(b0) * Math.tan(b) + Math.cos(b0) * Math.cos(l)); 168 double bb = Math.asin(Math.cos(b0) * Math.sin(b) - Math.sin(b0) * Math.cos(b) * Math.cos(l)); 34 169 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); 170 double y = R * lb; 171 double x = R / 2 * Math.log((1 + Math.sin(bb)) / (1 - Math.sin(bb))); 42 172 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); 173 return new EastNorth(y + yTrans, x + xTrans); 51 174 } 52 175 53 176 /** 54 177 * @param xy SwissGrid east/north (in meters) 55 178 * @return LatLon WGS84 (in degree) 56 179 */ 57 58 180 public LatLon eastNorth2latlon(EastNorth xy) { 59 double yp = (xy.east() - 600000d) / 1000000d;60 double xp = (xy.north() - 200000d) / 1000000d;181 double x = xy.north() - xTrans; 182 double y = xy.east() - yTrans; 61 183 62 // precompute squares of xp and yp 63 // 64 double xp_2 = Math.pow(xp,2); 65 double yp_2 = Math.pow(yp,2); 184 double lb = y / R; 185 double bb = 2 * (Math.atan(Math.exp(x / R)) - Math.PI / 4); 66 186 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); 187 double b = Math.asin(Math.cos(b0) * Math.sin(bb) + Math.sin(b0) * Math.cos(bb) * Math.cos(lb)); 188 double l = Math.atan2(Math.sin(lb), Math.cos(b0) * Math.cos(lb) - Math.sin(b0) * Math.tan(bb)); 73 189 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); 190 double lambda = lambda0 + l / alpha; 191 double phi = b; 192 double S = 0; 80 193 81 double lmb = lmbp * 100.0d / 36.0d; 82 double phi = phip * 100.0d / 36.0d; 194 // 5 iteration to fins S and phi 195 for (int i = 0; i < 6; i++) { 196 S = 1 / alpha * (Math.log(Math.tan(Math.PI / 4 + b / 2)) - K) + E 197 * Math.log(Math.tan(Math.PI / 4 + Math.asin(E * Math.sin(phi)) / 2)); 198 phi = 2 * Math.atan(Math.exp(S)) - Math.PI / 2; 199 } 83 200 84 return new LatLon(phi,lmb); 201 LatLon coord = new LatLon(Math.toDegrees(phi), Math.toDegrees(lambda)); 202 return correctCH1903toETRS89(coord); 85 203 } 86 204 87 @Override public String toString() { 205 @Override 206 public String toString() { 88 207 return tr("Swiss Grid (Switzerland)"); 89 208 } 90 209 … … 101 220 return "swissgrid"; 102 221 } 103 222 104 public Bounds getWorldBoundsLatLon() 105 { 106 return new Bounds( 107 new LatLon(45.7, 5.7), 108 new LatLon(47.9, 10.6)); 223 public Bounds getWorldBoundsLatLon() { 224 return new Bounds(new LatLon(45.7, 5.7), new LatLon(47.9, 10.6)); 109 225 } 110 226 111 227 public double getDefaultZoomInPPD() {
