source: josm/trunk/src/org/openstreetmap/josm/data/projection/Lambert.java@ 5067

Last change on this file since 5067 was 5067, checked in by bastiK, 12 years ago

extend options for ellipsoid, use formal definition instead of computed values

  • Property svn:eol-style set to native
File size: 7.9 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.io.InputStream;
9import java.util.Collection;
10import java.util.Collections;
11
12import javax.swing.JComboBox;
13import javax.swing.JLabel;
14import javax.swing.JPanel;
15
16import org.openstreetmap.josm.Main;
17import org.openstreetmap.josm.data.Bounds;
18import org.openstreetmap.josm.data.coor.LatLon;
19import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
20import org.openstreetmap.josm.data.projection.proj.ProjParameters;
21import org.openstreetmap.josm.tools.GBC;
22import org.openstreetmap.josm.tools.ImageProvider;
23
24/**
25 * 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 */
30public class Lambert extends AbstractProjection implements ProjectionSubPrefs {
31 /**
32 * Lambert I, II, III, and IV projection exponents
33 */
34 private static final double n[] = { 0.7604059656, 0.7289686274, 0.6959127966, 0.6712679322 };
35
36 /**
37 * Lambert I, II, III, and IV projection constants
38 */
39 private static final double c[] = { 11603796.98, 11745793.39, 11947992.52, 12136281.99 };
40
41 /**
42 * Lambert I, II, III, and IV false east
43 */
44 private static final double x_0s[] = { 600000.0, 600000.0, 600000.0, 234.358 };
45
46 /**
47 * Lambert I, II, III, and IV false north
48 */
49 private static final double y_fs[] = { 5657616.674, 6199695.768, 6791905.085, 7239161.542 };
50
51 /**
52 * France is divided in 4 Lambert projection zones (1,2,3 + 4th for Corsica)
53 */
54 public static final double cMaxLatZone1Radian = Math.toRadians(57 * 0.9);
55 public static final double cMinLatZone1Radian = Math.toRadians(46.1 * 0.9);// lowest latitude of Zone 4 (South Corsica)
56
57 public static final double[][] zoneLimitsDegree = {
58 {Math.toDegrees(cMaxLatZone1Radian), (53.5 * 0.9)}, // Zone 1 (reference values in grad *0.9)
59 {(53.5 * 0.9), (50.5 * 0.9)}, // Zone 2
60 {(50.5 * 0.9), (47.0 * 0.9)}, // Zone 3
61 {(47.51963 * 0.9), Math.toDegrees(cMinLatZone1Radian)} // Zone 4
62 };
63
64 public static final double cMinLonZonesRadian = Math.toRadians(-4.9074074074074059 * 0.9);
65
66 public static final double cMaxLonZonesRadian = Math.toRadians(10.2 * 0.9);
67
68 /**
69 * Allow some extension beyond the theoretical limits
70 */
71 public static final double cMaxOverlappingZonesDegree = 1.5;
72
73 public static final int DEFAULT_ZONE = 0;
74
75 private int layoutZone;
76
77 private static NTV2GridShiftFile ntf_rgf93Grid = null;
78
79 public static NTV2GridShiftFile getNtf_rgf93Grid() {
80 return ntf_rgf93Grid;
81 }
82
83 public Lambert() {
84 if (ntf_rgf93Grid == null) {
85 try {
86 String gridFileName = "ntf_r93_b.gsb";
87 InputStream is = Main.class.getResourceAsStream("/data/"+gridFileName);
88 if (is == null) {
89 throw new RuntimeException(tr("Error: failed to open input stream for resource ''/data/{0}''. Cannot load NTF<->RGF93 grid", gridFileName));
90 }
91 ntf_rgf93Grid = new NTV2GridShiftFile();
92 ntf_rgf93Grid.loadGridShiftFile(is, false);
93 } catch (Exception e) {
94 throw new RuntimeException(e);
95 }
96 }
97 updateParameters(DEFAULT_ZONE);
98 }
99
100 private void updateParameters(final int layoutZone) {
101 this.layoutZone = layoutZone;
102 ellps = Ellipsoid.clarkeIGN;
103 datum = null; // no datum needed, we have a shift file
104 nadgrids = ntf_rgf93Grid;
105 x_0 = x_0s[layoutZone];
106 lon_0 = 2.0 + 20.0 / 60 + 14.025 / 3600; // 0 grade Paris
107 if (proj == null) {
108 proj = new LambertConformalConic();
109 }
110 proj = new LambertConformalConic();
111 try {
112 proj.initialize(new ProjParameters() {{
113 ellps = Lambert.this.ellps;
114 lcc_n = n[layoutZone];
115 lcc_F = c[layoutZone] / ellps.a;
116 lcc_r0 = y_fs[layoutZone] / ellps.a;
117 }});
118 } catch (ProjectionConfigurationException e) {
119 throw new RuntimeException(e);
120 }
121 }
122
123 @Override
124 public String toString() {
125 return tr("Lambert 4 Zones (France)");
126 }
127
128 @Override
129 public Integer getEpsgCode() {
130 return 27561+layoutZone;
131 }
132
133 @Override
134 public int hashCode() {
135 return getClass().getName().hashCode()+layoutZone; // our only real variable
136 }
137
138 @Override
139 public String getCacheDirectoryName() {
140 return "lambert";
141 }
142
143 @Override
144 public Bounds getWorldBoundsLatLon()
145 {
146 Bounds b= new Bounds(
147 new LatLon(Math.max(zoneLimitsDegree[layoutZone][1] - cMaxOverlappingZonesDegree, Math.toDegrees(cMinLatZone1Radian)), Math.toDegrees(cMinLonZonesRadian)),
148 new LatLon(Math.min(zoneLimitsDegree[layoutZone][0] + cMaxOverlappingZonesDegree, Math.toDegrees(cMaxLatZone1Radian)), Math.toDegrees(cMaxLonZonesRadian)));
149 return b;
150 }
151
152 public int getLayoutZone() {
153 return layoutZone;
154 }
155
156 public static String[] lambert4zones = {
157 tr("{0} ({1} to {2} degrees)", 1,"51.30","48.15"),
158 tr("{0} ({1} to {2} degrees)", 2,"48.15","45.45"),
159 tr("{0} ({1} to {2} degrees)", 3,"45.45","42.76"),
160 tr("{0} (Corsica)", 4)
161 };
162
163 @Override
164 public void setupPreferencePanel(JPanel p, ActionListener listener) {
165 JComboBox prefcb = new JComboBox(lambert4zones);
166
167 prefcb.setSelectedIndex(layoutZone);
168 p.setLayout(new GridBagLayout());
169 p.add(new JLabel(tr("Lambert CC Zone")), GBC.std().insets(5,5,0,5));
170 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
171 /* Note: we use component position 2 below to find this again */
172 p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL));
173 p.add(new JLabel(ImageProvider.get("data/projection", "Departements_Lambert4Zones.png")), GBC.eol().fill(GBC.HORIZONTAL));
174 p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
175
176 if (listener != null) {
177 prefcb.addActionListener(listener);
178 }
179 }
180
181 @Override
182 public Collection<String> getPreferences(JPanel p) {
183 Object prefcb = p.getComponent(2);
184 if(!(prefcb instanceof JComboBox))
185 return null;
186 layoutZone = ((JComboBox)prefcb).getSelectedIndex();
187 return Collections.singleton(Integer.toString(layoutZone+1));
188 }
189
190 @Override
191 public void setPreferences(Collection<String> args) {
192 int layoutZone = DEFAULT_ZONE;
193 if (args != null) {
194 try {
195 for(String s : args)
196 {
197 layoutZone = Integer.parseInt(s)-1;
198 if(layoutZone < 0 || layoutZone > 3) {
199 layoutZone = DEFAULT_ZONE;
200 }
201 break;
202 }
203 } catch(NumberFormatException e) {}
204 }
205 updateParameters(layoutZone);
206 }
207
208 @Override
209 public String[] allCodes() {
210 String[] zones = new String[4];
211 for (int zone = 0; zone < 4; zone++) {
212 zones[zone] = "EPSG:"+(27561+zone);
213 }
214 return zones;
215 }
216
217 @Override
218 public Collection<String> getPreferencesFromCode(String code) {
219 if (code.startsWith("EPSG:2756") && code.length() == 10) {
220 try {
221 String zonestring = code.substring(9);
222 int zoneval = Integer.parseInt(zonestring);
223 if(zoneval >= 1 && zoneval <= 4)
224 return Collections.singleton(zonestring);
225 } catch(NumberFormatException e) {}
226 }
227 return null;
228 }
229
230}
Note: See TracBrowser for help on using the repository browser.