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

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

add option to select projection by code

this means it is no longer necessary to write a GUI for each new projection, because they are accessible in this list

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