source: josm/trunk/src/org/openstreetmap/josm/data/projection/Projections.java@ 8379

Last change on this file since 8379 was 8255, checked in by bastiK, 9 years ago

fixed #11369 - Add EPSG:2019 projection

  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.projection;
3
4import java.io.BufferedReader;
5import java.io.IOException;
6import java.io.InputStream;
7import java.io.InputStreamReader;
8import java.nio.charset.StandardCharsets;
9import java.util.Collection;
10import java.util.Collections;
11import java.util.HashMap;
12import java.util.HashSet;
13import java.util.Map;
14import java.util.Set;
15import java.util.regex.Matcher;
16import java.util.regex.Pattern;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.coor.EastNorth;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.projection.datum.Datum;
22import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
23import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper;
24import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
25import org.openstreetmap.josm.data.projection.proj.ClassProjFactory;
26import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
27import org.openstreetmap.josm.data.projection.proj.LonLat;
28import org.openstreetmap.josm.data.projection.proj.Mercator;
29import org.openstreetmap.josm.data.projection.proj.Proj;
30import org.openstreetmap.josm.data.projection.proj.ProjFactory;
31import org.openstreetmap.josm.data.projection.proj.SwissObliqueMercator;
32import org.openstreetmap.josm.data.projection.proj.TransverseMercator;
33import org.openstreetmap.josm.gui.preferences.projection.ProjectionChoice;
34import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
35import org.openstreetmap.josm.io.CachedFile;
36import org.openstreetmap.josm.tools.Pair;
37
38/**
39 * Class to handle projections
40 *
41 */
42public final class Projections {
43
44 private Projections() {
45 // Hide default constructor for utils classes
46 }
47
48 public static EastNorth project(LatLon ll) {
49 if (ll == null) return null;
50 return Main.getProjection().latlon2eastNorth(ll);
51 }
52
53 public static LatLon inverseProject(EastNorth en) {
54 if (en == null) return null;
55 return Main.getProjection().eastNorth2latlon(en);
56 }
57
58 /*********************************
59 * Registry for custom projection
60 *
61 * should be compatible to PROJ.4
62 */
63 public static final Map<String, ProjFactory> projs = new HashMap<>();
64 public static final Map<String, Ellipsoid> ellipsoids = new HashMap<>();
65 public static final Map<String, Datum> datums = new HashMap<>();
66 public static final Map<String, NTV2GridShiftFileWrapper> nadgrids = new HashMap<>();
67 public static final Map<String, Pair<String, String>> inits = new HashMap<>();
68
69 static {
70 registerBaseProjection("lonlat", LonLat.class, "core");
71 registerBaseProjection("josm:smerc", Mercator.class, "core");
72 registerBaseProjection("lcc", LambertConformalConic.class, "core");
73 registerBaseProjection("somerc", SwissObliqueMercator.class, "core");
74 registerBaseProjection("tmerc", TransverseMercator.class, "core");
75
76 ellipsoids.put("clrk66", Ellipsoid.clarke1866);
77 ellipsoids.put("clarkeIGN", Ellipsoid.clarkeIGN);
78 ellipsoids.put("intl", Ellipsoid.hayford);
79 ellipsoids.put("GRS67", Ellipsoid.GRS67);
80 ellipsoids.put("GRS80", Ellipsoid.GRS80);
81 ellipsoids.put("WGS84", Ellipsoid.WGS84);
82 ellipsoids.put("bessel", Ellipsoid.Bessel1841);
83
84 datums.put("WGS84", WGS84Datum.INSTANCE);
85 datums.put("GRS80", GRS80Datum.INSTANCE);
86
87 nadgrids.put("BETA2007.gsb", NTV2GridShiftFileWrapper.BETA2007);
88 nadgrids.put("ntf_r93_b.gsb", NTV2GridShiftFileWrapper.ntf_rgf93);
89
90 loadInits();
91 }
92
93 /**
94 * Plugins can register additional base projections.
95 *
96 * @param id The "official" PROJ.4 id. In case the projection is not supported
97 * by PROJ.4, use some prefix, e.g. josm:myproj or gdal:otherproj.
98 * @param fac The base projection factory.
99 * @param origin Multiple plugins may implement the same base projection.
100 * Provide plugin name or similar string, so it be differentiated.
101 */
102 public static void registerBaseProjection(String id, ProjFactory fac, String origin) {
103 projs.put(id, fac);
104 }
105
106 public static void registerBaseProjection(String id, Class<? extends Proj> projClass, String origin) {
107 registerBaseProjection(id, new ClassProjFactory(projClass), origin);
108 }
109
110 public static Proj getBaseProjection(String id) {
111 ProjFactory fac = projs.get(id);
112 if (fac == null) return null;
113 return fac.createInstance();
114 }
115
116 public static Ellipsoid getEllipsoid(String id) {
117 return ellipsoids.get(id);
118 }
119
120 public static Datum getDatum(String id) {
121 return datums.get(id);
122 }
123
124 public static NTV2GridShiftFileWrapper getNTV2Grid(String id) {
125 return nadgrids.get(id);
126 }
127
128 /**
129 * Get the projection definition string for the given id.
130 * @param id the id
131 * @return the string that can be processed by #{link CustomProjection}.
132 * Null, if the id isn't supported.
133 */
134 public static String getInit(String id) {
135 Pair<String, String> r = inits.get(id.toUpperCase());
136 if (r == null) return null;
137 return r.b;
138 }
139
140 /**
141 * Load +init "presets" from file
142 */
143 private static void loadInits() {
144 Pattern epsgPattern = Pattern.compile("<(\\d+)>(.*)<>");
145 try (
146 InputStream in = new CachedFile("resource://data/projection/epsg").getInputStream();
147 BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
148 ) {
149 String line, lastline = "";
150 while ((line = r.readLine()) != null) {
151 line = line.trim();
152 if (!line.startsWith("#") && !line.isEmpty()) {
153 if (!lastline.startsWith("#")) throw new AssertionError("EPSG file seems corrupted");
154 String name = lastline.substring(1).trim();
155 Matcher m = epsgPattern.matcher(line);
156 if (m.matches()) {
157 inits.put("EPSG:" + m.group(1), Pair.create(name, m.group(2).trim()));
158 } else {
159 Main.warn("Failed to parse line from the EPSG projection definition: "+line);
160 }
161 }
162 lastline = line;
163 }
164 } catch (IOException ex) {
165 throw new RuntimeException(ex);
166 }
167 }
168
169 private static final Set<String> allCodes = new HashSet<>();
170 private static final Map<String, ProjectionChoice> allProjectionChoicesByCode = new HashMap<>();
171 private static final Map<String, Projection> projectionsByCode_cache = new HashMap<>();
172
173 static {
174 for (ProjectionChoice pc : ProjectionPreference.getProjectionChoices()) {
175 for (String code : pc.allCodes()) {
176 allProjectionChoicesByCode.put(code, pc);
177 }
178 }
179 allCodes.addAll(inits.keySet());
180 allCodes.addAll(allProjectionChoicesByCode.keySet());
181 }
182
183 public static Projection getProjectionByCode(String code) {
184 Projection proj = projectionsByCode_cache.get(code);
185 if (proj != null) return proj;
186 ProjectionChoice pc = allProjectionChoicesByCode.get(code);
187 if (pc != null) {
188 Collection<String> pref = pc.getPreferencesFromCode(code);
189 pc.setPreferences(pref);
190 try {
191 proj = pc.getProjection();
192 } catch (Exception e) {
193 String cause = e.getMessage();
194 Main.warn("Unable to get projection "+code+" with "+pc + (cause != null ? ". "+cause : ""));
195 }
196 }
197 if (proj == null) {
198 Pair<String, String> pair = inits.get(code);
199 if (pair == null) return null;
200 String name = pair.a;
201 String init = pair.b;
202 proj = new CustomProjection(name, code, init, null);
203 }
204 projectionsByCode_cache.put(code, proj);
205 return proj;
206 }
207
208 public static Collection<String> getAllProjectionCodes() {
209 return Collections.unmodifiableCollection(allCodes);
210 }
211}
Note: See TracBrowser for help on using the repository browser.