source: josm/trunk/scripts/BuildProjectionDefinitions.java@ 13592

Last change on this file since 13592 was 13583, checked in by stoecker, 6 years ago

see #15915 - add ESRI text to ESRI specific codes

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2
3import java.io.BufferedWriter;
4import java.io.File;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.OutputStreamWriter;
8import java.nio.charset.StandardCharsets;
9import java.util.HashMap;
10import java.util.LinkedHashMap;
11import java.util.Map;
12
13import org.openstreetmap.josm.data.projection.CustomProjection;
14import org.openstreetmap.josm.data.projection.ProjectionConfigurationException;
15import org.openstreetmap.josm.data.projection.Projections;
16import org.openstreetmap.josm.data.projection.Projections.ProjectionDefinition;
17import org.openstreetmap.josm.data.projection.proj.Proj;
18
19/**
20 * Generates the list of projections by combining two sources: The list from the
21 * proj.4 project and a list maintained by the JOSM team.
22 */
23public class BuildProjectionDefinitions {
24
25 private static final String JOSM_EPSG_FILE = "data_nodist/projection/josm-epsg";
26 private static final String PROJ4_EPSG_FILE = "data_nodist/projection/epsg";
27 private static final String PROJ4_ESRI_FILE = "data_nodist/projection/esri";
28 private static final String OUTPUT_EPSG_FILE = "data/projection/custom-epsg";
29
30 private static final Map<String, ProjectionDefinition> epsgProj4 = new LinkedHashMap<>();
31 private static final Map<String, ProjectionDefinition> esriProj4 = new LinkedHashMap<>();
32 private static final Map<String, ProjectionDefinition> epsgJosm = new LinkedHashMap<>();
33
34 private static final boolean printStats = false;
35
36 // statistics:
37 private static int noInJosm = 0;
38 private static int noInProj4 = 0;
39 private static int noDeprecated = 0;
40 private static int noGeocent = 0;
41 private static int noBaseProjection = 0;
42 private static final Map<String, Integer> baseProjectionMap = new HashMap<>();
43 private static int noDatumgrid = 0;
44 private static int noJosm = 0;
45 private static int noProj4 = 0;
46 private static int noEsri = 0;
47 private static int noOmercNoBounds = 0;
48 private static int noEquatorStereo = 0;
49
50 /**
51 * Program entry point
52 * @param args command line arguments (not used)
53 * @throws IOException if any I/O error occurs
54 */
55 public static void main(String[] args) throws IOException {
56 buildList(args[0]);
57 }
58
59 static void initMap(String baseDir, String file, Map<String, ProjectionDefinition> map) throws IOException {
60 for (ProjectionDefinition pd : Projections.loadProjectionDefinitions(baseDir + File.separator + file)) {
61 map.put(pd.code, pd);
62 }
63 }
64
65 static void buildList(String baseDir) throws IOException {
66 initMap(baseDir, JOSM_EPSG_FILE, epsgJosm);
67 initMap(baseDir, PROJ4_EPSG_FILE, epsgProj4);
68 initMap(baseDir, PROJ4_ESRI_FILE, esriProj4);
69
70 try (FileOutputStream output = new FileOutputStream(baseDir + File.separator + OUTPUT_EPSG_FILE);
71 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8))) {
72 out.write("## This file is autogenerated, do not edit!\n");
73 out.write("## Run ant task \"epsg\" to rebuild.\n");
74 out.write(String.format("## Source files are %s (can be changed), %s and %s (copied from the proj.4 project).%n",
75 JOSM_EPSG_FILE, PROJ4_EPSG_FILE, PROJ4_ESRI_FILE));
76 out.write("##\n");
77 out.write("## Entries checked and maintained by the JOSM team:\n");
78 for (ProjectionDefinition pd : epsgJosm.values()) {
79 write(out, pd);
80 noJosm++;
81 }
82 out.write("## Other supported projections (source: proj.4):\n");
83 for (ProjectionDefinition pd : epsgProj4.values()) {
84 if (doInclude(pd, true, false)) {
85 write(out, pd);
86 noProj4++;
87 }
88 }
89 out.write("## ESRI-specific projections (source: proj.4):\n");
90 for (ProjectionDefinition pd : esriProj4.values()) {
91 pd = new ProjectionDefinition(pd.code, "ESRI: " + pd.name, pd.definition);
92 if (doInclude(pd, true, true)) {
93 write(out, pd);
94 noEsri++;
95 }
96 }
97 }
98
99 if (printStats) {
100 System.out.println(String.format("loaded %d entries from %s", epsgJosm.size(), JOSM_EPSG_FILE));
101 System.out.println(String.format("loaded %d entries from %s", epsgProj4.size(), PROJ4_EPSG_FILE));
102 System.out.println(String.format("loaded %d entries from %s", esriProj4.size(), PROJ4_ESRI_FILE));
103 System.out.println();
104 System.out.println("some entries from proj.4 have not been included:");
105 System.out.println(String.format(" * already in the maintained JOSM list: %d entries", noInJosm));
106 System.out.println(String.format(" * ESRI already in the standard EPSG list: %d entries", noInProj4));
107 System.out.println(String.format(" * deprecated: %d entries", noDeprecated));
108 System.out.println(String.format(" * using +proj=geocent, which is 3D (X,Y,Z) and not useful in JOSM: %d entries", noGeocent));
109 System.out.println(String.format(" * unsupported base projection: %d entries", noBaseProjection));
110 System.out.println(" in particular: " + baseProjectionMap);
111 System.out.println(String.format(" * requires data file for datum conversion: %d entries", noDatumgrid));
112 if (noOmercNoBounds > 0) {
113 System.out.println(String.format(" * projection is Oblique Mercator (requires bounds), but no bounds specified: %d entries", noOmercNoBounds));
114 }
115 if (noEquatorStereo > 0) {
116 System.out.println(String.format(" * projection is Equatorial Stereographic (see #15970): %d entries", noEquatorStereo));
117 }
118 System.out.println();
119 System.out.println(String.format("written %d entries from %s", noJosm, JOSM_EPSG_FILE));
120 System.out.println(String.format("written %d entries from %s", noProj4, PROJ4_EPSG_FILE));
121 System.out.println(String.format("written %d entries from %s", noEsri, PROJ4_ESRI_FILE));
122 }
123 }
124
125 static void write(BufferedWriter out, ProjectionDefinition pd) throws IOException {
126 out.write("# " + pd.name + "\n");
127 out.write("<"+pd.code.substring("EPSG:".length())+"> "+pd.definition+" <>\n");
128 }
129
130 static boolean doInclude(ProjectionDefinition pd, boolean noIncludeJosm, boolean noIncludeProj4) {
131
132 boolean result = true;
133
134 if (noIncludeJosm) {
135 // we already have this projection
136 if (epsgJosm.containsKey(pd.code)) {
137 result = false;
138 noInJosm++;
139 }
140 }
141 if (noIncludeProj4) {
142 // we already have this projection
143 if (epsgProj4.containsKey(pd.code)) {
144 result = false;
145 noInProj4++;
146 }
147 }
148
149 // exclude deprecated projections
150 // EPSG:4296 is also deprecated, but this is not mentioned in the name
151 if (pd.name.contains("deprecated") || pd.code.equals("EPSG:4296")) {
152 result = false;
153 noDeprecated++;
154 }
155
156 Map<String, String> parameters;
157 try {
158 parameters = CustomProjection.parseParameterList(pd.definition, true);
159 } catch (ProjectionConfigurationException ex) {
160 throw new RuntimeException(pd.code+":"+ex);
161 }
162 String proj = parameters.get(CustomProjection.Param.proj.key);
163
164 // +proj=geocent is 3D (X,Y,Z) "projection" - this is not useful in
165 // JOSM as we only deal with 2D maps
166 if ("geocent".equals(proj)) {
167 result = false;
168 noGeocent++;
169 }
170
171 // no support for NAD27 datum, as it requires a conversion database
172 String datum = parameters.get(CustomProjection.Param.datum.key);
173 if ("NAD27".equals(datum)) {
174 result = false;
175 noDatumgrid++;
176 }
177
178 // requires datum conversion database
179 if (parameters.containsKey("geoidgrids")) {
180 result = false;
181 noDatumgrid++;
182 }
183
184 // exclude entries where we don't support the base projection
185 Proj bp = Projections.getBaseProjection(proj);
186 if (result && !"utm".equals(proj) && bp == null) {
187 result = false;
188 noBaseProjection++;
189 if (!"geocent".equals(proj)) {
190 if (!baseProjectionMap.containsKey(proj)) {
191 baseProjectionMap.put(proj, 0);
192 }
193 baseProjectionMap.put(proj, baseProjectionMap.get(proj)+1);
194 }
195 }
196
197 if (result && "omerc".equals(proj) && !parameters.containsKey(CustomProjection.Param.bounds.key)) {
198 result = false;
199 noOmercNoBounds++;
200 }
201 // TODO: implement equatorial stereographic, see https://josm.openstreetmap.de/ticket/15970
202 if (result && "stere".equals(proj) && "0".equals(parameters.get(CustomProjection.Param.lat_0.key))) {
203 result = false;
204 noEquatorStereo++;
205 }
206
207 return result;
208 }
209}
Note: See TracBrowser for help on using the repository browser.