source: josm/trunk/src/org/openstreetmap/josm/data/projection/ProjectionCLI.java@ 13250

Last change on this file since 13250 was 13207, checked in by Don-vip, 6 years ago

enable PMD rule PreserveStackTrace + add missing jars to run new PMD rule designer

File size: 8.1 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.io.BufferedReader;
7import java.io.IOException;
8import java.io.InputStreamReader;
9import java.nio.charset.Charset;
10import java.nio.charset.StandardCharsets;
11import java.nio.file.Files;
12import java.nio.file.Paths;
13import java.util.ArrayList;
14import java.util.List;
15import java.util.function.Function;
16
17import org.openstreetmap.josm.CLIModule;
18import org.openstreetmap.josm.data.coor.EastNorth;
19import org.openstreetmap.josm.data.coor.LatLon;
20import org.openstreetmap.josm.data.coor.conversion.LatLonParser;
21import org.openstreetmap.josm.tools.I18n;
22import org.openstreetmap.josm.tools.Utils;
23
24import gnu.getopt.Getopt;
25import gnu.getopt.LongOpt;
26
27/**
28 * Command line interface for projecting coordinates.
29 * @since 12792
30 */
31public class ProjectionCLI implements CLIModule {
32
33 public static final ProjectionCLI INSTANCE = new ProjectionCLI();
34
35 private boolean argInverse = false; // NOPMD
36 private boolean argSwitchInput = false; // NOPMD
37 private boolean argSwitchOutput = false; // NOPMD
38
39 @Override
40 public String getActionKeyword() {
41 return "project";
42 }
43
44 @Override
45 public void processArguments(String[] argArray) {
46 Getopt.setI18nHandler(I18n::tr);
47 Getopt getopt = new Getopt("JOSM projection", argArray, "Irh", new LongOpt[] {
48 new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h')});
49
50 int c;
51 while ((c = getopt.getopt()) != -1) {
52 switch (c) {
53 case 'h':
54 showHelp();
55 System.exit(0);
56 case 'I':
57 argInverse = true;
58 break;
59 case 'r':
60 argSwitchInput = true;
61 break;
62 case 's':
63 argSwitchOutput = true;
64 break;
65 default:
66 // ignore
67 }
68 }
69
70 List<String> projParamFrom = new ArrayList<>();
71 List<String> projParamTo = new ArrayList<>();
72 List<String> otherPositional = new ArrayList<>();
73 boolean toTokenSeen = false;
74 // positional arguments:
75 for (int i = getopt.getOptind(); i < argArray.length; ++i) {
76 String arg = argArray[i];
77 if (arg.isEmpty()) throw new IllegalArgumentException("non-empty argument expected");
78 if (arg.startsWith("+")) {
79 if (arg.equals("+to")) {
80 toTokenSeen = true;
81 } else {
82 (toTokenSeen ? projParamTo : projParamFrom).add(arg);
83 }
84 } else {
85 otherPositional.add(arg);
86 }
87 }
88 String fromStr = Utils.join(" ", projParamFrom);
89 String toStr = Utils.join(" ", projParamTo);
90 try {
91 run(fromStr, toStr, otherPositional);
92 } catch (ProjectionConfigurationException | IllegalArgumentException | IOException ex) {
93 System.err.println(tr("Error: {0}", ex.getMessage()));
94 System.exit(1);
95 }
96 System.exit(0);
97 }
98
99 /**
100 * Displays help on the console
101 */
102 public static void showHelp() {
103 System.out.println(getHelp());
104 }
105
106 private static String getHelp() {
107 return tr("JOSM projection command line interface")+"\n\n"+
108 tr("Usage")+":\n"+
109 "\tjava -jar josm.jar project <options> <crs> +to <crs> [file]\n\n"+
110 tr("Description")+":\n"+
111 tr("Converts coordinates from one coordinate reference system to another.")+"\n\n"+
112 tr("Options")+":\n"+
113 "\t--help|-h "+tr("Show this help")+"\n"+
114 "\t-I "+tr("Switch input and output crs")+"\n"+
115 "\t-r "+tr("Switch order of input coordinates (east/north, lon/lat)")+"\n"+
116 "\t-s "+tr("Switch order of output coordinates (east/north, lon/lat)")+"\n\n"+
117 tr("<crs>")+":\n"+
118 tr("The format for input and output coordinate reference system"
119 + " is similar to that of the PROJ.4 software.")+"\n\n"+
120 tr("[file]")+":\n"+
121 tr("Reads input data from one or more files listed as positional arguments. "
122 + "When no files are given, or the filename is \"-\", data is read from "
123 + "standard input.")+"\n\n"+
124 tr("Examples")+":\n"+
125 " java -jar josm.jar project +init=epsg:4326 +to +init=epsg:3857 <<<\"11.232274 50.5685716\"\n"+
126 " => 1250371.1334500168 6545331.055189664\n\n"+
127 " java -jar josm.jar project +proj=lonlat +datum=WGS84 +to +proj=merc +a=6378137 +b=6378137 +nadgrids=@null <<EOF\n" +
128 " 11d13'56.19\"E 50d34'6.86\"N\n" +
129 " 118d39'30.42\"W 37d20'18.76\"N\n"+
130 " EOF\n"+
131 " => 1250371.1334500168 6545331.055189664\n" +
132 " -1.3208998232319113E7 4486401.160664663\n";
133 }
134
135 private void run(String fromStr, String toStr, List<String> files) throws ProjectionConfigurationException, IOException {
136 CustomProjection fromProj = createProjection(fromStr);
137 CustomProjection toProj = createProjection(toStr);
138 if (this.argInverse) {
139 CustomProjection tmp = fromProj;
140 fromProj = toProj;
141 toProj = tmp;
142 }
143
144 if (files.isEmpty() || files.get(0).equals("-")) {
145 processInput(fromProj, toProj, new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())));
146 } else {
147 for (String file : files) {
148 try (BufferedReader br = Files.newBufferedReader(Paths.get(file), StandardCharsets.UTF_8)) {
149 processInput(fromProj, toProj, br);
150 }
151 }
152 }
153 }
154
155 private void processInput(CustomProjection fromProj, CustomProjection toProj, BufferedReader reader) throws IOException {
156 String line;
157 while ((line = reader.readLine()) != null) {
158 line = line.trim();
159 if (line.isEmpty() || line.startsWith("#"))
160 continue;
161 EastNorth enIn;
162 if (fromProj.isGeographic()) {
163 enIn = parseEastNorth(line, LatLonParser::parseCoordinate);
164 } else {
165 enIn = parseEastNorth(line, ProjectionCLI::parseDouble);
166 }
167 LatLon ll = fromProj.eastNorth2latlon(enIn);
168 EastNorth enOut = toProj.latlon2eastNorth(ll);
169 double cOut1 = argSwitchOutput ? enOut.north() : enOut.east();
170 double cOut2 = argSwitchOutput ? enOut.east() : enOut.north();
171 System.out.println(Double.toString(cOut1) + " " + Double.toString(cOut2));
172 System.out.flush();
173 }
174 }
175
176 private CustomProjection createProjection(String params) throws ProjectionConfigurationException {
177 CustomProjection proj = new CustomProjection();
178 proj.update(params);
179 return proj;
180 }
181
182 private EastNorth parseEastNorth(String s, Function<String, Double> parser) {
183 String[] en = s.split("[;, ]+");
184 if (en.length != 2)
185 throw new IllegalArgumentException(tr("Expected two coordinates, separated by white space, found {0} in ''{1}''", en.length, s));
186 double east = parser.apply(en[0]);
187 double north = parser.apply(en[1]);
188 if (this.argSwitchInput)
189 return new EastNorth(north, east);
190 else
191 return new EastNorth(east, north);
192 }
193
194 private static double parseDouble(String s) {
195 try {
196 return Double.parseDouble(s);
197 } catch (NumberFormatException nfe) {
198 throw new IllegalArgumentException(tr("Unable to parse number ''{0}''", s), nfe);
199 }
200 }
201
202 /**
203 * Main class to run just the projection CLI.
204 * @param args command line arguments
205 */
206 public static void main(String[] args) {
207 ProjectionCLI.INSTANCE.processArguments(args);
208 }
209}
Note: See TracBrowser for help on using the repository browser.