diff --git a/.classpath b/.classpath index 18bef9fbae36b44b8666306ff38b40a8eb38ce76..0089bc9e4b96450df0e30611c4d29c34d13d461f 100644 --- a/.classpath +++ b/.classpath @@ -6,5 +6,6 @@ + diff --git a/lib/vtd-xml_2_13_1.jar b/lib/vtd-xml_2_13_1.jar new file mode 100644 index 0000000000000000000000000000000000000000..1e021e5f680589442fc8a3bc478b7049c6f369d4 Binary files /dev/null and b/lib/vtd-xml_2_13_1.jar differ diff --git a/src/eu/simstadt/regionchooser/RegionChooserBrowser.java b/src/eu/simstadt/regionchooser/RegionChooserBrowser.java index 0bd52d2fb90b11f3e689eff569e06830190c0233..e7efcc364ae40c703ce6f15adb61681b884ad077 100644 --- a/src/eu/simstadt/regionchooser/RegionChooserBrowser.java +++ b/src/eu/simstadt/regionchooser/RegionChooserBrowser.java @@ -18,6 +18,9 @@ import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; +import com.ximpleware.NavException; +import com.ximpleware.XPathEvalException; +import com.ximpleware.XPathParseException; import eu.simstadt.nf4j.ExportJobFromJavaFXRegionChooser; import javafx.beans.value.ObservableValue; import javafx.concurrent.Task; @@ -94,7 +97,8 @@ public void extractZIPtoGML(String zipFilename) throws IOException { public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml, String srsName) throws IOException, - ParseException, SAXParseException, XMLStreamException { + ParseException, SAXParseException, XMLStreamException, NumberFormatException, XPathParseException, + NavException, XPathEvalException { StringBuffer sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon, srsName); diff --git a/src/eu/simstadt/regionchooser/RegionExtractor.java b/src/eu/simstadt/regionchooser/RegionExtractor.java index 6ccdd19cc55f48bdba25627e2b7138d7eb9a77d1..f859ced2135771620ef1010200e4b9aa94daa483 100644 --- a/src/eu/simstadt/regionchooser/RegionExtractor.java +++ b/src/eu/simstadt/regionchooser/RegionExtractor.java @@ -1,11 +1,9 @@ package eu.simstadt.regionchooser; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.logging.Logger; import javax.xml.stream.XMLStreamException; import org.xml.sax.SAXParseException; import com.vividsolutions.jts.geom.Coordinate; @@ -14,95 +12,90 @@ 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; +import com.ximpleware.AutoPilot; +import com.ximpleware.NavException; +import com.ximpleware.VTDGen; +import com.ximpleware.VTDNav; +import com.ximpleware.XPathEvalException; +import com.ximpleware.XPathParseException; +import sun.misc.Launcher; public class RegionExtractor { static private WKTReader wktReader = new WKTReader(); + private static final Logger LOGGER = Logger.getLogger(Launcher.class.getName()); + static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, String wktPolygon, String srsName) - throws IOException, ParseException, SAXParseException, XMLStreamException { + throws SAXParseException, XMLStreamException, ParseException, XPathParseException, NavException, + NumberFormatException, XPathEvalException, IOException { 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()); + StringBuffer sb = new StringBuffer(); - Pattern cityObjectPattern = Pattern - .compile("(?s)<(core:)?cityObjectMember[^>]*>.*?<\\/(core:)?cityObjectMember>\\s*"); + int foundBuildingsCount = 0; + int buildingsCount = 0; + long offsetAndLength; + int buildingOffset = 0; + int buildingLength = 0; + int coordinatesOffset = 0; + int coordinatesLength = 0; + VTDGen parser = new VTDGen(); + if (parser.parseFile(citygmlPath.toString(), false)) { - Pattern coordinatesPattern = null; - switch (srsName) { - case "EPSG:31467": - coordinatesPattern = Pattern - .compile("(?> 32); + String cityObject = navigator.toRawString(buildingOffset, buildingLength); + // Add header + if (buildingsCount == 0) { + sb.append(navigator.toRawString(0, buildingOffset)); + } + buildingsCount += 1; + if (buildingsCount % 1000 == 0) { + LOGGER.info("1000 buildings parsed"); + } - throw new IllegalArgumentException("Sorry. " + srsName + " is not supported yet."); - } + int coordinatesCount = 0; + double xTotal = 0; + double yTotal = 0; - Matcher cityObjectMatcher = cityObjectPattern.matcher(s); - StringBuffer sb = new StringBuffer(); - int i = 0; - while (cityObjectMatcher.find()) + while (coordinatesFinder.evalXPath() != -1) { + offsetAndLength = navigator.getContentFragment(); + coordinatesOffset = (int) offsetAndLength; + coordinatesLength = (int) (offsetAndLength >> 32); + String posList = navigator.toRawString(coordinatesOffset, coordinatesLength); + String[] coordinates = posList.split(" "); + for (int k = 0; k < coordinates.length; k = k + 3) { + coordinatesCount++; + xTotal += Double.valueOf(coordinates[k]); + yTotal += Double.valueOf(coordinates[k + 1]); + } + } - { - cityObjectMatcher.appendReplacement(sb, ""); - String cityObject = cityObjectMatcher.group(); - Matcher coordinatesMatcher = coordinatesPattern.matcher(cityObject); - int coordinatesCount = 0; - double xTotal = 0; - double yTotal = 0; - while (coordinatesMatcher.find()) { - coordinatesCount++; - xTotal += Double.valueOf(coordinatesMatcher.group(1)); - yTotal += Double.valueOf(coordinatesMatcher.group(2)); - } - double x = xTotal / coordinatesCount; - double y = yTotal / coordinatesCount; - Coordinate coord = new Coordinate(x, y); - Point point = gf.createPoint(coord); - if (point.within(poly)) { - i++; - sb.append(cityObject); + double x = xTotal / coordinatesCount; + double y = yTotal / coordinatesCount; + Coordinate coord = new Coordinate(x, y); + Point point = gf.createPoint(coord); + if (point.within(poly)) { + foundBuildingsCount++; + sb.append(cityObject); + } } + LOGGER.info("Buildings found in selected region " + foundBuildingsCount); + int footerOffset = buildingOffset + buildingLength; + int footerLength = (int) (Files.size(citygmlPath) - footerOffset); + sb.append(navigator.toRawString(footerOffset, footerLength)); } - System.out.println("Buildings found in selected region " + i); - if (i > 0) - { - cityObjectMatcher.appendTail(sb); - } return sb; } - } diff --git a/src/eu/simstadt/regionchooser/website/script/simstadt_openlayers.js b/src/eu/simstadt/regionchooser/website/script/simstadt_openlayers.js index 8c5dd114441b436215d4b73dd3c762b07b1fd944..c0c4d7855f4a420f3b6e75a95d6861b40e6e7a2b 100644 --- a/src/eu/simstadt/regionchooser/website/script/simstadt_openlayers.js +++ b/src/eu/simstadt/regionchooser/website/script/simstadt_openlayers.js @@ -310,7 +310,7 @@ function downloadRegionFromNovaFACTORY(i) { } function sketchAsWKT(srsName) { - console.log(srsName); + console.log(srsName); //TODO: Check if proj4 knows this coordinate system srsName = (typeof srsName === 'undefined') ? 'EPSG:4326' : srsName; var wktFormat = new ol.format.WKT(); return wktFormat.writeFeature(sketch, { diff --git a/test/eu/simstadt/regionchooser/test/RegionExtractorTests.java b/test/eu/simstadt/regionchooser/test/RegionExtractorTests.java index ab319cf9520e5cfbda45841725c696fdb641dffe..b75b2db6bc1c42c167e5f9a6da8dc60fdadc253b 100644 --- a/test/eu/simstadt/regionchooser/test/RegionExtractorTests.java +++ b/test/eu/simstadt/regionchooser/test/RegionExtractorTests.java @@ -35,6 +35,8 @@ public void testExtract3BuildingsFromGSK3Model() throws Throwable { assertTrue(churchGMLString.contains("DEBW_LOD2_203056")); assertTrue(churchGMLString.contains("DEBW_LOD2_2869")); assertTrue(churchGMLString.contains("DEBW_LOD2_2909")); + assertTrue(churchGMLString.contains("