Commit 10446f7c authored by duminil's avatar duminil
Browse files

RegionChooser: Fast extractor of CoordinateReferenceSystem

parent 5c0578fe
...@@ -4,13 +4,18 @@ ...@@ -4,13 +4,18 @@
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Iterator; import java.util.Iterator;
import java.util.Optional;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import com.ximpleware.AutoPilot; import com.ximpleware.AutoPilot;
import com.ximpleware.NavException; import com.ximpleware.NavException;
import com.ximpleware.VTDGen; import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav; import com.ximpleware.VTDNav;
import com.ximpleware.XPathEvalException; import com.ximpleware.XPathEvalException;
import com.ximpleware.XPathParseException; import com.ximpleware.XPathParseException;
import eu.simstadt.geo.GeoUtils;
public class CityGmlIterator implements Iterable<BuildingXmlNode> public class CityGmlIterator implements Iterable<BuildingXmlNode>
...@@ -23,6 +28,7 @@ public class CityGmlIterator implements Iterable<BuildingXmlNode> ...@@ -23,6 +28,7 @@ public class CityGmlIterator implements Iterable<BuildingXmlNode>
private int buildingOffset = 0; private int buildingOffset = 0;
private int buildingLength = 0; private int buildingLength = 0;
private Path citygmlPath; private Path citygmlPath;
private Pattern srsNamePattern = Pattern.compile("(?i)(?<=srsName=\")[^\"]+(?=\")");
/* /*
* Simple class to parse a CityGML and extract cityObjectMember XML nodes and their coordinates. Since the * Simple class to parse a CityGML and extract cityObjectMember XML nodes and their coordinates. Since the
...@@ -39,7 +45,7 @@ public CityGmlIterator(Path citygmlPath) ...@@ -39,7 +45,7 @@ public CityGmlIterator(Path citygmlPath)
parser.parseFile(citygmlPath.toString(), false); parser.parseFile(citygmlPath.toString(), false);
this.navigator = parser.getNav(); this.navigator = parser.getNav();
this.buildingsFinder = new AutoPilot(navigator); this.buildingsFinder = new AutoPilot(navigator);
buildingsFinder.selectXPath("/CityModel/cityObjectMember[Building]"); //TODO: Check it's the only correct possibility buildingsFinder.selectXPath("/CityModel/cityObjectMember[Building]"); //TODO: Check it's the only correct possibility. //FIXME: BuildingPart too!
} }
@Override @Override
...@@ -87,4 +93,18 @@ public Object getFooter() throws IOException, NavException { ...@@ -87,4 +93,18 @@ public Object getFooter() throws IOException, NavException {
return navigator.toRawString(footerOffset, footerLength); return navigator.toRawString(footerOffset, footerLength);
} }
/*
* Fast scan of the 50 first lines to look for srsName
*
*/
public CoordinateReferenceSystem getCRS() throws IOException {
Optional<String> line = Files.lines(citygmlPath).limit(50).filter(srsNamePattern.asPredicate()).findFirst();
if (line.isPresent()) {
Matcher matcher = srsNamePattern.matcher(line.get());
matcher.find();
return GeoUtils.crsFromSrsName(matcher.group());
} else {
throw new IllegalArgumentException("No srsName found in the header of " + citygmlPath);
}
}
} }
package eu.simstadt.regionchooser.test; package eu.simstadt.regionchooser.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
...@@ -15,9 +16,10 @@ ...@@ -15,9 +16,10 @@
public class CitygmlParserTests public class CitygmlParserTests
{ {
private void testNoNanInCoordinates(Path citygmlPath) private void testCRSandNoNanInCoordinates(Path citygmlPath, String crsName)
throws NumberFormatException, XPathParseException, NavException, XPathEvalException, IOException { throws NumberFormatException, XPathParseException, NavException, XPathEvalException, IOException {
CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath); CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath);
assertEquals(crsName, buildingXmlNodes.getCRS().toString());
for (BuildingXmlNode buildingXmlNode : buildingXmlNodes) { for (BuildingXmlNode buildingXmlNode : buildingXmlNodes) {
assertFalse("Coordinate should be a double", Double.isNaN(buildingXmlNode.x)); assertFalse("Coordinate should be a double", Double.isNaN(buildingXmlNode.x));
assertFalse("Coordinate should be a double", Double.isNaN(buildingXmlNode.y)); assertFalse("Coordinate should be a double", Double.isNaN(buildingXmlNode.y));
...@@ -30,7 +32,6 @@ private void testNoNanInCoordinates(Path citygmlPath) ...@@ -30,7 +32,6 @@ private void testNoNanInCoordinates(Path citygmlPath)
assertTrue("Coordinates Min/Max should be plausible", buildingXmlNode.xMin < buildingXmlNode.x); assertTrue("Coordinates Min/Max should be plausible", buildingXmlNode.xMin < buildingXmlNode.x);
assertTrue("Coordinates Min/Max should be plausible", buildingXmlNode.yMin < buildingXmlNode.y); assertTrue("Coordinates Min/Max should be plausible", buildingXmlNode.yMin < buildingXmlNode.y);
} }
} }
@Test @Test
...@@ -38,20 +39,27 @@ public void testExtractCoordsFromStuttgart() ...@@ -38,20 +39,27 @@ public void testExtractCoordsFromStuttgart()
throws NumberFormatException, XPathParseException, NavException, XPathEvalException, IOException { throws NumberFormatException, XPathParseException, NavException, XPathEvalException, IOException {
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("Stuttgart.proj/Stuttgart_LOD0_LOD1_buildings_and_trees.gml"); Path citygmlPath = repo.resolve("Stuttgart.proj/Stuttgart_LOD0_LOD1_buildings_and_trees.gml");
testNoNanInCoordinates(citygmlPath); testCRSandNoNanInCoordinates(citygmlPath, "EPSG:31467");
} }
@Test @Test
public void testExtractCoordsFromGruenbuehl() throws Throwable { public void testExtractCoordsFromGruenbuehl() throws Throwable {
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("Gruenbuehl.proj/20140218_Gruenbuehl_LOD2_1building.gml"); Path citygmlPath = repo.resolve("Gruenbuehl.proj/20140218_Gruenbuehl_LOD2_1building.gml");
testNoNanInCoordinates(citygmlPath); testCRSandNoNanInCoordinates(citygmlPath, "EPSG:31467");
} }
@Test @Test
public void testExtractCoordsFromMunich() throws Throwable { public void testExtractCoordsFromMunich() throws Throwable {
Path repo = Paths.get("../TestRepository"); Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("Muenchen.proj/Munich_v_1_0_0.gml"); Path citygmlPath = repo.resolve("Muenchen.proj/Munich_v_1_0_0.gml");
testNoNanInCoordinates(citygmlPath); testCRSandNoNanInCoordinates(citygmlPath, "EPSG:32632");
}
@Test
public void testExtractCoordsFromNYC() throws Throwable {
Path repo = Paths.get("../TestRepository");
Path citygmlPath = repo.resolve("NewYork.proj/ManhattanSmall.gml");
testCRSandNoNanInCoordinates(citygmlPath, "EPSG:32118");
} }
} }
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