Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eric Duminil
RegionChooser
Commits
c49391c1
Commit
c49391c1
authored
Nov 28, 2023
by
Eric Duminil
Browse files
Allow Vegetation to be extracted too.
parent
b2536456
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/main/java/eu/simstadt/regionchooser/RegionExtractor.java
View file @
c49391c1
...
...
@@ -16,8 +16,8 @@
import
com.ximpleware.NavException
;
import
com.ximpleware.XPathEvalException
;
import
com.ximpleware.XPathParseException
;
import
eu.simstadt.regionchooser.fast_xml_parser.BuildingXmlNode
;
import
eu.simstadt.regionchooser.fast_xml_parser.CityGmlIterator
;
import
eu.simstadt.regionchooser.fast_xml_parser.CityObjectMember
;
public
class
RegionExtractor
...
...
@@ -51,8 +51,9 @@
static
int
selectRegionDirectlyFromCityGML
(
String
wktPolygon
,
String
srsName
,
Writer
sb
,
Path
...
citygmlPaths
)
throws
ParseException
,
XPathParseException
,
NavException
,
IOException
{
int
building
sCount
=
0
;
int
cityObject
sCount
=
0
;
int
foundBuildingsCount
=
0
;
// int foundVegetationCount = 0;
Geometry
poly
=
WKT_READER
.
read
(
wktPolygon
);
CityGmlIterator
citygml
=
null
;
...
...
@@ -61,11 +62,11 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr
LOGGER
.
info
(
"Parsing "
+
citygmlPath
);
//TODO: Allow citygmlPath for folders too, and iterate over gmls?
citygml
=
new
CityGmlIterator
(
citygmlPath
);
for
(
BuildingXmlNode
buildingXmlNode
:
citygml
)
{
if
(
building
sCount
==
0
)
{
for
(
CityObjectMember
buildingXmlNode
:
citygml
)
{
if
(
cityObject
sCount
==
0
)
{
sb
.
append
(
replaceEnvelopeInHeader
(
citygml
.
getHeader
(),
poly
.
getEnvelopeInternal
(),
srsName
));
}
building
sCount
+=
1
;
cityObject
sCount
+=
1
;
if
(
buildingXmlNode
.
hasCoordinates
())
{
Coordinate
coord
=
new
Coordinate
(
buildingXmlNode
.
x
,
buildingXmlNode
.
y
);
Point
point
=
GEOMETRY_FACTORY
.
createPoint
(
coord
);
...
...
@@ -74,7 +75,7 @@ static int selectRegionDirectlyFromCityGML(String wktPolygon, String srsName, Wr
sb
.
append
(
buildingXmlNode
.
toString
());
}
}
if
(
building
sCount
%
1000
==
0
)
{
if
(
cityObject
sCount
%
1000
==
0
)
{
LOGGER
.
info
(
"1000 buildings parsed"
);
}
}
...
...
src/main/java/eu/simstadt/regionchooser/fast_xml_parser/CityGmlIterator.java
View file @
c49391c1
...
...
@@ -13,7 +13,7 @@
import
com.ximpleware.XPathParseException
;
public
class
CityGmlIterator
implements
Iterable
<
BuildingXmlNode
>
public
class
CityGmlIterator
implements
Iterable
<
CityObjectMember
>
{
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
CityGmlIterator
.
class
.
getName
());
...
...
@@ -42,12 +42,12 @@ public CityGmlIterator(Path citygmlPath) throws XPathParseException {
parser
.
parseFile
(
citygmlPath
.
toString
(),
false
);
this
.
navigator
=
parser
.
getNav
();
this
.
buildingsFinder
=
new
AutoPilot
(
navigator
);
buildingsFinder
.
selectXPath
(
"/CityModel/c
ityObjectMember
[Building]"
);
//TODO: Check it's the only correct possibility. //FIXME: BuildingPart too!
buildingsFinder
.
selectXPath
(
C
ityObjectMember
.
XPATH_PATTERN
);
}
@Override
public
Iterator
<
BuildingXmlNode
>
iterator
()
{
return
new
Iterator
<
BuildingXmlNode
>()
{
public
Iterator
<
CityObjectMember
>
iterator
()
{
return
new
Iterator
<
CityObjectMember
>()
{
@Override
public
boolean
hasNext
()
{
...
...
@@ -60,12 +60,12 @@ public boolean hasNext() {
}
@Override
public
BuildingXmlNode
next
()
{
public
CityObjectMember
next
()
{
try
{
long
offsetAndLength
=
navigator
.
getElementFragment
();
buildingOffset
=
(
int
)
offsetAndLength
;
buildingLength
=
(
int
)
(
offsetAndLength
>>
32
);
return
new
BuildingXmlNode
(
navigator
,
buildingOffset
,
buildingLength
);
return
new
CityObjectMember
(
navigator
,
buildingOffset
,
buildingLength
);
}
catch
(
NavException
|
NumberFormatException
|
XPathParseException
|
XPathEvalException
ex
)
{
LOGGER
.
warning
(
"Error while parsing "
+
citygmlPath
);
}
...
...
src/main/java/eu/simstadt/regionchooser/fast_xml_parser/
BuildingXmlNode
.java
→
src/main/java/eu/simstadt/regionchooser/fast_xml_parser/
CityObjectMember
.java
View file @
c49391c1
...
...
@@ -7,11 +7,19 @@
import
com.ximpleware.XPathParseException
;
public
class
BuildingXmlNode
/**
* XML Node representing a CityObjectMember
*
*/
public
class
CityObjectMember
{
//TODO: Check it's the only correct possibility.
//FIXME: BuildingPart too!
static
final
String
XPATH_PATTERN
=
"/CityModel/cityObjectMember[Building or SolitaryVegetationObject or PlantCover]"
;
private
int
building
Offset
;
private
int
building
Length
;
private
int
node
Offset
;
private
int
node
Length
;
private
VTDNav
navigator
;
private
AutoPilot
coordinatesFinder
;
public
Double
x
;
...
...
@@ -22,14 +30,15 @@
public
Double
y
;
private
int
coordinatesCount
=
0
;
public
BuildingXmlNode
(
VTDNav
navigator
,
int
building
Offset
,
int
building
Length
)
public
CityObjectMember
(
VTDNav
navigator
,
int
node
Offset
,
int
node
Length
)
throws
XPathParseException
,
XPathEvalException
,
NavException
{
this
.
navigator
=
navigator
;
this
.
coordinatesFinder
=
new
AutoPilot
(
navigator
);
this
.
building
Length
=
building
Length
;
this
.
building
Offset
=
building
Offset
;
this
.
node
Length
=
node
Length
;
this
.
node
Offset
=
node
Offset
;
extractCoordinates
();
//TODO: Get Building ID too, in order to avoid duplicates?
//TODO: Get Node ID too, in order to avoid duplicates?
//TODO: Now that "Building" can be Vegetation too, define a method to check class?
}
public
boolean
hasCoordinates
()
{
...
...
@@ -84,7 +93,7 @@ private void extractCoordinates()
public
String
toString
()
{
try
{
return
navigator
.
toRawString
(
buildingOffset
,
building
Length
);
return
navigator
.
toRawString
(
nodeOffset
,
node
Length
);
}
catch
(
NavException
ex
)
{
return
""
;
}
...
...
src/main/java/eu/simstadt/regionchooser/fast_xml_parser/ConvexHullCalculator.java
View file @
c49391c1
...
...
@@ -55,7 +55,7 @@ public static Geometry calculateFromCityGML(Path citygmlPath) throws XPathParseE
GeometryFactory
geometryFactory
=
new
GeometryFactory
();
ArrayList
<
Coordinate
>
allPoints
=
new
ArrayList
<>();
CityGmlIterator
citygml
=
new
CityGmlIterator
(
citygmlPath
);
for
(
BuildingXmlNode
buildingXmlNode
:
citygml
)
{
for
(
CityObjectMember
buildingXmlNode
:
citygml
)
{
if
(
buildingXmlNode
.
hasCoordinates
())
{
allPoints
.
add
(
new
Coordinate
(
buildingXmlNode
.
xMin
,
buildingXmlNode
.
yMin
));
allPoints
.
add
(
new
Coordinate
(
buildingXmlNode
.
xMin
,
buildingXmlNode
.
yMax
));
...
...
src/test/java/eu/simstadt/regionchooser/fast_xml_parser/CitygmlParserTests.java
View file @
c49391c1
...
...
@@ -17,7 +17,7 @@
private
void
testNoNanInCoordinates
(
Path
citygmlPath
)
throws
XPathParseException
{
CityGmlIterator
buildingXmlNodes
=
new
CityGmlIterator
(
citygmlPath
);
for
(
BuildingXmlNode
buildingXmlNode
:
buildingXmlNodes
)
{
for
(
CityObjectMember
buildingXmlNode
:
buildingXmlNodes
)
{
assertTrue
(
buildingXmlNode
.
hasCoordinates
(),
"Buildings should have coordinates"
);
assertFalse
(
Double
.
isNaN
(
buildingXmlNode
.
x
),
COORDINATE_SHOULD_BE_A_DOUBLE
);
assertFalse
(
Double
.
isNaN
(
buildingXmlNode
.
y
),
COORDINATE_SHOULD_BE_A_DOUBLE
);
...
...
@@ -25,10 +25,11 @@ private void testNoNanInCoordinates(Path citygmlPath) throws XPathParseException
assertFalse
(
Double
.
isNaN
(
buildingXmlNode
.
yMax
),
COORDINATE_SHOULD_BE_A_DOUBLE
);
assertFalse
(
Double
.
isNaN
(
buildingXmlNode
.
xMin
),
COORDINATE_SHOULD_BE_A_DOUBLE
);
assertFalse
(
Double
.
isNaN
(
buildingXmlNode
.
yMin
),
COORDINATE_SHOULD_BE_A_DOUBLE
);
assertTrue
(
buildingXmlNode
.
xMax
>
buildingXmlNode
.
x
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
yMax
>
buildingXmlNode
.
y
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
xMin
<
buildingXmlNode
.
x
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
yMin
<
buildingXmlNode
.
y
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
// Some SolitaryVegetationObjects are defined with a single point.
assertTrue
(
buildingXmlNode
.
xMax
>=
buildingXmlNode
.
x
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
yMax
>=
buildingXmlNode
.
y
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
xMin
<=
buildingXmlNode
.
x
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
assertTrue
(
buildingXmlNode
.
yMin
<=
buildingXmlNode
.
y
,
COORDINATES_SHOULD_BE_PLAUSIBLE
);
}
}
...
...
@@ -66,7 +67,7 @@ public void testExtractNoCoordsFromEmptyBuilding() throws XPathParseException {
Path
citygmlPath
=
repo
.
resolve
(
"Stöckach_empty_buildings.gml"
);
CityGmlIterator
buildingXmlNodes
=
new
CityGmlIterator
(
citygmlPath
);
int
counter
=
0
;
for
(
BuildingXmlNode
buildingXmlNode
:
buildingXmlNodes
)
{
for
(
CityObjectMember
buildingXmlNode
:
buildingXmlNodes
)
{
assertFalse
(
buildingXmlNode
.
hasCoordinates
(),
"Empty Buildings shouldn't have coordinates"
);
assertTrue
(
Double
.
isNaN
(
buildingXmlNode
.
x
),
"Coordinate should be a Nan"
);
assertTrue
(
Double
.
isNaN
(
buildingXmlNode
.
y
),
"Coordinate should be a Nan"
);
...
...
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