Commit c49391c1 authored by Eric Duminil's avatar Eric Duminil
Browse files

Allow Vegetation to be extracted too.

parent b2536456
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import com.ximpleware.NavException; import com.ximpleware.NavException;
import com.ximpleware.XPathEvalException; import com.ximpleware.XPathEvalException;
import com.ximpleware.XPathParseException; import com.ximpleware.XPathParseException;
import eu.simstadt.regionchooser.fast_xml_parser.BuildingXmlNode;
import eu.simstadt.regionchooser.fast_xml_parser.CityGmlIterator; import eu.simstadt.regionchooser.fast_xml_parser.CityGmlIterator;
import eu.simstadt.regionchooser.fast_xml_parser.CityObjectMember;
public class RegionExtractor public class RegionExtractor
...@@ -51,8 +51,9 @@ ...@@ -51,8 +51,9 @@
static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Writer sb, static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Writer sb,
Path... citygmlPaths) throws ParseException, XPathParseException, NavException, IOException { Path... citygmlPaths) throws ParseException, XPathParseException, NavException, IOException {
int buildingsCount = 0; int cityObjectsCount = 0;
int foundBuildingsCount = 0; int foundBuildingsCount = 0;
// int foundVegetationCount = 0;
Geometry poly = WKT_READER.read(wktPolygon); Geometry poly = WKT_READER.read(wktPolygon);
CityGmlIterator citygml = null; CityGmlIterator citygml = null;
...@@ -61,11 +62,11 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr ...@@ -61,11 +62,11 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr
LOGGER.info("Parsing " + citygmlPath); LOGGER.info("Parsing " + citygmlPath);
//TODO: Allow citygmlPath for folders too, and iterate over gmls? //TODO: Allow citygmlPath for folders too, and iterate over gmls?
citygml = new CityGmlIterator(citygmlPath); citygml = new CityGmlIterator(citygmlPath);
for (BuildingXmlNode buildingXmlNode : citygml) { for (CityObjectMember buildingXmlNode : citygml) {
if (buildingsCount == 0) { if (cityObjectsCount == 0) {
sb.append(replaceEnvelopeInHeader(citygml.getHeader(), poly.getEnvelopeInternal(), srsName)); sb.append(replaceEnvelopeInHeader(citygml.getHeader(), poly.getEnvelopeInternal(), srsName));
} }
buildingsCount += 1; cityObjectsCount += 1;
if (buildingXmlNode.hasCoordinates()) { if (buildingXmlNode.hasCoordinates()) {
Coordinate coord = new Coordinate(buildingXmlNode.x, buildingXmlNode.y); Coordinate coord = new Coordinate(buildingXmlNode.x, buildingXmlNode.y);
Point point = GEOMETRY_FACTORY.createPoint(coord); Point point = GEOMETRY_FACTORY.createPoint(coord);
...@@ -74,7 +75,7 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr ...@@ -74,7 +75,7 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr
sb.append(buildingXmlNode.toString()); sb.append(buildingXmlNode.toString());
} }
} }
if (buildingsCount % 1000 == 0) { if (cityObjectsCount % 1000 == 0) {
LOGGER.info("1000 buildings parsed"); LOGGER.info("1000 buildings parsed");
} }
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
import com.ximpleware.XPathParseException; import com.ximpleware.XPathParseException;
public class CityGmlIterator implements Iterable<BuildingXmlNode> public class CityGmlIterator implements Iterable<CityObjectMember>
{ {
private static final Logger LOGGER = Logger.getLogger(CityGmlIterator.class.getName()); private static final Logger LOGGER = Logger.getLogger(CityGmlIterator.class.getName());
...@@ -42,12 +42,12 @@ public CityGmlIterator(Path citygmlPath) throws XPathParseException { ...@@ -42,12 +42,12 @@ public CityGmlIterator(Path citygmlPath) throws XPathParseException {
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. //FIXME: BuildingPart too! buildingsFinder.selectXPath(CityObjectMember.XPATH_PATTERN);
} }
@Override @Override
public Iterator<BuildingXmlNode> iterator() { public Iterator<CityObjectMember> iterator() {
return new Iterator<BuildingXmlNode>() { return new Iterator<CityObjectMember>() {
@Override @Override
public boolean hasNext() { public boolean hasNext() {
...@@ -60,12 +60,12 @@ public boolean hasNext() { ...@@ -60,12 +60,12 @@ public boolean hasNext() {
} }
@Override @Override
public BuildingXmlNode next() { public CityObjectMember next() {
try { try {
long offsetAndLength = navigator.getElementFragment(); long offsetAndLength = navigator.getElementFragment();
buildingOffset = (int) offsetAndLength; buildingOffset = (int) offsetAndLength;
buildingLength = (int) (offsetAndLength >> 32); buildingLength = (int) (offsetAndLength >> 32);
return new BuildingXmlNode(navigator, buildingOffset, buildingLength); return new CityObjectMember(navigator, buildingOffset, buildingLength);
} catch (NavException | NumberFormatException | XPathParseException | XPathEvalException ex) { } catch (NavException | NumberFormatException | XPathParseException | XPathEvalException ex) {
LOGGER.warning("Error while parsing " + citygmlPath); LOGGER.warning("Error while parsing " + citygmlPath);
} }
......
...@@ -7,11 +7,19 @@ ...@@ -7,11 +7,19 @@
import com.ximpleware.XPathParseException; import com.ximpleware.XPathParseException;
public class BuildingXmlNode /**
* XML Node representing a CityObjectMember
*
*/
public class CityObjectMember
{ {
//TODO: Check it's the only correct possibility.
//FIXME: BuildingPart too!
static final String XPATH_PATTERN = "/CityModel/cityObjectMember[Building or SolitaryVegetationObject or PlantCover]";
private int buildingOffset; private int nodeOffset;
private int buildingLength; private int nodeLength;
private VTDNav navigator; private VTDNav navigator;
private AutoPilot coordinatesFinder; private AutoPilot coordinatesFinder;
public Double x; public Double x;
...@@ -22,14 +30,15 @@ ...@@ -22,14 +30,15 @@
public Double y; public Double y;
private int coordinatesCount = 0; private int coordinatesCount = 0;
public BuildingXmlNode(VTDNav navigator, int buildingOffset, int buildingLength) public CityObjectMember(VTDNav navigator, int nodeOffset, int nodeLength)
throws XPathParseException, XPathEvalException, NavException { throws XPathParseException, XPathEvalException, NavException {
this.navigator = navigator; this.navigator = navigator;
this.coordinatesFinder = new AutoPilot(navigator); this.coordinatesFinder = new AutoPilot(navigator);
this.buildingLength = buildingLength; this.nodeLength = nodeLength;
this.buildingOffset = buildingOffset; this.nodeOffset = nodeOffset;
extractCoordinates(); extractCoordinates();
//TODO: Get Building ID too, in order to avoid duplicates? //TODO: Get Node ID too, in order to avoid duplicates?
//TODO: Now that "Building" can be Vegetation too, define a method to check class?
} }
public boolean hasCoordinates() { public boolean hasCoordinates() {
...@@ -84,7 +93,7 @@ private void extractCoordinates() ...@@ -84,7 +93,7 @@ private void extractCoordinates()
public String toString() { public String toString() {
try { try {
return navigator.toRawString(buildingOffset, buildingLength); return navigator.toRawString(nodeOffset, nodeLength);
} catch (NavException ex) { } catch (NavException ex) {
return ""; return "";
} }
......
...@@ -55,7 +55,7 @@ public static Geometry calculateFromCityGML(Path citygmlPath) throws XPathParseE ...@@ -55,7 +55,7 @@ public static Geometry calculateFromCityGML(Path citygmlPath) throws XPathParseE
GeometryFactory geometryFactory = new GeometryFactory(); GeometryFactory geometryFactory = new GeometryFactory();
ArrayList<Coordinate> allPoints = new ArrayList<>(); ArrayList<Coordinate> allPoints = new ArrayList<>();
CityGmlIterator citygml = new CityGmlIterator(citygmlPath); CityGmlIterator citygml = new CityGmlIterator(citygmlPath);
for (BuildingXmlNode buildingXmlNode : citygml) { for (CityObjectMember buildingXmlNode : citygml) {
if (buildingXmlNode.hasCoordinates()) { if (buildingXmlNode.hasCoordinates()) {
allPoints.add(new Coordinate(buildingXmlNode.xMin, buildingXmlNode.yMin)); allPoints.add(new Coordinate(buildingXmlNode.xMin, buildingXmlNode.yMin));
allPoints.add(new Coordinate(buildingXmlNode.xMin, buildingXmlNode.yMax)); allPoints.add(new Coordinate(buildingXmlNode.xMin, buildingXmlNode.yMax));
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
private void testNoNanInCoordinates(Path citygmlPath) throws XPathParseException { private void testNoNanInCoordinates(Path citygmlPath) throws XPathParseException {
CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath); CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath);
for (BuildingXmlNode buildingXmlNode : buildingXmlNodes) { for (CityObjectMember buildingXmlNode : buildingXmlNodes) {
assertTrue(buildingXmlNode.hasCoordinates(), "Buildings should have coordinates"); assertTrue(buildingXmlNode.hasCoordinates(), "Buildings should have coordinates");
assertFalse(Double.isNaN(buildingXmlNode.x), COORDINATE_SHOULD_BE_A_DOUBLE); assertFalse(Double.isNaN(buildingXmlNode.x), COORDINATE_SHOULD_BE_A_DOUBLE);
assertFalse(Double.isNaN(buildingXmlNode.y), COORDINATE_SHOULD_BE_A_DOUBLE); assertFalse(Double.isNaN(buildingXmlNode.y), COORDINATE_SHOULD_BE_A_DOUBLE);
...@@ -25,10 +25,11 @@ private void testNoNanInCoordinates(Path citygmlPath) throws XPathParseException ...@@ -25,10 +25,11 @@ private void testNoNanInCoordinates(Path citygmlPath) throws XPathParseException
assertFalse(Double.isNaN(buildingXmlNode.yMax), COORDINATE_SHOULD_BE_A_DOUBLE); assertFalse(Double.isNaN(buildingXmlNode.yMax), COORDINATE_SHOULD_BE_A_DOUBLE);
assertFalse(Double.isNaN(buildingXmlNode.xMin), COORDINATE_SHOULD_BE_A_DOUBLE); assertFalse(Double.isNaN(buildingXmlNode.xMin), COORDINATE_SHOULD_BE_A_DOUBLE);
assertFalse(Double.isNaN(buildingXmlNode.yMin), COORDINATE_SHOULD_BE_A_DOUBLE); assertFalse(Double.isNaN(buildingXmlNode.yMin), COORDINATE_SHOULD_BE_A_DOUBLE);
assertTrue(buildingXmlNode.xMax > buildingXmlNode.x, COORDINATES_SHOULD_BE_PLAUSIBLE); // Some SolitaryVegetationObjects are defined with a single point.
assertTrue(buildingXmlNode.yMax > buildingXmlNode.y, COORDINATES_SHOULD_BE_PLAUSIBLE); assertTrue(buildingXmlNode.xMax >= buildingXmlNode.x, COORDINATES_SHOULD_BE_PLAUSIBLE);
assertTrue(buildingXmlNode.xMin < buildingXmlNode.x, COORDINATES_SHOULD_BE_PLAUSIBLE); assertTrue(buildingXmlNode.yMax >= buildingXmlNode.y, COORDINATES_SHOULD_BE_PLAUSIBLE);
assertTrue(buildingXmlNode.yMin < buildingXmlNode.y, COORDINATES_SHOULD_BE_PLAUSIBLE); assertTrue(buildingXmlNode.xMin <= buildingXmlNode.x, COORDINATES_SHOULD_BE_PLAUSIBLE);
assertTrue(buildingXmlNode.yMin <= buildingXmlNode.y, COORDINATES_SHOULD_BE_PLAUSIBLE);
} }
} }
...@@ -66,7 +67,7 @@ public void testExtractNoCoordsFromEmptyBuilding() throws XPathParseException { ...@@ -66,7 +67,7 @@ public void testExtractNoCoordsFromEmptyBuilding() throws XPathParseException {
Path citygmlPath = repo.resolve("Stöckach_empty_buildings.gml"); Path citygmlPath = repo.resolve("Stöckach_empty_buildings.gml");
CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath); CityGmlIterator buildingXmlNodes = new CityGmlIterator(citygmlPath);
int counter = 0; int counter = 0;
for (BuildingXmlNode buildingXmlNode : buildingXmlNodes) { for (CityObjectMember buildingXmlNode : buildingXmlNodes) {
assertFalse(buildingXmlNode.hasCoordinates(), "Empty Buildings shouldn't have coordinates"); assertFalse(buildingXmlNode.hasCoordinates(), "Empty Buildings shouldn't have coordinates");
assertTrue(Double.isNaN(buildingXmlNode.x), "Coordinate should be a Nan"); assertTrue(Double.isNaN(buildingXmlNode.x), "Coordinate should be a Nan");
assertTrue(Double.isNaN(buildingXmlNode.y), "Coordinate should be a Nan"); assertTrue(Double.isNaN(buildingXmlNode.y), "Coordinate should be a Nan");
......
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