Commit d8c967ee authored by Eric Duminil's avatar Eric Duminil
Browse files

Merge branch 'experimental/picocli' into develop

parents f117faf4 476042e0
......@@ -272,3 +272,4 @@ $RECYCLE.BIN/
*.lnk
# End of https://www.gitignore.io/api/java,maven,macos,linux,eclipse,windows,netbeans,intellij
/-
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;
/**
* 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
@Command(name = "region_chooser", mixinStandardHelpOptions = true, version = "regionChooser x.x", description = "Extracts a region from one or more citygmls.", sortOptions = false)
class RegionChooserCLI implements Callable<Integer>
{
@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 RegionChooserCLI()).execute(args);
System.exit(exitCode);
}
}
\ No newline at end of file
package eu.simstadt.regionchooser;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.Callable;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
@Command(name = "region_chooser", mixinStandardHelpOptions = true, version = "regionChooser x.x", description = "Extracts a region from one or more citygmls.")
class RegionChooserCommandLineInterface implements Callable<Integer>
{
@Parameters(index = "0", description = "SRS Name : 'EPSG:31467' or just 31467")
String srsName;
@Parameters(index = "1", description = "Output file : output.gml")
Path outputCityGML;
@Parameters(index = "2..*", arity = "1..*", description = "The citygml files to extract from : input1.gml input2.gml")
List<Path> citygmls;
@Override
public Integer call() throws Exception { // your business logic goes here...
for (Path file : citygmls) {
System.out.println(file);
}
return 0;
}
// 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);
}
}
\ No newline at end of file
......@@ -13,6 +13,9 @@
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
import org.osgeo.proj4j.BasicCoordinateTransform;
import org.osgeo.proj4j.CRSFactory;
import org.osgeo.proj4j.CoordinateReferenceSystem;
......@@ -47,7 +50,7 @@ private RegionChooserUtils() {
* @param srsName
* @return CoordinateReferenceSystem
*/
private static CoordinateReferenceSystem crsFromSrsName(String srsName) {
public static CoordinateReferenceSystem crsFromSrsName(String srsName) {
// EPSG:31467
Pattern pEPSG = Pattern.compile("^(EPSG:\\d+)$");
Matcher mEPSG = pEPSG.matcher(srsName);
......@@ -111,6 +114,15 @@ public static Polygon changePolygonCRS(Polygon polygonInOriginalCRS, CoordinateR
return geometryFactory.createPolygon(convexHullcoordinates);
}
public static String wktPolygonToLocalCRS(String wktPolygonInWGS84, CoordinateReferenceSystem localCRS)
throws ParseException {
final WKTReader wktReader = new WKTReader();
final WKTWriter wktWriter = new WKTWriter();
// WKT coordinates are in WGS84, so should be first converted to srsName
Polygon wgs84Polygon = (Polygon) wktReader.read(wktPolygonInWGS84);
return wktWriter.write(changePolygonCRS(wgs84Polygon, WGS84, localCRS));
}
/**
*
* Fast scan of the 50 first lines of a Citygml file to look for srsName. It might not be as reliable as parsing the
......
......@@ -21,10 +21,10 @@
public class RegionExtractor
{
private static final WKTReader wktReader = new WKTReader();
private static final WKTReader WKT_READER = new WKTReader();
private static final Logger LOGGER = Logger.getLogger(RegionExtractor.class.getName());
private static final GeometryFactory gf = new GeometryFactory();
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
/**
* Main method behind RegionChooser. Given CityGMLs (as Path[]) and a geometry (as Well-known text POLYGON, in the
......@@ -48,10 +48,13 @@
static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Path... citygmlPaths)
throws ParseException, XPathParseException, NavException, IOException {
//TODO: Should actually write directly to a bufferedwriter
//TODO: Should return the number of found buildings.
int buildingsCount = 0;
int foundBuildingsCount = 0;
StringBuilder sb = new StringBuilder();
Geometry poly = wktReader.read(wktPolygon);
Geometry poly = WKT_READER.read(wktPolygon);
CityGmlIterator citygml = null;
for (int i = 0; i < citygmlPaths.length; i++) {
......@@ -65,7 +68,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
buildingsCount += 1;
if (buildingXmlNode.hasCoordinates()) {
Coordinate coord = new Coordinate(buildingXmlNode.x, buildingXmlNode.y);
Point point = gf.createPoint(coord);
Point point = GEOMETRY_FACTORY.createPoint(coord);
if (point.within(poly)) {
foundBuildingsCount++;
sb.append(buildingXmlNode.toString());
......@@ -75,13 +78,16 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
LOGGER.info("1000 buildings parsed");
}
}
}
if (citygml == null) {
throw new IllegalArgumentException("There should be at least one citygml");
}
if (foundBuildingsCount == 0) {
LOGGER.warning("No building found in the selected region.");
}
LOGGER.info("Buildings found in selected region " + foundBuildingsCount);
sb.append(citygml.getFooter());
return sb;
......
......@@ -28,7 +28,8 @@ public BuildingXmlNode(VTDNav navigator, int buildingOffset, int buildingLength)
this.coordinatesFinder = new AutoPilot(navigator);
this.buildingLength = buildingLength;
this.buildingOffset = buildingOffset;
extractCoordinates(); //NOTE: Should it be done lazily? Is there any reason to extract a BuildingXmlNode without coordinates?
extractCoordinates();
//TODO: Get Building ID too, in order to avoid duplicates?
}
public boolean hasCoordinates() {
......
......@@ -92,6 +92,7 @@ public static void extractHullsForEveryCityGML(Path repository, Consumer<String>
try {
Path kmlPath = getHullPath(repository, gmlPath);
if (Files.exists(kmlPath)) {
//TODO: Check if size is the same as original. Recreate otherwise.
LOGGER.fine("Using cache from " + repository.relativize(kmlPath));
return new String(Files.readAllBytes(kmlPath), StandardCharsets.UTF_8);
} else {
......
......@@ -69,7 +69,7 @@ var regionChooser = (function(){
dataPanel.append('.');
srsName = feature.get("srsName");
if (proj4.defs(srsName) === undefined){
console.warning(srsName + " isn't defined by Proj4js!")
console.warn(srsName + " isn't defined by Proj4js!")
}
};
......@@ -162,7 +162,7 @@ var regionChooser = (function(){
var sketch_percentage = Math.round(intersectionArea / polygonArea * 100);
intersections.addFeature(intersection);
var link = '<li>'
// TODO: If possible, highlight the corresponding polygon when hovering above a name.
// TODO: If possible, highlight the corresponding polygon when hovering above a name.
link += '<input type="checkbox" id="citygml_' + feature.getId() + '" class="select_citygml" onclick="regionChooser.isDownloadPossible();"><label for="citygml_' + feature.getId() + '">' + feature['name'] + '</label>';
link += " (" + citygml_percentage + "%";
......@@ -194,13 +194,13 @@ var regionChooser = (function(){
features_by_project = groupBy(kml_source.getFeatures(), "project");
Object.keys(features_by_project).forEach(function(project) {
features = features_by_project[project];
features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined);
if (features_and_intersections.length > 0){
intersection_found = true;
features = features_by_project[project];
features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined);
if (features_and_intersections.length > 0){
intersection_found = true;
dataPanel.append("<h2 class='info'>" + project);
features_and_intersections.forEach(l => showLinkToDownload(l[0], l[1], polygonArea));
}
features_and_intersections.forEach(l => showLinkToDownload(l[0], l[1], polygonArea));
}
});
if (intersection_found) {
......@@ -246,7 +246,7 @@ var regionChooser = (function(){
fxapp.downloadRegionFromCityGMLs(sketchAsWKT(srsName), project, citygmlNames.join(";"), srsName);
dataPanel.prepend("<h2 class='ok'>Done!</h2><br/>\n");
} catch (e) {
console.warning("ERROR : " + e);
console.warn("ERROR : " + e);
dataPanel.prepend("<h2 class='error'>Some problem occured!</h2><br/>\n");
}
var end = new Date().getTime();
......@@ -266,22 +266,9 @@ var regionChooser = (function(){
function displayInfo() {
dataPanel.empty();
var geom = /** @type {ol.geom.Polygon} */
(sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326'));
var geom = sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326');
var coordinates = geom.getLinearRing(0).getCoordinates();
var area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
var coords = geom.getLinearRing(0).getCoordinates();
if (!fromJavaFX) {
var wgs84_coords = "";
var n = coords.length;
for (var i = 0; i < n; i++) {
var wgs84_coord = coords[i];
wgs84_coords += "(" + wgs84_coord[1] + "," + wgs84_coord[0] + ")<br/>";
}
dataPanel.append("WGS84 Coordinates<br/>");
dataPanel.append(wgs84_coords + "<br/>\n");
}
//NOTE: Could show m², ha or km² depending on magnitude
dataPanel.append("<h3 class='clean'>Area : " + (area / 10000).toFixed(1) + " ha\n");
dataPanel.append('<div style="visibility:hidden" id="download_region">' +
......@@ -290,6 +277,7 @@ var regionChooser = (function(){
'<a href="#" onclick="regionChooser.checkCityGMLS(false);">(Select None)</a>\n'+
'</div>\n');
findIntersections();
dataPanel.append('<button type="button" onclick="regionChooser.copyCoordinatesToClipboard()" id="get_wgs84">Copy coordinates</button><br/>\n')
}
draw.on('drawend', function() {
......@@ -339,7 +327,7 @@ var regionChooser = (function(){
fxapp.log(message);
}
console.warning = function(message){
console.warn = function(message){
fxapp.warning(message);
}
}
......@@ -390,6 +378,48 @@ var regionChooser = (function(){
fxapp.selectRepository();
}
publicScope.copyCoordinatesToClipboard = function(){
var geom = sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326');
var wgs84Coords = geom.getLinearRing(0).getCoordinates();
var wktPolygon = "POLYGON((";
wktPolygon += wgs84Coords.map(lonLat => lonLat.join(" ")).join(", ");
publicScope.copyToClipboard(wktPolygon + "))");
}
// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and Internet Explorer 10+.
// Internet Explorer: The clipboard feature may be disabled by
// an administrator. By default a prompt is shown the first
// time the clipboard is used (per session).
// https://stackoverflow.com/a/33928558/6419007
publicScope.copyToClipboard = function(text) {
if (window.clipboardData && window.clipboardData.setData) {
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
return window.clipboardData.setData("Text", text);
}
else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
var textarea = document.createElement("textarea");
textarea.textContent = text;
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in Microsoft Edge.
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy"); // Security exception may be thrown by some browsers.
dataPanel.append("<h2 class='ok'>Coordinates copied to clipboard!</h2><br/>\n");
return;
}
catch (ex) {
console.warn("Copy to clipboard failed.", ex);
return prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
finally {
document.body.removeChild(textarea);
}
}
}
publicScope.showRepositoryName = function(path) {
document.getElementById("repo_path").textContent = path;
}
......
package eu.simstadt.regionchooser;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.AfterEach; // JUnit 5
import org.junit.jupiter.api.BeforeEach; // JUnit 5
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import picocli.CommandLine;
class RegionChooserTests
{
final PrintStream originalOut = System.out;
final PrintStream originalErr = System.err;
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final ByteArrayOutputStream err = new ByteArrayOutputStream();
private static final Path TEST_REPOSITORY = Paths.get("src/test/resources/testdata/");
@TempDir
Path tempDirectory;
Path outGML;
@BeforeEach
public void setUp() {
out.reset();
err.reset();
System.setOut(new PrintStream(out));
System.setErr(new PrintStream(err));
outGML = tempDirectory.resolve("output.gml");
}
@AfterEach
public void restore() throws IOException {
System.setOut(originalOut);
System.setErr(originalErr);
Files.deleteIfExists(outGML);
}
@Test
void testNoInput() {
new CommandLine(new RegionChooserCLI()).execute("");
String expectedErr = "Missing required options: '--input=input.gml', '--output=output.gml', '--wkt=polygon.wkt'";
assertTrue(err.toString().contains(expectedErr), err.toString() + " should contain " + expectedErr);
}
@Test
void testExtractRegionFromTwoCitygmls() throws IOException {
String wktPolygon = "POLYGON((3512984.7003764412 5405148.310572891,3513038.6360455155 5405010.072163861,3513142.7277745553 5405004.02571992,3514204.1661769524 5405563.192081669,3514399.2818417274 5405720.905457244,3514291.6158155007 5405896.706492759,3512984.7003764412 5405148.310572891))";
Path citygml1 = TEST_REPOSITORY.resolve("Stuttgart.proj/Stuttgart_LOD0_LOD1_small.gml");
Path citygml2 = TEST_REPOSITORY.resolve("Stuttgart.proj/Stöckach_überarbeitete GML-NoBuildingPart.gml");
Path inWKT = tempDirectory.resolve("polygon.wkt");
try (BufferedWriter wkt = Files.newBufferedWriter(inWKT)) {
wkt.write(wktPolygon);
}
assertFalse(Files.exists(outGML));
new CommandLine(new RegionChooserCLI()).execute("--input=" + citygml1 + "," + citygml2,
"--output=" + outGML, "--wkt=" + inWKT, "--epsg=31463", "--local");
assertTrue(Files.exists(outGML));
assertTrue(Files.size(outGML) > 600_000);
assertEquals(20, countBuildings(outGML));
}
@Test
void testExtractRegionFromTwoCitygmlsInWGS84() throws IOException {
String wktPolygon = "POLYGON((9.18991539528286 48.79067456353269, 9.195580220722313 48.7873947720947, 9.172062612079735 48.78241812742368, 9.170946813129538 48.78569824412753, 9.18991539528286 48.79067456353269))";
Path citygml1 = TEST_REPOSITORY.resolve("Stuttgart.proj/Stuttgart_LOD0_LOD1_small.gml");
Path citygml2 = TEST_REPOSITORY.resolve("Stuttgart.proj/Stöckach_überarbeitete GML-NoBuildingPart.gml");
Path inWKT = tempDirectory.resolve("polygon.wkt");
try (BufferedWriter wkt = Files.newBufferedWriter(inWKT)) {
wkt.write(wktPolygon);
}
assertFalse(Files.exists(outGML));
new CommandLine(new RegionChooserCLI()).execute("--input=" + citygml1 + "," + citygml2,
"--output=" + outGML, "--wkt=" + inWKT);
String expectedLog = "EPSG:31463";
assertTrue(err.toString().contains(expectedLog), err.toString() + " should contain " + expectedLog);
assertTrue(Files.exists(outGML));
assertTrue(Files.size(outGML) > 300_000);
assertEquals(22, countBuildings(outGML));
}
private long countBuildings(Path outGML) throws IOException {
return Files.readAllLines(outGML).stream().filter(line -> line.contains("bldg:Building gml:id=")).count();
}
@Test
void testExtractRegionWithStandardInput() throws IOException {
String wktPolygon = "POLYGON((-73.9959209576448 40.73286384885367, -73.996317924579 40.732359794090684, -73.9947515145143 40.7315061442504, -73.99422580154739 40.73214841515045, -73.9959209576448 40.73286384885367))";
Path citygml = TEST_REPOSITORY.resolve("NewYork.proj/ManhattanSmall.gml");
InputStream stdin = new ByteArrayInputStream(wktPolygon.getBytes(StandardCharsets.UTF_8));
System.setIn(stdin);
assertFalse(Files.exists(outGML));
new CommandLine(new RegionChooserCLI()).execute("--input=" + citygml, "--output=" + outGML,
"--wkt=-");
String expectedLog = "EPSG:32118";
assertTrue(err.toString().contains(expectedLog), err.toString() + " should contain " + expectedLog);
assertTrue(Files.exists(outGML));
assertEquals(2, countBuildings(outGML));
}
@Test
void testExtractRegionWithMissingInput() throws IOException {
String wktPolygon = "POLYGON((-73.9959209576448 40.73286384885367, -73.996317924579 40.732359794090684, -73.9947515145143 40.7315061442504, -73.99422580154739 40.73214841515045, -73.9959209576448 40.73286384885367))";
Path citygml = TEST_REPOSITORY.resolve("NewYork.proj/ManhattanSmall.gml");
Path inWKT = tempDirectory.resolve("polygon.wkt");
try (BufferedWriter wkt = Files.newBufferedWriter(inWKT)) {
wkt.write(wktPolygon);
}
new CommandLine(new RegionChooserCLI()).execute("--input=" + citygml, "--output=" + outGML,
"--wkt=-");
String expectedLog = "EPSG:32118";
assertTrue(err.toString().contains(expectedLog), err.toString() + " should contain " + expectedLog);
expectedLog = "Please provide \"POLYGON((x1 y1, x2 y2, ...))\" to standard input.";
assertTrue(err.toString().contains(expectedLog), err.toString() + " should contain " + expectedLog);
assertFalse(Files.exists(outGML));
}
}
......@@ -53,8 +53,7 @@ void testExtract3BuildingsFromGSK3Model() throws Throwable {
}
@Test
void testExtractBuildingsWithoutCommentsInBetween() throws Throwable {
//NOTE: Small region around WashingtonSquare
void testExtractBuildingsWithCommentsInBetween() throws Throwable {
String wktPolygon = "POLYGON((300259.78663489706 62835.835907766595,300230.33294975647 62792.0482567884,300213.5667431851 62770.83143720031,300183.6592861123 62730.20347659383,300252.9947486632 62676.938468840905,300273.3862256562 62701.767105345614,300257.5250407747 62715.760413539596,300308.2754543957 62805.14198211394,300259.78663489706 62835.835907766595))";
Path citygmlPath = TEST_REPOSITORY.resolve("NewYork.proj/ManhattanSmall.gml");
String archGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(wktPolygon, EPSG_32118, citygmlPath)
......@@ -65,10 +64,6 @@ void testExtractBuildingsWithoutCommentsInBetween() throws Throwable {
assertTrue(archGMLString.contains("uuid_0985cebb-922d-4b3e-95e5-15dc6089cd28"));
assertTrue(archGMLString.contains(CITY_MODEL_HEADER));
assertTrue(archGMLString.contains(CITY_MODEL_FOOTER));
assertFalse(archGMLString.contains("comment between buildings"),
"Comments between buildings shouldn't be extracted");
assertFalse(archGMLString.contains("comment after last building"),
"Comments after buildings shouldn't be extracted");
}
@Test
......
......@@ -7,25 +7,19 @@
import java.util.Arrays;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import com.ximpleware.NavException;
import com.ximpleware.XPathEvalException;
import com.ximpleware.XPathParseException;
public class RegionExtractorWithDifferentInputTests
class RegionExtractorWithDifferentInputTests
{
private static final WKTReader WKT_READER = new WKTReader();
private static final WKTWriter WKT_WRITER = new WKTWriter();
private static final Path TEST_REPOSITORY = Paths.get("src/test/resources/testdata/");
//NOTE: This test can be adapted to download a region which is too large for the server. Here with local coordinates
@Test
public void testExtractRegionWithLocalCRS()
void testExtractRegionWithLocalCRS()
throws IOException, XPathParseException, NavException, XPathEvalException, ParseException {
String citygml = "DA13_DA14_3D_Buildings_Port_Morris.gml";
String projectName = "NewYork";
......@@ -39,9 +33,8 @@ public void testExtractRegionWithLocalCRS()
"One weird shaped roof should be inside the region");
}
//NOTE: This test can be adapted to download a region which is too large for the server. Here with WGS84 coordinates
@Test
public void testExtractRegionWithWGS84()
void testExtractRegionWithWGS84()
throws ParseException, IOException, XPathParseException, NavException, XPathEvalException {
String wgs84WktPolygon = "POLYGON((-73.91140940026597 40.804246732157196,-73.91424181298568 40.80025100302325,-73.90934946374252 40.79755456207104,-73.90561582879378 40.80116062104605,-73.90960695580794 40.80340212653638,-73.91140940026597 40.804246732157196))";
String citygml = "DA13_DA14_3D_Buildings_Port_Morris.gml";
......@@ -49,19 +42,16 @@ public void testExtractRegionWithWGS84()
Path project = TEST_REPOSITORY.resolve(projectName + ".proj");
Path citygmlPath = project.resolve(citygml);
Polygon wgs84Polygon = (Polygon) WKT_READER.read(wgs84WktPolygon);
CoordinateReferenceSystem localCRS = RegionChooserUtils.crsFromCityGMLHeader(citygmlPath);
String localWktPolygon = WKT_WRITER
.write(RegionChooserUtils.changePolygonCRS(wgs84Polygon, RegionChooserUtils.WGS84, localCRS));
String localWktPolygon = RegionChooserUtils.wktPolygonToLocalCRS(wgs84WktPolygon, localCRS);
StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(localWktPolygon, localCRS.getName(),
citygmlPath);
assertTrue(sb.toString().contains("gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"),
"One weird shaped roof should be inside the region");
}
//NOTE: This test can be adapted to download a region which is too large for the server. Here with old coordinates from WebSimstadt
@Test
public void testExtractRegionWithOldCoordinates()
void testExtractRegionWithOldCoordinates()
throws ParseException, IOException, XPathParseException, NavException, XPathEvalException {
String oldFormatPolygon = "(40.81173171854368,-73.93268437431763)\r\n" +
"(40.81069231965162,-73.93068165999941)\r\n" +
......@@ -98,16 +88,12 @@ public void testExtractRegionWithOldCoordinates()
Path project = TEST_REPOSITORY.resolve(projectName + ".proj");
Path citygmlPath = project.resolve(citygml);
Polygon wgs84Polygon = (Polygon) WKT_READER.read(wgs84WktPolygon);
CoordinateReferenceSystem localCRS = RegionChooserUtils.crsFromCityGMLHeader(citygmlPath);
String localWktPolygon = WKT_WRITER
.write(RegionChooserUtils.changePolygonCRS(wgs84Polygon, RegionChooserUtils.WGS84, localCRS));
String localWktPolygon = RegionChooserUtils.wktPolygonToLocalCRS(wgs84WktPolygon, localCRS);
StringBuilder sb = RegionExtractor.selectRegionDirectlyFromCityGML(localWktPolygon, localCRS.getName(),
citygmlPath);
assertTrue(sb.toString().contains("gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"),
"One weird shaped roof should be inside the region");
}
//TODO: Write a method to merge RegionChooser results from multiple gmls
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment