Commit d118c3ac authored by duminil's avatar duminil
Browse files

RegionChooser: Documentation, refactoring and tests.

parent 671dfe38
...@@ -95,12 +95,10 @@ public void extractZIPtoGML(String zipFilename) throws IOException { ...@@ -95,12 +95,10 @@ public void extractZIPtoGML(String zipFilename) throws IOException {
zipFile.close(); zipFile.close();
} }
public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml, String srsName) public void downloadRegionFromCityGML(String wktPolygon, String project, String citygml)
throws IOException, throws IOException, ParseException, SAXParseException, XMLStreamException, NumberFormatException,
ParseException, SAXParseException, XMLStreamException, NumberFormatException, XPathParseException, XPathParseException, NavException, XPathEvalException {
NavException, XPathEvalException { StringBuffer sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon);
StringBuffer sb = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath(project, citygml), wktPolygon,
srsName);
File buildingIdsFile = selectSaveFileWithDialog(project, citygml, "selected_region"); File buildingIdsFile = selectSaveFileWithDialog(project, citygml, "selected_region");
if (buildingIdsFile != null) { if (buildingIdsFile != null) {
......
...@@ -12,9 +12,15 @@ public class RegionChooserFX extends Application ...@@ -12,9 +12,15 @@ public class RegionChooserFX extends Application
private Scene scene; private Scene scene;
protected final static Logger LOGGER = Logger.getLogger(RegionChooserFX.class.getName()); protected final static Logger LOGGER = Logger.getLogger(RegionChooserFX.class.getName());
/**
* Start point of RegionChooser application. Either "Run as Java" from Eclipse or run
* "RegionChooser.bat/.sh/.command" from deployed SimStadt folder.
*
* This application is basically just a scene and a browser for the RegionChooser website (HTML + Javascript frontend
* + Java backend). The Java part is written in RegionChooserBrowser.
*/
@Override @Override
public void start(Stage stage) { public void start(Stage stage) {
// create the scene
stage.setTitle("RegionChooserJavaFX"); stage.setTitle("RegionChooserJavaFX");
scene = new Scene(new RegionChooserBrowser(), 1024, 768, Color.web("#666970")); scene = new Scene(new RegionChooserBrowser(), 1024, 768, Color.web("#666970"));
stage.setScene(scene); stage.setScene(scene);
......
...@@ -25,7 +25,19 @@ ...@@ -25,7 +25,19 @@
private static final Logger LOGGER = Logger.getLogger(RegionExtractor.class.getName()); private static final Logger LOGGER = Logger.getLogger(RegionExtractor.class.getName());
private static final GeometryFactory gf = new GeometryFactory(); private static final GeometryFactory gf = new GeometryFactory();
static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, String wktPolygon, String srsName) /**
* Main method behind RegionChooser. Given a CityGML (as Path) and a geometry (as Well-known text POLYGON, in the
* same coordinate system as the CityGML), it iterates over each Building and checks if the building is inside the
* geometry. It only works with CityGML files smaller than 2GB. It uses VTD-XML parser instead of a whole
* Simstadt/Citydoctor/Citygml model.
*
*
* @param citygmlPath
* @param wktPolygon
* @return
* @throws Exception
*/
static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, String wktPolygon)
throws SAXParseException, XMLStreamException, ParseException, XPathParseException, NavException, throws SAXParseException, XMLStreamException, ParseException, XPathParseException, NavException,
NumberFormatException, XPathEvalException, IOException { NumberFormatException, XPathEvalException, IOException {
...@@ -37,11 +49,14 @@ static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, Str ...@@ -37,11 +49,14 @@ static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, Str
CityGmlIterator citygml = new CityGmlIterator(citygmlPath); CityGmlIterator citygml = new CityGmlIterator(citygmlPath);
for (BuildingXmlNode buildingXmlNode : citygml) { for (BuildingXmlNode buildingXmlNode : citygml) {
if (buildingsCount == 0) { if (buildingsCount == 0) {
//TODO: Replace original CityGML envelope with a smaller one, corresponding to wktPolygon
// Envelope env = poly.getEnvelopeInternal();
// System.out.println(env);
sb.append(citygml.getHeader()); sb.append(citygml.getHeader());
} }
buildingsCount += 1; buildingsCount += 1;
Coordinate coord = new Coordinate(buildingXmlNode.x, buildingXmlNode.y); Coordinate coord = new Coordinate(buildingXmlNode.x, buildingXmlNode.y);
Point point = gf.createPoint(coord); //NOTE: Should it be in buildingXmlNode? Point point = gf.createPoint(coord);
if (point.within(poly)) { if (point.within(poly)) {
foundBuildingsCount++; foundBuildingsCount++;
sb.append(buildingXmlNode.toString()); sb.append(buildingXmlNode.toString());
......
...@@ -221,20 +221,27 @@ function findIntersections() { ...@@ -221,20 +221,27 @@ function findIntersections() {
function downloadRegionFromCityGML(i) { function downloadRegionFromCityGML(i) {
// TODO: Disable all links // TODO: Disable all links
// TODO: DRY // TODO: DRY
$("html").addClass("wait");
var feature = kml_source.getFeatures()[i]; var feature = kml_source.getFeatures()[i];
// Waiting 100ms in order to let the cursor change // Waiting 100ms in order to let the cursor change
setTimeout(function() { setTimeout(function() {
// var start = new Date().getTime(); var start = new Date().getTime();
var srsName = feature.get("srsName") || "EPSG:31467"; var srsName = feature.get("srsName") || "EPSG:31467";
fxapp.downloadRegionFromCityGML(sketchAsWKT(srsName), feature.get("project"), feature.get("name"), srsName); if (proj4.defs(srsName)){
// var end = new Date().getTime(); $("html").addClass("wait");
// var time = end - start; console.log("Selected region is written in " + srsName + " coordinate system.");
// console.log('DL Execution time: ' + time); fxapp.downloadRegionFromCityGML(sketchAsWKT(srsName), feature.get("project"), feature.get("name"));
var end = new Date().getTime();
var time = end - start;
console.log('DL Execution time: ' + time);
setTimeout(function() { setTimeout(function() {
$("html").removeClass("wait"); $("html").removeClass("wait");
dataPanel.append("Done<br/>\n"); dataPanel.append("Done<br/>\n");
}, 100); }, 100);
} else {
var msg = "ERROR : Unknown coordinate system : \"" + srsName + "\". Cannot extract any region";
console.log(msg);
dataPanel.append(msg + "<br/>\n");
}
}, 100); }, 100);
} }
...@@ -313,7 +320,6 @@ function downloadRegionFromNovaFACTORY(i) { ...@@ -313,7 +320,6 @@ function downloadRegionFromNovaFACTORY(i) {
} }
function sketchAsWKT(srsName) { function sketchAsWKT(srsName) {
console.log(srsName); //TODO: Check if proj4 knows this coordinate system
srsName = (typeof srsName === 'undefined') ? 'EPSG:4326' : srsName; srsName = (typeof srsName === 'undefined') ? 'EPSG:4326' : srsName;
var wktFormat = new ol.format.WKT(); var wktFormat = new ol.format.WKT();
return wktFormat.writeFeature(sketch, { return wktFormat.writeFeature(sketch, {
......
package eu.simstadt.nf4j.async.test; package eu.simstadt.nf4j.async;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
......
package eu.simstadt.nf4j.async.test; package eu.simstadt.nf4j.async;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
......
package eu.simstadt.regionchooser.test; package eu.simstadt.regionchooser;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.junit.Test; import org.junit.Test;
import eu.simstadt.regionchooser.RegionExtractor;
public class RegionExtractorTests public class RegionExtractorTests
...@@ -26,11 +25,11 @@ public static int countRegexMatches(String str, String subStr) { ...@@ -26,11 +25,11 @@ public static int countRegexMatches(String str, String subStr) {
@Test @Test
public void testExtract3BuildingsFromGSK3Model() throws Throwable { public void testExtract3BuildingsFromGSK3Model() throws Throwable {
//NOTE: Small region around Martinskirche in Grünbühl //NOTE: Small region around Martinskirche in Grünbühl
// "EPSG:31467"
String wktPolygon = "POLYGON((3515848.896028535 5415823.108586172,3515848.9512289143 5415803.590347393,3515829.0815150724 5415803.338023346,3515830.9784850604 5415793.437034622,3515842.0946056456 5415793.272282251,3515843.3515515197 5415766.204935087,3515864.1064344468 5415766.557899496,3515876.489172751 5415805.433782301,3515876.343844858 5415822.009293416,3515848.896028535 5415823.108586172))"; String wktPolygon = "POLYGON((3515848.896028535 5415823.108586172,3515848.9512289143 5415803.590347393,3515829.0815150724 5415803.338023346,3515830.9784850604 5415793.437034622,3515842.0946056456 5415793.272282251,3515843.3515515197 5415766.204935087,3515864.1064344468 5415766.557899496,3515876.489172751 5415805.433782301,3515876.343844858 5415822.009293416,3515848.896028535 5415823.108586172))";
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("Gruenbuehl.proj/20140218_Gruenbuehl_LOD2.gml"); Path citygmlPath = repo.resolve("Gruenbuehl.proj/20140218_Gruenbuehl_LOD2.gml");
String churchGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon, "EPSG:31467") String churchGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
.toString();
assertEquals(countRegexMatches(churchGMLString, "<(core:)?cityObjectMember"), 3); assertEquals(countRegexMatches(churchGMLString, "<(core:)?cityObjectMember"), 3);
assertTrue(churchGMLString.contains("Donaustr")); assertTrue(churchGMLString.contains("Donaustr"));
assertTrue(churchGMLString.contains("DEBW_LOD2_203056")); assertTrue(churchGMLString.contains("DEBW_LOD2_203056"));
...@@ -41,13 +40,13 @@ public void testExtract3BuildingsFromGSK3Model() throws Throwable { ...@@ -41,13 +40,13 @@ public void testExtract3BuildingsFromGSK3Model() throws Throwable {
} }
@Test @Test
public void testExtract3BuildingsFromNAD83Model() throws Throwable { public void testExtractBuildingsWithoutCommentsInBetween() throws Throwable {
//NOTE: Small region around WashingtonSquare //NOTE: Small region around WashingtonSquare
// "EPSG:32118"
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))"; 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 repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/ManhattanSmall.gml"); Path citygmlPath = repo.resolve("NewYork.proj/ManhattanSmall.gml");
String archGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon, "EPSG:32118") String archGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
.toString();
assertEquals(countRegexMatches(archGMLString, "<(core:)?cityObjectMember"), 2); assertEquals(countRegexMatches(archGMLString, "<(core:)?cityObjectMember"), 2);
assertTrue(archGMLString.contains("WASHINGTON SQUARE")); assertTrue(archGMLString.contains("WASHINGTON SQUARE"));
assertTrue(archGMLString.contains("uuid_c0980a6e-05ea-4d09-bc83-efab226945a1")); assertTrue(archGMLString.contains("uuid_c0980a6e-05ea-4d09-bc83-efab226945a1"));
...@@ -58,14 +57,28 @@ public void testExtract3BuildingsFromNAD83Model() throws Throwable { ...@@ -58,14 +57,28 @@ public void testExtract3BuildingsFromNAD83Model() throws Throwable {
assertFalse(archGMLString.contains("comment after last building")); // Comment assertFalse(archGMLString.contains("comment after last building")); // Comment
} }
@Test
public void testExtractBuildingsAndChangeEnvelope() throws Throwable {
String wktPolygon = "POLYGON((299761.8123557725 61122.68126771413,299721.46983062755 61058.11626595352,299780.84627343423 61021.99295737501,299823.9079725632 61083.3979344517,299761.8123557725 61122.68126771413))";
Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/FamilyCourt_LOD2_with_PLUTO_attributes.gml");
String familyCourtBuilding = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
assertEquals(countRegexMatches(familyCourtBuilding, "<(core:)?cityObjectMember"), 1);
assertTrue(familyCourtBuilding.contains("Bldg_12210021066"));
assertFalse("The exported CityGML shouldn't contain the original envelope", familyCourtBuilding
.contains("<gml:lowerCorner>298393.46959639067 59277.34021543693 -11.892070104139751</gml:lowerCorner>"));
assertFalse("The exported CityGML shouldn't contain the original envelope", familyCourtBuilding
.contains("<gml:upperCorner>305641.79529639013 67101.44881543722 547.7591871983744</gml:upperCorner>"));
}
@Test @Test
public void testExtract0BuildingsWithWrongCoordinates() throws Throwable { public void testExtract0BuildingsWithWrongCoordinates() throws Throwable {
//NOTE: Small region, far away from NYC //NOTE: Small region, far away from NYC
// "EPSG:32118"
String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"; String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))";
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/ManhattanSmall.gml"); Path citygmlPath = repo.resolve("NewYork.proj/ManhattanSmall.gml");
String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon, "EPSG:32118") String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
.toString();
assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0); assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0);
assertTrue(emptyGMLString.contains("<CityModel")); // Header assertTrue(emptyGMLString.contains("<CityModel")); // Header
assertTrue(emptyGMLString.contains("</CityModel")); // Footer assertTrue(emptyGMLString.contains("</CityModel")); // Footer
...@@ -74,11 +87,11 @@ public void testExtract0BuildingsWithWrongCoordinates() throws Throwable { ...@@ -74,11 +87,11 @@ public void testExtract0BuildingsWithWrongCoordinates() throws Throwable {
@Test @Test
public void testExtract0BuildingsFromEmptyGML() throws Throwable { public void testExtract0BuildingsFromEmptyGML() throws Throwable {
//NOTE: Small region, with too many spaces between coordinates //NOTE: Small region, with too many spaces between coordinates
// "EPSG:32118"
String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"; String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))";
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/empty_model.gml"); Path citygmlPath = repo.resolve("NewYork.proj/empty_model.gml");
String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon, "EPSG:32118") String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
.toString();
assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0); assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0);
assertTrue(emptyGMLString.contains("<core:CityModel")); // Header assertTrue(emptyGMLString.contains("<core:CityModel")); // Header
assertTrue(emptyGMLString.contains("</core:CityModel")); // Footer assertTrue(emptyGMLString.contains("</core:CityModel")); // Footer
...@@ -90,8 +103,7 @@ public void testExtract0BuildingsFromWeirdGML() throws Throwable { ...@@ -90,8 +103,7 @@ public void testExtract0BuildingsFromWeirdGML() throws Throwable {
String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"; String wktPolygon = "POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))";
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/broken_nyc_lod2.gml"); Path citygmlPath = repo.resolve("NewYork.proj/broken_nyc_lod2.gml");
String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon, "EPSG:32118") String emptyGMLString = RegionExtractor.selectRegionDirectlyFromCityGML(citygmlPath, wktPolygon).toString();
.toString();
assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0); assertEquals(countRegexMatches(emptyGMLString, "<(core:)?cityObjectMember"), 0);
assertTrue(emptyGMLString.contains("<core:CityModel")); // Header assertTrue(emptyGMLString.contains("<core:CityModel")); // Header
assertTrue(emptyGMLString.contains("</core:CityModel")); // Footer assertTrue(emptyGMLString.contains("</core:CityModel")); // Footer
......
Supports Markdown
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