Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eric Duminil
RegionChooser
Commits
135d0bc4
Commit
135d0bc4
authored
Sep 29, 2022
by
Eric Duminil
Browse files
Allow extractor to work on multiple CityGMLs.
parent
3a9b7c9d
Pipeline
#6952
failed with stage
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/main/java/eu/simstadt/regionchooser/RegionChooserBrowser.java
View file @
135d0bc4
...
...
@@ -77,6 +77,7 @@ public void downloadRegionFromCityGML(String wktPolygon, String project, String
File
buildingIdsFile
=
selectSaveFileWithDialog
(
project
,
citygml
,
"selected_region"
);
if
(
buildingIdsFile
!=
null
)
{
try
(
BufferedWriter
writer
=
Files
.
newBufferedWriter
(
buildingIdsFile
.
toPath
()))
{
//NOTE: isn't there a better way??
writer
.
write
(
sb
.
toString
());
}
}
...
...
src/main/java/eu/simstadt/regionchooser/RegionExtractor.java
View file @
135d0bc4
...
...
@@ -27,13 +27,14 @@
private
static
final
GeometryFactory
gf
=
new
GeometryFactory
();
/**
* Main method behind RegionChooser. Given
a
CityGML (as Path) and a geometry (as Well-known text POLYGON, in the
* Main method behind RegionChooser. Given CityGML
s
(as Path
[]
) and a geometry (as Well-known text POLYGON, in the
* same coordinate system as the CityGML), it iterates over each Building and checks if the building is inside the
* geometry. It only works with CityGML files smaller than 2GB. It uses VTD-XML parser instead of a whole
* Simstadt/Citydoctor/Citygml model.
*
* @param wktPolygon
* @param
citygmlPath
* @param
string
* @param
srsName
* @param
citygmlPaths
*
*
* @return a StringBuffer, full with the extracted Citygml, including header, buildings and footer.
...
...
@@ -44,8 +45,7 @@
* @throws XPathParseException
* @throws NumberFormatException
*/
//TODO: Try with multiple paths
static
StringBuilder
selectRegionDirectlyFromCityGML
(
String
wktPolygon
,
String
srsName
,
Path
citygmlPath
)
static
StringBuilder
selectRegionDirectlyFromCityGML
(
String
wktPolygon
,
String
srsName
,
Path
...
citygmlPaths
)
throws
ParseException
,
XPathParseException
,
NavException
,
IOException
{
int
buildingsCount
=
0
;
...
...
@@ -53,23 +53,33 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
StringBuilder
sb
=
new
StringBuilder
();
Geometry
poly
=
wktReader
.
read
(
wktPolygon
);
CityGmlIterator
citygml
=
new
CityGmlIterator
(
citygmlPath
);
for
(
BuildingXmlNode
buildingXmlNode
:
citygml
)
{
if
(
buildingsCount
==
0
)
{
sb
.
append
(
replaceEnvelopeInHeader
(
citygml
.
getHeader
(),
poly
.
getEnvelopeInternal
(),
srsName
));
}
buildingsCount
+=
1
;
if
(
buildingXmlNode
.
hasCoordinates
())
{
Coordinate
coord
=
new
Coordinate
(
buildingXmlNode
.
x
,
buildingXmlNode
.
y
);
Point
point
=
gf
.
createPoint
(
coord
);
if
(
point
.
within
(
poly
))
{
foundBuildingsCount
++;
sb
.
append
(
buildingXmlNode
.
toString
());
CityGmlIterator
citygml
=
null
;
for
(
int
i
=
0
;
i
<
citygmlPaths
.
length
;
i
++)
{
Path
citygmlPath
=
citygmlPaths
[
i
];
LOGGER
.
info
(
"Parsing "
+
citygmlPath
);
citygml
=
new
CityGmlIterator
(
citygmlPath
);
for
(
BuildingXmlNode
buildingXmlNode
:
citygml
)
{
if
(
buildingsCount
==
0
)
{
sb
.
append
(
replaceEnvelopeInHeader
(
citygml
.
getHeader
(),
poly
.
getEnvelopeInternal
(),
srsName
));
}
buildingsCount
+=
1
;
if
(
buildingXmlNode
.
hasCoordinates
())
{
Coordinate
coord
=
new
Coordinate
(
buildingXmlNode
.
x
,
buildingXmlNode
.
y
);
Point
point
=
gf
.
createPoint
(
coord
);
if
(
point
.
within
(
poly
))
{
foundBuildingsCount
++;
sb
.
append
(
buildingXmlNode
.
toString
());
}
}
if
(
buildingsCount
%
1000
==
0
)
{
LOGGER
.
info
(
"1000 buildings parsed"
);
}
}
if
(
buildingsCount
%
1000
==
0
)
{
LOGGER
.
info
(
"1000 buildings parsed"
);
}
}
if
(
citygml
==
null
)
{
throw
new
IllegalArgumentException
(
"There should be at least one citygml"
);
}
LOGGER
.
info
(
"Buildings found in selected region "
+
foundBuildingsCount
);
...
...
src/test/java/eu/simstadt/regionchooser/RegionExtractorTests.java
View file @
135d0bc4
...
...
@@ -10,7 +10,7 @@
import
org.junit.jupiter.api.Test
;
public
class
RegionExtractorTests
class
RegionExtractorTests
{
private
static
final
String
EPSG_32118
=
"EPSG:32118"
;
private
static
final
String
CITY_OBJECT_MEMBER_REGEX
=
"<(core:)?cityObjectMember"
;
...
...
@@ -20,7 +20,7 @@
private
static
final
String
CORE_CITY_MODEL_FOOTER
=
"</core:CityModel"
;
private
static
final
Path
TEST_REPOSITORY
=
Paths
.
get
(
"src/test/resources/testdata/"
);
public
static
int
countRegexMatches
(
String
str
,
String
subStr
)
{
static
int
countRegexMatches
(
String
str
,
String
subStr
)
{
Pattern
pattern
=
Pattern
.
compile
(
subStr
);
Matcher
matcher
=
pattern
.
matcher
(
str
);
int
count
=
0
;
...
...
@@ -31,7 +31,7 @@ public static int countRegexMatches(String str, String subStr) {
}
@Test
public
void
testExtract3BuildingsFromGSK3Model
()
throws
Throwable
{
void
testExtract3BuildingsFromGSK3Model
()
throws
Throwable
{
//NOTE: Small region around Martinskirche in Grünbühl
String
wktPolygon
=
"POLYGON((3515848.896028535 5415823.108586172,3515848.9512289143 5415803.590347393,3515829.0815150724 5415803.338023346,3515830.9784850604 5415793.437034622,3515842.0946056456 5415793.272282251,3515843.3515515197 5415766.204935087,3515864.1064344468 5415766.557899496,3515876.489172751 5415805.433782301,3515876.343844858 5415822.009293416,3515848.896028535 5415823.108586172))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"Gruenbuehl.proj/20140218_Gruenbuehl_LOD2.gml"
);
...
...
@@ -53,7 +53,7 @@ public void testExtract3BuildingsFromGSK3Model() throws Throwable {
}
@Test
public
void
testExtractBuildingsWithoutCommentsInBetween
()
throws
Throwable
{
void
testExtractBuildingsWithoutCommentsInBetween
()
throws
Throwable
{
//NOTE: Small region around WashingtonSquare
String
wktPolygon
=
"POLYGON((300259.78663489706 62835.835907766595,300230.33294975647 62792.0482567884,300213.5667431851 62770.83143720031,300183.6592861123 62730.20347659383,300252.9947486632 62676.938468840905,300273.3862256562 62701.767105345614,300257.5250407747 62715.760413539596,300308.2754543957 62805.14198211394,300259.78663489706 62835.835907766595))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
...
...
@@ -72,7 +72,7 @@ public void testExtractBuildingsWithoutCommentsInBetween() throws Throwable {
}
@Test
public
void
testExtractBuildingsAndChangeEnvelope
()
throws
Throwable
{
void
testExtractBuildingsAndChangeEnvelope
()
throws
Throwable
{
String
wktPolygon
=
"POLYGON((299761.8123557725 61122.68126771413,299721.46983062755 61058.11626595352,299780.84627343423 61021.99295737501,299823.9079725632 61083.3979344517,299761.8123557725 61122.68126771413))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"NewYork.proj/FamilyCourt_LOD2_with_PLUTO_attributes.gml"
);
String
familyCourtBuilding
=
RegionExtractor
...
...
@@ -96,7 +96,7 @@ public void testExtractBuildingsAndChangeEnvelope() throws Throwable {
}
@Test
public
void
testExtract0BuildingsWithWrongCoordinates
()
throws
Throwable
{
void
testExtract0BuildingsWithWrongCoordinates
()
throws
Throwable
{
//NOTE: Small region, far away from NYC
String
wktPolygon
=
"POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
...
...
@@ -108,7 +108,7 @@ public void testExtract0BuildingsWithWrongCoordinates() throws Throwable {
}
@Test
public
void
testExtract0BuildingsFromEmptyGML
()
throws
Throwable
{
void
testExtract0BuildingsFromEmptyGML
()
throws
Throwable
{
//NOTE: Small region, with too many spaces between coordinates
String
wktPolygon
=
"POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"NewYork.proj/empty_model.gml"
);
...
...
@@ -120,7 +120,7 @@ public void testExtract0BuildingsFromEmptyGML() throws Throwable {
}
@Test
public
void
testExtract0BuildingsFromWeirdGML
()
throws
Throwable
{
void
testExtract0BuildingsFromWeirdGML
()
throws
Throwable
{
//NOTE: Small region, with too many spaces between coordinates
String
wktPolygon
=
"POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"NewYork.proj/broken_nyc_lod2.gml"
);
...
...
@@ -132,11 +132,24 @@ public void testExtract0BuildingsFromWeirdGML() throws Throwable {
}
@Test
public
void
testExtractBuildingsFromCitygmlWithoutZinEnvelope
()
throws
Throwable
{
void
testExtractBuildingsFromCitygmlWithoutZinEnvelope
()
throws
Throwable
{
String
wktPolygon
=
"POLYGON((3512683.1280912133 5404783.732132129,3512719.1608604863 5404714.627650777,3512831.40076119 5404768.344155442,3512790.239106708 5404838.614891164,3512683.1280912133 5404783.732132129))"
;
Path
citygmlPath
=
TEST_REPOSITORY
.
resolve
(
"Stuttgart.proj/Stuttgart_LOD0_LOD1_small.gml"
);
String
emptyGMLString
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
wktPolygon
,
"EPSG:31463"
,
citygmlPath
)
.
toString
();
assertEquals
(
2
,
countRegexMatches
(
emptyGMLString
,
"<bldg:Building gml:id"
));
}
@Test
void
testExtractBuildingsFrom2Citygmls
()
throws
Throwable
{
String
wktPolygon
=
"POLYGON((3512984.7003764412 5405148.310572891,3513038.6360455155 5405010.072163861,3513142.7277745553 5405004.02571992,3514204.1661769524 5405563.192081669,3514399.2818417274 5405720.905457244,3514291.6158155007 5405896.706492759,3512984.7003764412 5405148.310572891))"
;
Path
citygml1
=
TEST_REPOSITORY
.
resolve
(
"Stuttgart.proj/Stuttgart_LOD0_LOD1_small.gml"
);
Path
citygml2
=
TEST_REPOSITORY
.
resolve
(
"Stuttgart.proj/Stöckach_überarbeitete GML-NoBuildingPart.gml"
);
String
emptyGMLString
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
wktPolygon
,
"EPSG:31463"
,
citygml1
,
citygml2
).
toString
();
assertEquals
(
17
+
3
,
countRegexMatches
(
emptyGMLString
,
"<bldg:Building gml:id"
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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