Commit 3e042784 authored by Matthias Betz's avatar Matthias Betz
Browse files

add alkis land use parsing

parent eacaa411
......@@ -25,6 +25,19 @@
</repositories>
<dependencies>
<!-- https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>4.0.0</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.geotools/gt-shapefile -->
<dependency>
<groupId>org.geotools</groupId>
......
package de.hft.stuttgart.citygml.green.alkis;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.reader.CityGMLReadException;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import de.hft.stuttgart.citygml.green.osm.GreenArea;
import de.hft.stuttgart.citygml.green.osm.GreenEnricher;
import de.hft.stuttgart.citygml.green.osm.LandUseArea;
import de.hft.stuttgart.citygml.green.osm.OsmData;
import de.hft.stuttgart.citygml.green.osm.RoadArea;
import de.hft.stuttgart.citygml.green.osm.TreeUtils;
import jakarta.xml.bind.JAXBException;
public class AlkisGreenEnricher {
private static Set<String> greenAreaTypes = new HashSet<>();
private static Set<String> roadAreaTypes = new HashSet<>();
static {
greenAreaTypes.add("Wald");
greenAreaTypes.add("Landwirtschaft");
greenAreaTypes.add("Friedhof");
greenAreaTypes.add("Gehölz");
greenAreaTypes.add("Sport-, Freizeit- und Erholungsfläche");
roadAreaTypes.add("Weg");
roadAreaTypes.add("Straßenverkehr");
roadAreaTypes.add("Bahnverkehr");
}
public static void main(String[] args) throws IOException, CityGMLContextException, CityGMLReadException, JAXBException, CityGMLWriteException {
System.out.println("Reading CityGML file");
Path inFile = Paths.get(args[0]);
CityModel cityModel = GreenEnricher.readCityGml(inFile);
GreenEnricher.createTransformers(cityModel);
OsmData osmData = new OsmData();
String boundingBoxString = GreenEnricher.extractAndConvertBoundingBox(cityModel, osmData);
// HttpResponse<String> response = getOsmData(boundingBoxString);
// Files.write(Path.of("osm_response.xml"), response.body().getBytes(StandardCharsets.UTF_8));
// String osmResponse = response.body();
String osmResponse = Files.readString(Paths.get("data", "osm_response.xml"));
System.out.println("Parsing OSM response");
GreenEnricher.parseOsmResponse(osmResponse, osmData);
// ignore green areas from osm
osmData.getGreenAreas().clear();
parseAlkisData(osmData);
System.out.println("Fit data in bounding box");
GreenEnricher.fitToBoundingBox(osmData);
GreenEnricher.convertGreenAreasToCityGML(cityModel, osmData.getGreenAreas());
GreenEnricher.convertWaterAreasToCityGML(cityModel, osmData);
GreenEnricher.convertRoadAreasToCityGML(cityModel, osmData);
GreenEnricher.converLandUseAreasToCityGML(cityModel, osmData);
TreeUtils.insertTrees(cityModel, osmData);
GreenEnricher.clampToGround(cityModel);
String inputString = inFile.getFileName().toString();
String inputPathWithoutFileEnding = inputString.substring(0, inputString.lastIndexOf('.'));
Path outputPath = Paths.get("data", inputPathWithoutFileEnding + "_with_alkis_greens.gml");
System.out.println("Writing output file.");
GreenEnricher.writeCityGML(cityModel, outputPath);
System.out.println("Done");
}
private static void parseAlkisData(OsmData osmData) throws MalformedURLException, IOException {
Path alkisDataPath = Paths.get("data", "tn_09663", "Nutzung.shp");
Map<String, Object> readParameters = new HashMap<>();
readParameters.put("url", alkisDataPath.toUri().toURL());
readParameters.put("charset", StandardCharsets.UTF_8);
DataStore dataStore = DataStoreFinder.getDataStore(readParameters);
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
List<GreenArea> greenAreas = osmData.getGreenAreas();
List<RoadArea> roadAreas = osmData.getRoadAreas();
List<LandUseArea> landUseAreas = osmData.getLandUseAreas();
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
MultiPolygon geometry = (MultiPolygon) feature.getAttribute("the_geom");
String nutzart = feature.getAttribute("nutzart").toString();
if (geometry.getNumGeometries() > 1) {
throw new IllegalStateException();
}
if (greenAreaTypes.contains(nutzart)) {
greenAreas.add(new GreenArea((Polygon) geometry.getGeometryN(0)));
} else if (roadAreaTypes.contains(nutzart)) {
roadAreas.add(new RoadArea((Polygon) geometry.getGeometryN(0)));
} else {
landUseAreas.add(new LandUseArea((Polygon) geometry.getGeometryN(0)));
}
}
}
}
}
package de.hft.stuttgart.citygml.green.osm;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.io.StringReader;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
......@@ -13,20 +12,13 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.citygml4j.core.model.CityGMLVersion;
......@@ -34,12 +26,10 @@ import org.citygml4j.core.model.building.Building;
import org.citygml4j.core.model.core.AbstractCityObject;
import org.citygml4j.core.model.core.AbstractCityObjectProperty;
import org.citygml4j.core.model.core.AbstractFeature;
import org.citygml4j.core.model.core.AbstractGenericAttribute;
import org.citygml4j.core.model.core.AbstractGenericAttributeProperty;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.core.model.generics.StringAttribute;
import org.citygml4j.core.model.landuse.LandUse;
import org.citygml4j.core.model.transportation.Road;
import org.citygml4j.core.model.vegetation.PlantCover;
import org.citygml4j.core.model.vegetation.SolitaryVegetationObject;
import org.citygml4j.core.model.waterbody.WaterBody;
import org.citygml4j.core.visitor.ObjectWalker;
import org.citygml4j.xml.CityGMLContext;
......@@ -51,11 +41,6 @@ import org.citygml4j.xml.reader.CityGMLReader;
import org.citygml4j.xml.writer.CityGMLOutputFactory;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.citygml4j.xml.writer.CityGMLWriter;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
......@@ -67,12 +52,8 @@ import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.CRSFactory;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.locationtech.proj4j.ProjCoordinate;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xmlobjects.gml.model.geometry.DirectPosition;
import org.xmlobjects.gml.model.geometry.DirectPositionList;
import org.xmlobjects.gml.model.geometry.Envelope;
......@@ -82,10 +63,17 @@ import org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty;
import org.xmlobjects.gml.model.geometry.primitives.LinearRing;
import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty;
import de.hft.stuttgart.citygml.green.osm.jaxb.OSM;
import de.hft.stuttgart.citygml.green.osm.jaxb.OsmMember;
import de.hft.stuttgart.citygml.green.osm.jaxb.OsmNode;
import de.hft.stuttgart.citygml.green.osm.jaxb.OsmRelation;
import de.hft.stuttgart.citygml.green.osm.jaxb.OsmTag;
import de.hft.stuttgart.citygml.green.osm.jaxb.OsmWay;
import de.hft.stuttgart.citygml.green.osm.jaxb.WayNode;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
public class GreenEnricher {
private static final double TRUNK_PERCENTAGE = 0.2;
private static final double CROWN_PERCENTAGE = 1 - TRUNK_PERCENTAGE;
private static final int BOUNDING_BOX_INCREASE_IN_M = 100;
......@@ -113,6 +101,7 @@ public class GreenEnricher {
nwr["type"="waterway"];
nwr["waterway"="stream"];
nwr["water"="pond"];
nwr["landuse"="vineyard"];
);
out geom;""";
......@@ -122,23 +111,18 @@ public class GreenEnricher {
private static CoordinateReferenceSystem targetCRS = CRS_FACTORY.createFromName("EPSG:4326");
private static BasicCoordinateTransform transform;
private static BasicCoordinateTransform backTransform;
public static GeometryFactory geomFactory = new GeometryFactory();
public static final GeometryFactory GEOM_FACTORY = new GeometryFactory();
public static void main(String[] args) throws IOException, CityGMLContextException, CityGMLReadException,
InterruptedException, ParserConfigurationException, SAXException, CityGMLWriteException {
InterruptedException, ParserConfigurationException, CityGMLWriteException, JAXBException {
System.out.println("Reading CityGML file");
Path inFile = Paths.get(args[0]);
CityModel cityModel = readCityGml(inFile);
String epsgCode = extractEpsgCode(cityModel);
sourceCRS = CRS_FACTORY.createFromName(epsgCode);
transform = new BasicCoordinateTransform(sourceCRS, targetCRS);
backTransform = new BasicCoordinateTransform(targetCRS, sourceCRS);
createTransformers(cityModel);
OsmData osmData = new OsmData();
String boundingBoxString = extractAndConvertBoundingBox(cityModel, epsgCode, osmData);
String boundingBoxString = extractAndConvertBoundingBox(cityModel, osmData);
// HttpResponse<String> response = getOsmData(boundingBoxString);
// Files.write(Path.of("osm_response.xml"), response.body().getBytes(StandardCharsets.UTF_8));
// String osmResponse = response.body();
......@@ -146,9 +130,6 @@ public class GreenEnricher {
System.out.println("Parsing OSM response");
parseOsmResponse(osmResponse, osmData);
createBoundingBox(cityModel, osmData);
// List<GreenArea> newGreenAreas = new ArrayList<>();
System.out.println("Fit data in bounding box");
fitToBoundingBox(osmData);
......@@ -160,134 +141,30 @@ public class GreenEnricher {
convertGreenAreasToCityGML(cityModel, greenAreas);
convertWaterAreasToCityGML(cityModel, osmData);
for (Waterway waterWay : osmData.getWaterways()) {
}
// trees
TreeUtils.insertTrees(cityModel, osmData);
TreeKatasterData katasterData = parseTreeKatasterData(Paths.get("data", "Baum.shp"));
for (Iterator<TreePoint> iterator = osmData.getTreePoints().iterator(); iterator.hasNext();) {
TreePoint tp = iterator.next();
// if another tree from kataster is within 3m ignore it
for (Tree tree : katasterData.getTrees()) {
if (tp.getPoint().distance(tree.getPoint()) < 3) {
iterator.remove();
}
}
}
for (Tree tree : katasterData.getTrees()) {
double trunkRadius = tree.getTrunkRadius();
double trunkHeight = tree.getTrunkHeight();
double crownHeight = tree.getCrownHeight();
double crownRadius = tree.getCrownRadius();
Coordinate coordinate = tree.getPoint().getCoordinate();
if (Double.isNaN(coordinate.z)) {
coordinate.z = 0;
}
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, crownRadius, crownRadius, crownHeight);
SolitaryVegetationObject cover = new SolitaryVegetationObject();
StringAttribute typeAttribute = new StringAttribute("type", tree.getType());
AbstractGenericAttributeProperty attributeProp = new AbstractGenericAttributeProperty(typeAttribute);
cover.getGenericAttributes().add(attributeProp);
cover.setId(UUID.randomUUID().toString());
cover.setLod2MultiSurface(new MultiSurfaceProperty(generatedTree));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(cover));
}
for (TreePoint tp : osmData.getTreePoints()) {
// standard tree
double trunkRadius = 0.89 / (2 * Math.PI);
double trunkHeight = TRUNK_PERCENTAGE * 11.46;
double crownHeight = CROWN_PERCENTAGE * 11.46;
double crownRadius = 8 / 2d;
Coordinate coordinate = tp.getPoint().getCoordinate();
if (Double.isNaN(coordinate.z)) {
coordinate.z = 0;
}
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, crownRadius, crownRadius, crownHeight);
SolitaryVegetationObject cover = new SolitaryVegetationObject();
StringAttribute typeAttribute = new StringAttribute("type", "Acer campestre");
AbstractGenericAttributeProperty attributeProp = new AbstractGenericAttributeProperty(typeAttribute);
cover.getGenericAttributes().add(attributeProp);
cover.setId(UUID.randomUUID().toString());
cover.setLod2MultiSurface(new MultiSurfaceProperty(generatedTree));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(cover));
}
//
// for (TreeRow tr : osmData.getTreeRows()) {
// System.out.println(tr);
// }
clampToGround(cityModel);
String inputString = inFile.getFileName().toString();
String inputPathWithoutFileEnding = inputString.substring(0, inputString.lastIndexOf('.'));
Path outputPath = Paths.get("data", inputPathWithoutFileEnding + "_with_greens.gml");
Path outputPath = Paths.get("data", inputPathWithoutFileEnding + "_with_osm_greens.gml");
System.out.println("Writing output file.");
writeCityGML(cityModel, outputPath);
System.out.println("Done");
}
private static TreeKatasterData parseTreeKatasterData(Path path) throws IOException {
TreeKatasterData result = new TreeKatasterData();
Map<String, Object> readParameters = new HashMap<>();
readParameters.put("url", path.toUri().toURL());
readParameters.put("charset", StandardCharsets.UTF_8);
DataStore dataStore = DataStoreFinder.getDataStore(readParameters);
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source =
dataStore.getFeatureSource(typeName);
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
Tree tree = new Tree();
Point p = (Point) feature.getAttribute("the_geom");
tree.setPoint(p);
String type = feature.getAttribute("Bezeichnun").toString();
tree.setType(type);
Object treeHeightObject = feature.getAttribute("Baumhöhe");
if (treeHeightObject == null) {
continue;
}
int treeHeight = Integer.parseInt(treeHeightObject.toString());
double crownHeight = CROWN_PERCENTAGE * treeHeight;
double trunkHeight = TRUNK_PERCENTAGE * treeHeight;
tree.setCrownHeight(crownHeight);
tree.setTrunkHeight(trunkHeight);
Object crownWidth = feature.getAttribute("Kronenbrei");
if (crownWidth == null) {
continue;
}
tree.setCrownRadius(Float.parseFloat(crownWidth.toString()) / 2);
Object trunkCirc = feature.getAttribute("Stammumfan");
if (trunkCirc == null) {
continue;
}
tree.setTrunkRadius(Integer.parseInt(trunkCirc.toString()) / (2 * Math.PI) / 100);
result.getTrees().add(tree);
}
}
return result;
public static void createTransformers(CityModel cityModel) {
String epsgCode = extractEpsgCode(cityModel);
sourceCRS = CRS_FACTORY.createFromName(epsgCode);
transform = new BasicCoordinateTransform(sourceCRS, targetCRS);
backTransform = new BasicCoordinateTransform(targetCRS, sourceCRS);
}
private static void convertWaterAreasToCityGML(CityModel cityModel, OsmData osmData) {
public static void convertWaterAreasToCityGML(CityModel cityModel, OsmData osmData) {
for (WaterArea waterArea : osmData.getWaterAreas()) {
WaterBody wb = new WaterBody();
org.xmlobjects.gml.model.geometry.primitives.Polygon poly = convertToCityGmlPoly(waterArea.getArea());
......@@ -303,7 +180,7 @@ public class GreenEnricher {
}
}
private static void convertGreenAreasToCityGML(CityModel cityModel, List<GreenArea> greenAreas) {
public static void convertGreenAreasToCityGML(CityModel cityModel, List<GreenArea> greenAreas) {
for (GreenArea ga : greenAreas) {
org.xmlobjects.gml.model.geometry.primitives.Polygon poly = convertToCityGmlPoly(ga.getArea());
if (poly == null) {
......@@ -319,8 +196,65 @@ public class GreenEnricher {
}
}
private static void fitToBoundingBox(OsmData osmData) {
List<GreenArea> greenAreas = osmData.getGreenAreas();
public static void fitToBoundingBox(OsmData osmData) {
fitGreenAreas(osmData, osmData.getGreenAreas());
fitRoadAreas(osmData, osmData.getRoadAreas());
fitLandUseAreas(osmData, osmData.getLandUseAreas());
clipWaterAreasToBoundingBox(osmData);
for (Iterator<TreePoint> iterator = osmData.getTreePoints().iterator(); iterator.hasNext();) {
TreePoint tp = iterator.next();
if (!osmData.getBoundingBox().contains(tp.getPoint())) {
iterator.remove();
}
}
}
private static void fitLandUseAreas(OsmData osmData, List<LandUseArea> landUseAreas) {
List<LandUseArea> newLandUseAreas = new ArrayList<>();
for (LandUseArea landUseArea : landUseAreas) {
Polygon area = landUseArea.getArea();
Geometry intersection = area.intersection(osmData.getBoundingBox());
if (intersection instanceof MultiPolygon multi) {
Polygon poly1 = (Polygon) multi.getGeometryN(0);
landUseArea.setArea(poly1);
for (int k = 1; k < multi.getNumGeometries(); k++) {
LandUseArea newLandUseArea = new LandUseArea();
newLandUseArea.setArea((Polygon) multi.getGeometryN(k));
newLandUseAreas.add(newLandUseArea);
}
} else {
landUseArea.setArea((Polygon) intersection);
}
}
landUseAreas.addAll(newLandUseAreas);
}
private static void fitRoadAreas(OsmData osmData, List<RoadArea> roadAreas) {
List<RoadArea> newRoadAreas = new ArrayList<>();
for (RoadArea roadArea : roadAreas) {
Polygon area = roadArea.getArea();
Geometry intersection = area.intersection(osmData.getBoundingBox());
if (intersection instanceof MultiPolygon multi) {
Polygon poly1 = (Polygon) multi.getGeometryN(0);
roadArea.setArea(poly1);
for (int k = 1; k < multi.getNumGeometries(); k++) {
RoadArea newRoadArea = new RoadArea();
newRoadArea.setArea((Polygon) multi.getGeometryN(k));
newRoadAreas.add(newRoadArea);
}
} else {
roadArea.setArea((Polygon) intersection);
}
}
roadAreas.addAll(newRoadAreas);
}
private static void fitGreenAreas(OsmData osmData, List<GreenArea> greenAreas) {
List<GreenArea> newGreenAreas = new ArrayList<>();
for (GreenArea greenArea : greenAreas) {
Polygon area = greenArea.getArea();
......@@ -338,16 +272,6 @@ public class GreenEnricher {
}
}
greenAreas.addAll(newGreenAreas);
clipWaterAreasToBoundingBox(osmData);
for (Iterator<TreePoint> iterator = osmData.getTreePoints().iterator(); iterator.hasNext();) {
TreePoint tp = iterator.next();
if (!osmData.getBoundingBox().contains(tp.getPoint())) {
iterator.remove();
}
}
}
private static void clipWaterAreasToBoundingBox(OsmData osmData) {
......@@ -394,25 +318,7 @@ public class GreenEnricher {
}
}
}
private static void createBoundingBox(CityModel cityModel, OsmData osmData) {
// TODO Auto-generated method stub
}
// private static MultiSurface generateTree(Point p) {
// double radiusTrunk = 0.2;
//
// MultiSurface result = new MultiSurface();
//
// // trunk
// Coordinate center = p.getCoordinate();
// List<Coordinate> coords = new ArrayList<>();
// coords.add(new Coordinate(center.x, center.y + radiusTrunk));
// coords.add(new Coordinate(center.x + radiusTrunk / 2, center.y + Math.cos(0.5) * radiusTrunk));
// }
private static void clampToGround(CityModel cityModel) {
public static void clampToGround(CityModel cityModel) {
for (AbstractCityObjectProperty afp : cityModel.getCityObjectMembers()) {
AbstractCityObject af = afp.getObject();
if (af instanceof Building b) {
......@@ -487,7 +393,7 @@ public class GreenEnricher {
return response;
}
private static void writeCityGML(CityModel cityModel, Path outputPath)
public static void writeCityGML(CityModel cityModel, Path outputPath)
throws CityGMLWriteException, CityGMLContextException {
CityGMLContext context = CityGMLContext.newInstance();
CityGMLVersion version = CityGMLVersion.v2_0;
......@@ -499,28 +405,110 @@ public class GreenEnricher {
}
}
private static OsmData parseOsmResponse(String osmResponse, OsmData osmData)
throws ParserConfigurationException, SAXException, IOException {
Document document = createDomFromOsmResponse(osmResponse);
public static void parseOsmResponse(String osmResponse, OsmData osmData) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(OSM.class);
OSM osm = (OSM) context.createUnmarshaller().unmarshal(new StringReader(osmResponse));
parseTrees(osmData.getTreePoints(), osm.getNodes());
parseWays(osmData, osm);
parseRelations(osmData, osm);
}
// root element
Node osmItem = document.getChildNodes().item(0);
NodeList childNodes = osmItem.getChildNodes();
private static void parseRelations(OsmData data, OSM osm) {
for (OsmRelation rel : osm.getRelations()) {
boolean isWater = false;
Set<String> usedIds = new HashSet<>();
List<Polygon> polygons = new ArrayList<>();
List<Coordinate> coordinates = new ArrayList<>();
for (OsmMember member : rel.getMembers()) {
for (WayNode nd : member.getNodes()) {
ProjCoordinate converted = convertCoordinatesFrom84(nd.getLon(), nd.getLat());
coordinates.add(new Coordinate(converted.x, converted.y));
}
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (parseTreeIfPossible(osmData.getTreePoints(), node, usedIds)) {
continue;
if (member.getRole().isBlank()) {
// assume outer ring
// check if this ring is closed
if (coordinates.get(0).equals2D(coordinates.get(coordinates.size() - 1))) {
// ring is closed, create a polygon out of it
Polygon polygon = GEOM_FACTORY.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
coordinates.clear();
polygons.add(polygon);
}
}
}
if (parseGreenAreasIfPossible(osmData, node, usedIds)) {
continue;
if (!coordinates.isEmpty() && coordinates.get(0).equals2D(coordinates.get(coordinates.size() - 1))) {
// one huge polygon apparently
Polygon polygon = GEOM_FACTORY.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
coordinates.clear();
polygons.add(polygon);
} else {
// line
}
for (OsmTag tag : rel.getTags()) {
if ("water".equals(tag.getValue()) || "waterway".equals(tag.getKey())) {
isWater = true;
}
}
parseGreenRelationsIfPossible(osmData, node, usedIds);
if (isWater) {
for (Polygon p : polygons) {
data.getWaterAreas().add(new WaterArea(p));
}
} else {
for (Polygon p : polygons) {
data.getGreenAreas().add(new GreenArea(p));
}
}
}
}
private static void parseWays(OsmData data, OSM osm) {
for (OsmWay way : osm.getWays()) {
boolean water = false;
// search if it is water of green stuff
for (OsmTag tag : way.getTags()) {
if ("water".equals(tag.getValue()) || "waterway".equals(tag.getKey())) {
water = true;
}
}
return osmData;
List<Coordinate> coordinates = new ArrayList<>();
for (WayNode nd : way.getNodes()) {
ProjCoordinate converted = convertCoordinatesFrom84(nd.getLon(), nd.getLat());
coordinates.add(new Coordinate(converted.x, converted.y));
}
boolean isLine = false;
if (!coordinates.get(0).equals(coordinates.get(coordinates.size() - 1))) {
// assume line if start and end coordinate do not match?
isLine = true;
}
if (water) {
if (isLine) {
LineString lineString = GEOM_FACTORY
.createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getWaterways().add(new Waterway(lineString));
} else {
Polygon polygon = GEOM_FACTORY
.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getWaterAreas().add(new WaterArea(polygon));
}
} else {
if (isLine) {
LineString lineString = GEOM_FACTORY
.createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getTreeRows().add(new TreeRow(lineString));
} else {
Polygon polygon = GEOM_FACTORY
.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getGreenAreas().add(new GreenArea(polygon));
}
}
}
}
private static boolean parseGreenRelationsIfPossible(OsmData data, Node node, Set<String> usedIds) {
......@@ -583,17 +571,17 @@ public class GreenEnricher {
}
if (water) {
org.locationtech.jts.geom.LinearRing outerLinearRing = geomFactory
org.locationtech.jts.geom.LinearRing outerLinearRing = GEOM_FACTORY
.createLinearRing(outerRing.toArray(new Coordinate[outerRing.size()]));
// create the inner rings
List<org.locationtech.jts.geom.LinearRing> innerLinearRings = new ArrayList<>();
for (List<Coordinate> innerRing : innerRings) {
org.locationtech.jts.geom.LinearRing innerLinearRing = geomFactory
org.locationtech.jts.geom.LinearRing innerLinearRing = GEOM_FACTORY
.createLinearRing(innerRing.toArray(new Coordinate[innerRing.size()]));
innerLinearRings.add(innerLinearRing);
}
Polygon polygon = geomFactory.createPolygon(outerLinearRing,
Polygon polygon = GEOM_FACTORY.createPolygon(outerLinearRing,
innerLinearRings.toArray(new org.locationtech.jts.geom.LinearRing[innerLinearRings.size()]));
data.getWaterAreas().add(new WaterArea(polygon));
......@@ -625,16 +613,6 @@ public class GreenEnricher {
}
private static void validateRing(List<Coordinate> outerRing) {
if (outerRing.isEmpty()) {
return;
}
if (!outerRing.get(0).equals(outerRing.get(outerRing.size() - 1))) {
// close ring
outerRing.add(outerRing.get(0));
}
}
private static boolean parseGreenAreasIfPossible(OsmData data, Node node, Set<String> usedIds) {
if (!"way".equals(node.getNodeName())) {
return false;
......@@ -676,20 +654,20 @@ public class GreenEnricher {
if (water) {
if (line) {
LineString lineString = geomFactory
LineString lineString = GEOM_FACTORY
.createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getWaterways().add(new Waterway(lineString));
} else {
Polygon polygon = geomFactory.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
Polygon polygon = GEOM_FACTORY.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getWaterAreas().add(new WaterArea(polygon));
}
} else {
if (line) {
LineString lineString = geomFactory
LineString lineString = GEOM_FACTORY
.createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getTreeRows().add(new TreeRow(lineString));
} else {
Polygon polygon = geomFactory.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
Polygon polygon = GEOM_FACTORY.createPolygon(coordinates.toArray(new Coordinate[coordinates.size()]));
data.getGreenAreas().add(new GreenArea(polygon));
}
}
......@@ -709,41 +687,15 @@ public class GreenEnricher {
return namedItem.getNodeValue();
}
private static boolean parseTreeIfPossible(List<TreePoint> treePoints, Node node, Set<String> usedIds) {
if (!"node".equals(node.getNodeName())) {
return false;
}
String id = node.getAttributes().getNamedItem("id").getNodeValue();
if (usedIds.contains(id)) {
System.out.println("Already used node id " + id);
return true;
private static void parseTrees(List<TreePoint> treePoints, List<OsmNode> nodes) {
for (OsmNode node : nodes) {
ProjCoordinate converted = convertCoordinatesFrom84(node.getLon(), node.getLat());
Point point = GEOM_FACTORY.createPoint(new Coordinate(converted.x, converted.y));
treePoints.add(new TreePoint(point));
}
usedIds.add(id);
double lat = Double.parseDouble(node.getAttributes().getNamedItem("lat").getNodeValue());
double lon = Double.parseDouble(node.getAttributes().getNamedItem("lon").getNodeValue());
ProjCoordinate converted = convertCoordinatesFrom84(lon, lat);
Point point = geomFactory.createPoint(new Coordinate(converted.x, converted.y));
treePoints.add(new TreePoint(point));
return true;
}
private static Document createDomFromOsmResponse(String body)
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// to be compliant, completely disable DOCTYPE declaration:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// or completely disable external entities declarations:
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// or prohibit the use of all protocols by external entities:
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
DocumentBuilder builder = factory.newDocumentBuilder();
ByteArrayInputStream input = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
return builder.parse(input);
}
private static CityModel readCityGml(Path inFile) throws CityGMLContextException, CityGMLReadException {
public static CityModel readCityGml(Path inFile) throws CityGMLContextException, CityGMLReadException {
CityGMLContext context = CityGMLContext.newInstance();
CityGMLInputFactory in = context.createCityGMLInputFactory();
try (CityGMLReader reader = in.createCityGMLReader(inFile)) {
......@@ -774,7 +726,7 @@ public class GreenEnricher {
return srsName;
}
private static String extractAndConvertBoundingBox(CityModel cityModel, String epsgCode, OsmData osmData) {
public static String extractAndConvertBoundingBox(CityModel cityModel, OsmData osmData) {
Envelope calculatedEnvelope = cityModel.computeEnvelope();
DirectPosition lowerCorner = calculatedEnvelope.getLowerCorner();
......@@ -805,7 +757,7 @@ public class GreenEnricher {
bboxCoordinates.add(new Coordinate(lowerCorner.getValue().get(0) - BOUNDING_BOX_INCREASE_IN_M,
lowerCorner.getValue().get(1) - BOUNDING_BOX_INCREASE_IN_M));
Polygon poly = geomFactory.createPolygon(bboxCoordinates.toArray(new Coordinate[bboxCoordinates.size()]));
Polygon poly = GEOM_FACTORY.createPolygon(bboxCoordinates.toArray(new Coordinate[bboxCoordinates.size()]));
osmData.setBoundingBox(poly);
return lowerCornerProjected.y + "," + lowerCornerProjected.x + "," + upperCornerProjected.y + ","
......@@ -832,4 +784,38 @@ public class GreenEnricher {
return result;
}
public static void convertRoadAreasToCityGML(CityModel cityModel, OsmData osmData) {
for (RoadArea roadArea : osmData.getRoadAreas()) {
Road road = new Road();
org.xmlobjects.gml.model.geometry.primitives.Polygon poly = convertToCityGmlPoly(roadArea.getArea());
if (poly == null) {
System.out.println("Skipping RoadArea: " + roadArea.getArea());
continue;
}
MultiSurface ms = new MultiSurface();
road.setId(UUID.randomUUID().toString());
ms.getSurfaceMember().add(new SurfaceProperty(poly));
road.setLod0MultiSurface(new MultiSurfaceProperty(ms));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(road));
}
}
public static void converLandUseAreasToCityGML(CityModel cityModel, OsmData osmData) {
for (LandUseArea landUseArea : osmData.getLandUseAreas()) {
LandUse landUse = new LandUse();
org.xmlobjects.gml.model.geometry.primitives.Polygon poly = convertToCityGmlPoly(landUseArea.getArea());
if (poly == null) {
System.out.println("Skipping RoadArea: " + landUseArea.getArea());
continue;
}
MultiSurface ms = new MultiSurface();
landUse.setId(UUID.randomUUID().toString());
ms.getSurfaceMember().add(new SurfaceProperty(poly));
landUse.setLod0MultiSurface(new MultiSurfaceProperty(ms));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(landUse));
}
}
}
package de.hft.stuttgart.citygml.green.osm;
import org.locationtech.jts.geom.Polygon;
public class LandUseArea {
private Polygon area;
public LandUseArea() {
}
public LandUseArea(Polygon area) {
this.area = area;
}
public void setArea(Polygon area) {
this.area = area;
}
public Polygon getArea() {
return area;
}
@Override
public String toString() {
return "LandUseArea [area=" + area + "]";
}
}
......@@ -14,6 +14,8 @@ public class OsmData {
private List<TreeRow> treeRows = new ArrayList<>();
private List<Waterway> waterways = new ArrayList<>();
private List<WaterArea> waterAreas = new ArrayList<>();
private List<RoadArea> roadAreas = new ArrayList<>();
private List<LandUseArea> landUseAreas = new ArrayList<>();
public void setBoundingBox(Polygon boundingBox) {
this.boundingBox = boundingBox;
......@@ -42,5 +44,13 @@ public class OsmData {
public List<TreeRow> getTreeRows() {
return treeRows;
}
public List<RoadArea> getRoadAreas() {
return roadAreas;
}
public List<LandUseArea> getLandUseAreas() {
return landUseAreas;
}
}
package de.hft.stuttgart.citygml.green.osm;
import org.locationtech.jts.geom.Polygon;
public class RoadArea {
private Polygon area;
public RoadArea() {
}
public RoadArea(Polygon area) {
this.area = area;
}
public void setArea(Polygon area) {
this.area = area;
}
public Polygon getArea() {
return area;
}
@Override
public String toString() {
return "RoadArea [area=" + area + "]";
}
}
......@@ -104,7 +104,7 @@ public class TreeGenerator {
List<Coordinate> secondRing = ringCoordinates.get(1);
for (int i = 0; i < secondRing.size(); i++) {
Coordinate[] coordArray = new Coordinate[] { topPoint, secondRing.get(i), secondRing.get((i + 1) % secondRing.size()), topPoint };
Polygon polygon = GreenEnricher.geomFactory.createPolygon(coordArray);
Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
}
......@@ -118,7 +118,7 @@ public class TreeGenerator {
Coordinate p3 = bottomRing.get(j);
Coordinate p4 = bottomRing.get(nextRingIndex);
Coordinate[] coordArray = new Coordinate[] { p1, p3, p4, p2, p1 };
Polygon polygon = GreenEnricher.geomFactory.createPolygon(coordArray);
Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
}
......@@ -131,7 +131,7 @@ public class TreeGenerator {
Coordinate p1 = bottomRing.get(i);
Coordinate p2 = bottomRing.get(nextRingIndex);
Coordinate[] coordArray = new Coordinate[] { p2, p1, bottomPoint, p2 };
Polygon polygon = GreenEnricher.geomFactory.createPolygon(coordArray);
Polygon polygon = GreenEnricher.GEOM_FACTORY.createPolygon(coordArray);
var convertedPoly = GreenEnricher.convertToCityGmlPoly(polygon);
ms.getSurfaceMember().add(new SurfaceProperty(convertedPoly));
}
......@@ -140,7 +140,7 @@ public class TreeGenerator {
}
private static Polygon convertPolygon(List<Coordinate> trunkWestCoordinateList) {
return GreenEnricher.geomFactory
return GreenEnricher.GEOM_FACTORY
.createPolygon(trunkWestCoordinateList.toArray(new Coordinate[trunkWestCoordinateList.size()]));
}
......
package de.hft.stuttgart.citygml.green.osm;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
public class TreeKatasterData {
public static final double TRUNK_PERCENTAGE = 0.2;
public static final double CROWN_PERCENTAGE = 1 - TRUNK_PERCENTAGE;
private List<Tree> trees;
public static TreeKatasterData parseTreeKatasterData(Path path) throws IOException {
TreeKatasterData result = new TreeKatasterData();
Map<String, Object> readParameters = new HashMap<>();
readParameters.put("url", path.toUri().toURL());
readParameters.put("charset", StandardCharsets.UTF_8);
DataStore dataStore = DataStoreFinder.getDataStore(readParameters);
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
Tree tree = new Tree();
Point p = (Point) feature.getAttribute("the_geom");
tree.setPoint(p);
String type = feature.getAttribute("Bezeichnun").toString();
tree.setType(type);
Object treeHeightObject = feature.getAttribute("Baumhöhe");
if (treeHeightObject == null) {
continue;
}
int treeHeight = Integer.parseInt(treeHeightObject.toString());
double crownHeight = CROWN_PERCENTAGE * treeHeight;
double trunkHeight = TRUNK_PERCENTAGE * treeHeight;
tree.setCrownHeight(crownHeight);
tree.setTrunkHeight(trunkHeight);
Object crownWidth = feature.getAttribute("Kronenbrei");
if (crownWidth == null) {
continue;
}
tree.setCrownRadius(Float.parseFloat(crownWidth.toString()) / 2);
Object trunkCirc = feature.getAttribute("Stammumfan");
if (trunkCirc == null) {
continue;
}
tree.setTrunkRadius(Integer.parseInt(trunkCirc.toString()) / (2 * Math.PI) / 100);
result.getTrees().add(tree);
}
}
return result;
}
public List<Tree> getTrees() {
if (trees == null) {
trees = new ArrayList<>();
......
package de.hft.stuttgart.citygml.green.osm;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.UUID;
import org.citygml4j.core.model.core.AbstractCityObjectProperty;
import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.core.model.vegetation.SolitaryVegetationObject;
import org.locationtech.jts.geom.Coordinate;
import org.xmlobjects.gml.model.basictypes.Code;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurface;
import org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty;
public class TreeUtils {
public static void insertTrees(CityModel cityModel, OsmData osmData) throws IOException {
TreeKatasterData katasterData = TreeKatasterData.parseTreeKatasterData(Paths.get("data", "Baum.shp"));
generateTreesFromKataster(cityModel, katasterData);
// All kataster trees are taken, osm trees are removed
filterDuplicateTreesFromOSM(osmData, katasterData);
generateTreesFromOSM(cityModel, osmData);
}
private static void filterDuplicateTreesFromOSM(OsmData osmData, TreeKatasterData katasterData) {
for (Iterator<TreePoint> iterator = osmData.getTreePoints().iterator(); iterator.hasNext();) {
TreePoint tp = iterator.next();
// if another tree from kataster is within 3m ignore it
for (Tree tree : katasterData.getTrees()) {
if (tp.getPoint().distance(tree.getPoint()) < 3) {
iterator.remove();
}
}
}
}
private static void generateTreesFromOSM(CityModel cityModel, OsmData osmData) {
for (TreePoint tp : osmData.getTreePoints()) {
// standard tree
double trunkRadius = 0.89 / (2 * Math.PI);
double trunkHeight = TreeKatasterData.TRUNK_PERCENTAGE * 11.46;
double crownHeight = TreeKatasterData.CROWN_PERCENTAGE * 11.46;
double crownRadius = 8 / 2d;
Coordinate coordinate = tp.getPoint().getCoordinate();
if (Double.isNaN(coordinate.z)) {
coordinate.z = 0;
}
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, crownRadius,
crownRadius, crownHeight);
SolitaryVegetationObject cover = new SolitaryVegetationObject();
cover.setSpecies(new Code("Acer campestre"));
cover.setId(UUID.randomUUID().toString());
cover.setLod2MultiSurface(new MultiSurfaceProperty(generatedTree));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(cover));
}
}
private static void generateTreesFromKataster(CityModel cityModel, TreeKatasterData katasterData) {
for (Tree tree : katasterData.getTrees()) {
double trunkRadius = tree.getTrunkRadius();
double trunkHeight = tree.getTrunkHeight();
double crownHeight = tree.getCrownHeight();
double crownRadius = tree.getCrownRadius();
Coordinate coordinate = tree.getPoint().getCoordinate();
if (Double.isNaN(coordinate.z)) {
coordinate.z = 0;
}
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, crownRadius,
crownRadius, crownHeight);
SolitaryVegetationObject cover = new SolitaryVegetationObject();
cover.setSpecies(new Code(tree.getType()));
cover.setId(UUID.randomUUID().toString());
cover.setLod2MultiSurface(new MultiSurfaceProperty(generatedTree));
cityModel.getCityObjectMembers().add(new AbstractCityObjectProperty(cover));
}
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import jakarta.xml.bind.annotation.XmlAttribute;
public class Bounds {
@XmlAttribute(name = "minlat")
private double minLat;
@XmlAttribute(name = "minlon")
private double minLon;
@XmlAttribute(name = "maxlat")
private double maxLat;
@XmlAttribute(name = "maxlon")
private double maxLon;
public double getMaxLat() {
return maxLat;
}
public double getMaxLon() {
return maxLon;
}
public double getMinLat() {
return minLat;
}
public double getMinLon() {
return minLon;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import jakarta.xml.bind.annotation.XmlAttribute;
public class Meta {
@XmlAttribute(name = "osm_base")
private String osmBase;
public String getOsmBase() {
return osmBase;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "osm")
public class OSM {
@XmlAttribute
private String version;
@XmlAttribute
private String generator;
@XmlElement
private String note;
@XmlElement
private Meta meta;
@XmlElement
private Bounds bounds;
@XmlElements(value = { @XmlElement(name = "node", type = OsmNode.class) })
private List<OsmNode> nodes;
@XmlElements(value = { @XmlElement(name = "way", type = OsmWay.class) })
private List<OsmWay> ways;
@XmlElements(value = { @XmlElement(name = "relation", type = OsmRelation.class) })
private List<OsmRelation> relations;
public List<OsmRelation> getRelations() {
if (relations == null) {
relations = new ArrayList<>();
}
return relations;
}
public List<OsmWay> getWays() {
if (ways == null) {
ways = new ArrayList<>();
}
return ways;
}
public List<OsmNode> getNodes() {
if (nodes == null) {
nodes = new ArrayList<>();
}
return nodes;
}
public Bounds getBounds() {
return bounds;
}
public String getVersion() {
return version;
}
public String getGenerator() {
return generator;
}
public String getNote() {
return note;
}
public Meta getMeta() {
return meta;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
public class OsmMember {
@XmlAttribute
private String type;
@XmlAttribute
private String ref;
@XmlAttribute
private String role;
@XmlElements(value = { @XmlElement(name = "nd", type = WayNode.class) })
private List<WayNode> nodes;
public List<WayNode> getNodes() {
if (nodes == null) {
nodes = new ArrayList<>();
}
return nodes;
}
public String getRef() {
return ref;
}
public String getRole() {
return role;
}
public String getType() {
return type;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
public class OsmNode {
@XmlAttribute
private String id;
@XmlAttribute
private double lat;
@XmlAttribute
private double lon;
@XmlElements(value = { @XmlElement(name = "tag", type = OsmTag.class) })
private List<OsmTag> tags;
public String getId() {
return id;
}
public double getLat() {
return lat;
}
public double getLon() {
return lon;
}
public List<OsmTag> getTags() {
if (tags == null) {
tags = new ArrayList<>();
}
return tags;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
public class OsmRelation {
@XmlAttribute
private String id;
@XmlElement
private Bounds bounds;
@XmlElements(value = { @XmlElement(name = "member", type = OsmMember.class) })
private List<OsmMember> members;
@XmlElements(value = { @XmlElement(name = "tag", type = OsmTag.class) })
private List<OsmTag> tags;
public List<OsmTag> getTags() {
if (tags == null) {
tags = new ArrayList<>();
}
return tags;
}
public List<OsmMember> getMembers() {
if (members == null) {
members = new ArrayList<>();
}
return members;
}
public Bounds getBounds() {
return bounds;
}
public String getId() {
return id;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import jakarta.xml.bind.annotation.XmlAttribute;
public class OsmTag {
@XmlAttribute(name = "k")
private String key;
@XmlAttribute(name = "v")
private String value;
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import java.util.ArrayList;
import java.util.List;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
public class OsmWay {
@XmlAttribute
private String id;
@XmlElement
private Bounds bounds;
@XmlElements(value = { @XmlElement(name = "nd", type = WayNode.class) })
private List<WayNode> nodes;
@XmlElements(value = { @XmlElement(name = "tag", type = OsmTag.class) })
private List<OsmTag> tags;
public List<OsmTag> getTags() {
if (tags == null) {
tags = new ArrayList<>();
}
return tags;
}
public String getId() {
return id;
}
public Bounds getBounds() {
return bounds;
}
public List<WayNode> getNodes() {
if (nodes == null) {
nodes = new ArrayList<>();
}
return nodes;
}
}
package de.hft.stuttgart.citygml.green.osm.jaxb;
import jakarta.xml.bind.annotation.XmlAttribute;
public class WayNode {
@XmlAttribute
private String ref;
@XmlAttribute
private double lat;
@XmlAttribute
private double lon;
public double getLat() {
return lat;
}
public double getLon() {
return lon;
}
public String getRef() {
return ref;
}
}
package de.hft.stuttgart.citygml.green.alkis;
import java.io.IOException;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.reader.CityGMLReadException;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.junit.jupiter.api.Test;
import jakarta.xml.bind.JAXBException;
class AlkisGreenEnricherTest {
@Test
void testAlkisGreen() throws IOException, CityGMLContextException, CityGMLReadException, JAXBException, CityGMLWriteException {
String[] args = new String[] {"data/Grombühl_v3.gml"};
AlkisGreenEnricher.main(args);
}
}
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