diff --git a/src/eu/simstadt/regionchooser/RegionChooserBrowser.java b/src/eu/simstadt/regionchooser/RegionChooserBrowser.java index e8f86239b4f3fb86b17f18c300e7836de58f96bc..1a42a2a8701e9d0978e5df5e49c7e860bc66d12c 100644 --- a/src/eu/simstadt/regionchooser/RegionChooserBrowser.java +++ b/src/eu/simstadt/regionchooser/RegionChooserBrowser.java @@ -13,6 +13,8 @@ import java.util.prefs.Preferences; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.xml.stream.XMLStreamException; +import org.xml.sax.SAXParseException; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; @@ -91,7 +93,7 @@ public void extractZIPtoGML(String zipFilename) throws IOException { } public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml) throws IOException, - ParseException { + ParseException, SAXParseException, XMLStreamException { StringBuffer sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon); File buildingIdsFile = selectSaveFileWithDialog(project, citygml, "selected_region"); diff --git a/src/eu/simstadt/regionchooser/RegionExtractor.java b/src/eu/simstadt/regionchooser/RegionExtractor.java index 9c4faf55d3b9214bbf17769a336af645be346d01..c0a40030c9b3c4ebe9df910d601a340a75aff0e2 100644 --- a/src/eu/simstadt/regionchooser/RegionExtractor.java +++ b/src/eu/simstadt/regionchooser/RegionExtractor.java @@ -6,12 +6,16 @@ import java.nio.file.Path; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.xml.stream.XMLStreamException; +import org.xml.sax.SAXParseException; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; +import de.hft.stuttgart.citydoctor.writer.CityDoctorModel; +import eu.simstadt.geo.GeoCoordinatesAccessor; public class RegionExtractor @@ -19,38 +23,48 @@ static private WKTReader wktReader = new WKTReader(); static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, String wktPolygon) - throws IOException, ParseException { - // Instant start = Instant.now(); + throws IOException, ParseException, SAXParseException, XMLStreamException { //TODO: wktPolygon should be in WGS84, and converted here to locate coordinates system - //TODO: GetSRSName, either via CityDoctorModel or reading 50 first lines of the citygmlfile - // CityDoctorModel model = CityDoctorModel.loadWithEnergyADEAndNoSchemaValidation(citygmlPath.toFile()); - // GeoCoordinatesAccessor coordinates = GeoCoordinatesAccessor.coordinatesComputedFromBuildingsIfNeeded(model); - // System.out.println(coordinates.getCoordinateReferenceSystem().getName()); + CityDoctorModel model = CityDoctorModel.loadWithEnergyADEAndNoSchemaValidation(citygmlPath.toFile()); + //TODO: Could extract srsName directly from citygml header. It would be much faster for big files + GeoCoordinatesAccessor coordinates = GeoCoordinatesAccessor.coordinatesComputedFromBuildingsIfNeeded(model); + String srsName = coordinates.getCoordinateReferenceSystem().getName(); Geometry poly = wktReader.read(wktPolygon); final GeometryFactory gf = new GeometryFactory(); //TODO: Don't read all the file. Not possible for 15GB gml files String s = new String(Files.readAllBytes(citygmlPath), Charset.defaultCharset()); Pattern cityObjectPattern = Pattern - .compile("(?s)<(core:)?cityObjectMember>.*?<\\/(core:)?cityObjectMember>\\s*"); - //TODO: Allow other coordinate systems. Either use distinc patterns depending on EPSG, or use CityDoctorModel - Pattern gsk3CoordinatesPattern = Pattern - .compile("(?<![\\d\\.])(3\\d\\d\\d\\d\\d\\d[\\.\\d]*) (5\\d\\d\\d\\d\\d\\d[\\.\\d]*)"); + .compile("(?s)<(core:)?cityObjectMember[^>]*>.*?<\\/(core:)?cityObjectMember>\\s*"); + + Pattern coordinatesPattern = null; + switch (srsName) { + case "EPSG:31467": + coordinatesPattern = Pattern + .compile("(?<![\\d\\.])(3\\d\\d\\d\\d\\d\\d[\\.\\d]*) (5\\d\\d\\d\\d\\d\\d[\\.\\d]*)"); + break; + case "EPSG:32118": + coordinatesPattern = Pattern + .compile("(?<![\\d\\.])([23]\\d\\d\\d\\d\\d[\\.\\d]*) ([4-8]\\d\\d\\d\\d[\\.\\d]*)"); + break; + default: + throw new IllegalArgumentException("Sorry. " + srsName + " is not supported yet."); + } Matcher cityObjectMatcher = cityObjectPattern.matcher(s); StringBuffer sb = new StringBuffer(); int i = 0; while (cityObjectMatcher.find()) { cityObjectMatcher.appendReplacement(sb, ""); String cityObject = cityObjectMatcher.group(); - Matcher gsk3CoordinatesMatcher = gsk3CoordinatesPattern.matcher(cityObject); + Matcher coordinatesMatcher = coordinatesPattern.matcher(cityObject); int coordinatesCount = 0; double xTotal = 0; double yTotal = 0; - while (gsk3CoordinatesMatcher.find()) { + while (coordinatesMatcher.find()) { coordinatesCount++; - xTotal += Double.valueOf(gsk3CoordinatesMatcher.group(1)); - yTotal += Double.valueOf(gsk3CoordinatesMatcher.group(2)); + xTotal += Double.valueOf(coordinatesMatcher.group(1)); + yTotal += Double.valueOf(coordinatesMatcher.group(2)); } double x = xTotal / coordinatesCount; double y = yTotal / coordinatesCount; @@ -65,7 +79,6 @@ static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, Str if (i > 0) { cityObjectMatcher.appendTail(sb); } - // System.out.println(Duration.between(start, Instant.now())); return sb; }