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
78ce1bc2
Commit
78ce1bc2
authored
Jun 15, 2016
by
duminil
Browse files
RegionChooser: Beginning to merge both RegionChoosers.
parent
1d8b4cd7
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/eu/simstadt/regionchooser/RegionChooserBrowser.java
View file @
78ce1bc2
...
@@ -78,7 +78,7 @@ public void extractZIPtoGML(String zipFilename) throws IOException {
...
@@ -78,7 +78,7 @@ public void extractZIPtoGML(String zipFilename) throws IOException {
BufferedWriter
cityGMLOutput
=
Files
.
newBufferedWriter
(
extractedCityGML
.
toPath
());
BufferedWriter
cityGMLOutput
=
Files
.
newBufferedWriter
(
extractedCityGML
.
toPath
());
String
buf
=
null
;
String
buf
=
null
;
while
((
buf
=
cityGMLZipReader
.
readLine
())
!=
null
)
{
while
((
buf
=
cityGMLZipReader
.
readLine
())
!=
null
)
{
cityGMLOutput
.
write
(
buf
.
replace
(
"srsName=\"\""
,
"srsName=\"EPSG:31467\""
));
cityGMLOutput
.
write
(
buf
.
replace
(
"srsName=\"\""
,
"srsName=\"EPSG:31467\""
));
//TODO: Get EPSG:id from NovaFactory Server?
}
}
cityGMLZipReader
.
close
();
cityGMLZipReader
.
close
();
cityGMLInputStream
.
close
();
cityGMLInputStream
.
close
();
...
...
src/eu/simstadt/regionchooser/RegionChooserBrowserNewYorkEdition.java
deleted
100644 → 0
View file @
1d8b4cd7
package
eu.simstadt.regionchooser
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.prefs.Preferences
;
import
com.vividsolutions.jts.io.ParseException
;
import
com.vividsolutions.jts.io.WKTReader
;
import
javafx.beans.value.ObservableValue
;
import
javafx.concurrent.Worker.State
;
import
javafx.geometry.HPos
;
import
javafx.geometry.VPos
;
import
javafx.scene.layout.Region
;
import
javafx.scene.web.WebEngine
;
import
javafx.scene.web.WebView
;
import
javafx.stage.FileChooser
;
import
javafx.stage.Stage
;
import
netscape.javascript.JSObject
;
public
class
RegionChooserBrowserNewYorkEdition
extends
Region
{
public
class
JavaScriptFXBridge
{
private
Path
repo
;
private
WKTReader
wktReader
=
new
WKTReader
();
public
JavaScriptFXBridge
()
{
Preferences
userPrefs
=
Preferences
.
userRoot
().
node
(
"/eu/simstadt/desktop"
);
String
repoString
=
userPrefs
.
get
(
"RECENT_REPOSITORY"
,
null
);
if
(
repoString
==
null
)
{
repo
=
Paths
.
get
(
"../TestRepository"
);
}
else
{
repo
=
Paths
.
get
(
repoString
);
}
}
public
void
downloadRegionFromCityGML
(
String
wktPolygon
,
String
project
,
String
citygml
)
throws
IOException
,
ParseException
{
StringBuffer
sb
=
RegionExtractorNewYorkEdition
.
selectRegionDirectlyFromCityGML
(
citygmlPath
(
project
,
citygml
),
wktPolygon
);
File
buildingIdsFile
=
selectSaveFileWithDialog
(
project
,
citygml
,
"selected_region"
);
if
(
buildingIdsFile
!=
null
)
{
BufferedWriter
writer
=
Files
.
newBufferedWriter
(
buildingIdsFile
.
toPath
());
writer
.
write
(
sb
.
toString
());
writer
.
close
();
}
}
private
File
selectSaveFileWithDialog
(
String
project
,
String
citygml
,
String
suffix
)
{
Stage
mainStage
=
(
Stage
)
RegionChooserBrowserNewYorkEdition
.
this
.
getScene
().
getWindow
();
FileChooser
fileChooser
=
new
FileChooser
();
fileChooser
.
setTitle
(
"Save CITYGML ids"
);
if
(
project
!=
null
)
{
fileChooser
.
setInitialDirectory
(
repo
.
resolve
(
project
+
".proj"
).
toFile
());
}
else
{
fileChooser
.
setInitialDirectory
(
repo
.
toFile
());
}
if
(
suffix
.
isEmpty
())
{
fileChooser
.
setInitialFileName
(
citygml
);
}
else
{
fileChooser
.
setInitialFileName
(
citygml
.
replace
(
"."
,
"_"
+
suffix
+
"."
));
}
FileChooser
.
ExtensionFilter
extFilter
=
new
FileChooser
.
ExtensionFilter
(
"GML files (*.gml)"
,
"*.gml"
);
fileChooser
.
getExtensionFilters
().
add
(
extFilter
);
return
fileChooser
.
showSaveDialog
(
mainStage
);
}
public
boolean
checkIfCityGMLSAreAvailable
(
String
project
,
String
citygml
)
{
Path
p
=
citygmlPath
(
project
,
citygml
);
return
Files
.
isReadable
(
p
);
}
public
void
log
(
String
text
)
{
System
.
out
.
println
(
text
);
}
private
Path
citygmlPath
(
String
project
,
String
citygml
)
{
return
repo
.
resolve
(
project
+
".proj"
).
resolve
(
citygml
);
}
}
final
WebView
browser
=
new
WebView
();
final
WebEngine
webEngine
=
browser
.
getEngine
();
public
RegionChooserBrowserNewYorkEdition
()
{
//apply the styles
getStyleClass
().
add
(
"browser"
);
String
url
=
RegionChooserNewYorkEdition
.
class
.
getResource
(
"website/index_nyc.html"
).
toExternalForm
();
webEngine
.
load
(
url
);
// load the web page
// process page loading
webEngine
.
getLoadWorker
().
stateProperty
().
addListener
(
(
ObservableValue
<?
extends
State
>
ov
,
State
oldState
,
State
newState
)
->
{
if
(
newState
==
State
.
SUCCEEDED
)
{
JSObject
win
=
(
JSObject
)
webEngine
.
executeScript
(
"window"
);
JavaScriptFXBridge
fxapp
=
new
JavaScriptFXBridge
();
win
.
setMember
(
"fxapp"
,
fxapp
);
webEngine
.
executeScript
(
"console.log = function(message)\n"
+
"{\n"
+
" fxapp.log(message);\n"
+
"};"
);
}
});
//add the web view to the scene
getChildren
().
add
(
browser
);
}
@Override
protected
void
layoutChildren
()
{
double
w
=
getWidth
();
double
h
=
getHeight
();
layoutInArea
(
browser
,
0
,
0
,
w
,
h
,
0
,
HPos
.
CENTER
,
VPos
.
CENTER
);
}
@Override
protected
double
computePrefWidth
(
double
height
)
{
return
900
;
}
@Override
protected
double
computePrefHeight
(
double
width
)
{
return
600
;
}
}
src/eu/simstadt/regionchooser/RegionChooserNewYorkEdition.java
deleted
100644 → 0
View file @
1d8b4cd7
package
eu.simstadt.regionchooser
;
import
java.util.logging.Logger
;
import
javafx.application.Application
;
import
javafx.scene.Scene
;
import
javafx.scene.paint.Color
;
import
javafx.stage.Stage
;
public
class
RegionChooserNewYorkEdition
extends
Application
{
private
Scene
scene
;
protected
final
static
Logger
LOGGER
=
Logger
.
getLogger
(
RegionChooserNewYorkEdition
.
class
.
getName
());
@Override
public
void
start
(
Stage
stage
)
{
// create the scene
stage
.
setTitle
(
"RegionChooserNewYorkEdition"
);
scene
=
new
Scene
(
new
RegionChooserBrowserNewYorkEdition
(),
1024
,
768
,
Color
.
web
(
"#666970"
));
stage
.
setScene
(
scene
);
stage
.
show
();
}
public
static
void
main
(
String
[]
args
)
{
launch
(
args
);
}
}
src/eu/simstadt/regionchooser/RegionExtractor.java
View file @
78ce1bc2
...
@@ -57,8 +57,9 @@ static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, Str
...
@@ -57,8 +57,9 @@ static public StringBuffer selectRegionDirectlyFromCityGML(Path citygmlPath, Str
}
}
}
}
System
.
out
.
println
(
"Buildings found in selected region "
+
i
);
System
.
out
.
println
(
"Buildings found in selected region "
+
i
);
//TODO: Don't write anything if i==0
if
(
i
>
0
)
{
cityObjectMatcher
.
appendTail
(
sb
);
cityObjectMatcher
.
appendTail
(
sb
);
}
// System.out.println(Duration.between(start, Instant.now()));
// System.out.println(Duration.between(start, Instant.now()));
return
sb
;
return
sb
;
}
}
...
...
src/eu/simstadt/regionchooser/RegionExtractorNewYorkEdition.java
deleted
100644 → 0
View file @
1d8b4cd7
package
eu.simstadt.regionchooser
;
import
java.io.IOException
;
import
java.nio.charset.Charset
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
com.vividsolutions.jts.geom.Coordinate
;
import
com.vividsolutions.jts.geom.Geometry
;
import
com.vividsolutions.jts.geom.GeometryFactory
;
import
com.vividsolutions.jts.geom.Point
;
import
com.vividsolutions.jts.io.ParseException
;
import
com.vividsolutions.jts.io.WKTReader
;
public
class
RegionExtractorNewYorkEdition
{
static
private
WKTReader
wktReader
=
new
WKTReader
();
static
public
StringBuffer
selectRegionDirectlyFromCityGML
(
Path
citygmlPath
,
String
wktPolygon
)
throws
IOException
,
ParseException
{
// Instant start = Instant.now();
Geometry
poly
=
wktReader
.
read
(
wktPolygon
);
final
GeometryFactory
gf
=
new
GeometryFactory
();
String
s
=
new
String
(
Files
.
readAllBytes
(
citygmlPath
),
Charset
.
defaultCharset
());
Pattern
cityObjectPattern
=
Pattern
.
compile
(
"(?s)<(core:)?cityObjectMember[^>]*>.*?<\\/(core:)?cityObjectMember>\\s*"
);
Pattern
nad83CoordinatesPattern
=
Pattern
.
compile
(
"(?<![\\d\\.])([23]\\d\\d\\d\\d\\d[\\.\\d]*) ([4-8]\\d\\d\\d\\d[\\.\\d]*)"
);
Matcher
cityObjectMatcher
=
cityObjectPattern
.
matcher
(
s
);
StringBuffer
sb
=
new
StringBuffer
();
int
i
=
0
;
while
(
cityObjectMatcher
.
find
())
{
cityObjectMatcher
.
appendReplacement
(
sb
,
""
);
String
cityObject
=
cityObjectMatcher
.
group
();
Matcher
nad83CoordinatesMatcher
=
nad83CoordinatesPattern
.
matcher
(
cityObject
);
int
coordinatesCount
=
0
;
double
xTotal
=
0
;
double
yTotal
=
0
;
while
(
nad83CoordinatesMatcher
.
find
())
{
coordinatesCount
++;
xTotal
+=
Double
.
valueOf
(
nad83CoordinatesMatcher
.
group
(
1
));
yTotal
+=
Double
.
valueOf
(
nad83CoordinatesMatcher
.
group
(
2
));
}
double
x
=
xTotal
/
coordinatesCount
;
double
y
=
yTotal
/
coordinatesCount
;
Coordinate
coord
=
new
Coordinate
(
x
,
y
);
Point
point
=
gf
.
createPoint
(
coord
);
if
(
point
.
within
(
poly
))
{
i
++;
sb
.
append
(
cityObject
);
}
}
System
.
out
.
println
(
"Buildings found in selected region "
+
i
);
cityObjectMatcher
.
appendTail
(
sb
);
return
sb
;
}
}
src/eu/simstadt/regionchooser/website/data/citygml_hulls.kml
View file @
78ce1bc2
...
@@ -481,5 +481,59 @@
...
@@ -481,5 +481,59 @@
</outerBoundaryIs>
</outerBoundaryIs>
</Polygon>
</Polygon>
</Placemark>
</Placemark>
<Placemark>
<name>
Manhattan.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.019012,40.7062519,0 -74.0189717,40.7058604,0 -74.0189418,40.7057319,0 -74.0184794,40.7042805,0 -74.0172664,40.7028968,0 -74.015158,40.7011657,0 -74.015107,40.7011428,0 -74.0135003,40.7004843,0 -73.9746149,40.698469,0 -73.9698348,40.7010661,0 -73.9696604,40.7011962,0 -73.969608,40.7498934,0 -73.9696103,40.7577021,0 -73.970055,40.7578905,0 -73.9702186,40.7579597,0 -73.9706688,40.7580941,0 -73.9716929,40.7582638,0 -73.9788927,40.7582855,0 -73.9888251,40.7582835,0 -73.9925648,40.7582471,0 -73.9980335,40.7581217,0 -73.9997291,40.7580401,0 -74.0002613,40.7578747,0 -74.0065919,40.7556662,0 -74.006643,40.7555973,0 -74.0071602,40.7548532,0 -74.0087472,40.7523398,0 -74.0112393,40.7479423,0 -74.019012,40.7062519,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark>
<name>
ManhattanSmall.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.0056253,40.7294668,0 -74.0053484,40.7272316,0 -74.005111,40.7272111,0 -74.0050053,40.727202,0 -73.9968092,40.7271834,0 -73.9928453,40.7273709,0 -73.9905297,40.7275413,0 -73.9904107,40.7277055,0 -73.9903612,40.7277749,0 -73.9902701,40.7280447,0 -73.9902142,40.7327445,0 -73.9903382,40.7336279,0 -73.9909377,40.7347126,0 -73.9910923,40.7347799,0 -73.9932613,40.7348532,0 -73.99814,40.7348976,0 -74.0012625,40.7349003,0 -74.0026956,40.7348996,0 -74.004586,40.7348956,0 -74.0049082,40.7348889,0 -74.0051523,40.734853,0 -74.0052862,40.734824,0 -74.0054646,40.7331513,0 -74.0056253,40.7294668,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark>
<name>
NYC_Flatiron_Buildings_Streets_Lots_20150907.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
<Data
name=
"download_region_url"
>
<value>
http://dmz15.rz.hft-stuttgart.de:3012/projects/4/citygmls/4/download_region
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.001835,40.7457938,0 -74.0015806,40.7410453,0 -74.0011234,40.7365237,0 -73.9995822,40.7354488,0 -73.9992522,40.7353105,0 -73.9945852,40.7346727,0 -73.9789847,40.7347695,0 -73.978572,40.7356558,0 -73.9775771,40.738207,0 -73.9767318,40.7435084,0 -73.9776122,40.7464249,0 -73.978865,40.7477171,0 -73.9991288,40.7492605,0 -74.0004421,40.7477074,0 -74.001835,40.7457938,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</Document>
</kml>
</kml>
src/eu/simstadt/regionchooser/website/data/citygml_hulls_nyc.kml
deleted
100644 → 0
View file @
1d8b4cd7
<?xml version="1.0" encoding="UTF-8"?>
<kml>
<Document>
<Placemark>
<name>
Manhattan.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.019012,40.7062519,0 -74.0189717,40.7058604,0 -74.0189418,40.7057319,0 -74.0184794,40.7042805,0 -74.0172664,40.7028968,0 -74.015158,40.7011657,0 -74.015107,40.7011428,0 -74.0135003,40.7004843,0 -73.9746149,40.698469,0 -73.9698348,40.7010661,0 -73.9696604,40.7011962,0 -73.969608,40.7498934,0 -73.9696103,40.7577021,0 -73.970055,40.7578905,0 -73.9702186,40.7579597,0 -73.9706688,40.7580941,0 -73.9716929,40.7582638,0 -73.9788927,40.7582855,0 -73.9888251,40.7582835,0 -73.9925648,40.7582471,0 -73.9980335,40.7581217,0 -73.9997291,40.7580401,0 -74.0002613,40.7578747,0 -74.0065919,40.7556662,0 -74.006643,40.7555973,0 -74.0071602,40.7548532,0 -74.0087472,40.7523398,0 -74.0112393,40.7479423,0 -74.019012,40.7062519,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark>
<name>
ManhattanSmall.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.0056253,40.7294668,0 -74.0053484,40.7272316,0 -74.005111,40.7272111,0 -74.0050053,40.727202,0 -73.9968092,40.7271834,0 -73.9928453,40.7273709,0 -73.9905297,40.7275413,0 -73.9904107,40.7277055,0 -73.9903612,40.7277749,0 -73.9902701,40.7280447,0 -73.9902142,40.7327445,0 -73.9903382,40.7336279,0 -73.9909377,40.7347126,0 -73.9910923,40.7347799,0 -73.9932613,40.7348532,0 -73.99814,40.7348976,0 -74.0012625,40.7349003,0 -74.0026956,40.7348996,0 -74.004586,40.7348956,0 -74.0049082,40.7348889,0 -74.0051523,40.734853,0 -74.0052862,40.734824,0 -74.0054646,40.7331513,0 -74.0056253,40.7294668,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark>
<name>
NYC_Flatiron_Buildings_Streets_Lots_20150907.gml
</name>
<ExtendedData>
<Data
name=
"project"
>
<value>
NewYork
</value>
</Data>
<Data
name=
"download_region_url"
>
<value>
http://dmz15.rz.hft-stuttgart.de:3012/projects/4/citygmls/4/download_region
</value>
</Data>
</ExtendedData>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>
1
</tessellate>
<coordinates>
-74.001835,40.7457938,0 -74.0015806,40.7410453,0 -74.0011234,40.7365237,0 -73.9995822,40.7354488,0 -73.9992522,40.7353105,0 -73.9945852,40.7346727,0 -73.9789847,40.7347695,0 -73.978572,40.7356558,0 -73.9775771,40.738207,0 -73.9767318,40.7435084,0 -73.9776122,40.7464249,0 -73.978865,40.7477171,0 -73.9991288,40.7492605,0 -74.0004421,40.7477074,0 -74.001835,40.7457938,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
test/eu/simstadt/regionchooser/test/RegionExtractorTests.java
View file @
78ce1bc2
...
@@ -8,7 +8,6 @@
...
@@ -8,7 +8,6 @@
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
org.junit.Test
;
import
org.junit.Test
;
import
eu.simstadt.regionchooser.RegionExtractor
;
import
eu.simstadt.regionchooser.RegionExtractor
;
import
eu.simstadt.regionchooser.RegionExtractorNewYorkEdition
;
public
class
RegionExtractorTests
public
class
RegionExtractorTests
...
@@ -43,7 +42,7 @@ public void testExtract3BuildingsFromNAD83Model() throws Throwable {
...
@@ -43,7 +42,7 @@ public void testExtract3BuildingsFromNAD83Model() throws Throwable {
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))"
;
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
repo
=
Paths
.
get
(
"../TestRepository"
);
Path
repo
=
Paths
.
get
(
"../TestRepository"
);
Path
citygmlPath
=
repo
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
Path
citygmlPath
=
repo
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
String
archGMLString
=
RegionExtractor
NewYorkEdition
.
selectRegionDirectlyFromCityGML
(
citygmlPath
,
wktPolygon
)
String
archGMLString
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
citygmlPath
,
wktPolygon
)
.
toString
();
.
toString
();
assertEquals
(
countRegexMatches
(
archGMLString
,
"<(core:)?cityObjectMember"
),
2
);
assertEquals
(
countRegexMatches
(
archGMLString
,
"<(core:)?cityObjectMember"
),
2
);
assertTrue
(
archGMLString
.
contains
(
"WASHINGTON SQUARE"
));
assertTrue
(
archGMLString
.
contains
(
"WASHINGTON SQUARE"
));
...
@@ -57,8 +56,8 @@ public void testExtract0BuildingsWithWrongCoordinates() throws Throwable {
...
@@ -57,8 +56,8 @@ public void testExtract0BuildingsWithWrongCoordinates() throws Throwable {
String
wktPolygon
=
"POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"
;
String
wktPolygon
=
"POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))"
;
Path
repo
=
Paths
.
get
(
"../TestRepository"
);
Path
repo
=
Paths
.
get
(
"../TestRepository"
);
Path
citygmlPath
=
repo
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
Path
citygmlPath
=
repo
.
resolve
(
"NewYork.proj/ManhattanSmall.gml"
);
String
arch
GMLString
=
RegionExtractor
NewYorkEdition
.
selectRegionDirectlyFromCityGML
(
citygmlPath
,
wktPolygon
)
String
empty
GMLString
=
RegionExtractor
.
selectRegionDirectlyFromCityGML
(
citygmlPath
,
wktPolygon
)
.
toString
();
.
toString
();
assertEquals
(
countRegexMatches
(
arch
GMLString
,
"<(core:)?cityObjectMember"
),
0
);
assertEquals
(
countRegexMatches
(
empty
GMLString
,
"<(core:)?cityObjectMember"
),
0
);
}
}
}
}
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