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

Last change on this file since 4275 was 4225, checked in by stoecker, 13 years ago

fix the error of last checkin

  • Property svn:eol-style set to native
File size: 8.8 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.awt.event.ActionListener;
8import java.util.Collection;
9import java.util.Collections;
10
11import javax.swing.JComboBox;
12import javax.swing.JLabel;
13import javax.swing.JPanel;
14
15import org.openstreetmap.josm.data.Bounds;
16import org.openstreetmap.josm.data.coor.EastNorth;
17import org.openstreetmap.josm.data.coor.LatLon;
18import org.openstreetmap.josm.tools.GBC;
19import org.openstreetmap.josm.tools.ImageProvider;
20
21/**
22 * This class implements the Lambert Conic Conform 9 Zones projection as specified by the IGN
23 * in this document http://professionnels.ign.fr/DISPLAY/000/526/700/5267002/transformation.pdf
24 * @author Pieren
25 *
26 */
27public class LambertCC9Zones implements Projection, ProjectionSubPrefs {
28
29 /**
30 * Lambert 9 zones projection exponents
31 */
32 public static final double n[] = { 0.6691500006885269, 0.682018118346418, 0.6946784863203991, 0.7071272481559119,
33 0.7193606118567315, 0.7313748510399917, 0.7431663060711892, 0.7547313851789208, 0.7660665655489937};
34
35 /**
36 * Lambert 9 zones projection constants
37 */
38 public static final double c[] = { 1.215363305807804E7, 1.2050261119223533E7, 1.195716926884592E7, 1.18737533925172E7,
39 1.1799460698022118E7, 1.17337838820243E7, 1.16762559948139E7, 1.1626445901183508E7, 1.1583954251630554E7};
40
41 /**
42 * Lambert 9 zones false east
43 */
44 public static final double Xs = 1700000;
45
46 /**
47 * Lambert 9 zones false north
48 */
49 public static final double Ys[] = { 8293467.503439436, 9049604.665107645, 9814691.693461388, 1.0588107871787189E7,
50 1.1369285637569271E7, 1.2157704903382052E7, 1.2952888086405803E7, 1.3754395745267643E7, 1.4561822739114787E7};
51
52 /**
53 * Lambert I, II, III, and IV longitudinal offset to Greenwich meridian
54 */
55 public static final double lg0 = 0.04079234433198; // 2deg20'14.025"
56
57 /**
58 * precision in iterative schema
59 */
60
61 public static final double epsilon = 1e-12;
62
63 /**
64 * France is divided in 9 Lambert projection zones, CC42 to CC50.
65 */
66 public static final double cMaxLatZonesRadian = Math.toRadians(51.1);
67
68 public static final double cMinLatZonesDegree = 41.0;
69 public static final double cMinLatZonesRadian = Math.toRadians(cMinLatZonesDegree);
70
71 public static final double cMinLonZonesRadian = Math.toRadians(-5.0);
72
73 public static final double cMaxLonZonesRadian = Math.toRadians(10.2);
74
75 public static final double lambda0 = Math.toRadians(3);
76 public static final double e = Ellipsoid.GRS80.e; // but in doc=0.08181919112
77 public static final double e2 =Ellipsoid.GRS80.e2;
78 public static final double a = Ellipsoid.GRS80.a;
79
80 public static final double cMaxOverlappingZones = 1.5;
81
82 public static final int DEFAULT_ZONE = 0;
83
84 private static int layoutZone = DEFAULT_ZONE;
85
86 private double L(double phi, double e) {
87 double sinphi = Math.sin(phi);
88 return (0.5*Math.log((1+sinphi)/(1-sinphi))) - e/2*Math.log((1+e*sinphi)/(1-e*sinphi));
89 }
90
91 /**
92 * @param p WGS84 lat/lon (ellipsoid GRS80) (in degree)
93 * @return eastnorth projection in Lambert Zone (ellipsoid Clark)
94 */
95 public EastNorth latlon2eastNorth(LatLon p) {
96 double lt = Math.toRadians(p.lat());
97 double lg = Math.toRadians(p.lon());
98 if (lt >= cMinLatZonesRadian && lt <= cMaxLatZonesRadian && lg >= cMinLonZonesRadian && lg <= cMaxLonZonesRadian)
99 return ConicProjection(lt, lg, layoutZone);
100 return ConicProjection(lt, lg, 0);
101 }
102
103 /**
104 *
105 * @param lat latitude in grad
106 * @param lon longitude in grad
107 * @param nz Lambert CC zone number (from 1 to 9) - 1 !
108 * @return EastNorth projected coordinates in meter
109 */
110 private EastNorth ConicProjection(double lat, double lon, int nz) {
111 double R = c[nz]*Math.exp(-n[nz]*L(lat,e));
112 double gamma = n[nz]*(lon-lambda0);
113 double X = Xs + R*Math.sin(gamma);
114 double Y = Ys[nz] + -R*Math.cos(gamma);
115 return new EastNorth(X, Y);
116 }
117
118 public LatLon eastNorth2latlon(EastNorth p) {
119 return Geographic(p, layoutZone);
120 }
121
122 private LatLon Geographic(EastNorth ea, int nz) {
123 double R = Math.sqrt(Math.pow(ea.getX()-Xs,2)+Math.pow(ea.getY()-Ys[nz], 2));
124 double gamma = Math.atan((ea.getX()-Xs)/(Ys[nz]-ea.getY()));
125 double lon = lambda0+gamma/n[nz];
126 double latIso = (-1/n[nz])*Math.log(Math.abs(R/c[nz]));
127 double lat = Ellipsoid.GRS80.latitude(latIso, e, epsilon);
128 return new LatLon(Math.toDegrees(lat), Math.toDegrees(lon));
129 }
130
131 @Override public String toString() {
132 return tr("Lambert CC9 Zone (France)");
133 }
134
135 public static int north2ZoneNumber(double north) {
136 int nz = (int)(north /1000000) - 1;
137 if (nz < 0) return 0;
138 else if (nz > 8) return 8;
139 else return nz;
140 }
141
142 public String toCode() {
143 return "EPSG:"+(3942+layoutZone); //CC42 is EPSG:3942 (up to EPSG:3950 for CC50)
144 }
145
146 @Override
147 public int hashCode() {
148 return getClass().getName().hashCode()+layoutZone; // our only real variable
149 }
150
151 public String getCacheDirectoryName() {
152 return "lambert";
153 }
154
155 /**
156 * Returns the default zoom scale in pixel per degree ({@see #NavigatableComponent#scale}))
157 */
158 public double getDefaultZoomInPPD() {
159 // this will set the map scaler to about 1000 m (in default scale, 1 pixel will be 10 meters)
160 return 10.0;
161 }
162
163 public Bounds getWorldBoundsLatLon()
164 {
165 double medLatZone = cMinLatZonesDegree + (layoutZone+1);
166 return new Bounds(
167 new LatLon(Math.max(medLatZone - 1.0 - cMaxOverlappingZones, cMinLatZonesDegree), -4.9),
168 new LatLon(Math.min(medLatZone + 1.0 + cMaxOverlappingZones, Math.toDegrees(cMaxLatZonesRadian)), 10.2));
169 }
170
171 public int getLayoutZone() {
172 return layoutZone;
173 }
174
175 private static String[] lambert9zones = {
176 tr("{0} ({1} to {2} degrees)", 1,41,43),
177 tr("{0} ({1} to {2} degrees)", 2,42,44),
178 tr("{0} ({1} to {2} degrees)", 3,43,45),
179 tr("{0} ({1} to {2} degrees)", 4,44,46),
180 tr("{0} ({1} to {2} degrees)", 5,45,47),
181 tr("{0} ({1} to {2} degrees)", 6,46,48),
182 tr("{0} ({1} to {2} degrees)", 7,47,49),
183 tr("{0} ({1} to {2} degrees)", 8,48,50),
184 tr("{0} ({1} to {2} degrees)", 9,49,51)
185 };
186
187 @Override
188 public void setupPreferencePanel(JPanel p, ActionListener listener) {
189 JComboBox prefcb = new JComboBox(lambert9zones);
190
191 prefcb.setSelectedIndex(layoutZone);
192 p.setLayout(new GridBagLayout());
193 p.add(new JLabel(tr("Lambert CC Zone")), GBC.std().insets(5,5,0,5));
194 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
195 /* Note: we use component position 2 below to find this again */
196 p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL));
197 p.add(new JLabel(ImageProvider.get("data/projection", "LambertCC9Zones.png")), GBC.eol().fill(GBC.HORIZONTAL));
198 p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
199
200 if (listener != null) {
201 prefcb.addActionListener(listener);
202 }
203 }
204
205 public Collection<String> getPreferences(JPanel p) {
206 Object prefcb = p.getComponent(2);
207 if(!(prefcb instanceof JComboBox))
208 return null;
209 layoutZone = ((JComboBox)prefcb).getSelectedIndex();
210 return Collections.singleton(Integer.toString(layoutZone+1));
211 }
212
213 public void setPreferences(Collection<String> args)
214 {
215 layoutZone = DEFAULT_ZONE;
216 if (args != null) {
217 try {
218 for(String s : args)
219 {
220 layoutZone = Integer.parseInt(s)-1;
221 if(layoutZone < 0 || layoutZone > 8) {
222 layoutZone = DEFAULT_ZONE;
223 }
224 break;
225 }
226 } catch(NumberFormatException e) {}
227 }
228 }
229
230 @Override
231 public String[] allCodes() {
232 String[] zones = new String[9];
233 for (int zone = 0; zone < 9; zone++) {
234 zones[zone] = "EPSG:" + (3942 + zone);
235 }
236 return zones;
237 }
238
239 public Collection<String> getPreferencesFromCode(String code)
240 {
241 //zone 1=CC42=EPSG:3942 up to zone 9=CC50=EPSG:3950
242 if (code.startsWith("EPSG:39") && code.length() == 9) {
243 try {
244 String zonestring = code.substring(5,9);
245 int zoneval = Integer.parseInt(zonestring)-3942;
246 if(zoneval >= 0 && zoneval <= 8)
247 return Collections.singleton(String.valueOf(zoneval+1));
248 } catch(NumberFormatException e) {}
249 }
250 return null;
251 }
252}
Note: See TracBrowser for help on using the repository browser.