Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Mayer
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
);
for
(
int
k
=
1
;
k
<
multi
.
getNumGeometries
();
k
++)
{
WaterArea
newWaterArea
=
new
WaterArea
();
newWaterArea
.
setArea
((
Polygon
)
multi
.
getGeometryN
(
k
));
newWaterAreas
.
add
(
newWaterArea
);
}
}
else
{
waterArea
.
setArea
((
Polygon
)
intersection
);
}
}
}
private
static
void
removeDuplicateAreas
(
List
<
GreenArea
>
greenAreas
)
{
for
(
int
i
=
0
;
i
<
greenAreas
.
size
();
i
++)
{
for
(
int
j
=
i
+
1
;
j
<
greenAreas
.
size
();
j
++)
{
GreenArea
area1
=
greenAreas
.
get
(
i
);
GreenArea
area2
=
greenAreas
.
get
(
j
);
if
(
area1
.
getArea
().
intersects
(
area2
.
getArea
()))
{
Geometry
difference
=
area1
.
getArea
().
difference
(
area2
.
getArea
());
System
.
out
.
println
(
difference
);
if
(
difference
instanceof
MultiPolygon
)
{
MultiPolygon
multi
=
(
MultiPolygon
)
difference
;
Polygon
poly1
=
(
Polygon
)
multi
.
getGeometryN
(
0
);
area1
.
setArea
(
poly1
);
for
(
int
k
=
1
;
k
<
multi
.
getNumGeometries
();
k
++)
{
GreenArea
newGreenArea
=
new
GreenArea
();
newGreenArea
.
setArea
((
Polygon
)
multi
.
getGeometryN
(
k
));
greenAreas
.
add
(
newGreenArea
);
}
}
else
{
area1
.
setArea
((
Polygon
)
difference
);
}
}
}
}
}
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
)
{
for
(
AbstractCityObjectProperty
afp
:
cityModel
.
getCityObjectMembers
())
{
AbstractCityObject
af
=
afp
.
getObject
();
if
(
af
instanceof
Building
b
)
{
Envelope
envelope
=
b
.
computeEnvelope
();
Double
lowestZ
=
envelope
.
getLowerCorner
().
getValue
().
get
(
2
);
b
.
accept
(
new
ObjectWalker
()
{
@Override
public
void
visit
(
LinearRing
linearRing
)
{
List
<
Double
>
values
=
linearRing
.
getControlPoints
().
getPosList
().
getValue
();
for
(
int
i
=
2
;
i
<
values
.
size
();
i
=
i
+
3
)
{
values
.
set
(
i
,
values
.
get
(
i
)
-
lowestZ
);
}
}
});
}
}
}
public
static
org
.
xmlobjects
.
gml
.
model
.
geometry
.
primitives
.
Polygon
convertToCityGmlPoly
(
Polygon
area
)
{
if
(
area
.
getExteriorRing
().
getCoordinates
().
length
==
0
)
{
return
null
;
}
org
.
xmlobjects
.
gml
.
model
.
geometry
.
primitives
.
Polygon
result
=
new
org
.
xmlobjects
.
gml
.
model
.
geometry
.
primitives
.
Polygon
();
LinearRing
lr
=
new
LinearRing
();
result
.
setExterior
(
new
AbstractRingProperty
(
lr
));
DirectPositionList
posList
=
new
DirectPositionList
();
lr
.
getControlPoints
().
setPosList
(
posList
);
List
<
Double
>
values
=
posList
.
getValue
();
for
(
Coordinate
coord
:
area
.
getExteriorRing
().
getCoordinates
())
{
values
.
add
(
coord
.
x
);
values
.
add
(
coord
.
y
);
if
(
Double
.
isNaN
(
coord
.
z
))
{
coord
.
z
=
0
;
}
values
.
add
(
coord
.
z
);
}
for
(
int
i
=
0
;
i
<
area
.
getNumInteriorRing
();
i
++)
{
LinearRing
innerRing
=
new
LinearRing
();
result
.
getInterior
().
add
(
new
AbstractRingProperty
(
innerRing
));
DirectPositionList
innerPosList
=
new
DirectPositionList
();
innerRing
.
getControlPoints
().
setPosList
(
innerPosList
);
List
<
Double
>
innerValues
=
innerPosList
.
getValue
();
Coordinate
[]
coordinates
=
area
.
getInteriorRingN
(
i
).
getCoordinates
();
for
(
Coordinate
coord
:
coordinates
)
{
innerValues
.
add
(
coord
.
x
);
innerValues
.
add
(
coord
.
y
);
if
(
Double
.
isNaN
(
coord
.
z
))
{
coord
.
z
=
0
;
}
innerValues
.
add
(
coord
.
z
);
}
}
return
result
;
}
private
static
HttpResponse
<
String
>
getOsmData
(
String
boundingBoxString
)
throws
IOException
,
InterruptedException
{
String
data
=
OSM_STRING
.
replace
(
"{{bbox}}"
,
boundingBoxString
);
String
body
=
URLEncoder
.
encode
(
"data"
,
StandardCharsets
.
UTF_8
)
+
"="
+
URLEncoder
.
encode
(
data
,
StandardCharsets
.
UTF_8
);
HttpClient
client
=
HttpClient
.
newHttpClient
();
HttpRequest
request
=
HttpRequest
.
newBuilder
().
uri
(
OVERPASS_API_URI
)
.
POST
(
HttpRequest
.
BodyPublishers
.
ofString
(
body
)).
build
();
System
.
out
.
println
(
"Retrieving OSM data of bounding box: "
+
boundingBoxString
);
HttpResponse
<
String
>
response
=
client
.
send
(
request
,
HttpResponse
.
BodyHandlers
.
ofString
());
if
(
response
.
statusCode
()
!=
200
)
{
System
.
err
.
println
(
"Failed to retrieve OSM data. Return code: "
+
response
.
statusCode
());
System
.
exit
(
1
);
}
return
response
;
}
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
);
}
}
private
static
OsmData
parseOsmResponse
(
String
osmResponse
,
OsmData
osmData
)
throws
ParserConfigurationException
,
SAXException
,
IOException
{
Document
document
=
createDomFromOsmResponse
(
osmResponse
);
// root element
Node
osmItem
=
document
.
getChildNodes
().
item
(
0
);
NodeList
childNodes
=
osmItem
.
getChildNodes
();
Set
<
String
>
usedIds
=
new
HashSet
<>();
for
(
int
i
=
0
;
i
<
childNodes
.
getLength
();
i
++)
{
Node
node
=
childNodes
.
item
(
i
);
if
(
parseTreeIfPossible
(
osmData
.
getTreePoints
(),
node
,
usedIds
))
{
continue
;
}
if
(
parseGreenAreasIfPossible
(
osmData
,
node
,
usedIds
))
{
continue
;
}
parseGreenRelationsIfPossible
(
osmData
,
node
,
usedIds
);
}
return
osmData
;
}
private
static
boolean
parseGreenRelationsIfPossible
(
OsmData
data
,
Node
node
,
Set
<
String
>
usedIds
)
{
if
(!
"relation"
.
equals
(
node
.
getNodeName
()))
{
return
false
;
}
String
nodeValue
=
node
.
getAttributes
().
getNamedItem
(
"id"
).
getNodeValue
();
System
.
out
.
println
(
"Relation: "
+
nodeValue
);
NodeList
childNodes
=
node
.
getChildNodes
();
List
<
List
<
Coordinate
>>
innerRings
=
new
ArrayList
<>();
List
<
Coordinate
>
outerRing
=
new
ArrayList
<>();
boolean
water
=
false
;
for
(
int
i
=
0
;
i
<
childNodes
.
getLength
();
i
++)
{
Node
boundsOrMember
=
childNodes
.
item
(
i
);
if
(!
"member"
.
equals
(
boundsOrMember
.
getNodeName
()))
{
if
(
"tag"
.
equals
(
boundsOrMember
.
getNodeName
()))
{
if
(
"water"
.
equals
(
boundsOrMember
.
getAttributes
().
getNamedItem
(
"v"
).
getNodeValue
()))
{
water
=
true
;
}
}
continue
;
}
Node
member
=
boundsOrMember
;
String
role
=
member
.
getAttributes
().
getNamedItem
(
"role"
).
getNodeValue
();
if
(!
"way"
.
equals
(
member
.
getAttributes
().
getNamedItem
(
"type"
).
getNodeValue
()))
{
continue
;
}
String
referenceId
=
member
.
getAttributes
().
getNamedItem
(
"ref"
).
getNodeValue
();
if
(
usedIds
.
contains
(
referenceId
))
{
System
.
out
.
println
(
"Relation contains way that is already used "
+
referenceId
);
continue
;
}
List
<
Coordinate
>
ringCoords
;
if
(
"inner"
.
equals
(
role
))
{
ringCoords
=
new
ArrayList
<>();
innerRings
.
add
(
ringCoords
);
}
else
if
(
"outer"
.
equals
(
role
))
{
// outer ring
outerRing
.
clear
();
ringCoords
=
outerRing
;
}
else
if
(
"main_stream"
.
equals
(
role
))
{
ringCoords
=
outerRing
;
}
else
if
(
"side_stream"
.
equals
(
role
))
{
ringCoords
=
outerRing
;
}
else
{
System
.
out
.
println
(
"Unknown role: "
+
role
);
// probably waterway
continue
;
}
NodeList
memberNodes
=
member
.
getChildNodes
();
for
(
int
memberNodesIndex
=
0
;
memberNodesIndex
<
memberNodes
.
getLength
();
memberNodesIndex
++)
{
Node
nd
=
memberNodes
.
item
(
memberNodesIndex
);
if
(
"nd"
.
equals
(
nd
.
getNodeName
()))
{
double
lat
=
Double
.
parseDouble
(
nd
.
getAttributes
().
getNamedItem
(
"lat"
).
getNodeValue
());
double
lon
=
Double
.
parseDouble
(
nd
.
getAttributes
().
getNamedItem
(
"lon"
).
getNodeValue
());
ProjCoordinate
converted
=
convertCoordinatesFrom84
(
lon
,
lat
);
ringCoords
.
add
(
new
Coordinate
(
converted
.
x
,
converted
.
y
));
}
}
}
if
(
water
)
{
org
.
locationtech
.
jts
.
geom
.
LinearRing
outerLinearRing
=
geomFactory
.
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
.
createLinearRing
(
innerRing
.
toArray
(
new
Coordinate
[
innerRing
.
size
()]));
innerLinearRings
.
add
(
innerLinearRing
);
}
Polygon
polygon
=
geomFactory
.
createPolygon
(
outerLinearRing
,
innerLinearRings
.
toArray
(
new
org
.
locationtech
.
jts
.
geom
.
LinearRing
[
innerLinearRings
.
size
()]));
data
.
getWaterAreas
().
add
(
new
WaterArea
(
polygon
));
}
// validateRing(outerRing);
// create the outer ring
// org.locationtech.jts.geom.LinearRing outerLinearRing = geomFactory
// .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
// .createLinearRing(innerRing.toArray(new Coordinate[innerRing.size()]));
// innerLinearRings.add(innerLinearRing);
// }
//
// if (outerRing.isEmpty()) {
// return false;
// }
//
// // create the polygon
// Polygon polygon = geomFactory.createPolygon(outerLinearRing,
// innerLinearRings.toArray(new org.locationtech.jts.geom.LinearRing[innerLinearRings.size()]));
//
// data.getGreenAreas().add(new GreenArea(polygon));
return
true
;
}
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
;
}
boolean
water
=
false
;
String
id
=
node
.
getAttributes
().
getNamedItem
(
"id"
).
getNodeValue
();
if
(
usedIds
.
contains
(
id
))
{
System
.
out
.
println
(
"Already used way id "
+
id
);
return
true
;
}
usedIds
.
add
(
id
);
NodeList
childNodes
=
node
.
getChildNodes
();
List
<
Coordinate
>
coordinates
=
new
ArrayList
<>();
boolean
line
=
false
;
for
(
int
i
=
0
;
i
<
childNodes
.
getLength
();
i
++)
{
Node
child
=
childNodes
.
item
(
i
);
if
(
"nd"
.
equals
(
child
.
getNodeName
()))
{
double
lat
=
Double
.
parseDouble
(
getTagValue
(
child
,
"lat"
));
double
lon
=
Double
.
parseDouble
(
getTagValue
(
child
,
"lon"
));
ProjCoordinate
converted
=
convertCoordinatesFrom84
(
lon
,
lat
);
coordinates
.
add
(
new
Coordinate
(
converted
.
x
,
converted
.
y
));
}
else
if
(
"tag"
.
equals
(
child
.
getNodeName
()))
{
// if (existTagWithValue(child, "k", "natural") && existTagWithValue(child, "v", "tree_row")) {
// line = true;
// }
if
((
existTagWithValue
(
child
,
"k"
,
"natural"
)
&&
existTagWithValue
(
child
,
"v"
,
"water"
))
||
existTagWithValue
(
child
,
"k"
,
"waterway"
))
{
water
=
true
;
}
}
}
if
(!
coordinates
.
get
(
0
).
equals
(
coordinates
.
get
(
coordinates
.
size
()
-
1
)))
{
// assume line if start and end coordinate do not match?
line
=
true
;
}
if
(
water
)
{
if
(
line
)
{
LineString
lineString
=
geomFactory
.
createLineString
(
coordinates
.
toArray
(
new
Coordinate
[
coordinates
.
size
()]));
data
.
getWaterways
().
add
(
new
Waterway
(
lineString
));
}
else
{
Polygon
polygon
=
geomFactory
.
createPolygon
(
coordinates
.
toArray
(
new
Coordinate
[
coordinates
.
size
()]));
data
.
getWaterAreas
().
add
(
new
WaterArea
(
polygon
));
}
}
else
{
if
(
line
)
{
LineString
lineString
=
geomFactory
.
createLineString
(
coordinates
.
toArray
(
new
Coordinate
[
coordinates
.
size
()]));
data
.
getTreeRows
().
add
(
new
TreeRow
(
lineString
));
}
else
{
Polygon
polygon
=
geomFactory
.
createPolygon
(
coordinates
.
toArray
(
new
Coordinate
[
coordinates
.
size
()]));
data
.
getGreenAreas
().
add
(
new
GreenArea
(
polygon
));
}
}
return
true
;
}
private
static
boolean
existTagWithValue
(
Node
node
,
String
key
,
String
value
)
{
return
value
.
equals
(
getTagValue
(
node
,
key
));
}
private
static
String
getTagValue
(
Node
node
,
String
tagName
)
{
Node
namedItem
=
node
.
getAttributes
().
getNamedItem
(
tagName
);
if
(
namedItem
==
null
)
{
return
null
;
}
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
;
}
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
{
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
String
extractEpsgCode
(
CityModel
cityModel
)
{
Envelope
envelope
=
cityModel
.
getBoundedBy
().
getEnvelope
();
String
srsName
=
envelope
.
getSrsName
();
return
parseEpsg
(
srsName
);
}
private
static
String
parseEpsg
(
String
srsName
)
{
int
utmIndex
=
srsName
.
indexOf
(
"UTM"
);
if
(
utmIndex
>
0
)
{
return
"EPSG:258"
+
srsName
.
substring
(
utmIndex
+
3
,
utmIndex
+
5
);
}
Pattern
p
=
Pattern
.
compile
(
"EPSG:+([0-9]+)"
);
Matcher
m
=
p
.
matcher
(
srsName
);
if
(
m
.
find
())
{
return
"EPSG:"
+
m
.
group
(
1
);
}
return
srsName
;
}
private
static
String
extractAndConvertBoundingBox
(
CityModel
cityModel
,
String
epsgCode
,
OsmData
osmData
)
{
Envelope
calculatedEnvelope
=
cityModel
.
computeEnvelope
();
DirectPosition
lowerCorner
=
calculatedEnvelope
.
getLowerCorner
();
ProjCoordinate
p1
=
new
ProjCoordinate
(
lowerCorner
.
getValue
().
get
(
0
),
lowerCorner
.
getValue
().
get
(
1
));
ProjCoordinate
lowerCornerProjected
=
new
ProjCoordinate
();
transform
.
transform
(
p1
,
lowerCornerProjected
);
DirectPosition
upperCorner
=
calculatedEnvelope
.
getUpperCorner
();
p1
.
x
=
upperCorner
.
getValue
().
get
(
0
);
p1
.
y
=
upperCorner
.
getValue
().
get
(
1
);
ProjCoordinate
upperCornerProjected
=
new
ProjCoordinate
();
transform
.
transform
(
p1
,
upperCornerProjected
);
lowerCornerProjected
.
x
-=
BOUNDING_BOX_INCREASE
;
lowerCornerProjected
.
y
-=
BOUNDING_BOX_INCREASE
;
upperCornerProjected
.
x
+=
BOUNDING_BOX_INCREASE
;
upperCornerProjected
.
y
+=
BOUNDING_BOX_INCREASE
;
List
<
Coordinate
>
bboxCoordinates
=
new
ArrayList
<>();
bboxCoordinates
.
add
(
new
Coordinate
(
lowerCorner
.
getValue
().
get
(
0
)
-
BOUNDING_BOX_INCREASE_IN_M
,
lowerCorner
.
getValue
().
get
(
1
)
-
BOUNDING_BOX_INCREASE_IN_M
));
bboxCoordinates
.
add
(
new
Coordinate
(
lowerCorner
.
getValue
().
get
(
0
)
-
BOUNDING_BOX_INCREASE_IN_M
,
upperCorner
.
getValue
().
get
(
1
)
+
BOUNDING_BOX_INCREASE_IN_M
));
bboxCoordinates
.
add
(
new
Coordinate
(
upperCorner
.
getValue
().
get
(
0
)
+
BOUNDING_BOX_INCREASE_IN_M
,
upperCorner
.
getValue
().
get
(
1
)
+
BOUNDING_BOX_INCREASE_IN_M
));
bboxCoordinates
.
add
(
new
Coordinate
(
upperCorner
.
getValue
().
get
(
0
)
+
BOUNDING_BOX_INCREASE_IN_M
,
lowerCorner
.
getValue
().
get
(
1
)
-
BOUNDING_BOX_INCREASE_IN_M
));
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
()]));
osmData
.
setBoundingBox
(
poly
);
return
lowerCornerProjected
.
y
+
","
+
lowerCornerProjected
.
x
+
","
+
upperCornerProjected
.
y
+
","
+
upperCornerProjected
.
x
;
}
private
static
ProjCoordinate
convertCoordinatesFrom84
(
double
x
,
double
y
)
{
ProjCoordinate
p1
=
new
ProjCoordinate
(
x
,
y
);
ProjCoordinate
result
=
new
ProjCoordinate
();
backTransform
.
transform
(
p1
,
result
);
return
result
;
}
private
static
ProjCoordinate
convertCoordinatesTo84
(
DirectPosition
point
)
{
double
x
=
point
.
getValue
().
get
(
0
);
double
y
=
point
.
getValue
().
get
(
1
);
return
convertCoordinatesTo84
(
x
,
y
);
}
private
static
ProjCoordinate
convertCoordinatesTo84
(
double
x
,
double
y
)
{
ProjCoordinate
p1
=
new
ProjCoordinate
(
x
,
y
);
ProjCoordinate
result
=
new
ProjCoordinate
();
transform
.
transform
(
p1
,
result
);
return
result
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/OsmData.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.locationtech.jts.geom.Polygon
;
public
class
OsmData
{
private
Polygon
boundingBox
;
private
List
<
TreePoint
>
treePoints
=
new
ArrayList
<>();
private
List
<
GreenArea
>
greenAreas
=
new
ArrayList
<>();
private
List
<
TreeRow
>
treeRows
=
new
ArrayList
<>();
private
List
<
Waterway
>
waterways
=
new
ArrayList
<>();
private
List
<
WaterArea
>
waterAreas
=
new
ArrayList
<>();
public
void
setBoundingBox
(
Polygon
boundingBox
)
{
this
.
boundingBox
=
boundingBox
;
}
public
List
<
WaterArea
>
getWaterAreas
()
{
return
waterAreas
;
}
public
List
<
Waterway
>
getWaterways
()
{
return
waterways
;
}
public
Polygon
getBoundingBox
()
{
return
boundingBox
;
}
public
List
<
GreenArea
>
getGreenAreas
()
{
return
greenAreas
;
}
public
List
<
TreePoint
>
getTreePoints
()
{
return
treePoints
;
}
public
List
<
TreeRow
>
getTreeRows
()
{
return
treeRows
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreeGenerator.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
org.locationtech.jts.geom.Coordinate
;
import
org.locationtech.jts.geom.Polygon
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty
;
public
class
TreeGenerator
{
private
static
final
double
TRUNK_INCREASE_FACTOR
=
1.2
;
public
static
MultiSurface
generateTree
(
Coordinate
point
,
double
trunkRadius
,
double
trunkHeight
,
double
crownXRadius
,
double
crownYRadius
,
double
crownHeight
)
{
List
<
Coordinate
>
trunkWestCoordinateList
=
new
ArrayList
<>();
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
double
drawTrunkHeight
=
trunkHeight
*
TRUNK_INCREASE_FACTOR
;
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkWestPolygon
=
convertPolygon
(
trunkWestCoordinateList
);
var
trunkWestConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkWestPolygon
);
MultiSurface
ms
=
new
MultiSurface
();
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkWestConvertedPolygon
));
List
<
Coordinate
>
trunkEastCoordinateList
=
new
ArrayList
<>();
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkEastPolygon
=
convertPolygon
(
trunkEastCoordinateList
);
var
trunkEastConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkEastPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkEastConvertedPolygon
));
List
<
Coordinate
>
trunkSouthCoordinateList
=
new
ArrayList
<>();
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkSouthPolygon
=
convertPolygon
(
trunkSouthCoordinateList
);
var
trunkSouthConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkSouthPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkSouthConvertedPolygon
));
List
<
Coordinate
>
trunkNorthCoordinateList
=
new
ArrayList
<>();
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
Polygon
trunkNorthPolygon
=
convertPolygon
(
trunkNorthCoordinateList
);
var
trunkNorthConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkNorthPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkNorthConvertedPolygon
));
/*-
* Spheroid formula:
* x = a * sin(thetha) * cos(phi)
* y = b * sin(thetha) * sin(phi)
* z = c * cos(thetha)
*
* 0 <= theta <= pi
* 0 <= phi < 2 pi
*/
// create crown
// divide by 2 to get radius, height is diameter
double
c
=
crownHeight
/
2
D
;
double
a
=
crownXRadius
;
double
b
=
crownYRadius
;
int
numberOfThetaRings
=
5
;
int
numberOfPhiRings
=
10
;
double
thetaDelta
=
Math
.
PI
/
(
numberOfThetaRings
-
1
);
double
phiDelta
=
Math
.
PI
*
2
/
numberOfPhiRings
;
List
<
List
<
Coordinate
>>
ringCoordinates
=
new
ArrayList
<>();
// top point triangles
Coordinate
topPoint
=
new
Coordinate
(
point
.
x
,
point
.
y
,
point
.
z
+
c
+
trunkHeight
+
c
);
ringCoordinates
.
add
(
Collections
.
singletonList
(
topPoint
));
for
(
int
i
=
1
;
i
<
numberOfThetaRings
-
1
;
i
++)
{
double
theta
=
i
*
thetaDelta
;
List
<
Coordinate
>
coords
=
new
ArrayList
<>();
ringCoordinates
.
add
(
coords
);
for
(
int
j
=
0
;
j
<
numberOfPhiRings
;
j
++)
{
double
phi
=
j
*
phiDelta
;
double
x
=
a
*
Math
.
sin
(
theta
)
*
Math
.
cos
(
phi
)
+
point
.
x
;
double
y
=
b
*
Math
.
sin
(
theta
)
*
Math
.
sin
(
phi
)
+
point
.
y
;
double
z
=
c
*
Math
.
cos
(
theta
)
+
point
.
z
+
trunkHeight
+
c
;
Coordinate
p1
=
new
Coordinate
(
x
,
y
,
z
);
coords
.
add
(
p1
);
}
}
Coordinate
bottomPoint
=
new
Coordinate
(
point
.
x
,
point
.
y
,
point
.
z
+
trunkHeight
);
ringCoordinates
.
add
(
Collections
.
singletonList
(
bottomPoint
));
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
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
for
(
int
i
=
1
;
i
<
ringCoordinates
.
size
()
-
2
;
i
++)
{
List
<
Coordinate
>
topRing
=
ringCoordinates
.
get
(
i
);
List
<
Coordinate
>
bottomRing
=
ringCoordinates
.
get
(
i
+
1
);
for
(
int
j
=
0
;
j
<
topRing
.
size
();
j
++)
{
int
nextRingIndex
=
(
j
+
1
)
%
topRing
.
size
();
Coordinate
p1
=
topRing
.
get
(
j
);
Coordinate
p2
=
topRing
.
get
(
nextRingIndex
);
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
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
}
// bottom point triangles
List
<
Coordinate
>
bottomRing
=
ringCoordinates
.
get
(
ringCoordinates
.
size
()
-
2
);
for
(
int
i
=
0
;
i
<
bottomRing
.
size
();
i
++)
{
int
nextRingIndex
=
(
i
+
1
)
%
bottomRing
.
size
();
Coordinate
p1
=
bottomRing
.
get
(
i
);
Coordinate
p2
=
bottomRing
.
get
(
nextRingIndex
);
Coordinate
[]
coordArray
=
new
Coordinate
[]
{
p2
,
p1
,
bottomPoint
,
p2
};
Polygon
polygon
=
GreenEnricher
.
geomFactory
.
createPolygon
(
coordArray
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
return
ms
;
}
private
static
Polygon
convertPolygon
(
List
<
Coordinate
>
trunkWestCoordinateList
)
{
return
GreenEnricher
.
geomFactory
.
createPolygon
(
trunkWestCoordinateList
.
toArray
(
new
Coordinate
[
trunkWestCoordinateList
.
size
()]));
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreePoint.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Point
;
public
class
TreePoint
{
private
Point
point
;
public
TreePoint
()
{
}
public
TreePoint
(
Point
point
)
{
this
.
point
=
point
;
}
public
void
setPoint
(
Point
point
)
{
this
.
point
=
point
;
}
public
Point
getPoint
()
{
return
point
;
}
@Override
public
String
toString
()
{
return
"TreePoint [point="
+
point
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreeRow.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.LineString
;
public
class
TreeRow
{
private
LineString
line
;
public
TreeRow
()
{
}
public
TreeRow
(
LineString
line
)
{
this
.
line
=
line
;
}
public
LineString
getLine
()
{
return
line
;
}
public
void
setLine
(
LineString
line
)
{
this
.
line
=
line
;
}
@Override
public
String
toString
()
{
return
"TreeRow [line="
+
line
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/WaterArea.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Polygon
;
public
class
WaterArea
{
private
Polygon
area
;
public
WaterArea
()
{
}
public
WaterArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
void
setArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
Polygon
getArea
()
{
return
area
;
}
@Override
public
String
toString
()
{
return
"WaterArea [area="
+
area
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Waterway.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.LineString
;
public
class
Waterway
{
private
LineString
line
;
public
Waterway
()
{
}
public
Waterway
(
LineString
line
)
{
super
();
this
.
line
=
line
;
}
public
void
setLine
(
LineString
line
)
{
this
.
line
=
line
;
}
public
LineString
getLine
()
{
return
line
;
}
@Override
public
String
toString
()
{
return
"Waterway [line="
+
line
+
"]"
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment