- Timestamp:
- 2009-11-22T22:39:10+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data/projection
- Files:
-
- 4 added
- 3 deleted
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/projection/Ellipsoid.java
r2304 r2507 165 165 } 166 166 } 167 168 169 -
trunk/src/org/openstreetmap/josm/data/projection/GaussLaborde_Reunion.java
r2114 r2507 217 217 218 218 public double getDefaultZoomInPPD() { 219 // this will set the map scaler to about 1000 m 220 return 10.0 2;219 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters) 220 return 10.0; 221 221 } 222 222 } -
trunk/src/org/openstreetmap/josm/data/projection/Lambert.java
r2304 r2507 1 //License: GPL. For details, see LICENSE file. 2 //Thanks to Johan Montagnat and its geoconv java converter application 3 //(http://www.i3s.unice.fr/~johan/gps/ , published under GPL license) 4 //from which some code and constants have been reused here. 1 // License: GPL. For details, see LICENSE file. 5 2 package org.openstreetmap.josm.data.projection; 6 3 7 4 import static org.openstreetmap.josm.tools.I18n.tr; 8 5 9 import javax.swing.JOptionPane; 6 import java.awt.GridBagLayout; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.util.Collection; 10 import java.util.Collections; 11 12 import javax.swing.JComboBox; 13 import javax.swing.JLabel; 14 import javax.swing.JPanel; 10 15 11 16 import org.openstreetmap.josm.Main; … … 13 18 import org.openstreetmap.josm.data.coor.EastNorth; 14 19 import org.openstreetmap.josm.data.coor.LatLon; 15 16 public class Lambert implements Projection { 20 import org.openstreetmap.josm.tools.GBC; 21 22 /** 23 * This class provides the two methods <code>latlon2eastNorth</code> and <code>eastNorth2latlon</code> 24 * converting the JOSM LatLon coordinates in WGS84 system (GPS) to and from East North values in 25 * the projection Lambert conic conform 4 zones using the French geodetic system NTF. 26 * This newer version uses the grid translation NTF<->RGF93 provided by IGN for a submillimetric accuracy. 27 * (RGF93 is the French geodetic system similar to WGS84 but not mathematically equal) 28 * @author Pieren 29 */ 30 public class Lambert implements Projection, ProjectionSubPrefs { 17 31 /** 18 32 * Lambert I, II, III, and IV projection exponents … … 49 63 * France is divided in 4 Lambert projection zones (1,2,3 + 4th for Corsica) 50 64 */ 51 public static final double cMaxLatZone1 = Math.toRadians(57 * 0.9); 52 53 public static final double zoneLimits[] = { Math.toRadians(53.5 * 0.9), // between Zone 1 and Zone 2 (in grad *0.9) 54 Math.toRadians(50.5 * 0.9), // between Zone 2 and Zone 3 55 Math.toRadians(47.51963 * 0.9), // between Zone 3 and Zone 4 56 Math.toRadians(46.17821 * 0.9) };// lowest latitude of Zone 4 57 58 public static final double cMinLonZones = Math.toRadians(-4.9074074074074059 * 0.9); 59 60 public static final double cMaxLonZones = Math.toRadians(10.2 * 0.9); 61 62 /** 63 * Because josm cannot work correctly if two zones are displayed, we allow some overlapping 64 */ 65 public static final double cMaxOverlappingZones = Math.toRadians(1.5 * 0.9); 66 67 public static int layoutZone = -1; 68 69 private static int currentZone = 0; 65 public static final double cMaxLatZone1Radian = Math.toRadians(57 * 0.9); 66 public static final double cMinLatZone1Radian = Math.toRadians(46.1 * 0.9);// lowest latitude of Zone 4 (South Corsica) 67 68 public static final double zoneLimitsDegree[][] = { 69 {Math.toDegrees(cMaxLatZone1Radian), (53.5 * 0.9)}, // Zone 1 (reference values in grad *0.9) 70 {(53.5 * 0.9), (50.5 * 0.9)}, // Zone 2 71 {(50.5 * 0.9), (47.0 * 0.9)}, // Zone 3 72 {(47.51963 * 0.9), Math.toDegrees(cMinLatZone1Radian)} // Zone 4 73 }; 74 75 public static final double cMinLonZonesRadian = Math.toRadians(-4.9074074074074059 * 0.9); 76 77 public static final double cMaxLonZonesRadian = Math.toRadians(10.2 * 0.9); 78 79 /** 80 * Allow some extension beyond the theoretical limits 81 */ 82 public static final double cMaxOverlappingZonesDegree = 1.5; 83 84 public static final int DEFAULT_ZONE = 0; 85 86 private static int layoutZone = DEFAULT_ZONE; 87 88 private static NTV2GridShiftFile ntf_rgf93Grid = null; 89 90 public static NTV2GridShiftFile getNtf_rgf93Grid() { 91 return ntf_rgf93Grid; 92 } 93 94 public Lambert() { 95 if (ntf_rgf93Grid == null) { 96 try { 97 String gridFileName = "ntf_r93_b.gsb"; 98 InputStream is = Main.class.getResourceAsStream("/data/"+gridFileName); 99 ntf_rgf93Grid = new NTV2GridShiftFile(); 100 ntf_rgf93Grid.loadGridShiftFile(is, false); 101 //System.out.println("NTF<->RGF93 grid loaded."); 102 } catch (Exception e) { 103 e.printStackTrace(); 104 } 105 } 106 } 70 107 71 108 /** 72 109 * @param p WGS84 lat/lon (ellipsoid GRS80) (in degree) 73 110 * @return eastnorth projection in Lambert Zone (ellipsoid Clark) 111 * @throws IOException 74 112 */ 75 113 public EastNorth latlon2eastNorth(LatLon p) { 76 114 // translate ellipsoid GRS80 (WGS83) => Clark 77 LatLon geo = GRS802Clark(p);78 double lt = geo.lat(); // in radian79 double lg = geo.lon();115 LatLon geo = WGS84_to_NTF(p); 116 double lt = Math.toRadians(geo.lat()); // in radian 117 double lg = Math.toRadians(geo.lon()); 80 118 81 119 // check if longitude and latitude are inside the French Lambert zones 82 currentZone = 0; 83 boolean outOfLambertZones = false; 84 if (lt >= zoneLimits[3] && lt <= cMaxLatZone1 && lg >= cMinLonZones && lg <= cMaxLonZones) { 85 // zone I 86 if (lt > zoneLimits[0]) { 87 currentZone = 0; 88 } else if (lt > zoneLimits[1]) { 89 currentZone = 1; 90 } else if (lt > zoneLimits[2]) { 91 currentZone = 2; 92 } else if (lt > zoneLimits[3]) 93 // Note: zone IV is dedicated to Corsica island and extends from 47.8 to 94 // 45.9 degrees of latitude. There is an overlap with zone III that can be 95 // solved only with longitude (covers Corsica if lon > 7.2 degree) 96 if (lg < Math.toRadians(8 * 0.9)) { 97 currentZone = 2; 98 } else { 99 currentZone = 3; 100 } 101 } else { 102 outOfLambertZones = true; // possible when MAX_LAT is used 103 } 104 if (!outOfLambertZones) { 105 if (layoutZone == -1) { 106 layoutZone = currentZone; 107 } else if (layoutZone != currentZone) { 108 if (farawayFromLambertZoneFrance(lt,lg)) { 109 JOptionPane.showMessageDialog(Main.parent, 110 tr("IMPORTANT : data positioned far away from\n" 111 + "the current Lambert zone limits.\n" 112 + "Do not upload any data after this message.\n" 113 + "Undo your last action, save your work\n" 114 + "and start a new layer on the new zone."), 115 tr("Warning"), 116 JOptionPane.WARNING_MESSAGE); 117 layoutZone = -1; 118 } else { 119 System.out.println("temporarily extend Lambert zone " + layoutZone + " projection at lat,lon:" 120 + lt + "," + lg); 121 } 122 } 123 } 124 if (layoutZone == -1) 125 return ConicProjection(lt, lg, Xs[currentZone], Ys[currentZone], c[currentZone], n[currentZone]); 126 return ConicProjection(lt, lg, Xs[layoutZone], Ys[layoutZone], c[layoutZone], n[layoutZone]); 120 if (lt >= cMinLatZone1Radian && lt <= cMaxLatZone1Radian && lg >= cMinLonZonesRadian && lg <= cMaxLonZonesRadian) 121 return ConicProjection(lt, lg, Xs[layoutZone], Ys[layoutZone], c[layoutZone], n[layoutZone]); 122 return ConicProjection(lt, lg, Xs[0], Ys[0], c[0], n[0]); 127 123 } 128 124 129 125 public LatLon eastNorth2latlon(EastNorth p) { 130 126 LatLon geo; 131 if (layoutZone == -1) { 132 // possible until the Lambert zone is determined by latlon2eastNorth() with a valid LatLon 133 geo = Geographic(p, Xs[currentZone], Ys[currentZone], c[currentZone], n[currentZone]); 134 } else { 135 geo = Geographic(p, Xs[layoutZone], Ys[layoutZone], c[layoutZone], n[layoutZone]); 136 } 137 // translate ellipsoid Clark => GRS80 (WGS83) 138 LatLon wgs = Clark2GRS80(geo); 139 return new LatLon(Math.toDegrees(wgs.lat()), Math.toDegrees(wgs.lon())); 127 geo = Geographic(p, Xs[layoutZone], Ys[layoutZone], c[layoutZone], n[layoutZone]); 128 // translate geodetic system from NTF (ellipsoid Clark) to RGF93/WGS84 (ellipsoid GRS80) 129 return NTF_to_WGS84(geo); 140 130 } 141 131 … … 145 135 146 136 public String toCode() { 147 return "EPSG:"+(27561+ currentZone);137 return "EPSG:"+(27561+layoutZone); 148 138 } 149 139 … … 182 172 * @param c projection constant 183 173 * @param n projection exponent 184 * @return LatLon in radian174 * @return LatLon in degree 185 175 */ 186 176 private LatLon Geographic(EastNorth eastNorth, double Xs, double Ys, double c, double n) { … … 201 191 lat = nlt; 202 192 } 203 return new LatLon( lat, lon); // in radian193 return new LatLon(Math.toDegrees(lat), Math.toDegrees(lon)); // in radian 204 194 } 205 195 … … 207 197 * Translate latitude/longitude in WGS84, (ellipsoid GRS80) to Lambert 208 198 * geographic, (ellipsoid Clark) 209 */ 210 private LatLon GRS802Clark(LatLon wgs) { 211 double lat = Math.toRadians(wgs.lat()); // degree to radian 212 double lon = Math.toRadians(wgs.lon()); 213 // WGS84 geographic => WGS84 cartesian 214 double N = Ellipsoid.GRS80.a / (Math.sqrt(1.0 - Ellipsoid.GRS80.e2 * Math.sin(lat) * Math.sin(lat))); 215 double X = (N/* +height */) * Math.cos(lat) * Math.cos(lon); 216 double Y = (N/* +height */) * Math.cos(lat) * Math.sin(lon); 217 double Z = (N * (1.0 - Ellipsoid.GRS80.e2)/* + height */) * Math.sin(lat); 218 // WGS84 => Lambert ellipsoide similarity 219 X += 168.0; 220 Y += 60.0; 221 Z += -320.0; 222 // Lambert cartesian => Lambert geographic 223 return Geographic(X, Y, Z, Ellipsoid.clarke); 224 } 225 226 private LatLon Clark2GRS80(LatLon lambert) { 227 double lat = lambert.lat(); // in radian 228 double lon = lambert.lon(); 229 // Lambert geographic => Lambert cartesian 230 double N = Ellipsoid.clarke.a / (Math.sqrt(1.0 - Ellipsoid.clarke.e2 * Math.sin(lat) * Math.sin(lat))); 231 double X = (N/* +height */) * Math.cos(lat) * Math.cos(lon); 232 double Y = (N/* +height */) * Math.cos(lat) * Math.sin(lon); 233 double Z = (N * (1.0 - Ellipsoid.clarke.e2)/* + height */) * Math.sin(lat); 234 // Lambert => WGS84 ellipsoide similarity 235 X += -168.0; 236 Y += -60.0; 237 Z += 320.0; 238 // WGS84 cartesian => WGS84 geographic 239 return Geographic(X, Y, Z, Ellipsoid.GRS80); 240 } 241 242 /** 243 * initializes from cartesian coordinates 244 * 245 * @param X 246 * 1st coordinate in meters 247 * @param Y 248 * 2nd coordinate in meters 249 * @param Z 250 * 3rd coordinate in meters 251 * @param ell 252 * reference ellipsoid 253 */ 254 private LatLon Geographic(double X, double Y, double Z, Ellipsoid ell) { 255 double norm = Math.sqrt(X * X + Y * Y); 256 double lg = 2.0 * Math.atan(Y / (X + norm)); 257 double lt = Math.atan(Z / (norm * (1.0 - (ell.a * ell.e2 / Math.sqrt(X * X + Y * Y + Z * Z))))); 258 double delta = 1.0; 259 while (delta > epsilon) { 260 double s2 = Math.sin(lt); 261 s2 *= s2; 262 double l = Math.atan((Z / norm) 263 / (1.0 - (ell.a * ell.e2 * Math.cos(lt) / (norm * Math.sqrt(1.0 - ell.e2 * s2))))); 264 delta = Math.abs(l - lt); 265 lt = l; 266 } 267 double s2 = Math.sin(lt); 268 s2 *= s2; 269 // h = norm / Math.cos(lt) - ell.a / Math.sqrt(1.0 - ell.e2 * s2); 270 return new LatLon(lt, lg); 271 } 272 273 private boolean farawayFromLambertZoneFrance(double lat, double lon) { 274 if (lat < (zoneLimits[3] - cMaxOverlappingZones) || (lat > (cMaxLatZone1 + cMaxOverlappingZones)) 275 || (lon < (cMinLonZones - cMaxOverlappingZones)) || (lon > (cMaxLonZones + cMaxOverlappingZones))) 276 return true; 277 return false; 199 * @throws IOException 200 */ 201 private LatLon WGS84_to_NTF(LatLon wgs) { 202 NTV2GridShift gs = new NTV2GridShift(wgs); 203 if (ntf_rgf93Grid != null) { 204 ntf_rgf93Grid.gridShiftReverse(gs); 205 return new LatLon(wgs.lat()+gs.getLatShiftDegrees(), wgs.lon()+gs.getLonShiftPositiveEastDegrees()); 206 } 207 return new LatLon(0,0); 208 } 209 210 private LatLon NTF_to_WGS84(LatLon ntf) { 211 NTV2GridShift gs = new NTV2GridShift(ntf); 212 if (ntf_rgf93Grid != null) { 213 ntf_rgf93Grid.gridShiftForward(gs); 214 return new LatLon(ntf.lat()+gs.getLatShiftDegrees(), ntf.lon()+gs.getLonShiftPositiveEastDegrees()); 215 } 216 return new LatLon(0,0); 278 217 } 279 218 280 219 public Bounds getWorldBoundsLatLon() 281 220 { 282 // These are not the Lambert Zone boundaries but we keep these values until coordinates outside the 283 // projection boundaries are handled correctly. 284 return new Bounds( 285 new LatLon(-85.05112877980659, -180.0), 286 new LatLon(85.05112877980659, 180.0)); 287 /*return new Bounds( 288 new LatLon(45.0, -4.9074074074074059), 289 new LatLon(57.0, 10.2));*/ 290 } 291 221 Bounds b= new Bounds( 222 new LatLon(zoneLimitsDegree[layoutZone][1] - cMaxOverlappingZonesDegree, -4.9074074074074059), 223 new LatLon(zoneLimitsDegree[layoutZone][0] + cMaxOverlappingZonesDegree, 10.2)); 224 return b; 225 } 226 227 /** 228 * Returns the default zoom scale in pixel per degree ({@see #NavigatableComponent#scale})) 229 */ 292 230 public double getDefaultZoomInPPD() { 293 // TODO FIXME 294 return 0; 295 } 231 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters) 232 return 10.0; 233 } 234 235 public int getLayoutZone() { 236 return layoutZone; 237 } 238 239 public static String[] lambert4zones = { 240 tr("{0} ({1} to {2} degrees)", 1,"51.30","48.15"), 241 tr("{0} ({1} to {2} degrees)", 1,"48.15","45.45"), 242 tr("{0} ({1} to {2} degrees)", 1,"45.45","42.76"), 243 tr("{0} (Corsica)", 4) 244 }; 245 246 public void setupPreferencePanel(JPanel p) { 247 JComboBox prefcb = new JComboBox(lambert4zones); 248 249 prefcb.setSelectedIndex(layoutZone); 250 p.setLayout(new GridBagLayout()); 251 p.add(new JLabel(tr("Lambert CC Zone")), GBC.std().insets(5,5,0,5)); 252 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); 253 /* Note: we use component position 2 below to find this again */ 254 p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL)); 255 p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH)); 256 } 257 258 public Collection<String> getPreferences(JPanel p) { 259 Object prefcb = p.getComponent(2); 260 if(!(prefcb instanceof JComboBox)) 261 return null; 262 layoutZone = ((JComboBox)prefcb).getSelectedIndex(); 263 return Collections.singleton(Integer.toString(layoutZone+1)); 264 } 265 266 public void setPreferences(Collection<String> args) { 267 layoutZone = DEFAULT_ZONE; 268 if (args != null) { 269 try { 270 for(String s : args) 271 { 272 layoutZone = Integer.parseInt(s)-1; 273 if(layoutZone < 0 || layoutZone > 3) { 274 layoutZone = DEFAULT_ZONE; 275 } 276 break; 277 } 278 } catch(NumberFormatException e) {} 279 } 280 } 281 282 public Collection<String> getPreferencesFromCode(String code) { 283 if (code.startsWith("EPSG:2756") && code.length() == 9) { 284 try { 285 String zonestring = code.substring(9); 286 int zoneval = Integer.parseInt(zonestring); 287 if(zoneval >= 1 && zoneval <= 4) 288 return Collections.singleton(zonestring); 289 } catch(NumberFormatException e) {} 290 } 291 return null; 292 } 293 296 294 } -
trunk/src/org/openstreetmap/josm/data/projection/LambertCC9Zones.java
r2304 r2507 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import javax.swing.JOptionPane; 7 8 import org.openstreetmap.josm.Main; 6 import java.awt.GridBagLayout; 7 import java.util.Collection; 8 import java.util.Collections; 9 10 import javax.swing.JComboBox; 11 import javax.swing.JLabel; 12 import javax.swing.JPanel; 13 9 14 import org.openstreetmap.josm.data.Bounds; 10 15 import org.openstreetmap.josm.data.coor.EastNorth; … … 12 17 import org.openstreetmap.josm.data.projection.Projection; 13 18 import org.openstreetmap.josm.data.projection.Ellipsoid; 19 import org.openstreetmap.josm.tools.GBC; 20 import org.openstreetmap.josm.tools.ImageProvider; 14 21 15 22 /** … … 19 26 * 20 27 */ 21 public class LambertCC9Zones implements Projection {28 public class LambertCC9Zones implements Projection, ProjectionSubPrefs { 22 29 23 30 /** … … 58 65 * France is divided in 9 Lambert projection zones, CC42 to CC50. 59 66 */ 60 public static final double cMaxLatZones = Math.toRadians(51.1); 61 62 public static final double cMinLatZones = Math.toRadians(41.0); 63 64 public static final double cMinLonZones = Math.toRadians(-5.0); 65 66 public static final double cMaxLonZones = Math.toRadians(10.2); 67 public static final double cMaxLatZonesRadian = Math.toRadians(51.1); 68 69 public static final double cMinLatZonesDegree = 41.0; 70 public static final double cMinLatZonesRadian = Math.toRadians(cMinLatZonesDegree); 71 72 public static final double cMinLonZonesRadian = Math.toRadians(-5.0); 73 74 public static final double cMaxLonZonesRadian = Math.toRadians(10.2); 67 75 68 76 public static final double lambda0 = Math.toRadians(3); … … 70 78 public static final double e2 =Ellipsoid.GRS80.e2; 71 79 public static final double a = Ellipsoid.GRS80.a; 72 /** 73 * Because josm cannot work correctly if two zones are displayed, we allow some overlapping74 */ 75 public static final double cMaxOverlappingZones = Math.toRadians(1.5);76 77 p ublic static int layoutZone = -1;80 81 public static final double cMaxOverlappingZones = 1.5; 82 83 public static final int DEFAULT_ZONE = 0; 84 85 private static int layoutZone = DEFAULT_ZONE; 78 86 79 87 private double L(double phi, double e) { … … 89 97 double lt = Math.toRadians(p.lat()); 90 98 double lg = Math.toRadians(p.lon()); 91 // check if longitude and latitude are inside the French Lambert zones and seek a zone number 92 // if it is not already defined in layoutZone 93 int possibleZone = 0; 94 boolean outOfLambertZones = false; 95 if (lt >= cMinLatZones && lt <= cMaxLatZones && lg >= cMinLonZones && lg <= cMaxLonZones) { 96 /* with Lambert CC9 zones, each latitude is present in two zones. If the layout 97 zone is not already set, we choose arbitrary the first possible zone */ 98 possibleZone = (int)p.lat()-42; 99 if (possibleZone > 8) { 100 possibleZone = 8; 101 } 102 if (possibleZone < 0) { 103 possibleZone = 0; 104 } 105 } else { 106 outOfLambertZones = true; // possible when MAX_LAT is used 107 } 108 if (!outOfLambertZones) { 109 if (layoutZone == -1) { 110 if (layoutZone != possibleZone) { 111 System.out.println("change Lambert zone from "+layoutZone+" to "+possibleZone); 112 } 113 layoutZone = possibleZone; 114 } else if (Math.abs(layoutZone - possibleZone) > 1) { 115 if (farawayFromLambertZoneFrance(lt, lg)) { 116 JOptionPane.showMessageDialog(Main.parent, 117 tr("IMPORTANT : data positioned far away from\n" 118 + "the current Lambert zone limits.\n" 119 + "Do not upload any data after this message.\n" 120 + "Undo your last action, save your work\n" 121 + "and start a new layer on the new zone."), 122 tr("Warning"), 123 JOptionPane.WARNING_MESSAGE); 124 layoutZone = -1; 125 } else { 126 System.out.println("temporarily extend Lambert zone " + layoutZone + " projection at lat,lon:" 127 + lt + "," + lg); 128 } 129 } 130 } 131 if (layoutZone == -1) 132 return ConicProjection(lt, lg, possibleZone); 133 return ConicProjection(lt, lg, layoutZone); 134 } 135 136 /** 137 * 99 if (lt >= cMinLatZonesRadian && lt <= cMaxLatZonesRadian && lg >= cMinLonZonesRadian && lg <= cMaxLonZonesRadian) 100 return ConicProjection(lt, lg, layoutZone); 101 return ConicProjection(lt, lg, 0); 102 } 103 104 /** 105 * 138 106 * @param lat latitude in grad 139 107 * @param lon longitude in grad … … 150 118 151 119 public LatLon eastNorth2latlon(EastNorth p) { 152 layoutZone = north2ZoneNumber(p.north());153 120 return Geographic(p, layoutZone); 154 121 } … … 174 141 } 175 142 176 public static boolean isInL9CCZones(LatLon p) {177 double lt = Math.toRadians(p.lat());178 double lg = Math.toRadians(p.lon());179 if (lg >= cMinLonZones && lg <= cMaxLonZones && lt >= cMinLatZones && lt <= cMaxLatZones)180 return true;181 return false;182 }183 184 143 public String toCode() { 185 if (layoutZone == -1) 186 return "EPSG:"+(3942); 187 return "EPSG:"+(3942+layoutZone); //CC42 is EPSG:3842 (up to EPSG:3950 for CC50) 144 return "EPSG:"+(3942+layoutZone); //CC42 is EPSG:3942 (up to EPSG:3950 for CC50) 188 145 } 189 146 … … 192 149 } 193 150 194 private boolean farawayFromLambertZoneFrance(double lat, double lon) { 195 if (lat < (cMinLatZones - cMaxOverlappingZones) || (lat > (cMaxLatZones + cMaxOverlappingZones)) 196 || (lon < (cMinLonZones - cMaxOverlappingZones)) || (lon > (cMaxLonZones + cMaxOverlappingZones))) 197 return true; 198 return false; 199 } 200 151 /** 152 * Returns the default zoom scale in pixel per degree ({@see #NavigatableComponent#scale})) 153 */ 201 154 public double getDefaultZoomInPPD() { 202 // TODO Auto-generated method stub203 return 0;155 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters) 156 return 10.0; 204 157 } 205 158 206 159 public Bounds getWorldBoundsLatLon() 207 160 { 208 // These are not the Lambert Zone boundaries but we keep these values until coordinates outside the 209 // projection boundaries are handled correctly. 161 double medLatZone = cMinLatZonesDegree + (layoutZone+1); 210 162 return new Bounds( 211 new LatLon(-85.05112877980659, -180.0), 212 new LatLon(85.05112877980659, 180.0)); 213 /*return new Bounds( 214 new LatLon(45.0, -4.9074074074074059), 215 new LatLon(57.0, 10.2));*/ 216 } 217 163 new LatLon(medLatZone - 1.0 - cMaxOverlappingZones, -4.9), 164 new LatLon(medLatZone + 1.0 + cMaxOverlappingZones, 10.2)); 165 } 166 167 public int getLayoutZone() { 168 return layoutZone; 169 } 170 171 private static String[] lambert9zones = { 172 tr("{0} ({1} to {2} degrees)", 1,41,43), 173 tr("{0} ({1} to {2} degrees)", 2,42,44), 174 tr("{0} ({1} to {2} degrees)", 3,43,45), 175 tr("{0} ({1} to {2} degrees)", 4,44,46), 176 tr("{0} ({1} to {2} degrees)", 5,45,47), 177 tr("{0} ({1} to {2} degrees)", 6,46,48), 178 tr("{0} ({1} to {2} degrees)", 7,47,49), 179 tr("{0} ({1} to {2} degrees)", 8,48,50), 180 tr("{0} ({1} to {2} degrees)", 9,49,51) 181 }; 182 183 public void setupPreferencePanel(JPanel p) { 184 JComboBox prefcb = new JComboBox(lambert9zones); 185 186 prefcb.setSelectedIndex(layoutZone); 187 p.setLayout(new GridBagLayout()); 188 p.add(new JLabel(tr("Lambert CC Zone")), GBC.std().insets(5,5,0,5)); 189 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); 190 /* Note: we use component position 2 below to find this again */ 191 p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL)); 192 p.add(new JLabel(ImageProvider.get("data/projection", "LambertCC9Zones.png")), GBC.eol().fill(GBC.HORIZONTAL)); 193 p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH)); 194 } 195 196 public Collection<String> getPreferences(JPanel p) { 197 Object prefcb = p.getComponent(2); 198 if(!(prefcb instanceof JComboBox)) 199 return null; 200 layoutZone = ((JComboBox)prefcb).getSelectedIndex(); 201 if (layoutZone == 0) { 202 layoutZone = layoutZone +1 -1; 203 } 204 return Collections.singleton(Integer.toString(layoutZone+1)); 205 } 206 207 public void setPreferences(Collection<String> args) 208 { 209 layoutZone = DEFAULT_ZONE; 210 if (args != null) { 211 try { 212 for(String s : args) 213 { 214 layoutZone = Integer.parseInt(s)-1; 215 if(layoutZone < 0 || layoutZone > 8) { 216 layoutZone = DEFAULT_ZONE; 217 } 218 break; 219 } 220 } catch(NumberFormatException e) {} 221 } 222 if (layoutZone == 0) { 223 layoutZone = layoutZone +1 -1; 224 } 225 } 226 227 public Collection<String> getPreferencesFromCode(String code) 228 { 229 //zone 1=CC42=EPSG:3942 up to zone 9=CC50=EPSG:3950 230 if (code.startsWith("EPSG:39") && code.length() == 9) { 231 try { 232 String zonestring = code.substring(5,4); 233 int zoneval = Integer.parseInt(zonestring)-3942; 234 if(zoneval >= 0 && zoneval <= 8) 235 return Collections.singleton(zonestring); 236 } catch(NumberFormatException e) {} 237 } 238 return null; 239 } 218 240 } 219 -
trunk/src/org/openstreetmap/josm/data/projection/Projection.java
r2304 r2507 28 28 new SwissGrid(), 29 29 new UTM(), 30 new UTM_20N_Guadeloupe_Ste_Anne(), 31 new UTM_20N_Guadeloupe_Fort_Marigot(), 32 new UTM_20N_Martinique_Fort_Desaix(), 30 new UTM_20N_France_DOM(), 33 31 new GaussLaborde_Reunion(), 34 32 new LambertCC9Zones() // Still needs proper default zoom -
trunk/src/org/openstreetmap/josm/data/projection/ProjectionSubPrefs.java
r2499 r2507 10 10 * Generates the GUI for the given preference and packs them in a JPanel 11 11 * so they may be displayed if the projection is selected. 12 *13 * Implementation hints:14 * <ul>15 * <li>Do not return <code>null</code> as it is assumed that if this16 * interface is implemented the projection actually has prefs to17 * display/save.</li>18 * <li>Cache the JPanel in a local variable so that changes are19 * persistent even if the user chooses another projection in between.20 * Destroy the panel on destroyCachedPanel() so that the pre-selected21 * settings may update the preferences are updated from the outside</li>22 * </li>23 * @return24 12 */ 25 13 public void setupPreferencePanel(JPanel p); -
trunk/src/org/openstreetmap/josm/data/projection/UTM_20N_France_DOM.java
r1929 r2507 3 3 4 4 /** 5 * This class is not a direct implementation of Projection. It collects all methods used 6 * for the projection of the French departements in the Caribbean Sea UTM zone 20N 7 * but using each time different local geodesic settings for the 7 parameters transformation algorithm. 5 * This class implements all projections for French departements in the Caribbean Sea using 6 * UTM zone 20N transvers Mercator and specific geodesic settings (7 parameters transformation algorithm). 8 7 */ 8 import static org.openstreetmap.josm.tools.I18n.tr; 9 10 import java.awt.GridBagLayout; 11 import java.util.Collection; 12 import java.util.Collections; 13 14 import javax.swing.JComboBox; 15 import javax.swing.JLabel; 16 import javax.swing.JPanel; 17 18 import org.openstreetmap.josm.data.Bounds; 9 19 import org.openstreetmap.josm.data.coor.EastNorth; 10 20 import org.openstreetmap.josm.data.coor.LatLon; 11 12 public class UTM_20N_France_DOM { 21 import org.openstreetmap.josm.tools.GBC; 22 23 public class UTM_20N_France_DOM implements Projection, ProjectionSubPrefs { 24 25 private static String FortMarigotName = tr("Guadeloupe Fort-Marigot 1949"); 26 private static String SainteAnneName = tr("Guadeloupe Ste-Anne 1948"); 27 private static String MartiniqueName = tr("Martinique Fort Desaix 1952"); 28 public static String[] utmGeodesicsNames = { FortMarigotName, SainteAnneName, MartiniqueName}; 29 30 private Bounds FortMarigotBounds = new Bounds( new LatLon(17.6,-63.25), new LatLon(18.5,-62.5)); 31 private Bounds SainteAnneBounds = new Bounds( new LatLon(15.8,-61.9), new LatLon(16.6,-60.9)); 32 private Bounds MartiniqueBounds = new Bounds( new LatLon(14.25,-61.25), new LatLon(15.025,-60.725)); 33 private Bounds[] utmBounds = { FortMarigotBounds, SainteAnneBounds, MartiniqueBounds}; 34 35 private String FortMarigotEPSG = "EPSG::2969"; 36 private String SainteAnneEPSG = "EPSG::2970"; 37 private String MartiniqueEPSG = "EPSG::2973"; 38 private String[] utmEPSGs = { FortMarigotEPSG, SainteAnneEPSG, MartiniqueEPSG}; 13 39 14 40 /** … … 28 54 * UTM zone (from 1 to 60) 29 55 */ 30 int zone= 20;56 private static int ZONE = 20; 31 57 /** 32 58 * whether north or south hemisphere 33 59 */ 34 60 private boolean isNorth = true; 61 62 public static final int DEFAULT_GEODESIC = 0; 63 64 private static int currentGeodesic = DEFAULT_GEODESIC; 65 35 66 /** 36 67 * 7 parameters transformation 37 68 */ 38 double tx = 0.0;39 double ty = 0.0;40 double tz = 0.0;41 double rx = 0;42 double ry = 0;43 double rz = 0;44 double scaleDiff = 0;69 private static double tx = 0.0; 70 private static double ty = 0.0; 71 private static double tz = 0.0; 72 private static double rx = 0; 73 private static double ry = 0; 74 private static double rz = 0; 75 private static double scaleDiff = 0; 45 76 /** 46 77 * precision in iterative schema … … 50 81 public final static double RAD_TO_DEG = 180 / Math.PI; 51 82 52 public UTM_20N_France_DOM(double[] translation, double[] rotation, double scaleDiff) { 53 this.tx = translation[0]; 54 this.ty = translation[1]; 55 this.tz = translation[2]; 56 this.rx = rotation[0]/206264.806247096355; // seconds to radian 57 this.ry = rotation[1]/206264.806247096355; 58 this.rz = rotation[2]/206264.806247096355; 59 this.scaleDiff = scaleDiff; 60 } 83 private void refresh7ParametersTranslation() { 84 //System.out.println("Current UTM geodesic system: " + utmGeodesicsNames[currentGeodesic]); 85 if (currentGeodesic == 0) { // UTM_20N_Guadeloupe_Fort_Marigot 86 set7ParametersTranslation(new double[]{136.596, 248.148, -429.789}, 87 new double[]{0, 0, 0}, 88 0); 89 } else if (currentGeodesic == 1) { // UTM_20N_Guadeloupe_Ste_Anne 90 set7ParametersTranslation(new double[]{-472.29, -5.63, -304.12}, 91 new double[]{0.4362, -0.8374, 0.2563}, 92 1.8984E-6); 93 } else { // UTM_20N_Martinique_Fort_Desaix 94 set7ParametersTranslation(new double[]{126.926, 547.939, 130.409}, 95 new double[]{-2.78670, 5.16124, -0.85844}, 96 13.82265E-6); 97 } 98 } 99 100 private void set7ParametersTranslation(double[] translation, double[] rotation, double scalediff) { 101 tx = translation[0]; 102 ty = translation[1]; 103 tz = translation[2]; 104 rx = rotation[0]/206264.806247096355; // seconds to radian 105 ry = rotation[1]/206264.806247096355; 106 rz = rotation[2]/206264.806247096355; 107 scaleDiff = scalediff; 108 } 109 61 110 public EastNorth latlon2eastNorth(LatLon p) { 62 111 // translate ellipsoid GRS80 (WGS83) => reference ellipsoid geographic … … 128 177 double r6d = Math.PI / 30.0; 129 178 //zone = (int) Math.floor((coord.lon() + Math.PI) / r6d) + 1; 130 lg0 = r6d * ( zone- 0.5) - Math.PI;179 lg0 = r6d * (ZONE - 0.5) - Math.PI; 131 180 double e2 = e * e; 132 181 double e4 = e2 * e2; … … 169 218 170 219 public LatLon eastNorth2latlon(EastNorth p) { 171 MTProjection(p.east(), p.north(), zone, isNorth);220 MTProjection(p.east(), p.north(), ZONE, isNorth); 172 221 LatLon geo = Geographic(p, Ellipsoid.hayford.a, Ellipsoid.hayford.e, 0.0 /* z */); 173 222 174 223 // reference ellipsoid geographic => reference ellipsoid cartesian 175 //Hayford2GRS80(ellipsoid, geo);176 224 double N = Ellipsoid.hayford.a / (Math.sqrt(1.0 - Ellipsoid.hayford.e2 * Math.sin(geo.lat()) * Math.sin(geo.lat()))); 177 225 double X = (N /*+ h*/) * Math.cos(geo.lat()) * Math.cos(geo.lon()); … … 310 358 } 311 359 360 public String getCacheDirectoryName() { 361 return this.toString(); 362 } 363 364 /** 365 * Returns the default zoom scale in pixel per degree ({@see #NavigatableComponent#scale})) 366 */ 367 public double getDefaultZoomInPPD() { 368 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters) 369 return 10.0; 370 } 371 372 public Bounds getWorldBoundsLatLon() { 373 return utmBounds[currentGeodesic]; 374 } 375 376 public String toCode() { 377 return utmEPSGs[currentGeodesic]; 378 } 379 380 @Override public String toString() { 381 return (tr("UTM 20N (France)")); 382 } 383 384 public int getCurrentGeodesic() { 385 return currentGeodesic; 386 } 387 388 public void setupPreferencePanel(JPanel p) { 389 JComboBox prefcb = new JComboBox(utmGeodesicsNames); 390 391 prefcb.setSelectedIndex(currentGeodesic); 392 p.setLayout(new GridBagLayout()); 393 p.add(new JLabel(tr("UTM20 North Geodesic system")), GBC.std().insets(5,5,0,5)); 394 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); 395 p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL)); 396 p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH)); 397 } 398 399 public Collection<String> getPreferences(JPanel p) { 400 Object prefcb = p.getComponent(2); 401 if(!(prefcb instanceof JComboBox)) 402 return null; 403 currentGeodesic = ((JComboBox)prefcb).getSelectedIndex(); 404 refresh7ParametersTranslation(); 405 return Collections.singleton(Integer.toString(currentGeodesic+1)); 406 } 407 408 public Collection<String> getPreferencesFromCode(String code) { 409 for (int i=0; i < utmEPSGs.length; i++ ) 410 if (utmEPSGs[i].endsWith(code)) 411 return Collections.singleton(Integer.toString(i)); 412 return null; 413 } 414 415 public void setPreferences(Collection<String> args) { 416 currentGeodesic = DEFAULT_GEODESIC; 417 if (args != null) { 418 try { 419 for(String s : args) 420 { 421 currentGeodesic = Integer.parseInt(s)-1; 422 if(currentGeodesic < 0 || currentGeodesic > 2) { 423 currentGeodesic = DEFAULT_GEODESIC; 424 } 425 break; 426 } 427 } catch(NumberFormatException e) {} 428 } 429 refresh7ParametersTranslation(); 430 } 431 312 432 }
Note:
See TracChangeset
for help on using the changeset viewer.