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

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

move ntv2 to datum (see #7494)

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