package eu.simstadt.regionchooser; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Scanner; import java.util.concurrent.Callable; import org.osgeo.proj4j.CoordinateReferenceSystem; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; import picocli.CommandLine.Spec; // Example usage: // --input /home/ricou/Desktop/CGSC_Repository/Würzburg.proj/LoD2_566_5516_2_BY.gml,/home/ricou/Desktop/CGSC_Repository/Würzburg.proj/LoD2_568_5516_2_BY.gml // --output /home/ricou/Desktop/output.gml // --wkt /home/ricou/Desktop/grombuhl.txt @Command(name = "region_chooser", mixinStandardHelpOptions = true, version = "regionChooser x.x", description = "Extracts a region from one or more citygmls.", sortOptions = false) class RegionChooserCommandLineInterface implements Callable { @Spec CommandSpec spec; //TODO: Add --gui? @Option(names = { "-i", "--input" }, required = true, split = ",", description = "Citygml files to extract from", paramLabel = "input.gml") //TODO: Allow folders too? Path[] citygmls; @Option(names = { "-o", "--output" }, required = true, description = "Output file", paramLabel = "output.gml") Path outputCityGML; @Option(names = { "-e", "--epsg" }, description = "EPSG id for coordinate reference system", paramLabel = "31467") Integer espgId; @Option(names = { "-l", "--local" }, description = "Are WKT coordinates in local CRS?", paramLabel = "local_coordinates?") boolean localCoordinates; @Option(names = { "-w", "--wkt" }, required = true, description = "File containing WKT polygon, or - for stdin", paramLabel = "polygon.wkt") String wktFile = "-"; @Override public Integer call() throws Exception { CoordinateReferenceSystem localCRS; if (espgId == null) { localCRS = RegionChooserUtils.crsFromCityGMLHeader(citygmls[0]); } else { localCRS = RegionChooserUtils.crsFromSrsName("EPSG:" + espgId); } logInfo("Coordinate system: " + localCRS); String wktPolygon; if (wktFile.equals("-")) { if (System.in.available() == 0) { throw new IllegalArgumentException("Please provide \"POLYGON((x1 y1, x2 y2, ...))\" to standard input."); } else { wktPolygon = getInput(); } } else { 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); } } if (!localCoordinates) { // WKT coordinates are in WGS84, so should be first converted to srsName wktPolygon = RegionChooserUtils.wktPolygonToLocalCRS(wktPolygon, localCRS); } logInfo("WKT Polygon expressed in local coordinates: " + wktPolygon); StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(wktPolygon, localCRS.toString(), citygmls); RegionChooserUtils.writeStringBuilderToFile(sb, outputCityGML); return 0; } private void logInfo(String message) { spec.commandLine().getErr().println(message); } private static String getInput() { try (Scanner myObj = new Scanner(System.in)) { return myObj.nextLine(); } } // 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) { int exitCode = new CommandLine(new RegionChooserCommandLineInterface()).execute(args); System.exit(exitCode); } }