Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CircularGreenSimCity
CircularGreenSimCity
Commits
690d78b9
Commit
690d78b9
authored
Feb 24, 2023
by
Matthias Betz
Browse files
initial commit for osm data enricher
parent
fb3bf74b
Changes
10
Hide whitespace changes
Inline
Side-by-side
enrich-citygml-with-greenarea/.gitignore
0 → 100644
View file @
690d78b9
# Created by https://www.gitignore.io/api/java,maven,macos,linux,eclipse,windows,netbeans,intellij
# Edit at https://www.gitignore.io/?templates=java,maven,macos,linux,eclipse,windows,netbeans,intellij
# User specific
.sonarlint/
Servers/
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
### Eclipse Patch ###
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Annotation Processing
.apt_generated
.sts4-cache/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
### NetBeans ###
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.gitignore.io/api/java,maven,macos,linux,eclipse,windows,netbeans,intellij
enrich-citygml-with-greenarea/pom.xml
0 → 100644
View file @
690d78b9
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
de.hft.stuttgart
</groupId>
<artifactId>
enrich-citygml-with-osm
</artifactId>
<version>
0.0.1-SNAPSHOT
</version>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>
org.junit.jupiter
</groupId>
<artifactId>
junit-jupiter-api
</artifactId>
<version>
5.9.2
</version>
<scope>
test
</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-core -->
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-core
</artifactId>
<version>
3.0.0-rc.5
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.proj4j/proj4j -->
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j
</artifactId>
<version>
1.1.4
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>
org.locationtech.jts
</groupId>
<artifactId>
jts-core
</artifactId>
<version>
1.19.0
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-xml -->
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-xml
</artifactId>
<version>
3.0.0-rc.5
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenArea.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Polygon
;
public
class
GreenArea
{
private
Polygon
area
;
public
GreenArea
()
{
}
public
GreenArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
void
setArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
Polygon
getArea
()
{
return
area
;
}
@Override
public
String
toString
()
{
return
"GreenArea [area="
+
area
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.net.URLEncoder
;
import
java.net.http.HttpClient
;
import
java.net.http.HttpRequest
;
import
java.net.http.HttpResponse
;
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.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.UUID
;
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
;
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.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
;
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.Geometry
;
import
org.locationtech.jts.geom.GeometryFactory
;
import
org.locationtech.jts.geom.LineString
;
import
org.locationtech.jts.geom.MultiPolygon
;
import
org.locationtech.jts.geom.Point
;
import
org.locationtech.jts.geom.Polygon
;
import
org.locationtech.proj4j.BasicCoordinateTransform
;
import
org.locationtech.proj4j.CRSFactory
;
import
org.locationtech.proj4j.CoordinateReferenceSystem
;
import
org.locationtech.proj4j.ProjCoordinate
;
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
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty
;
import
org.xmlobjects.gml.model.geometry.primitives.AbstractRingProperty
;
import
org.xmlobjects.gml.model.geometry.primitives.LinearRing
;
import
org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty
;
public
class
GreenEnricher
{
private
static
final
int
BOUNDING_BOX_INCREASE_IN_M
=
100
;
// in degrees
// add around 30m ( 1" = 30m -> 0.00277 = 900m)
private
static
final
double
BOUNDING_BOX_INCREASE
=
0.00277
;
private
static
final
String
OSM_STRING
=
"""
[bbox:{{bbox}}];
(
nwr["
leisure
"="
garden
"];
nwr["
landuse
"="
forest
"];
nwr["
natural
"="
tree
"];
nwr["
leisure
"="
park
"];
nwr["
natural
"="
tree_row
"];
nwr["
natural
"="
wood
"];
nwr["
landuse
"="
grass
"];
nwr["
landuse
"="
orchard
"];
nwr["
natural
"="
scrub
"];
nwr["
landuse
"="
meadow
"];
nwr["
landuse
"="
farmland
"];
nwr["
landuse
"="
allotments
"];
nwr["
natural
"="
water
"];
nwr["
water
"="
river
"];
nwr["
type
"="
waterway
"];
nwr["
waterway
"="
stream
"];
nwr["
water
"="
pond
"];
);
out geom;"""
;
private
static
final
URI
OVERPASS_API_URI
=
URI
.
create
(
"http://www.overpass-api.de/api/interpreter"
);
private
static
final
CRSFactory
CRS_FACTORY
=
new
CRSFactory
();
private
static
CoordinateReferenceSystem
sourceCRS
;
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
void
main
(
String
[]
args
)
throws
IOException
,
CityGMLContextException
,
CityGMLReadException
,
InterruptedException
,
ParserConfigurationException
,
SAXException
,
CityGMLWriteException
{
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
);
OsmData
osmData
=
new
OsmData
();
String
boundingBoxString
=
extractAndConvertBoundingBox
(
cityModel
,
epsgCode
,
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
(
"osm_response.xml"
));
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
);
System
.
out
.
println
(
"Filter intersecting areas"
);
List
<
GreenArea
>
greenAreas
=
osmData
.
getGreenAreas
();
removeDuplicateAreas
(
greenAreas
);
convertGreenAreasToCityGML
(
cityModel
,
greenAreas
);
convertWaterAreasToCityGML
(
cityModel
,
osmData
);
for
(
Waterway
waterWay
:
osmData
.
getWaterways
())
{
}
for
(
TreePoint
tp
:
osmData
.
getTreePoints
())
{
double
trunkRadius
=
0.2
;
double
trunkHeight
=
1
;
Coordinate
coordinate
=
tp
.
getPoint
().
getCoordinate
();
if
(
Double
.
isNaN
(
coordinate
.
z
))
{
coordinate
.
z
=
0
;
}
MultiSurface
generatedTree
=
TreeGenerator
.
generateTree
(
coordinate
,
trunkRadius
,
trunkHeight
,
5
,
5
,
10
);
SolitaryVegetationObject
cover
=
new
SolitaryVegetationObject
();
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
(
inputPathWithoutFileEnding
+
"_with_greens.gml"
);
System
.
out
.
println
(
"Writing output file."
);
writeCityGML
(
cityModel
,
outputPath
);
System
.
out
.
println
(
"Done"
);
}
private
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
());
if
(
poly
==
null
)
{
System
.
out
.
println
(
"Skipping WaterBody "
+
waterArea
.
getArea
());
continue
;
}
MultiSurface
ms
=
new
MultiSurface
();
wb
.
setId
(
UUID
.
randomUUID
().
toString
());
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
poly
));
wb
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
cityModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
wb
));
}
}
private
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
)
{
System
.
out
.
println
(
"Skipping "
+
ga
.
getArea
());
continue
;
}
PlantCover
cover
=
new
PlantCover
();
MultiSurface
ms
=
new
MultiSurface
();
cover
.
setId
(
UUID
.
randomUUID
().
toString
());
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
poly
));
cover
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
cityModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
cover
));
}
}
private
static
void
fitToBoundingBox
(
OsmData
osmData
)
{
List
<
GreenArea
>
greenAreas
=
osmData
.
getGreenAreas
();
List
<
GreenArea
>
newGreenAreas
=
new
ArrayList
<>();
for
(
GreenArea
greenArea
:
greenAreas
)
{
Polygon
area
=
greenArea
.
getArea
();
Geometry
intersection
=
area
.
intersection
(
osmData
.
getBoundingBox
());
if
(
intersection
instanceof
MultiPolygon
multi
)
{
Polygon
poly1
=
(
Polygon
)
multi
.
getGeometryN
(
0
);
greenArea
.
setArea
(
poly1
);
for
(
int
k
=
1
;
k
<
multi
.
getNumGeometries
();
k
++)
{
GreenArea
newGreenArea
=
new
GreenArea
();
newGreenArea
.
setArea
((
Polygon
)
multi
.
getGeometryN
(
k
));
newGreenAreas
.
add
(
newGreenArea
);
}
}
else
{
greenArea
.
setArea
((
Polygon
)
intersection
);
}
}
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
)
{
List
<
WaterArea
>
newWaterAreas
=
new
ArrayList
<>();
for
(
WaterArea
waterArea
:
osmData
.
getWaterAreas
())
{
Polygon
area
=
waterArea
.
getArea
();
Geometry
intersection
=
area
.
intersection
(
osmData
.
getBoundingBox
());
if
(
intersection
instanceof
MultiPolygon
multi
)
{
Polygon
poly1
=
(
Polygon
)
multi
.
getGeometryN
(
0
);
waterArea
.
setArea
(
poly1
);