diff --git a/src/main/java/eu/simstadt/regionchooser/RegionChooserCommandLineInterface.java b/src/main/java/eu/simstadt/regionchooser/RegionChooserCommandLineInterface.java index 7b01e1dfbec33a1c7f64d47c79bc9de56106a65e..7dd29e3afadfcb81e23da0a420a55f3a7fa32b69 100644 --- a/src/main/java/eu/simstadt/regionchooser/RegionChooserCommandLineInterface.java +++ b/src/main/java/eu/simstadt/regionchooser/RegionChooserCommandLineInterface.java @@ -7,9 +7,6 @@ import java.util.Scanner; import java.util.concurrent.Callable; import java.util.logging.Logger; -import org.locationtech.jts.geom.Polygon; -import org.locationtech.jts.io.WKTReader; -import org.locationtech.jts.io.WKTWriter; import org.osgeo.proj4j.CoordinateReferenceSystem; import picocli.CommandLine; import picocli.CommandLine.Command; @@ -49,7 +46,6 @@ class RegionChooserCommandLineInterface implements Callable<Integer> @Override public Integer call() throws Exception { - //TODO: Move as much logic to utils as possible //TODO: Test CoordinateReferenceSystem localCRS; @@ -76,12 +72,8 @@ public Integer call() throws Exception { } if (!localCoordinates) { - final WKTReader WKT_READER = new WKTReader(); - final WKTWriter WKT_WRITER = new WKTWriter(); // WKT coordinates are in WGS84, so should be first converted to srsName - Polygon wgs84Polygon = (Polygon) WKT_READER.read(wktPolygon); - wktPolygon = WKT_WRITER - .write(RegionChooserUtils.changePolygonCRS(wgs84Polygon, RegionChooserUtils.WGS84, localCRS)); + wktPolygon = RegionChooserUtils.wktPolygonToLocalCRS(wktPolygon, localCRS); } LOGGER.info("WKT Polygon expressed in local coordinates: " + wktPolygon); diff --git a/src/main/java/eu/simstadt/regionchooser/RegionChooserUtils.java b/src/main/java/eu/simstadt/regionchooser/RegionChooserUtils.java index 71e87b43c308657f8a4ac451bf91745a9dbb3480..b7dde84da5917dc127195dff4233f8dc7873d98c 100644 --- a/src/main/java/eu/simstadt/regionchooser/RegionChooserUtils.java +++ b/src/main/java/eu/simstadt/regionchooser/RegionChooserUtils.java @@ -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; @@ -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 diff --git a/src/main/java/eu/simstadt/regionchooser/RegionExtractor.java b/src/main/java/eu/simstadt/regionchooser/RegionExtractor.java index 39a1ec5d150ef98f6dd3196ae52708e502e146e7..8adcfcb7e7ccabc6a18543208fd4de3e154fd87a 100644 --- a/src/main/java/eu/simstadt/regionchooser/RegionExtractor.java +++ b/src/main/java/eu/simstadt/regionchooser/RegionExtractor.java @@ -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 @@ -54,7 +54,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s 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++) { @@ -68,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()); diff --git a/src/test/java/eu/simstadt/regionchooser/RegionExtractorWithDifferentInputTests.java b/src/test/java/eu/simstadt/regionchooser/RegionExtractorWithDifferentInputTests.java index 47bd64717d5db996940dfda49901ff1abe8ba5d3..cc7aa042d8c4c4c883050fa5365b723193d1fff4 100644 --- a/src/test/java/eu/simstadt/regionchooser/RegionExtractorWithDifferentInputTests.java +++ b/src/test/java/eu/simstadt/regionchooser/RegionExtractorWithDifferentInputTests.java @@ -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,10 +42,8 @@ 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"), @@ -61,7 +52,7 @@ public void testExtractRegionWithWGS84() //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 +89,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 }