RegionChooserCLI.java 4.25 KB
Newer Older
Eric Duminil's avatar
Eric Duminil committed
1
2
package eu.simstadt.regionchooser;

Eric Duminil's avatar
Eric Duminil committed
3
import java.nio.charset.StandardCharsets;
Eric Duminil's avatar
Eric Duminil committed
4
import java.nio.file.Files;
Eric Duminil's avatar
Eric Duminil committed
5
import java.nio.file.Path;
Eric Duminil's avatar
Eric Duminil committed
6
import java.nio.file.Paths;
Eric Duminil's avatar
Eric Duminil committed
7
import java.util.Scanner;
Eric Duminil's avatar
Eric Duminil committed
8
import java.util.concurrent.Callable;
Eric Duminil's avatar
Eric Duminil committed
9
import org.osgeo.proj4j.CoordinateReferenceSystem;
Eric Duminil's avatar
Eric Duminil committed
10
11
import picocli.CommandLine;
import picocli.CommandLine.Command;
12
import picocli.CommandLine.Model.CommandSpec;
Eric Duminil's avatar
Eric Duminil committed
13
import picocli.CommandLine.Option;
14
import picocli.CommandLine.Spec;
Eric Duminil's avatar
Eric Duminil committed
15

Eric Duminil's avatar
Eric Duminil committed
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

/**
 * Command Line Interface for RegionChooser. Could be useful to extract large regions on server, or automate the process
 * from batch/python scripts.
 * 
 */

// Usage: region_chooser [-hlV] [-e=31467] -o=output.gml -w=polygon.wkt -i=input.
//                       gml[,input.gml...] [-i=input.gml[,input.gml...]]...
// Extracts a region from one or more citygmls.
//   -i, --input=input.gml[,input.gml...]
//                             Citygml files to extract from
//   -o, --output=output.gml   Output file
//   -e, --epsg=31467          EPSG id for coordinate reference system
//    -l, --local               Are WKT coordinates in local CRS?
//   -w, --wkt=polygon.wkt     File containing WKT polygon, or - for stdin
//   -h, --help                Show this help message and exit.
//   -V, --version             Print version information and exit.


// Example:
// --input CGSC_Repository/Würzburg.proj/LoD2_566_5516_2_BY.gml,CGSC_Repository/Würzburg.proj/LoD2_568_5516_2_BY.gml
// --output ./output.gml
// --wkt ./grombuhl.txt
Eric Duminil's avatar
Eric Duminil committed
40

Eric Duminil's avatar
Eric Duminil committed
41

Eric Duminil's avatar
Eric Duminil committed
42
@Command(name = "region_chooser", mixinStandardHelpOptions = true, version = "regionChooser x.x", description = "Extracts a region from one or more citygmls.", sortOptions = false)
Eric Duminil's avatar
Eric Duminil committed
43
class RegionChooserCLI implements Callable<Integer>
Eric Duminil's avatar
Eric Duminil committed
44
{
45
46
	@Spec
	CommandSpec spec;
Eric Duminil's avatar
Notes.    
Eric Duminil committed
47

48
	//TODO: Add --gui?
Eric Duminil's avatar
Notes.    
Eric Duminil committed
49

Eric Duminil's avatar
Eric Duminil committed
50
51
	@Option(names = { "-i",
			"--input" }, required = true, split = ",", description = "Citygml files to extract from", paramLabel = "input.gml")
Eric Duminil's avatar
todo    
Eric Duminil committed
52
	//TODO: Allow folders too?
Eric Duminil's avatar
Eric Duminil committed
53
	Path[] citygmls;
Eric Duminil's avatar
Eric Duminil committed
54

Eric Duminil's avatar
Eric Duminil committed
55
56
	@Option(names = { "-o",
			"--output" }, required = true, description = "Output file", paramLabel = "output.gml")
Eric Duminil's avatar
Eric Duminil committed
57
	Path outputCityGML;
Eric Duminil's avatar
Eric Duminil committed
58

Eric Duminil's avatar
Eric Duminil committed
59
60
	@Option(names = { "-e", "--epsg" }, description = "EPSG id for coordinate reference system", paramLabel = "31467")
	Integer espgId;
Eric Duminil's avatar
Eric Duminil committed
61

Eric Duminil's avatar
Eric Duminil committed
62
63
64
	@Option(names = { "-l",
			"--local" }, description = "Are WKT coordinates in local CRS?", paramLabel = "local_coordinates?")
	boolean localCoordinates;
Eric Duminil's avatar
Eric Duminil committed
65

Eric Duminil's avatar
Eric Duminil committed
66
	@Option(names = { "-w",
Eric Duminil's avatar
Eric Duminil committed
67
			"--wkt" }, required = true, description = "File containing WKT polygon, or - for stdin", paramLabel = "polygon.wkt")
Eric Duminil's avatar
Eric Duminil committed
68
69
	String wktFile = "-";

Eric Duminil's avatar
Eric Duminil committed
70
	@Override
Eric Duminil's avatar
Eric Duminil committed
71
	public Integer call() throws Exception {
Eric Duminil's avatar
Eric Duminil committed
72
		CoordinateReferenceSystem localCRS;
Eric Duminil's avatar
Eric Duminil committed
73

Eric Duminil's avatar
Eric Duminil committed
74
		if (espgId == null) {
Eric Duminil's avatar
Eric Duminil committed
75
			localCRS = RegionChooserUtils.crsFromCityGMLHeader(citygmls[0]);
Eric Duminil's avatar
Eric Duminil committed
76
		} else {
Eric Duminil's avatar
Eric Duminil committed
77
			localCRS = RegionChooserUtils.crsFromSrsName("EPSG:" + espgId);
Eric Duminil's avatar
Eric Duminil committed
78
		}
79
		logInfo("Coordinate system: " + localCRS);
Eric Duminil's avatar
Eric Duminil committed
80

Eric Duminil's avatar
Eric Duminil committed
81
		String wktPolygon;
Eric Duminil's avatar
Eric Duminil committed
82

Eric Duminil's avatar
Eric Duminil committed
83
84
		if (wktFile.equals("-")) {
			if (System.in.available() == 0) {
Eric Duminil's avatar
Eric Duminil committed
85
				throw new IllegalArgumentException("Please provide \"POLYGON((x1 y1, x2 y2, ...))\" to standard input.");
Eric Duminil's avatar
Eric Duminil committed
86
			} else {
Eric Duminil's avatar
Eric Duminil committed
87
				wktPolygon = getInput();
Eric Duminil's avatar
Eric Duminil committed
88
			}
Eric Duminil's avatar
Eric Duminil committed
89
		} else {
Eric Duminil's avatar
Eric Duminil committed
90
91
92
93
			wktPolygon = new String(Files.readAllBytes(Paths.get(wktFile)), StandardCharsets.UTF_8);
			if (wktPolygon.isEmpty()) {
				throw new IllegalArgumentException("Please write \"POLYGON((x1 y1, x2 y2, ...))\" inside " + wktFile);
			}
Eric Duminil's avatar
Eric Duminil committed
94
		}
Eric Duminil's avatar
Eric Duminil committed
95

Eric Duminil's avatar
Eric Duminil committed
96
97
		if (!localCoordinates) {
			// WKT coordinates are in WGS84, so should be first converted to srsName
Eric Duminil's avatar
Eric Duminil committed
98
			wktPolygon = RegionChooserUtils.wktPolygonToLocalCRS(wktPolygon, localCRS);
Eric Duminil's avatar
Eric Duminil committed
99
100
		}

101
		logInfo("WKT Polygon expressed in local coordinates: " + wktPolygon);
Eric Duminil's avatar
Eric Duminil committed
102

Eric Duminil's avatar
Eric Duminil committed
103
		StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(wktPolygon, localCRS.toString(), citygmls);
Eric Duminil's avatar
Eric Duminil committed
104
105
106

		RegionChooserUtils.writeStringBuilderToFile(sb, outputCityGML);

Eric Duminil's avatar
Eric Duminil committed
107
		return 0;
Eric Duminil's avatar
Eric Duminil committed
108
109
	}

110
111
112
113
	private void logInfo(String message) {
		spec.commandLine().getErr().println(message);
	}

Eric Duminil's avatar
Eric Duminil committed
114
	private static String getInput() {
Eric Duminil's avatar
Eric Duminil committed
115
116
117
		try (Scanner myObj = new Scanner(System.in)) {
			return myObj.nextLine();
		}
Eric Duminil's avatar
Eric Duminil committed
118
119
	}

Eric Duminil's avatar
Eric Duminil committed
120
121
122
	// this example implements Callable, so parsing, error handling and handling user
	// requests for usage help or version help can be done with one line of code.
	public static void main(String... args) {
Eric Duminil's avatar
Eric Duminil committed
123
		int exitCode = new CommandLine(new RegionChooserCLI()).execute(args);
Eric Duminil's avatar
Eric Duminil committed
124
		System.exit(exitCode);
Eric Duminil's avatar
Eric Duminil committed
125
	}
Eric Duminil's avatar
Eric Duminil committed
126
}