Commit ccd43258 authored by Matthias Betz's avatar Matthias Betz
Browse files

year of construction and tree analyzer

parent 734233d1
......@@ -10,7 +10,27 @@
<maven.compiler.target>17</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.geotools/gt-shapefile -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>24.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
......
package de.hft.stuttgart.citygml.green.kataster;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
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.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
public class StandardTreeFinder {
public static void main(String[] args) throws IOException {
File f = new File("data/Baum.shp");
Map<String, AtomicInteger> treeTypes = new HashMap<>();
List<Integer> ages = new ArrayList<>();
List<Integer> treeHeights = new ArrayList<>();
List<Float> crownWidths = new ArrayList<>();
List<Integer> trunkCircs = new ArrayList<>();
Map<String, Object> map = new HashMap<>();
map.put("url", f.toURI().toURL());
map.put("charset", StandardCharsets.UTF_8);
DataStore dataStore = DataStoreFinder.getDataStore(map);
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source =
dataStore.getFeatureSource(typeName);
int featureCount = 0;
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
featureCount++;
SimpleFeature feature = features.next();
String type = feature.getAttribute("Baumart").toString();
treeTypes.compute(type, (k, v) -> {
if (v == null) {
v = new AtomicInteger(0);
}
v.incrementAndGet();
return v;
});
Object ageObject = feature.getAttribute("Alter am S");
if (ageObject != null) {
ages.add(Integer.parseInt(ageObject.toString()));
}
Object treeHeight = feature.getAttribute("Baumhöhe");
if (treeHeight != null) {
treeHeights.add(Integer.parseInt(treeHeight.toString()));
}
Object crownWidth = feature.getAttribute("Kronenbrei");
if (crownWidth != null) {
crownWidths.add(Float.parseFloat(crownWidth.toString()));
}
Object trunkCirc = feature.getAttribute("Stammumfan");
if (trunkCirc != null) {
trunkCircs.add(Integer.parseInt(trunkCirc.toString()));
}
}
}
System.out.println("Number of trees: " + featureCount);
for (Entry<String, AtomicInteger> e : treeTypes.entrySet()) {
System.out.println(e.getKey() + ": " + e.getValue());
}
System.out.println();
IntSummaryStatistics treeHeightsStatistics = treeHeights.stream().collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("TreeHeightAverage: " + treeHeightsStatistics.getAverage());
IntSummaryStatistics agesStatistics = ages.stream().collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("AverageAge: " + agesStatistics);
Double averageCrown = crownWidths.stream().collect(Collectors.averagingDouble(Float::doubleValue));
System.out.println("AverageCrownWidth: " + averageCrown);
Double averageTrunkCirc = trunkCircs.stream().collect(Collectors.averagingInt(Integer::intValue));
System.out.println("AverageTrunkCirc: " + averageTrunkCirc);
}
}
......@@ -112,6 +112,8 @@ public class GreenEnricher {
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);
......@@ -123,7 +125,7 @@ public class GreenEnricher {
// 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("osm_response.xml"));
String osmResponse = Files.readString(Paths.get("data", "osm_response.xml"));
System.out.println("Parsing OSM response");
parseOsmResponse(osmResponse, osmData);
......@@ -146,12 +148,12 @@ public class GreenEnricher {
for (TreePoint tp : osmData.getTreePoints()) {
double trunkRadius = 0.2;
double trunkHeight = 1;
double trunkHeight = 3;
Coordinate coordinate = tp.getPoint().getCoordinate();
if (Double.isNaN(coordinate.z)) {
coordinate.z = 0;
}
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, 5, 5, 10);
MultiSurface generatedTree = TreeGenerator.generateTree(coordinate, trunkRadius, trunkHeight, 3, 3, 10);
SolitaryVegetationObject cover = new SolitaryVegetationObject();
cover.setId(UUID.randomUUID().toString());
cover.setLod2MultiSurface(new MultiSurfaceProperty(generatedTree));
......@@ -166,7 +168,7 @@ public class GreenEnricher {
String inputString = inFile.getFileName().toString();
String inputPathWithoutFileEnding = inputString.substring(0, inputString.lastIndexOf('.'));
Path outputPath = Paths.get(inputPathWithoutFileEnding + "_with_greens.gml");
Path outputPath = Paths.get("data", inputPathWithoutFileEnding + "_with_greens.gml");
System.out.println("Writing output file.");
writeCityGML(cityModel, outputPath);
System.out.println("Done");
......
package de.hft.stuttgart.citygml.green.osm;
import org.locationtech.jts.geom.Coordinate;
public class Tree {
private Coordinate point;
private double trunkHeight;
private double trunkRadius;
private double crownRadius;
private double crownHeight;
public Coordinate getPoint() {
return point;
}
public void setPoint(Coordinate point) {
this.point = point;
}
public double getTrunkHeight() {
return trunkHeight;
}
public void setTrunkHeight(double trunkHeight) {
this.trunkHeight = trunkHeight;
}
public double getTrunkRadius() {
return trunkRadius;
}
public void setTrunkRadius(double trunkRadius) {
this.trunkRadius = trunkRadius;
}
public double getCrownRadius() {
return crownRadius;
}
public void setCrownRadius(double crownRadius) {
this.crownRadius = crownRadius;
}
public double getCrownHeight() {
return crownHeight;
}
public void setCrownHeight(double crownHeight) {
this.crownHeight = crownHeight;
}
}
package de.hft.stuttgart.citygml.green.osm;
import java.util.ArrayList;
import java.util.List;
public class TreeKatasterData {
private List<Tree> trees;
public List<Tree> getTrees() {
if (trees == null) {
trees = new ArrayList<>();
}
return trees;
}
}
package de.hft.stuttgart.citygml.yoc.analysis;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import org.citygml4j.core.model.CityGMLVersion;
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.CityModel;
import org.citygml4j.xml.CityGMLContext;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.module.citygml.CoreModule;
import org.citygml4j.xml.reader.CityGMLInputFactory;
import org.citygml4j.xml.reader.CityGMLReadException;
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.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.xmlobjects.gml.model.geometry.DirectPosition;
public class YearOfConstructionAnalyzer {
public static void main(String[] args) throws CityGMLContextException, CityGMLReadException, CityGMLWriteException {
Path inputFile = Paths.get("data", "Grombühl_v3.gml");
CityModel cityModel = readCityGml(inputFile);
List<AbstractCityObjectProperty> cityObjectMembers = cityModel.getCityObjectMembers();
Map<String, AtomicInteger> missingYocUsageCount = new HashMap<>();
GeometryFactory factory = new GeometryFactory();
Map<Point, Building> centersMap = new HashMap<>();
for (AbstractCityObjectProperty acop : cityObjectMembers) {
AbstractCityObject abstractCityObject = acop.getObject();
if (abstractCityObject instanceof Building b) {
DirectPosition center = b.computeEnvelope().getCenter();
Point point = factory.createPoint(new Coordinate(center.getValue().get(0), center.getValue().get(1)));
centersMap.put(point, b);
}
}
for (AbstractCityObjectProperty acop : cityObjectMembers) {
AbstractCityObject abstractCityObject = acop.getObject();
if (abstractCityObject instanceof Building b && b.getDateOfConstruction() == null) {
String function = b.getFunctions().get(0).getValue();
if ("31001_1000".equals(function)) {
DirectPosition center = b.computeEnvelope().getCenter();
double lowestDistance = Double.MAX_VALUE;
Point point = factory.createPoint(new Coordinate(center.getValue().get(0), center.getValue().get(1)));
Building nearestBuilding = null;
for (Entry<Point, Building> e : centersMap.entrySet()) {
if (e.getValue() == b) {
continue;
}
if (e.getKey().distance(point) < lowestDistance && e.getValue().getDateOfConstruction() != null) {
lowestDistance = e.getKey().distance(point);
nearestBuilding = e.getValue();
}
}
if (nearestBuilding == null) {
throw new IllegalStateException();
}
System.out.println("Assigning " + b.getId() + " yoc of: " + nearestBuilding.getDateOfConstruction());
b.setDateOfConstruction(nearestBuilding.getDateOfConstruction());
}
missingYocUsageCount.compute(function, (k, v) -> {
if (v == null) {
v = new AtomicInteger(0);
}
v.getAndIncrement();
return v;
});
}
}
writeCityGML(cityModel, Paths.get("out.gml"));
}
private static CityModel readCityGml(Path inFile) throws CityGMLContextException, CityGMLReadException {
CityGMLContext context = CityGMLContext.newInstance();
CityGMLInputFactory in = context.createCityGMLInputFactory();
try (CityGMLReader reader = in.createCityGMLReader(inFile)) {
AbstractFeature feature = reader.next();
if (feature instanceof CityModel cm) {
return cm;
}
}
throw new IllegalStateException("CityGML does not contain a CityModel feature type");
}
private static void writeCityGML(CityModel cityModel, Path outputPath)
throws CityGMLWriteException, CityGMLContextException {
CityGMLContext context = CityGMLContext.newInstance();
CityGMLVersion version = CityGMLVersion.v2_0;
CityGMLOutputFactory out = context.createCityGMLOutputFactory(version);
try (CityGMLWriter writer = out.createCityGMLWriter(outputPath, StandardCharsets.UTF_8.name())) {
writer.withIndent(" ").withDefaultSchemaLocations().withDefaultPrefixes()
.withDefaultNamespace(CoreModule.of(version).getNamespaceURI()).write(cityModel);
}
}
}
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