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
782889f0
Commit
782889f0
authored
Oct 10, 2022
by
Eric Duminil
Browse files
Refactor and tests
parent
af8031da
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/main/java/eu/simstadt/regionchooser/RegionChooserCommandLineInterface.java
View file @
782889f0
...
@@ -7,9 +7,6 @@
...
@@ -7,9 +7,6 @@
import
java.util.Scanner
;
import
java.util.Scanner
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Callable
;
import
java.util.logging.Logger
;
import
java.util.logging.Logger
;
import
org.locationtech.jts.geom.Polygon
;
import
org.locationtech.jts.io.WKTReader
;
import
org.locationtech.jts.io.WKTWriter
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
import
picocli.CommandLine
;
import
picocli.CommandLine
;
import
picocli.CommandLine.Command
;
import
picocli.CommandLine.Command
;
...
@@ -49,7 +46,6 @@ class RegionChooserCommandLineInterface implements Callable<Integer>
...
@@ -49,7 +46,6 @@ class RegionChooserCommandLineInterface implements Callable<Integer>
@Override
@Override
public
Integer
call
()
throws
Exception
{
public
Integer
call
()
throws
Exception
{
//TODO: Move as much logic to utils as possible
//TODO: Test
//TODO: Test
CoordinateReferenceSystem
localCRS
;
CoordinateReferenceSystem
localCRS
;
...
@@ -76,12 +72,8 @@ public Integer call() throws Exception {
...
@@ -76,12 +72,8 @@ public Integer call() throws Exception {
}
}
if
(!
localCoordinates
)
{
if
(!
localCoordinates
)
{
final
WKTReader
WKT_READER
=
new
WKTReader
();
final
WKTWriter
WKT_WRITER
=
new
WKTWriter
();
// WKT coordinates are in WGS84, so should be first converted to srsName
// WKT coordinates are in WGS84, so should be first converted to srsName
Polygon
wgs84Polygon
=
(
Polygon
)
WKT_READER
.
read
(
wktPolygon
);
wktPolygon
=
RegionChooserUtils
.
wktPolygonToLocalCRS
(
wktPolygon
,
localCRS
);
wktPolygon
=
WKT_WRITER
.
write
(
RegionChooserUtils
.
changePolygonCRS
(
wgs84Polygon
,
RegionChooserUtils
.
WGS84
,
localCRS
));
}
}
LOGGER
.
info
(
"WKT Polygon expressed in local coordinates: "
+
wktPolygon
);
LOGGER
.
info
(
"WKT Polygon expressed in local coordinates: "
+
wktPolygon
);
...
...
src/main/java/eu/simstadt/regionchooser/RegionChooserUtils.java
View file @
782889f0
...
@@ -13,6 +13,9 @@
...
@@ -13,6 +13,9 @@
import
org.locationtech.jts.geom.Coordinate
;
import
org.locationtech.jts.geom.Coordinate
;
import
org.locationtech.jts.geom.GeometryFactory
;
import
org.locationtech.jts.geom.GeometryFactory
;
import
org.locationtech.jts.geom.Polygon
;
import
org.locationtech.jts.geom.Polygon
;
import
org.locationtech.jts.io.ParseException
;
import
org.locationtech.jts.io.WKTReader
;
import
org.locationtech.jts.io.WKTWriter
;
import
org.osgeo.proj4j.BasicCoordinateTransform
;
import
org.osgeo.proj4j.BasicCoordinateTransform
;
import
org.osgeo.proj4j.CRSFactory
;
import
org.osgeo.proj4j.CRSFactory
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
...
@@ -111,6 +114,15 @@ public static Polygon changePolygonCRS(Polygon polygonInOriginalCRS, CoordinateR
...
@@ -111,6 +114,15 @@ public static Polygon changePolygonCRS(Polygon polygonInOriginalCRS, CoordinateR
return
geometryFactory
.
createPolygon
(
convexHullcoordinates
);
return
geometryFactory
.
createPolygon
(
convexHullcoordinates
);
}
}
public
static
String
wktPolygonToLocalCRS
(
String
wktPolygonInWGS84
,
CoordinateReferenceSystem
localCRS
)
throws
ParseException
{
final
WKTReader
wktReader
=
new
WKTReader
();
final
WKTWriter
wktWriter
=
new
WKTWriter
();
// WKT coordinates are in WGS84, so should be first converted to srsName
Polygon
wgs84Polygon
=
(
Polygon
)
wktReader
.
read
(
wktPolygonInWGS84
);
return
wktWriter
.
write
(
changePolygonCRS
(
wgs84Polygon
,
WGS84
,
localCRS
));
}
/**
/**
*
*
* Fast scan of the 50 first lines of a Citygml file to look for srsName. It might not be as reliable as parsing the
* Fast scan of the 50 first lines of a Citygml file to look for srsName. It might not be as reliable as parsing the
...
...
src/main/java/eu/simstadt/regionchooser/RegionExtractor.java
View file @
782889f0
...
@@ -21,10 +21,10 @@
...
@@ -21,10 +21,10 @@
public
class
RegionExtractor
public
class
RegionExtractor
{
{
private
static
final
WKTReader
wktReader
=
new
WKTReader
();
private
static
final
WKTReader
WKT_READER
=
new
WKTReader
();
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
RegionExtractor
.
class
.
getName
());
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
RegionExtractor
.
class
.
getName
());
private
static
final
GeometryFactory
gf
=
new
GeometryFactory
();
private
static
final
GeometryFactory
GEOMETRY_FACTORY
=
new
GeometryFactory
();
/**
/**
* Main method behind RegionChooser. Given CityGMLs (as Path[]) and a geometry (as Well-known text POLYGON, in the
* Main method behind RegionChooser. Given CityGMLs (as Path[]) and a geometry (as Well-known text POLYGON, in the
...
@@ -54,7 +54,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
...
@@ -54,7 +54,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
int
buildingsCount
=
0
;
int
buildingsCount
=
0
;
int
foundBuildingsCount
=
0
;
int
foundBuildingsCount
=
0
;
StringBuilder
sb
=
new
StringBuilder
();
StringBuilder
sb
=
new
StringBuilder
();
Geometry
poly
=
wktReader
.
read
(
wktPolygon
);
Geometry
poly
=
WKT_READER
.
read
(
wktPolygon
);
CityGmlIterator
citygml
=
null
;
CityGmlIterator
citygml
=
null
;
for
(
int
i
=
0
;
i
<
citygmlPaths
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
citygmlPaths
.
length
;
i
++)
{
...
@@ -68,7 +68,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
...
@@ -68,7 +68,7 @@ static StringBuilder selectRegionDirectlyFromCityGML(String wktPolygon, String s
buildingsCount
+=
1
;
buildingsCount
+=
1
;
if
(
buildingXmlNode
.
hasCoordinates
())
{
if
(
buildingXmlNode
.
hasCoordinates
())
{
Coordinate
coord
=
new
Coordinate
(
buildingXmlNode
.
x
,
buildingXmlNode
.
y
);
Coordinate
coord
=
new
Coordinate
(
buildingXmlNode
.
x
,
buildingXmlNode
.
y
);
Point
point
=
gf
.
createPoint
(
coord
);
Point
point
=
GEOMETRY_FACTORY
.
createPoint
(
coord
);
if
(
point
.
within
(
poly
))
{
if
(
point
.
within
(
poly
))
{
foundBuildingsCount
++;
foundBuildingsCount
++;
sb
.
append
(
buildingXmlNode
.
toString
());
sb
.
append
(
buildingXmlNode
.
toString
());
...
...
src/test/java/eu/simstadt/regionchooser/RegionExtractorWithDifferentInputTests.java
View file @
782889f0
...
@@ -7,25 +7,19 @@
...
@@ -7,25 +7,19 @@
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.api.Test
;
import
org.locationtech.jts.geom.Polygon
;
import
org.locationtech.jts.io.ParseException
;
import
org.locationtech.jts.io.ParseException
;
import
org.locationtech.jts.io.WKTReader
;
import
org.locationtech.jts.io.WKTWriter
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
import
org.osgeo.proj4j.CoordinateReferenceSystem
;
import
com.ximpleware.NavException
;
import
com.ximpleware.NavException
;
import
com.ximpleware.XPathEvalException
;
import
com.ximpleware.XPathEvalException
;
import
com.ximpleware.XPathParseException
;
import
com.ximpleware.XPathParseException
;
public
class
RegionExtractorWithDifferentInputTests
class
RegionExtractorWithDifferentInputTests
{
{
private
static
final
WKTReader
WKT_READER
=
new
WKTReader
();
private
static
final
WKTWriter
WKT_WRITER
=
new
WKTWriter
();
private
static
final
Path
TEST_REPOSITORY
=
Paths
.
get
(
"src/test/resources/testdata/"
);
private
static
final
Path
TEST_REPOSITORY
=
Paths
.
get
(
"src/test/resources/testdata/"
);
//NOTE: This test can be adapted to download a region which is too large for the server. Here with local coordinates
@Test
@Test
public
void
testExtractRegionWithLocalCRS
()
void
testExtractRegionWithLocalCRS
()
throws
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
,
ParseException
{
throws
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
,
ParseException
{
String
citygml
=
"DA13_DA14_3D_Buildings_Port_Morris.gml"
;
String
citygml
=
"DA13_DA14_3D_Buildings_Port_Morris.gml"
;
String
projectName
=
"NewYork"
;
String
projectName
=
"NewYork"
;
...
@@ -39,9 +33,8 @@ public void testExtractRegionWithLocalCRS()
...
@@ -39,9 +33,8 @@ public void testExtractRegionWithLocalCRS()
"One weird shaped roof should be inside the region"
);
"One weird shaped roof should be inside the region"
);
}
}
//NOTE: This test can be adapted to download a region which is too large for the server. Here with WGS84 coordinates
@Test
@Test
public
void
testExtractRegionWithWGS84
()
void
testExtractRegionWithWGS84
()
throws
ParseException
,
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
{
throws
ParseException
,
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
{
String
wgs84WktPolygon
=
"POLYGON((-73.91140940026597 40.804246732157196,-73.91424181298568 40.80025100302325,-73.90934946374252 40.79755456207104,-73.90561582879378 40.80116062104605,-73.90960695580794 40.80340212653638,-73.91140940026597 40.804246732157196))"
;
String
wgs84WktPolygon
=
"POLYGON((-73.91140940026597 40.804246732157196,-73.91424181298568 40.80025100302325,-73.90934946374252 40.79755456207104,-73.90561582879378 40.80116062104605,-73.90960695580794 40.80340212653638,-73.91140940026597 40.804246732157196))"
;
String
citygml
=
"DA13_DA14_3D_Buildings_Port_Morris.gml"
;
String
citygml
=
"DA13_DA14_3D_Buildings_Port_Morris.gml"
;
...
@@ -49,10 +42,8 @@ public void testExtractRegionWithWGS84()
...
@@ -49,10 +42,8 @@ public void testExtractRegionWithWGS84()
Path
project
=
TEST_REPOSITORY
.
resolve
(
projectName
+
".proj"
);
Path
project
=
TEST_REPOSITORY
.
resolve
(
projectName
+
".proj"
);
Path
citygmlPath
=
project
.
resolve
(
citygml
);
Path
citygmlPath
=
project
.
resolve
(
citygml
);
Polygon
wgs84Polygon
=
(
Polygon
)
WKT_READER
.
read
(
wgs84WktPolygon
);
CoordinateReferenceSystem
localCRS
=
RegionChooserUtils
.
crsFromCityGMLHeader
(
citygmlPath
);
CoordinateReferenceSystem
localCRS
=
RegionChooserUtils
.
crsFromCityGMLHeader
(
citygmlPath
);
String
localWktPolygon
=
WKT_WRITER
String
localWktPolygon
=
RegionChooserUtils
.
wktPolygonToLocalCRS
(
wgs84WktPolygon
,
localCRS
);
.
write
(
RegionChooserUtils
.
changePolygonCRS
(
wgs84Polygon
,
RegionChooserUtils
.
WGS84
,
localCRS
));
StringBuilder
sb
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
localWktPolygon
,
localCRS
.
getName
(),
StringBuilder
sb
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
localWktPolygon
,
localCRS
.
getName
(),
citygmlPath
);
citygmlPath
);
assertTrue
(
sb
.
toString
().
contains
(
"gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"
),
assertTrue
(
sb
.
toString
().
contains
(
"gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"
),
...
@@ -61,7 +52,7 @@ public void testExtractRegionWithWGS84()
...
@@ -61,7 +52,7 @@ public void testExtractRegionWithWGS84()
//NOTE: This test can be adapted to download a region which is too large for the server. Here with old coordinates from WebSimstadt
//NOTE: This test can be adapted to download a region which is too large for the server. Here with old coordinates from WebSimstadt
@Test
@Test
public
void
testExtractRegionWithOldCoordinates
()
void
testExtractRegionWithOldCoordinates
()
throws
ParseException
,
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
{
throws
ParseException
,
IOException
,
XPathParseException
,
NavException
,
XPathEvalException
{
String
oldFormatPolygon
=
"(40.81173171854368,-73.93268437431763)\r\n"
+
String
oldFormatPolygon
=
"(40.81173171854368,-73.93268437431763)\r\n"
+
"(40.81069231965162,-73.93068165999941)\r\n"
+
"(40.81069231965162,-73.93068165999941)\r\n"
+
...
@@ -98,16 +89,12 @@ public void testExtractRegionWithOldCoordinates()
...
@@ -98,16 +89,12 @@ public void testExtractRegionWithOldCoordinates()
Path
project
=
TEST_REPOSITORY
.
resolve
(
projectName
+
".proj"
);
Path
project
=
TEST_REPOSITORY
.
resolve
(
projectName
+
".proj"
);
Path
citygmlPath
=
project
.
resolve
(
citygml
);
Path
citygmlPath
=
project
.
resolve
(
citygml
);
Polygon
wgs84Polygon
=
(
Polygon
)
WKT_READER
.
read
(
wgs84WktPolygon
);
CoordinateReferenceSystem
localCRS
=
RegionChooserUtils
.
crsFromCityGMLHeader
(
citygmlPath
);
CoordinateReferenceSystem
localCRS
=
RegionChooserUtils
.
crsFromCityGMLHeader
(
citygmlPath
);
String
localWktPolygon
=
WKT_WRITER
String
localWktPolygon
=
RegionChooserUtils
.
wktPolygonToLocalCRS
(
wgs84WktPolygon
,
localCRS
);
.
write
(
RegionChooserUtils
.
changePolygonCRS
(
wgs84Polygon
,
RegionChooserUtils
.
WGS84
,
localCRS
));
StringBuilder
sb
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
localWktPolygon
,
localCRS
.
getName
(),
StringBuilder
sb
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
localWktPolygon
,
localCRS
.
getName
(),
citygmlPath
);
citygmlPath
);
assertTrue
(
sb
.
toString
().
contains
(
"gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"
),
assertTrue
(
sb
.
toString
().
contains
(
"gml_ZVHMQQ6BZGRT0O3Q6RGXF12BDOV49QIZ58XB"
),
"One weird shaped roof should be inside the region"
);
"One weird shaped roof should be inside the region"
);
}
}
//TODO: Write a method to merge RegionChooser results from multiple gmls
}
}
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