diff --git a/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java b/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java index b6346294a8105d6dde7c7da09ae5c7a232d94fda..c8193c30278a71e29f9ba470501b8c6283b1a5ab 100644 --- a/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java +++ b/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java @@ -2,6 +2,7 @@ package de.hft.stuttgart.citygml.green.osm; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -12,11 +13,14 @@ 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; @@ -30,7 +34,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.vegetation.PlantCover; import org.citygml4j.core.model.vegetation.SolitaryVegetationObject; import org.citygml4j.core.model.waterbody.WaterBody; @@ -44,6 +51,11 @@ 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; @@ -55,6 +67,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; @@ -69,6 +83,9 @@ import org.xmlobjects.gml.model.geometry.primitives.LinearRing; import org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty; 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; @@ -145,20 +162,65 @@ public class GreenEnricher { for (Waterway waterWay : osmData.getWaterways()) { } + + // trees + + TreeKatasterData katasterData = parseTreeKatasterData(Paths.get("data", "Baum.shp")); + for (Iterator 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()) { - double trunkRadius = 0.2; - double trunkHeight = 3; + // 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, 3, 3, 10); + 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); @@ -175,6 +237,56 @@ public class GreenEnricher { } + private static TreeKatasterData parseTreeKatasterData(Path path) throws IOException { + TreeKatasterData result = new TreeKatasterData(); + Map 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 source = + dataStore.getFeatureSource(typeName); + + FeatureCollection collection = source.getFeatures(); + try (FeatureIterator 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; + } + private static void convertWaterAreasToCityGML(CityModel cityModel, OsmData osmData) { for (WaterArea waterArea : osmData.getWaterAreas()) { WaterBody wb = new WaterBody(); diff --git a/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Tree.java b/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Tree.java index ba8b68ff93f0645bf8771d8747c619e6d7acc974..62e1dce133af8e8a4553b4de3bc381623834e711 100644 --- a/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Tree.java +++ b/enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Tree.java @@ -1,20 +1,29 @@ package de.hft.stuttgart.citygml.green.osm; -import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Point; public class Tree { - private Coordinate point; + private String type; + private Point point; private double trunkHeight; private double trunkRadius; private double crownRadius; private double crownHeight; - public Coordinate getPoint() { + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public Point getPoint() { return point; } - public void setPoint(Coordinate point) { + public void setPoint(Point point) { this.point = point; }