source: josm/trunk/src/org/openstreetmap/josm/data/projection/LambertCC9Zones.java@ 2512

Last change on this file since 2512 was 2509, checked in by stoecker, 14 years ago

fixed NPE - closes #3989

File size: 8.3 KB
Line 
1//License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.projection;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.util.Collection;
8import java.util.Collections;
9
10import javax.swing.JComboBox;
11import javax.swing.JLabel;
12import javax.swing.JPanel;
13
14import org.openstreetmap.josm.data.Bounds;
15import org.openstreetmap.josm.data.coor.EastNorth;
16import org.openstreetmap.josm.data.coor.LatLon;
17import org.openstreetmap.josm.data.projection.Projection;
18import org.openstreetmap.josm.data.projection.Ellipsoid;
19import org.openstreetmap.josm.tools.GBC;
20import org.openstreetmap.josm.tools.ImageProvider;
21
22/**
23 * This class implements the Lambert Conic Conform 9 Zones projection as specified by the IGN
24 * in this document http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
25 * @author Pieren
26 *
27 */
28public class LambertCC9Zones implements Projection, ProjectionSubPrefs {
29
30 /**
31 * Lambert 9 zones projection exponents
32 */
33 public static final double n[] = { 0.6691500006885269, 0.682018118346418, 0.6946784863203991, 0.7071272481559119,
34 0.7193606118567315, 0.7313748510399917, 0.7431663060711892, 0.7547313851789208, 0.7660665655489937};
35
36 /**
37 * Lambert 9 zones projection constants
38 */
39 public static final double c[] = { 1.215363305807804E7, 1.2050261119223533E7, 1.195716926884592E7, 1.18737533925172E7,
40 1.1799460698022118E7, 1.17337838820243E7, 1.16762559948139E7, 1.1626445901183508E7, 1.1583954251630554E7};
41
42 /**
43 * Lambert 9 zones false east
44 */
45 public static final double Xs = 1700000;
46
47 /**
48 * Lambert 9 zones false north
49 */
50 public static final double Ys[] = { 8293467.503439436, 9049604.665107645, 9814691.693461388, 1.0588107871787189E7,
51 1.1369285637569271E7, 1.2157704903382052E7, 1.2952888086405803E7, 1.3754395745267643E7, 1.4561822739114787E7};
52
53 /**
54 * Lambert I, II, III, and IV longitudinal offset to Greenwich meridian
55 */
56 public static final double lg0 = 0.04079234433198; // 2deg20'14.025"
57
58 /**
59 * precision in iterative schema
60 */
61
62 public static final double epsilon = 1e-12;
63
64 /**
65 * France is divided in 9 Lambert projection zones, CC42 to CC50.
66 */
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);
75
76 public static final double lambda0 = Math.toRadians(3);
77 public static final double e = Ellipsoid.GRS80.e; // but in doc=0.08181919112
78 public static final double e2 =Ellipsoid.GRS80.e2;
79 public static final double a = Ellipsoid.GRS80.a;
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;
86
87 private double L(double phi, double e) {
88 double sinphi = Math.sin(phi);
89 return (0.5*Math.log((1+sinphi)/(1-sinphi))) - e/2*Math.log((1+e*sinphi)/(1-e*sinphi));
90 }
91
92 /**
93 * @param p WGS84 lat/lon (ellipsoid GRS80) (in degree)
94 * @return eastnorth projection in Lambert Zone (ellipsoid Clark)
95 */
96 public EastNorth latlon2eastNorth(LatLon p) {
97 double lt = Math.toRadians(p.lat());
98 double lg = Math.toRadians(p.lon());
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 *
106 * @param lat latitude in grad
107 * @param lon longitude in grad
108 * @param nz Lambert CC zone number (from 1 to 9) - 1 !
109 * @return EastNorth projected coordinates in meter
110 */
111 private EastNorth ConicProjection(double lat, double lon, int nz) {
112 double R = c[nz]*Math.exp(-n[nz]*L(lat,e));
113 double gamma = n[nz]*(lon-lambda0);
114 double X = Xs + R*Math.sin(gamma);
115 double Y = Ys[nz] + -R*Math.cos(gamma);
116 return new EastNorth(X, Y);
117 }
118
119 public LatLon eastNorth2latlon(EastNorth p) {
120 return Geographic(p, layoutZone);
121 }
122
123 private LatLon Geographic(EastNorth ea, int nz) {
124 double R = Math.sqrt(Math.pow(ea.getX()-Xs,2)+Math.pow(ea.getY()-Ys[nz], 2));
125 double gamma = Math.atan((ea.getX()-Xs)/(Ys[nz]-ea.getY()));
126 double lon = lambda0+gamma/n[nz];
127 double latIso = (-1/n[nz])*Math.log(Math.abs(R/c[nz]));
128 double lat = Ellipsoid.GRS80.latitude(latIso, e, epsilon);
129 return new LatLon(Math.toDegrees(lat), Math.toDegrees(lon));
130 }
131
132 @Override public String toString() {
133 return tr("Lambert CC9 Zone (France)");
134 }
135
136 public static int north2ZoneNumber(double north) {
137 int nz = (int)(north /1000000) - 1;
138 if (nz < 0) return 0;
139 else if (nz > 8) return 8;
140 else return nz;
141 }
142
143 public String toCode() {
144 return "EPSG:"+(3942+layoutZone); //CC42 is EPSG:3942 (up to EPSG:3950 for CC50)
145 }
146
147 public String getCacheDirectoryName() {
148 return "lambert";
149 }
150
151 /**
152 * Returns the default zoom scale in pixel per degree ({@see #NavigatableComponent#scale}))
153 */
154 public double getDefaultZoomInPPD() {
155 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters)
156 return 10.0;
157 }
158
159 public Bounds getWorldBoundsLatLon()
160 {
161 double medLatZone = cMinLatZonesDegree + (layoutZone+1);
162 return new Bounds(
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 return Collections.singleton(Integer.toString(layoutZone+1));
202 }
203
204 public void setPreferences(Collection<String> args)
205 {
206 layoutZone = DEFAULT_ZONE;
207 if (args != null) {
208 try {
209 for(String s : args)
210 {
211 layoutZone = Integer.parseInt(s)-1;
212 if(layoutZone < 0 || layoutZone > 8) {
213 layoutZone = DEFAULT_ZONE;
214 }
215 break;
216 }
217 } catch(NumberFormatException e) {}
218 }
219 }
220
221 public Collection<String> getPreferencesFromCode(String code)
222 {
223 //zone 1=CC42=EPSG:3942 up to zone 9=CC50=EPSG:3950
224 if (code.startsWith("EPSG:39") && code.length() == 9) {
225 try {
226 String zonestring = code.substring(5,4);
227 int zoneval = Integer.parseInt(zonestring)-3942;
228 if(zoneval >= 0 && zoneval <= 8)
229 return Collections.singleton(zonestring);
230 } catch(NumberFormatException e) {}
231 }
232 return null;
233 }
234}
Note: See TracBrowser for help on using the repository browser.