Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
9e161477
Commit
9e161477
authored
Oct 02, 2024
by
Riegel
Browse files
Format code
parent
6b536067
Pipeline
#10248
passed with stage
in 1 minute and 13 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java
View file @
9e161477
...
...
@@ -45,1133 +45,1133 @@ import javafx.stage.FileChooser.ExtensionFilter;
public
class
CityDoctorController
{
private
static
final
int
MAX_FEATURES_PER_CHUNK
=
200
;
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
CityDoctorController
.
class
);
private
MainWindow
mainWindow
;
private
CityDoctorModel
model
;
private
ParserConfiguration
currentConfig
;
private
String
sourceFile
;
private
Checker
currentChecker
;
private
HighlightController
highlightController
;
private
Renderer
renderer
;
private
AtomicInteger
buildingChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
vegetationChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
transportationChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
bridgeChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
waterChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
landChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
cityFurnitureChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
otherObjectsChunkNr
=
new
AtomicInteger
(
0
);
public
CityDoctorController
(
MainWindow
mainWindow
,
HighlightController
highlightController
,
Renderer
renderer
)
{
this
.
mainWindow
=
mainWindow
;
this
.
highlightController
=
highlightController
;
this
.
renderer
=
renderer
;
}
public
void
loadCityGml
(
String
path
,
int
numberOfRoundingPlaces
,
ProgressListener
l
,
boolean
useValidation
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
loadCityGml
(
path
,
numberOfRoundingPlaces
,
l
,
useValidation
,
false
);
}
public
void
loadCityGml
(
String
path
,
int
numberOfRoundingPlaces
,
ProgressListener
l
,
boolean
useValidation
,
boolean
lowMemory
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
try
{
Platform
.
runLater
(()
->
{
mainWindow
.
getOpenBtn
().
setDisable
(
true
);
mainWindow
.
getWriteReportButton
().
setDisable
(
true
);
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
clearTrees
();
mainWindow
.
resetSearchBar
();
mainWindow
.
resetFilterComboBox
();
});
currentChecker
=
null
;
currentConfig
=
new
ParserConfiguration
(
numberOfRoundingPlaces
,
useValidation
,
lowMemory
);
GMLValidationHandler
handler
=
null
;
List
<
String
>
validationIssues
=
new
ArrayList
<>();
if
(
useValidation
)
{
handler
=
new
GMLValidationHandler
()
{
@Override
public
void
error
(
SAXParseException
exception
)
{
if
(
exception
.
getLineNumber
()
>=
0
)
{
String
s
=
"In line "
+
exception
.
getLineNumber
()
+
":"
;
validationIssues
.
add
(
s
);
}
validationIssues
.
add
(
exception
.
getMessage
());
}
@Override
public
void
warning
(
SAXParseException
exception
)
{
error
(
exception
);
}
@Override
public
void
fatalError
(
SAXParseException
exception
)
{
error
(
exception
);
}
};
}
model
=
CityGmlParser
.
parseCityGmlFile
(
path
,
currentConfig
,
l
,
handler
);
if
(!
validationIssues
.
isEmpty
())
{
StringJoiner
sj
=
new
StringJoiner
(
"\n"
);
validationIssues
.
stream
().
forEach
(
sj:
:
add
);
throw
new
InvalidGmlFileException
(
sj
.
toString
());
}
mainWindow
.
getClickHandler
().
setConfig
(
currentConfig
);
sourceFile
=
path
;
renderer
.
reset
();
Platform
.
runLater
(()
->
{
mainWindow
.
addFileNameToTitle
(
path
);
mainWindow
.
getCheckButton
().
setDisable
(
false
);
mainWindow
.
getLod1Btn
().
setDisable
(
false
);
mainWindow
.
getLod2Btn
().
setDisable
(
false
);
mainWindow
.
getLod3Btn
().
setDisable
(
false
);
mainWindow
.
getLod4Btn
().
setDisable
(
false
);
mainWindow
.
getWorldBtn
().
setDisable
(
false
);
mainWindow
.
getSaveBtn
().
setDisable
(
false
);
buildTrees
();
});
}
finally
{
Platform
.
runLater
(()
->
mainWindow
.
getOpenBtn
().
setDisable
(
false
));
}
}
public
void
buildTrees
()
{
resetFeatureChunks
();
buildBuildings
(
model
);
buildVegetation
(
model
.
getVegetation
());
buildTransportation
(
model
.
getTransportation
());
buildBridges
(
model
);
buildWater
(
model
);
buildLand
(
model
);
buildCityFurniture
(
model
);
private
static
final
int
MAX_FEATURES_PER_CHUNK
=
200
;
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
CityDoctorController
.
class
);
private
MainWindow
mainWindow
;
private
CityDoctorModel
model
;
private
ParserConfiguration
currentConfig
;
private
String
sourceFile
;
private
Checker
currentChecker
;
private
HighlightController
highlightController
;
private
Renderer
renderer
;
private
AtomicInteger
buildingChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
vegetationChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
transportationChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
bridgeChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
waterChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
landChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
cityFurnitureChunkNr
=
new
AtomicInteger
(
0
);
private
AtomicInteger
otherObjectsChunkNr
=
new
AtomicInteger
(
0
);
public
CityDoctorController
(
MainWindow
mainWindow
,
HighlightController
highlightController
,
Renderer
renderer
)
{
this
.
mainWindow
=
mainWindow
;
this
.
highlightController
=
highlightController
;
this
.
renderer
=
renderer
;
}
public
void
loadCityGml
(
String
path
,
int
numberOfRoundingPlaces
,
ProgressListener
l
,
boolean
useValidation
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
loadCityGml
(
path
,
numberOfRoundingPlaces
,
l
,
useValidation
,
false
);
}
public
void
loadCityGml
(
String
path
,
int
numberOfRoundingPlaces
,
ProgressListener
l
,
boolean
useValidation
,
boolean
lowMemory
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
try
{
Platform
.
runLater
(()
->
{
mainWindow
.
getOpenBtn
().
setDisable
(
true
);
mainWindow
.
getWriteReportButton
().
setDisable
(
true
);
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
clearTrees
();
mainWindow
.
resetSearchBar
();
mainWindow
.
resetFilterComboBox
();
});
currentChecker
=
null
;
currentConfig
=
new
ParserConfiguration
(
numberOfRoundingPlaces
,
useValidation
,
lowMemory
);
GMLValidationHandler
handler
=
null
;
List
<
String
>
validationIssues
=
new
ArrayList
<>();
if
(
useValidation
)
{
handler
=
new
GMLValidationHandler
()
{
@Override
public
void
error
(
SAXParseException
exception
)
{
if
(
exception
.
getLineNumber
()
>=
0
)
{
String
s
=
"In line "
+
exception
.
getLineNumber
()
+
":"
;
validationIssues
.
add
(
s
);
}
validationIssues
.
add
(
exception
.
getMessage
());
}
@Override
public
void
warning
(
SAXParseException
exception
)
{
error
(
exception
);
}
@Override
public
void
fatalError
(
SAXParseException
exception
)
{
error
(
exception
);
}
};
}
model
=
CityGmlParser
.
parseCityGmlFile
(
path
,
currentConfig
,
l
,
handler
);
if
(!
validationIssues
.
isEmpty
())
{
StringJoiner
sj
=
new
StringJoiner
(
"\n"
);
validationIssues
.
stream
().
forEach
(
sj:
:
add
);
throw
new
InvalidGmlFileException
(
sj
.
toString
());
}
mainWindow
.
getClickHandler
().
setConfig
(
currentConfig
);
sourceFile
=
path
;
renderer
.
reset
();
Platform
.
runLater
(()
->
{
mainWindow
.
addFileNameToTitle
(
path
);
mainWindow
.
getCheckButton
().
setDisable
(
false
);
mainWindow
.
getLod1Btn
().
setDisable
(
false
);
mainWindow
.
getLod2Btn
().
setDisable
(
false
);
mainWindow
.
getLod3Btn
().
setDisable
(
false
);
mainWindow
.
getLod4Btn
().
setDisable
(
false
);
mainWindow
.
getWorldBtn
().
setDisable
(
false
);
mainWindow
.
getSaveBtn
().
setDisable
(
false
);
buildTrees
();
});
}
finally
{
Platform
.
runLater
(()
->
mainWindow
.
getOpenBtn
().
setDisable
(
false
));
}
}
public
void
buildTrees
()
{
resetFeatureChunks
();
buildBuildings
(
model
);
buildVegetation
(
model
.
getVegetation
());
buildTransportation
(
model
.
getTransportation
());
buildBridges
(
model
);
buildWater
(
model
);
buildLand
(
model
);
buildCityFurniture
(
model
);
buildOtherCityObjects
(
model
);
}
private
void
resetFeatureChunks
()
{
buildingChunkNr
.
set
(
0
);
vegetationChunkNr
.
set
(
0
);
transportationChunkNr
.
set
(
0
);
bridgeChunkNr
.
set
(
0
);
waterChunkNr
.
set
(
0
);
landChunkNr
.
set
(
0
);
cityFurnitureChunkNr
.
set
(
0
);
otherObjectsChunkNr
.
set
(
0
);
}
private
void
buildLand
(
CityDoctorModel
model
)
{
if
(
model
.
getLand
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
landView
=
mainWindow
.
getTerrainView
();
TreeItem
<
Renderable
>
landRoot
=
new
TreeItem
<>(
new
AllTerrainNode
(
model
.
getLand
()));
landRoot
.
setExpanded
(
true
);
landView
.
setRoot
(
landRoot
);
buildLandFromList
(
model
.
getLand
(),
landView
.
getRoot
());
addMoreButtonIfNecessary
(
model
.
getLand
(),
landView
,
landRoot
,
landChunkNr
);
}
private
void
buildLandFromList
(
List
<
CityObject
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
landChunk
=
landChunkNr
.
get
();
for
(
int
i
=
landChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
landChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
CityObject
land
=
list
.
get
(
i
);
Renderable
node
;
if
(
land
instanceof
ReliefObject
relief
)
{
node
=
new
ReliefNode
(
relief
);
}
else
if
(
land
instanceof
TinObject
tin
)
{
node
=
new
TinNode
(
tin
);
}
else
{
node
=
new
LandUseNode
((
LandObject
)
land
);
}
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
land
,
item
);
if
(
land
instanceof
ReliefObject
relief
)
{
createTinNodes
(
relief
,
item
);
}
}
}
private
void
createTinNodes
(
ReliefObject
relief
,
TreeItem
<
Renderable
>
item
)
{
if
(
relief
.
getComponents
().
isEmpty
())
{
return
;
}
AllTinNode
allTinText
=
new
AllTinNode
(
relief
.
getComponents
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allTinText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
TinObject
tin
:
relief
.
getComponents
())
{
TinNode
tinNode
=
new
TinNode
(
tin
);
TreeItem
<
Renderable
>
tinNodeItem
=
new
TreeItem
<>(
tinNode
);
tinNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
tinNodeItem
);
createGeometryNodes
(
tin
,
tinNodeItem
);
}
}
private
void
buildCityFurniture
(
CityDoctorModel
model
){
if
(
model
.
getCityFurniture
().
isEmpty
()){
return
;
}
TreeView
<
Renderable
>
cityFurnitureView
=
mainWindow
.
getCityFurnitureView
();
TreeItem
<
Renderable
>
cityFurnitureRoot
=
new
TreeItem
<>(
new
AllCityFurnitureNode
(
model
.
getCityFurniture
()));
cityFurnitureRoot
.
setExpanded
(
true
);
cityFurnitureView
.
setRoot
(
cityFurnitureRoot
);
buildTreeFromList
(
model
.
getCityFurniture
(),
cityFurnitureView
.
getRoot
(),
cityFurnitureChunkNr
);
addMoreButtonIfNecessary
(
model
.
getCityFurniture
(),
cityFurnitureView
,
cityFurnitureRoot
,
cityFurnitureChunkNr
);
}
private
void
buildOtherCityObjects
(
CityDoctorModel
model
){
if
(
model
.
getGenericCityObjects
().
isEmpty
()){
return
;
}
TreeView
<
Renderable
>
otherObjectsView
=
mainWindow
.
getOtherObjectsView
();
TreeItem
<
Renderable
>
otherObjectsRoot
=
new
TreeItem
<>(
new
AllOtherObjectsNode
(
model
.
getGenericCityObjects
()));
otherObjectsRoot
.
setExpanded
(
true
);
otherObjectsView
.
setRoot
(
otherObjectsRoot
);
buildTreeFromList
(
model
.
getGenericCityObjects
(),
otherObjectsView
.
getRoot
(),
otherObjectsChunkNr
);
addMoreButtonIfNecessary
(
model
.
getGenericCityObjects
(),
otherObjectsView
,
otherObjectsRoot
,
otherObjectsChunkNr
);
}
private
void
buildWater
(
CityDoctorModel
model
)
{
if
(
model
.
getWater
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
waterView
=
mainWindow
.
getWaterView
();
TreeItem
<
Renderable
>
waterRoot
=
new
TreeItem
<>(
new
AllWaterNode
(
model
.
getWater
()));
waterRoot
.
setExpanded
(
true
);
waterView
.
setRoot
(
waterRoot
);
buildTreeFromList
(
model
.
getWater
(),
waterView
.
getRoot
(),
waterChunkNr
);
addMoreButtonIfNecessary
(
model
.
getWater
(),
waterView
,
waterRoot
,
waterChunkNr
);
}
private
void
buildBridges
(
CityDoctorModel
model
)
{
if
(
model
.
getBridges
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
bridgeView
=
mainWindow
.
getBridgeView
();
TreeItem
<
Renderable
>
bridgeRoot
=
new
TreeItem
<>(
new
AllBridgesNode
(
model
.
getBridges
()));
bridgeRoot
.
setExpanded
(
true
);
bridgeView
.
setRoot
(
bridgeRoot
);
buildBridgeTreeFromList
(
model
.
getBridges
(),
bridgeView
.
getRoot
());
addMoreButtonIfNecessary
(
model
.
getBridges
(),
bridgeView
,
bridgeRoot
,
bridgeChunkNr
);
}
private
void
buildTransportation
(
List
<
TransportationObject
>
trans
)
{
if
(
trans
.
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
transView
=
mainWindow
.
getTransportationView
();
TreeItem
<
Renderable
>
transRoot
=
new
TreeItem
<>(
new
AllTransportationNode
(
model
.
getTransportation
()));
transRoot
.
setExpanded
(
true
);
transView
.
setRoot
(
transRoot
);
buildTreeFromList
(
trans
,
transView
.
getRoot
(),
transportationChunkNr
);
addMoreButtonIfNecessary
(
trans
,
transView
,
transRoot
,
transportationChunkNr
);
}
private
void
buildVegetation
(
List
<
Vegetation
>
veg
)
{
if
(
veg
.
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
vegetationsView
=
mainWindow
.
getVegetationView
();
TreeItem
<
Renderable
>
vegRoot
=
new
TreeItem
<>(
new
AllVegetationNode
(
model
.
getVegetation
()));
vegRoot
.
setExpanded
(
true
);
vegetationsView
.
setRoot
(
vegRoot
);
buildTreeFromListWithProducer
(
veg
,
vegetationsView
.
getRoot
(),
vegetationChunkNr
,
VegetationNode:
:
new
);
addMoreButtonIfNecessary
(
veg
,
vegetationsView
,
vegRoot
,
vegetationChunkNr
);
}
private
void
addMoreButtonIfNecessary
(
List
<?
extends
CityObject
>
list
,
TreeView
<
Renderable
>
view
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
Runnable
run
=
new
Runnable
()
{
public
void
run
()
{
// 29 is the height of one item
int
numberOfDisplayedItems
=
(
int
)
(
view
.
getHeight
()
/
29
);
int
selectedIndex
=
view
.
getSelectionModel
().
getSelectedIndex
();
// remove button node
root
.
getChildren
().
remove
(
root
.
getChildren
().
size
()
-
1
);
chunkCounter
.
incrementAndGet
();
int
visibleFeatures
=
countVisibleNodes
(
view
);
buildTreeFromList
(
list
,
root
,
chunkCounter
);
updateTree
(
root
);
if
(
selectedIndex
>=
0
)
{
view
.
getSelectionModel
().
select
(
selectedIndex
);
}
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
this
)));
}
view
.
scrollTo
(
visibleFeatures
-
numberOfDisplayedItems
+
1
);
}
};
// add button for expansion
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
run
)));
}
}
private
void
buildBuildings
(
CityDoctorModel
model
)
{
if
(
model
.
getBuildings
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
new
TreeItem
<>(
new
AllBuildingsNode
(
model
.
getBuildings
()));
root
.
setExpanded
(
true
);
buildBuildingTreeFromList
(
model
.
getBuildings
(),
root
);
addMoreButtonToBuildingsIfNecessary
(
model
.
getBuildings
(),
buildingsView
,
root
,
buildingChunkNr
);
buildingsView
.
setRoot
(
root
);
}
private
void
addMoreButtonToBuildingsIfNecessary
(
List
<
Building
>
list
,
TreeView
<
Renderable
>
view
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
Runnable
run
=
new
Runnable
()
{
public
void
run
()
{
// 29 is the height of one item
int
numberOfDisplayedItems
=
(
int
)
(
view
.
getHeight
()
/
29
);
int
selectedIndex
=
view
.
getSelectionModel
().
getSelectedIndex
();
// remove button node
root
.
getChildren
().
remove
(
root
.
getChildren
().
size
()
-
1
);
chunkCounter
.
getAndIncrement
();
int
visibleFeatures
=
countVisibleNodes
(
view
);
buildBuildingTreeFromList
(
list
,
root
);
updateTree
(
root
);
if
(
selectedIndex
>=
0
)
{
view
.
getSelectionModel
().
select
(
selectedIndex
);
}
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
this
)));
}
view
.
scrollTo
(
visibleFeatures
-
numberOfDisplayedItems
+
1
);
}
};
// add button for expansion
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
run
)));
}
}
private
static
int
countVisibleNodes
(
TreeView
<
Renderable
>
view
)
{
return
countVisibleNodes
(
view
.
getRoot
())
+
1
;
}
private
static
int
countVisibleNodes
(
TreeItem
<
Renderable
>
root
)
{
int
visibleFeatures
=
root
.
getChildren
().
size
();
for
(
TreeItem
<
Renderable
>
child
:
root
.
getChildren
())
{
if
(!
child
.
getChildren
().
isEmpty
()
&&
child
.
isExpanded
())
{
visibleFeatures
+=
countVisibleNodes
(
child
);
}
}
return
visibleFeatures
;
}
private
void
buildTreeFromList
(
List
<?
extends
CityObject
>
cos
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
int
chunk
=
chunkCounter
.
get
();
for
(
int
i
=
chunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
chunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
cos
.
size
();
i
++)
{
CityObject
co
=
cos
.
get
(
i
);
CityObjectNode
node
=
new
CityObjectNode
(
co
);
TreeItem
<
Renderable
>
nodeItem
=
new
TreeItem
<>(
node
);
nodeItem
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
nodeItem
);
createGeometryNodes
(
co
,
nodeItem
);
}
}
private
<
T
extends
CityObject
>
void
buildTreeFromListWithProducer
(
List
<
T
>
cos
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
,
Function
<
T
,
Renderable
>
nodeProducer
)
{
int
chunk
=
chunkCounter
.
get
();
for
(
int
i
=
chunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
chunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
cos
.
size
();
i
++)
{
T
co
=
cos
.
get
(
i
);
Renderable
node
=
nodeProducer
.
apply
(
co
);
TreeItem
<
Renderable
>
nodeItem
=
new
TreeItem
<>(
node
);
nodeItem
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
nodeItem
);
createGeometryNodes
(
co
,
nodeItem
);
}
}
private
void
clearTrees
()
{
mainWindow
.
getBuildingsView
().
setRoot
(
null
);
mainWindow
.
getVegetationView
().
setRoot
(
null
);
mainWindow
.
getTransportationView
().
setRoot
(
null
);
mainWindow
.
getBridgeView
().
setRoot
(
null
);
mainWindow
.
getWaterView
().
setRoot
(
null
);
mainWindow
.
getTerrainView
().
setRoot
(
null
);
mainWindow
.
getCityFurnitureView
().
setRoot
(
null
);
}
private
void
resetFeatureChunks
()
{
buildingChunkNr
.
set
(
0
);
vegetationChunkNr
.
set
(
0
);
transportationChunkNr
.
set
(
0
);
bridgeChunkNr
.
set
(
0
);
waterChunkNr
.
set
(
0
);
landChunkNr
.
set
(
0
);
cityFurnitureChunkNr
.
set
(
0
);
otherObjectsChunkNr
.
set
(
0
);
}
private
void
buildLand
(
CityDoctorModel
model
)
{
if
(
model
.
getLand
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
landView
=
mainWindow
.
getTerrainView
();
TreeItem
<
Renderable
>
landRoot
=
new
TreeItem
<>(
new
AllTerrainNode
(
model
.
getLand
()));
landRoot
.
setExpanded
(
true
);
landView
.
setRoot
(
landRoot
);
buildLandFromList
(
model
.
getLand
(),
landView
.
getRoot
());
addMoreButtonIfNecessary
(
model
.
getLand
(),
landView
,
landRoot
,
landChunkNr
);
}
private
void
buildLandFromList
(
List
<
CityObject
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
landChunk
=
landChunkNr
.
get
();
for
(
int
i
=
landChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
landChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
CityObject
land
=
list
.
get
(
i
);
Renderable
node
;
if
(
land
instanceof
ReliefObject
relief
)
{
node
=
new
ReliefNode
(
relief
);
}
else
if
(
land
instanceof
TinObject
tin
)
{
node
=
new
TinNode
(
tin
);
}
else
{
node
=
new
LandUseNode
((
LandObject
)
land
);
}
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
land
,
item
);
if
(
land
instanceof
ReliefObject
relief
)
{
createTinNodes
(
relief
,
item
);
}
}
}
private
void
createTinNodes
(
ReliefObject
relief
,
TreeItem
<
Renderable
>
item
)
{
if
(
relief
.
getComponents
().
isEmpty
())
{
return
;
}
AllTinNode
allTinText
=
new
AllTinNode
(
relief
.
getComponents
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allTinText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
TinObject
tin
:
relief
.
getComponents
())
{
TinNode
tinNode
=
new
TinNode
(
tin
);
TreeItem
<
Renderable
>
tinNodeItem
=
new
TreeItem
<>(
tinNode
);
tinNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
tinNodeItem
);
createGeometryNodes
(
tin
,
tinNodeItem
);
}
}
private
void
buildCityFurniture
(
CityDoctorModel
model
)
{
if
(
model
.
getCityFurniture
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
cityFurnitureView
=
mainWindow
.
getCityFurnitureView
();
TreeItem
<
Renderable
>
cityFurnitureRoot
=
new
TreeItem
<>(
new
AllCityFurnitureNode
(
model
.
getCityFurniture
()));
cityFurnitureRoot
.
setExpanded
(
true
);
cityFurnitureView
.
setRoot
(
cityFurnitureRoot
);
buildTreeFromList
(
model
.
getCityFurniture
(),
cityFurnitureView
.
getRoot
(),
cityFurnitureChunkNr
);
addMoreButtonIfNecessary
(
model
.
getCityFurniture
(),
cityFurnitureView
,
cityFurnitureRoot
,
cityFurnitureChunkNr
);
}
private
void
buildOtherCityObjects
(
CityDoctorModel
model
)
{
if
(
model
.
getGenericCityObjects
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
otherObjectsView
=
mainWindow
.
getOtherObjectsView
();
TreeItem
<
Renderable
>
otherObjectsRoot
=
new
TreeItem
<>(
new
AllOtherObjectsNode
(
model
.
getGenericCityObjects
()));
otherObjectsRoot
.
setExpanded
(
true
);
otherObjectsView
.
setRoot
(
otherObjectsRoot
);
buildTreeFromList
(
model
.
getGenericCityObjects
(),
otherObjectsView
.
getRoot
(),
otherObjectsChunkNr
);
addMoreButtonIfNecessary
(
model
.
getGenericCityObjects
(),
otherObjectsView
,
otherObjectsRoot
,
otherObjectsChunkNr
);
}
private
void
buildWater
(
CityDoctorModel
model
)
{
if
(
model
.
getWater
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
waterView
=
mainWindow
.
getWaterView
();
TreeItem
<
Renderable
>
waterRoot
=
new
TreeItem
<>(
new
AllWaterNode
(
model
.
getWater
()));
waterRoot
.
setExpanded
(
true
);
waterView
.
setRoot
(
waterRoot
);
buildTreeFromList
(
model
.
getWater
(),
waterView
.
getRoot
(),
waterChunkNr
);
addMoreButtonIfNecessary
(
model
.
getWater
(),
waterView
,
waterRoot
,
waterChunkNr
);
}
private
void
buildBridges
(
CityDoctorModel
model
)
{
if
(
model
.
getBridges
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
bridgeView
=
mainWindow
.
getBridgeView
();
TreeItem
<
Renderable
>
bridgeRoot
=
new
TreeItem
<>(
new
AllBridgesNode
(
model
.
getBridges
()));
bridgeRoot
.
setExpanded
(
true
);
bridgeView
.
setRoot
(
bridgeRoot
);
buildBridgeTreeFromList
(
model
.
getBridges
(),
bridgeView
.
getRoot
());
addMoreButtonIfNecessary
(
model
.
getBridges
(),
bridgeView
,
bridgeRoot
,
bridgeChunkNr
);
}
private
void
buildTransportation
(
List
<
TransportationObject
>
trans
)
{
if
(
trans
.
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
transView
=
mainWindow
.
getTransportationView
();
TreeItem
<
Renderable
>
transRoot
=
new
TreeItem
<>(
new
AllTransportationNode
(
model
.
getTransportation
()));
transRoot
.
setExpanded
(
true
);
transView
.
setRoot
(
transRoot
);
buildTreeFromList
(
trans
,
transView
.
getRoot
(),
transportationChunkNr
);
addMoreButtonIfNecessary
(
trans
,
transView
,
transRoot
,
transportationChunkNr
);
}
private
void
buildVegetation
(
List
<
Vegetation
>
veg
)
{
if
(
veg
.
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
vegetationsView
=
mainWindow
.
getVegetationView
();
TreeItem
<
Renderable
>
vegRoot
=
new
TreeItem
<>(
new
AllVegetationNode
(
model
.
getVegetation
()));
vegRoot
.
setExpanded
(
true
);
vegetationsView
.
setRoot
(
vegRoot
);
buildTreeFromListWithProducer
(
veg
,
vegetationsView
.
getRoot
(),
vegetationChunkNr
,
VegetationNode:
:
new
);
addMoreButtonIfNecessary
(
veg
,
vegetationsView
,
vegRoot
,
vegetationChunkNr
);
}
private
void
addMoreButtonIfNecessary
(
List
<?
extends
CityObject
>
list
,
TreeView
<
Renderable
>
view
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
Runnable
run
=
new
Runnable
()
{
public
void
run
()
{
// 29 is the height of one item
int
numberOfDisplayedItems
=
(
int
)
(
view
.
getHeight
()
/
29
);
int
selectedIndex
=
view
.
getSelectionModel
().
getSelectedIndex
();
// remove button node
root
.
getChildren
().
remove
(
root
.
getChildren
().
size
()
-
1
);
chunkCounter
.
incrementAndGet
();
int
visibleFeatures
=
countVisibleNodes
(
view
);
buildTreeFromList
(
list
,
root
,
chunkCounter
);
updateTree
(
root
);
if
(
selectedIndex
>=
0
)
{
view
.
getSelectionModel
().
select
(
selectedIndex
);
}
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
this
)));
}
view
.
scrollTo
(
visibleFeatures
-
numberOfDisplayedItems
+
1
);
}
};
// add button for expansion
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
run
)));
}
}
private
void
buildBuildings
(
CityDoctorModel
model
)
{
if
(
model
.
getBuildings
().
isEmpty
())
{
return
;
}
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
new
TreeItem
<>(
new
AllBuildingsNode
(
model
.
getBuildings
()));
root
.
setExpanded
(
true
);
buildBuildingTreeFromList
(
model
.
getBuildings
(),
root
);
addMoreButtonToBuildingsIfNecessary
(
model
.
getBuildings
(),
buildingsView
,
root
,
buildingChunkNr
);
buildingsView
.
setRoot
(
root
);
}
private
void
addMoreButtonToBuildingsIfNecessary
(
List
<
Building
>
list
,
TreeView
<
Renderable
>
view
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
Runnable
run
=
new
Runnable
()
{
public
void
run
()
{
// 29 is the height of one item
int
numberOfDisplayedItems
=
(
int
)
(
view
.
getHeight
()
/
29
);
int
selectedIndex
=
view
.
getSelectionModel
().
getSelectedIndex
();
// remove button node
root
.
getChildren
().
remove
(
root
.
getChildren
().
size
()
-
1
);
chunkCounter
.
getAndIncrement
();
int
visibleFeatures
=
countVisibleNodes
(
view
);
buildBuildingTreeFromList
(
list
,
root
);
updateTree
(
root
);
if
(
selectedIndex
>=
0
)
{
view
.
getSelectionModel
().
select
(
selectedIndex
);
}
if
((
chunkCounter
.
get
()
+
1
)
*
MAX_FEATURES_PER_CHUNK
<
list
.
size
())
{
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
this
)));
}
view
.
scrollTo
(
visibleFeatures
-
numberOfDisplayedItems
+
1
);
}
};
// add button for expansion
root
.
getChildren
().
add
(
new
TreeItem
<>(
new
ButtonRenderable
(
run
)));
}
}
private
static
int
countVisibleNodes
(
TreeView
<
Renderable
>
view
)
{
return
countVisibleNodes
(
view
.
getRoot
())
+
1
;
}
private
static
int
countVisibleNodes
(
TreeItem
<
Renderable
>
root
)
{
int
visibleFeatures
=
root
.
getChildren
().
size
();
for
(
TreeItem
<
Renderable
>
child
:
root
.
getChildren
())
{
if
(!
child
.
getChildren
().
isEmpty
()
&&
child
.
isExpanded
())
{
visibleFeatures
+=
countVisibleNodes
(
child
);
}
}
return
visibleFeatures
;
}
private
void
buildTreeFromList
(
List
<?
extends
CityObject
>
cos
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
)
{
int
chunk
=
chunkCounter
.
get
();
for
(
int
i
=
chunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
chunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
cos
.
size
();
i
++)
{
CityObject
co
=
cos
.
get
(
i
);
CityObjectNode
node
=
new
CityObjectNode
(
co
);
TreeItem
<
Renderable
>
nodeItem
=
new
TreeItem
<>(
node
);
nodeItem
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
nodeItem
);
createGeometryNodes
(
co
,
nodeItem
);
}
}
private
<
T
extends
CityObject
>
void
buildTreeFromListWithProducer
(
List
<
T
>
cos
,
TreeItem
<
Renderable
>
root
,
AtomicInteger
chunkCounter
,
Function
<
T
,
Renderable
>
nodeProducer
)
{
int
chunk
=
chunkCounter
.
get
();
for
(
int
i
=
chunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
chunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
cos
.
size
();
i
++)
{
T
co
=
cos
.
get
(
i
);
Renderable
node
=
nodeProducer
.
apply
(
co
);
TreeItem
<
Renderable
>
nodeItem
=
new
TreeItem
<>(
node
);
nodeItem
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
nodeItem
);
createGeometryNodes
(
co
,
nodeItem
);
}
}
private
void
clearTrees
()
{
mainWindow
.
getBuildingsView
().
setRoot
(
null
);
mainWindow
.
getVegetationView
().
setRoot
(
null
);
mainWindow
.
getTransportationView
().
setRoot
(
null
);
mainWindow
.
getBridgeView
().
setRoot
(
null
);
mainWindow
.
getWaterView
().
setRoot
(
null
);
mainWindow
.
getTerrainView
().
setRoot
(
null
);
mainWindow
.
getCityFurnitureView
().
setRoot
(
null
);
mainWindow
.
getOtherObjectsView
().
setRoot
(
null
);
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getGlobalErrorsView
().
getItems
().
clear
();
clearGeometryTrees
();
}
private
void
clearGeometryTrees
()
{
highlightController
.
clearHighlights
();
mainWindow
.
getPolygonsView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getEdgeView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getVertexView
().
getRoot
().
getChildren
().
clear
();
}
private
void
buildBuildingTreeFromList
(
List
<
Building
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
buildingChunk
=
buildingChunkNr
.
get
();
for
(
int
i
=
buildingChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
buildingChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
Building
b
=
list
.
get
(
i
);
BuildingNode
node
=
new
BuildingNode
(
b
);
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
b
,
item
);
createBoundarySurfaceNodes
(
b
.
getBoundarySurfaces
(),
item
);
createBuildingInstallationNodes
(
b
,
item
);
createBuildingRoomNodes
(
b
,
item
);
createBuildingFurnitureNodes
(
b
,
item
);
createBuildingPartNodes
(
b
,
item
);
}
}
private
void
buildBridgeTreeFromList
(
List
<
BridgeObject
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
bridgeChunk
=
bridgeChunkNr
.
get
();
for
(
int
i
=
bridgeChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
bridgeChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
BridgeObject
bridge
=
list
.
get
(
i
);
BridgeNode
node
=
new
BridgeNode
(
bridge
);
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
bridge
,
item
);
createBoundarySurfaceNodes
(
bridge
.
getBoundarySurfaces
(),
item
);
createBridgeInstallationNodes
(
bridge
,
item
);
createConstructiveElementsNodes
(
bridge
,
item
);
createBridgePartNodes
(
bridge
,
item
);
}
}
private
void
createBridgeInstallationNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
root
)
{
createInstallationNodes
(
bridge
.
getBridgeInstallations
(),
root
);
}
private
void
createConstructiveElementsNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
item
)
{
if
(
bridge
.
getConstructiveElements
().
isEmpty
())
{
return
;
}
AllBridgeConstructiveElementsNode
allBceNode
=
new
AllBridgeConstructiveElementsNode
(
bridge
.
getConstructiveElements
());
TreeItem
<
Renderable
>
allBceNodeTextItem
=
new
TreeItem
<>(
allBceNode
);
item
.
getChildren
().
add
(
allBceNodeTextItem
);
for
(
BridgeConstructiveElement
bce
:
bridge
.
getConstructiveElements
())
{
BridgeConstructiveElementNode
bceNode
=
new
BridgeConstructiveElementNode
(
bce
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bceNode
);
bpNodeItem
.
setExpanded
(
true
);
allBceNodeTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bce
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bce
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createBridgePartNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
item
)
{
if
(
bridge
.
getParts
().
isEmpty
())
{
return
;
}
AllBridgePartsNode
allBpsText
=
new
AllBridgePartsNode
(
bridge
.
getParts
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBpsText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
BridgeObject
bp
:
bridge
.
getParts
())
{
BridgeNode
bpNode
=
new
BridgeNode
(
bp
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bpNode
);
bpNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bp
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bp
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createBuildingInstallationNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createInstallationNodes
(
ab
.
getBuildingInstallations
(),
root
);
}
private
void
createInstallationNodes
(
List
<
Installation
>
installations
,
TreeItem
<
Renderable
>
root
)
{
if
(
installations
.
isEmpty
())
{
return
;
}
AllInstallationsNode
allBiNode
=
new
AllInstallationsNode
(
installations
);
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBiNode
);
root
.
getChildren
().
add
(
allBpsTextItem
);
for
(
Installation
bi
:
installations
)
{
InstallationNode
biNode
=
new
InstallationNode
(
bi
);
TreeItem
<
Renderable
>
biItem
=
new
TreeItem
<>(
biNode
);
biItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
biItem
);
createGeometryNodes
(
bi
,
biItem
);
createBoundarySurfaceNodes
(
bi
.
getBoundarySurfaces
(),
biItem
);
}
}
private
void
createBuildingRoomNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createRoomNodes
(
ab
.
getBuildingRooms
(),
root
);
}
private
void
createRoomNodes
(
List
<?
extends
AbstractRoom
>
rooms
,
TreeItem
<
Renderable
>
root
)
{
if
(
rooms
.
isEmpty
())
{
return
;
}
AllRoomsNode
allRoNode
=
new
AllRoomsNode
(
rooms
);
TreeItem
<
Renderable
>
allRoNodeTextItem
=
new
TreeItem
<>(
allRoNode
);
root
.
getChildren
().
add
(
allRoNodeTextItem
);
for
(
AbstractRoom
room
:
rooms
)
{
RoomNode
roomNode
=
new
RoomNode
(
room
);
TreeItem
<
Renderable
>
roomNodeTextItem
=
new
TreeItem
<>(
roomNode
);
roomNodeTextItem
.
setExpanded
(
true
);
allRoNodeTextItem
.
getChildren
().
add
(
roomNodeTextItem
);
createGeometryNodes
(
room
,
roomNodeTextItem
);
createBoundarySurfaceNodes
(
room
.
getBoundarySurfaceList
(),
roomNodeTextItem
);
}
}
private
void
createBuildingFurnitureNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createFurnitureNodes
(
ab
.
getBuildingRoomFurnitureList
(),
root
);
}
private
void
createFurnitureNodes
(
List
<?
extends
AbstractFurniture
>
furniture
,
TreeItem
<
Renderable
>
root
){
if
(
furniture
.
isEmpty
())
{
return
;
}
AllFurnitureNode
allFnNode
=
new
AllFurnitureNode
(
furniture
);
TreeItem
<
Renderable
>
allFnNodeTextItem
=
new
TreeItem
<>(
allFnNode
);
root
.
getChildren
().
add
(
allFnNodeTextItem
);
for
(
AbstractFurniture
fn
:
furniture
)
{
FurnitureNode
fnNode
=
new
FurnitureNode
(
fn
);
TreeItem
<
Renderable
>
fnNodeTextItem
=
new
TreeItem
<>(
fnNode
);
fnNodeTextItem
.
setExpanded
(
true
);
allFnNodeTextItem
.
getChildren
().
add
(
fnNodeTextItem
);
createGeometryNodes
(
fn
,
fnNodeTextItem
);
createBoundarySurfaceNodes
(
fn
.
getBoundarySurfaceList
(),
fnNodeTextItem
);
}
}
private
void
createBoundarySurfaceNodes
(
List
<
BoundarySurface
>
bsList
,
TreeItem
<
Renderable
>
root
)
{
if
(
bsList
.
isEmpty
())
{
return
;
}
AllBoundarySurfacesNode
allBsText
=
new
AllBoundarySurfacesNode
(
bsList
);
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBsText
);
root
.
getChildren
().
add
(
allBpsTextItem
);
allBpsTextItem
.
getChildren
().
add
(
new
TreeItem
<>());
allBpsTextItem
.
expandedProperty
().
addListener
((
obs
,
old
,
newV
)
->
{
if
(
Boolean
.
TRUE
.
equals
(
newV
)
&&
allBpsTextItem
.
getChildren
().
size
()
==
1
)
{
Platform
.
runLater
(()
->
{
allBpsTextItem
.
getChildren
().
clear
();
for
(
BoundarySurface
bs
:
bsList
)
{
BoundarySurfaceNode
bsText
=
new
BoundarySurfaceNode
(
bs
);
TreeItem
<
Renderable
>
bsTextItem
=
new
TreeItem
<>(
bsText
);
bsTextItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bsTextItem
);
createGeometryNodes
(
bs
,
bsTextItem
);
createOpeningNodes
(
bs
.
getOpenings
(),
bsTextItem
);
}
updateTree
(
allBpsTextItem
);
});
}
});
}
private
void
createOpeningNodes
(
List
<
Opening
>
openings
,
TreeItem
<
Renderable
>
root
)
{
if
(
openings
==
null
||
openings
.
isEmpty
())
{
return
;
}
AllOpeningsNode
allOpeningsNode
=
new
AllOpeningsNode
(
openings
);
TreeItem
<
Renderable
>
allOpeningsItem
=
new
TreeItem
<>(
allOpeningsNode
);
for
(
Opening
o
:
openings
)
{
OpeningNode
openingNode
=
new
OpeningNode
(
o
);
TreeItem
<
Renderable
>
openingsItem
=
new
TreeItem
<>(
openingNode
);
allOpeningsItem
.
getChildren
().
add
(
openingsItem
);
}
root
.
getChildren
().
add
(
allOpeningsItem
);
}
private
void
createBuildingPartNodes
(
Building
ab
,
TreeItem
<
Renderable
>
item
)
{
if
(
ab
.
getBuildingParts
().
isEmpty
())
{
return
;
}
AllBuildingPartsNode
allBpsText
=
new
AllBuildingPartsNode
(
ab
.
getBuildingParts
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBpsText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
BuildingPart
bp
:
ab
.
getBuildingParts
())
{
BuildingPartNode
bpNode
=
new
BuildingPartNode
(
bp
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bpNode
);
bpNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bp
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bp
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createGeometryNodes
(
CityObject
co
,
TreeItem
<
Renderable
>
item
)
{
for
(
Geometry
geom
:
co
.
getGeometries
())
{
GeometryNode
geomNode
=
new
GeometryNode
(
geom
);
TreeItem
<
Renderable
>
geomItem
=
new
TreeItem
<>(
geomNode
);
item
.
getChildren
().
add
(
geomItem
);
}
}
public
void
startChecks
(
ValidationConfiguration
config
,
ProgressListener
l
)
{
if
(
model
==
null
)
{
logger
.
warn
(
Localization
.
getText
(
"CityDoctorController.noDatamodel"
));
return
;
}
if
(
sourceFile
==
null
)
{
logger
.
warn
(
Localization
.
getText
(
"CityDoctorController.noSourceFile"
));
return
;
}
try
{
Platform
.
runLater
(()
->
{
mainWindow
.
getCheckButton
().
setDisable
(
true
);
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getGlobalErrorsView
().
getItems
().
clear
();
});
config
.
setNumberOfRoundingPlacesInGlobalParameters
(
currentConfig
.
getNumberOfRoundingPlaces
());
config
.
setParserConfig
(
currentConfig
);
currentChecker
=
new
Checker
(
config
,
model
);
currentChecker
.
runChecks
(
l
);
Platform
.
runLater
(()
->
{
// apply check results to tree views
updateFeatureTrees
();
updateTree
(
mainWindow
.
getPolygonsView
().
getRoot
());
for
(
CheckError
e
:
model
.
getGlobalErrors
())
{
if
(
e
instanceof
SchematronError
se
)
{
mainWindow
.
getGlobalErrorsView
().
getItems
().
add
(
se
.
getErrorIdString
());
}
}
renderer
.
refresh
();
mainWindow
.
getWriteReportButton
().
setDisable
(
false
);
});
}
finally
{
Platform
.
runLater
(()
->
mainWindow
.
getCheckButton
().
setDisable
(
false
));
}
}
void
updateFeatureTrees
()
{
updateTree
(
mainWindow
.
getBuildingsView
().
getRoot
());
updateTree
(
mainWindow
.
getVegetationView
().
getRoot
());
updateTree
(
mainWindow
.
getBridgeView
().
getRoot
());
updateTree
(
mainWindow
.
getTerrainView
().
getRoot
());
updateTree
(
mainWindow
.
getCityFurnitureView
().
getRoot
());
updateTree
(
mainWindow
.
getTransportationView
().
getRoot
());
updateTree
(
mainWindow
.
getWaterView
().
getRoot
());
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getGlobalErrorsView
().
getItems
().
clear
();
clearGeometryTrees
();
}
private
void
clearGeometryTrees
()
{
highlightController
.
clearHighlights
();
mainWindow
.
getPolygonsView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getEdgeView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getVertexView
().
getRoot
().
getChildren
().
clear
();
}
private
void
buildBuildingTreeFromList
(
List
<
Building
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
buildingChunk
=
buildingChunkNr
.
get
();
for
(
int
i
=
buildingChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
buildingChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
Building
b
=
list
.
get
(
i
);
BuildingNode
node
=
new
BuildingNode
(
b
);
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
b
,
item
);
createBoundarySurfaceNodes
(
b
.
getBoundarySurfaces
(),
item
);
createBuildingInstallationNodes
(
b
,
item
);
createBuildingRoomNodes
(
b
,
item
);
createBuildingFurnitureNodes
(
b
,
item
);
createBuildingPartNodes
(
b
,
item
);
}
}
private
void
buildBridgeTreeFromList
(
List
<
BridgeObject
>
list
,
TreeItem
<
Renderable
>
root
)
{
int
bridgeChunk
=
bridgeChunkNr
.
get
();
for
(
int
i
=
bridgeChunk
*
MAX_FEATURES_PER_CHUNK
;
i
<
(
bridgeChunk
+
1
)
*
MAX_FEATURES_PER_CHUNK
&&
i
<
list
.
size
();
i
++)
{
BridgeObject
bridge
=
list
.
get
(
i
);
BridgeNode
node
=
new
BridgeNode
(
bridge
);
TreeItem
<
Renderable
>
item
=
new
TreeItem
<>(
node
);
item
.
setExpanded
(
true
);
root
.
getChildren
().
add
(
item
);
createGeometryNodes
(
bridge
,
item
);
createBoundarySurfaceNodes
(
bridge
.
getBoundarySurfaces
(),
item
);
createBridgeInstallationNodes
(
bridge
,
item
);
createConstructiveElementsNodes
(
bridge
,
item
);
createBridgePartNodes
(
bridge
,
item
);
}
}
private
void
createBridgeInstallationNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
root
)
{
createInstallationNodes
(
bridge
.
getBridgeInstallations
(),
root
);
}
private
void
createConstructiveElementsNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
item
)
{
if
(
bridge
.
getConstructiveElements
().
isEmpty
())
{
return
;
}
AllBridgeConstructiveElementsNode
allBceNode
=
new
AllBridgeConstructiveElementsNode
(
bridge
.
getConstructiveElements
());
TreeItem
<
Renderable
>
allBceNodeTextItem
=
new
TreeItem
<>(
allBceNode
);
item
.
getChildren
().
add
(
allBceNodeTextItem
);
for
(
BridgeConstructiveElement
bce
:
bridge
.
getConstructiveElements
())
{
BridgeConstructiveElementNode
bceNode
=
new
BridgeConstructiveElementNode
(
bce
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bceNode
);
bpNodeItem
.
setExpanded
(
true
);
allBceNodeTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bce
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bce
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createBridgePartNodes
(
BridgeObject
bridge
,
TreeItem
<
Renderable
>
item
)
{
if
(
bridge
.
getParts
().
isEmpty
())
{
return
;
}
AllBridgePartsNode
allBpsText
=
new
AllBridgePartsNode
(
bridge
.
getParts
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBpsText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
BridgeObject
bp
:
bridge
.
getParts
())
{
BridgeNode
bpNode
=
new
BridgeNode
(
bp
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bpNode
);
bpNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bp
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bp
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createBuildingInstallationNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createInstallationNodes
(
ab
.
getBuildingInstallations
(),
root
);
}
private
void
createInstallationNodes
(
List
<
Installation
>
installations
,
TreeItem
<
Renderable
>
root
)
{
if
(
installations
.
isEmpty
())
{
return
;
}
AllInstallationsNode
allBiNode
=
new
AllInstallationsNode
(
installations
);
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBiNode
);
root
.
getChildren
().
add
(
allBpsTextItem
);
for
(
Installation
bi
:
installations
)
{
InstallationNode
biNode
=
new
InstallationNode
(
bi
);
TreeItem
<
Renderable
>
biItem
=
new
TreeItem
<>(
biNode
);
biItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
biItem
);
createGeometryNodes
(
bi
,
biItem
);
createBoundarySurfaceNodes
(
bi
.
getBoundarySurfaces
(),
biItem
);
}
}
private
void
createBuildingRoomNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createRoomNodes
(
ab
.
getBuildingRooms
(),
root
);
}
private
void
createRoomNodes
(
List
<?
extends
AbstractRoom
>
rooms
,
TreeItem
<
Renderable
>
root
)
{
if
(
rooms
.
isEmpty
())
{
return
;
}
AllRoomsNode
allRoNode
=
new
AllRoomsNode
(
rooms
);
TreeItem
<
Renderable
>
allRoNodeTextItem
=
new
TreeItem
<>(
allRoNode
);
root
.
getChildren
().
add
(
allRoNodeTextItem
);
for
(
AbstractRoom
room
:
rooms
)
{
RoomNode
roomNode
=
new
RoomNode
(
room
);
TreeItem
<
Renderable
>
roomNodeTextItem
=
new
TreeItem
<>(
roomNode
);
roomNodeTextItem
.
setExpanded
(
true
);
allRoNodeTextItem
.
getChildren
().
add
(
roomNodeTextItem
);
createGeometryNodes
(
room
,
roomNodeTextItem
);
createBoundarySurfaceNodes
(
room
.
getBoundarySurfaceList
(),
roomNodeTextItem
);
}
}
private
void
createBuildingFurnitureNodes
(
Building
ab
,
TreeItem
<
Renderable
>
root
)
{
createFurnitureNodes
(
ab
.
getBuildingRoomFurnitureList
(),
root
);
}
private
void
createFurnitureNodes
(
List
<?
extends
AbstractFurniture
>
furniture
,
TreeItem
<
Renderable
>
root
)
{
if
(
furniture
.
isEmpty
())
{
return
;
}
AllFurnitureNode
allFnNode
=
new
AllFurnitureNode
(
furniture
);
TreeItem
<
Renderable
>
allFnNodeTextItem
=
new
TreeItem
<>(
allFnNode
);
root
.
getChildren
().
add
(
allFnNodeTextItem
);
for
(
AbstractFurniture
fn
:
furniture
)
{
FurnitureNode
fnNode
=
new
FurnitureNode
(
fn
);
TreeItem
<
Renderable
>
fnNodeTextItem
=
new
TreeItem
<>(
fnNode
);
fnNodeTextItem
.
setExpanded
(
true
);
allFnNodeTextItem
.
getChildren
().
add
(
fnNodeTextItem
);
createGeometryNodes
(
fn
,
fnNodeTextItem
);
createBoundarySurfaceNodes
(
fn
.
getBoundarySurfaceList
(),
fnNodeTextItem
);
}
}
private
void
createBoundarySurfaceNodes
(
List
<
BoundarySurface
>
bsList
,
TreeItem
<
Renderable
>
root
)
{
if
(
bsList
.
isEmpty
())
{
return
;
}
AllBoundarySurfacesNode
allBsText
=
new
AllBoundarySurfacesNode
(
bsList
);
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBsText
);
root
.
getChildren
().
add
(
allBpsTextItem
);
allBpsTextItem
.
getChildren
().
add
(
new
TreeItem
<>());
allBpsTextItem
.
expandedProperty
().
addListener
((
obs
,
old
,
newV
)
->
{
if
(
Boolean
.
TRUE
.
equals
(
newV
)
&&
allBpsTextItem
.
getChildren
().
size
()
==
1
)
{
Platform
.
runLater
(()
->
{
allBpsTextItem
.
getChildren
().
clear
();
for
(
BoundarySurface
bs
:
bsList
)
{
BoundarySurfaceNode
bsText
=
new
BoundarySurfaceNode
(
bs
);
TreeItem
<
Renderable
>
bsTextItem
=
new
TreeItem
<>(
bsText
);
bsTextItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bsTextItem
);
createGeometryNodes
(
bs
,
bsTextItem
);
createOpeningNodes
(
bs
.
getOpenings
(),
bsTextItem
);
}
updateTree
(
allBpsTextItem
);
});
}
});
}
private
void
createOpeningNodes
(
List
<
Opening
>
openings
,
TreeItem
<
Renderable
>
root
)
{
if
(
openings
==
null
||
openings
.
isEmpty
())
{
return
;
}
AllOpeningsNode
allOpeningsNode
=
new
AllOpeningsNode
(
openings
);
TreeItem
<
Renderable
>
allOpeningsItem
=
new
TreeItem
<>(
allOpeningsNode
);
for
(
Opening
o
:
openings
)
{
OpeningNode
openingNode
=
new
OpeningNode
(
o
);
TreeItem
<
Renderable
>
openingsItem
=
new
TreeItem
<>(
openingNode
);
allOpeningsItem
.
getChildren
().
add
(
openingsItem
);
}
root
.
getChildren
().
add
(
allOpeningsItem
);
}
private
void
createBuildingPartNodes
(
Building
ab
,
TreeItem
<
Renderable
>
item
)
{
if
(
ab
.
getBuildingParts
().
isEmpty
())
{
return
;
}
AllBuildingPartsNode
allBpsText
=
new
AllBuildingPartsNode
(
ab
.
getBuildingParts
());
TreeItem
<
Renderable
>
allBpsTextItem
=
new
TreeItem
<>(
allBpsText
);
item
.
getChildren
().
add
(
allBpsTextItem
);
for
(
BuildingPart
bp
:
ab
.
getBuildingParts
())
{
BuildingPartNode
bpNode
=
new
BuildingPartNode
(
bp
);
TreeItem
<
Renderable
>
bpNodeItem
=
new
TreeItem
<>(
bpNode
);
bpNodeItem
.
setExpanded
(
true
);
allBpsTextItem
.
getChildren
().
add
(
bpNodeItem
);
createGeometryNodes
(
bp
,
bpNodeItem
);
createBoundarySurfaceNodes
(
bp
.
getBoundarySurfaces
(),
bpNodeItem
);
}
}
private
void
createGeometryNodes
(
CityObject
co
,
TreeItem
<
Renderable
>
item
)
{
for
(
Geometry
geom
:
co
.
getGeometries
())
{
GeometryNode
geomNode
=
new
GeometryNode
(
geom
);
TreeItem
<
Renderable
>
geomItem
=
new
TreeItem
<>(
geomNode
);
item
.
getChildren
().
add
(
geomItem
);
}
}
public
void
startChecks
(
ValidationConfiguration
config
,
ProgressListener
l
)
{
if
(
model
==
null
)
{
logger
.
warn
(
Localization
.
getText
(
"CityDoctorController.noDatamodel"
));
return
;
}
if
(
sourceFile
==
null
)
{
logger
.
warn
(
Localization
.
getText
(
"CityDoctorController.noSourceFile"
));
return
;
}
try
{
Platform
.
runLater
(()
->
{
mainWindow
.
getCheckButton
().
setDisable
(
true
);
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getGlobalErrorsView
().
getItems
().
clear
();
});
config
.
setNumberOfRoundingPlacesInGlobalParameters
(
currentConfig
.
getNumberOfRoundingPlaces
());
config
.
setParserConfig
(
currentConfig
);
currentChecker
=
new
Checker
(
config
,
model
);
currentChecker
.
runChecks
(
l
);
Platform
.
runLater
(()
->
{
// apply check results to tree views
updateFeatureTrees
();
updateTree
(
mainWindow
.
getPolygonsView
().
getRoot
());
for
(
CheckError
e
:
model
.
getGlobalErrors
())
{
if
(
e
instanceof
SchematronError
se
)
{
mainWindow
.
getGlobalErrorsView
().
getItems
().
add
(
se
.
getErrorIdString
());
}
}
renderer
.
refresh
();
mainWindow
.
getWriteReportButton
().
setDisable
(
false
);
});
}
finally
{
Platform
.
runLater
(()
->
mainWindow
.
getCheckButton
().
setDisable
(
false
));
}
}
void
updateFeatureTrees
()
{
updateTree
(
mainWindow
.
getBuildingsView
().
getRoot
());
updateTree
(
mainWindow
.
getVegetationView
().
getRoot
());
updateTree
(
mainWindow
.
getBridgeView
().
getRoot
());
updateTree
(
mainWindow
.
getTerrainView
().
getRoot
());
updateTree
(
mainWindow
.
getCityFurnitureView
().
getRoot
());
updateTree
(
mainWindow
.
getTransportationView
().
getRoot
());
updateTree
(
mainWindow
.
getWaterView
().
getRoot
());
updateTree
(
mainWindow
.
getOtherObjectsView
().
getRoot
());
renderer
.
updateErrors
();
}
private
void
updateTree
(
TreeItem
<
Renderable
>
root
)
{
if
(
root
==
null
)
{
return
;
}
for
(
TreeItem
<
Renderable
>
item
:
root
.
getChildren
())
{
updateItem
(
item
);
}
}
private
void
updateItem
(
TreeItem
<
Renderable
>
item
)
{
if
(
item
.
getValue
()
==
null
)
{
return
;
}
item
.
getValue
().
refreshTextColor
();
for
(
TreeItem
<
Renderable
>
child
:
item
.
getChildren
())
{
updateItem
(
child
);
}
}
public
void
writePdfReport
(
File
pdfFile
)
{
if
(
currentChecker
==
null
)
{
return
;
}
currentChecker
.
writePdfReport
(
pdfFile
.
getAbsolutePath
());
}
public
void
writeXmlReport
(
File
xmlFile
)
{
if
(
currentChecker
==
null
)
{
return
;
}
currentChecker
.
writeXmlReport
(
xmlFile
.
getAbsolutePath
());
}
private
Map
<
ErrorId
,
ErrorStat
>
getErrorStats
()
{
Map
<
ErrorId
,
ErrorStat
>
stats
=
new
HashMap
<>();
addErrorStats
(
stats
,
model
.
getBridges
());
addErrorStats
(
stats
,
model
.
getBuildings
());
addErrorStats
(
stats
,
model
.
getLand
());
addErrorStats
(
stats
,
model
.
getTransportation
());
addErrorStats
(
stats
,
model
.
getVegetation
());
addErrorStats
(
stats
,
model
.
getWater
());
renderer
.
updateErrors
();
}
private
void
updateTree
(
TreeItem
<
Renderable
>
root
)
{
if
(
root
==
null
)
{
return
;
}
for
(
TreeItem
<
Renderable
>
item
:
root
.
getChildren
())
{
updateItem
(
item
);
}
}
private
void
updateItem
(
TreeItem
<
Renderable
>
item
)
{
if
(
item
.
getValue
()
==
null
)
{
return
;
}
item
.
getValue
().
refreshTextColor
();
for
(
TreeItem
<
Renderable
>
child
:
item
.
getChildren
())
{
updateItem
(
child
);
}
}
public
void
writePdfReport
(
File
pdfFile
)
{
if
(
currentChecker
==
null
)
{
return
;
}
currentChecker
.
writePdfReport
(
pdfFile
.
getAbsolutePath
());
}
public
void
writeXmlReport
(
File
xmlFile
)
{
if
(
currentChecker
==
null
)
{
return
;
}
currentChecker
.
writeXmlReport
(
xmlFile
.
getAbsolutePath
());
}
private
Map
<
ErrorId
,
ErrorStat
>
getErrorStats
()
{
Map
<
ErrorId
,
ErrorStat
>
stats
=
new
HashMap
<>();
addErrorStats
(
stats
,
model
.
getBridges
());
addErrorStats
(
stats
,
model
.
getBuildings
());
addErrorStats
(
stats
,
model
.
getLand
());
addErrorStats
(
stats
,
model
.
getTransportation
());
addErrorStats
(
stats
,
model
.
getVegetation
());
addErrorStats
(
stats
,
model
.
getWater
());
addErrorStats
(
stats
,
model
.
getCityFurniture
());
addErrorStats
(
stats
,
model
.
getGenericCityObjects
());
return
stats
;
}
private
void
addErrorStats
(
Map
<
ErrorId
,
ErrorStat
>
stats
,
List
<?
extends
CityObject
>
cos
)
{
List
<
CheckError
>
errors
=
new
ArrayList
<>();
for
(
CityObject
co
:
cos
)
{
co
.
collectContainedErrors
(
errors
);
}
Set
<
CheckError
>
filteredErrors
=
new
HashSet
<>(
errors
);
for
(
CheckError
error
:
filteredErrors
)
{
ErrorStat
stat
=
stats
.
computeIfAbsent
(
error
.
getErrorId
(),
ErrorStat:
:
new
);
stat
.
incrementCount
();
}
}
public
void
export
(
Building
b
)
{
if
(
model
==
null
)
{
return
;
}
CityDoctorModel
newModel
=
new
CityDoctorModel
(
model
.
getParserConfig
(),
model
.
getFile
());
newModel
.
setCityModel
(
new
CityModel
());
newModel
.
addBuilding
(
b
);
FileChooser
fc
=
new
FileChooser
();
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"CityGML"
,
"*.gml"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"OFF - Object File Format"
,
"*.off"
));
File
dir
=
new
File
(
Settings
.
get
(
Settings
.
LAST_OPEN_FOLDER
,
""
));
if
(
dir
.
exists
()
&&
dir
.
isDirectory
())
{
fc
.
setInitialDirectory
(
dir
);
}
else
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
""
);
}
File
f
=
fc
.
showSaveDialog
(
mainWindow
.
getMainStage
());
if
(
f
!=
null
)
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
f
.
getParent
());
try
{
newModel
.
saveAs
(
f
.
getAbsolutePath
(),
true
);
}
catch
(
CityDoctorWriteException
e
)
{
logger
.
error
(
e
);
}
}
}
public
void
showWorld
()
{
if
(
model
!=
null
)
{
renderer
.
render
(
model
);
}
}
public
void
storeModel
(
File
f
,
boolean
saveQualityAde
)
throws
CityDoctorWriteException
{
if
(
model
==
null
)
{
return
;
}
model
.
saveAs
(
f
.
getAbsolutePath
(),
saveQualityAde
);
}
public
void
searchFeature
(
String
searchString
,
FeatureType
selectedTab
)
{
if
(
model
==
null
||
searchString
==
null
||
searchString
.
trim
().
isEmpty
())
{
return
;
}
mainWindow
.
unselectEverything
();
resetFeatureChunks
();
if
(
selectedTab
==
FeatureType
.
BUILDING
)
{
List
<
Building
>
foundBuildings
=
filterFeatures
(
searchString
,
model
.
getBuildings
());
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
buildingsView
.
getRoot
();
root
.
getChildren
().
clear
();
buildBuildingTreeFromList
(
foundBuildings
,
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
foundBuildings
,
buildingsView
,
root
,
buildingChunkNr
);
}
else
{
TreeView
<
Renderable
>
view
;
List
<?
extends
CityObject
>
cos
;
AtomicInteger
chunkCounter
;
switch
(
selectedTab
)
{
case
VEGETATION:
view
=
mainWindow
.
getVegetationView
();
cos
=
filterFeatures
(
searchString
,
model
.
getVegetation
());
chunkCounter
=
vegetationChunkNr
;
break
;
case
BRIDGE:
view
=
mainWindow
.
getBridgeView
();
cos
=
filterFeatures
(
searchString
,
model
.
getBridges
());
chunkCounter
=
bridgeChunkNr
;
break
;
case
TRANSPORTATION:
view
=
mainWindow
.
getTransportationView
();
cos
=
filterFeatures
(
searchString
,
model
.
getTransportation
());
chunkCounter
=
transportationChunkNr
;
break
;
case
WATER:
view
=
mainWindow
.
getWaterView
();
cos
=
filterFeatures
(
searchString
,
model
.
getWater
());
chunkCounter
=
waterChunkNr
;
break
;
case
LAND:
view
=
mainWindow
.
getTerrainView
();
cos
=
filterFeatures
(
searchString
,
model
.
getLand
());
chunkCounter
=
landChunkNr
;
break
;
case
CITY_FURNITURE:
view
=
mainWindow
.
getCityFurnitureView
();
cos
=
filterFeatures
(
searchString
,
model
.
getCityFurniture
());
chunkCounter
=
cityFurnitureChunkNr
;
break
;
case
GENERIC_CITY_OBJECT:
view
=
mainWindow
.
getOtherObjectsView
();
cos
=
filterFeatures
(
searchString
,
model
.
getGenericCityObjects
());
chunkCounter
=
otherObjectsChunkNr
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab"
);
}
TreeItem
<
Renderable
>
root
=
view
.
getRoot
();
root
.
getChildren
().
clear
();
buildTreeFromList
(
cos
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
cos
,
view
,
root
,
chunkCounter
);
}
}
private
<
T
extends
CityObject
>
List
<
T
>
filterFeatures
(
String
searchString
,
List
<
T
>
features
)
{
List
<
T
>
foundFeatures
=
new
ArrayList
<>();
for
(
T
t
:
features
)
{
if
(
t
.
getGmlId
().
getGmlString
().
contains
(
searchString
))
{
foundFeatures
.
add
(
t
);
}
}
return
foundFeatures
;
}
public
void
resetSearch
(
FeatureType
selectedTab
)
{
if
(
model
==
null
)
{
return
;
}
resetFeatureChunks
();
if
(
selectedTab
==
FeatureType
.
BUILDING
)
{
// buildings are handled differently, because of surface and building
// installations
TreeItem
<
Renderable
>
root
=
mainWindow
.
getBuildingsView
().
getRoot
();
if
(
root
!=
null
)
{
root
.
getChildren
().
clear
();
buildBuildingTreeFromList
(
model
.
getBuildings
(),
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
model
.
getBuildings
(),
mainWindow
.
getBuildingsView
(),
root
,
buildingChunkNr
);
}
}
else
{
TreeView
<
Renderable
>
view
;
List
<?
extends
CityObject
>
cos
;
AtomicInteger
chunkCounter
;
switch
(
selectedTab
)
{
case
VEGETATION:
view
=
mainWindow
.
getVegetationView
();
cos
=
model
.
getVegetation
();
chunkCounter
=
vegetationChunkNr
;
break
;
case
BRIDGE:
view
=
mainWindow
.
getBridgeView
();
cos
=
model
.
getBridges
();
chunkCounter
=
bridgeChunkNr
;
break
;
case
TRANSPORTATION:
view
=
mainWindow
.
getTransportationView
();
cos
=
model
.
getTransportation
();
chunkCounter
=
transportationChunkNr
;
break
;
case
WATER:
view
=
mainWindow
.
getWaterView
();
cos
=
model
.
getWater
();
chunkCounter
=
waterChunkNr
;
break
;
case
LAND:
view
=
mainWindow
.
getTerrainView
();
cos
=
model
.
getLand
();
chunkCounter
=
landChunkNr
;
break
;
case
CITY_FURNITURE:
view
=
mainWindow
.
getCityFurnitureView
();
cos
=
model
.
getCityFurniture
();
chunkCounter
=
cityFurnitureChunkNr
;
break
;
case
GENERIC_CITY_OBJECT:
view
=
mainWindow
.
getOtherObjectsView
();
cos
=
model
.
getGenericCityObjects
();
chunkCounter
=
otherObjectsChunkNr
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab"
);
}
TreeItem
<
Renderable
>
root
=
view
.
getRoot
();
root
.
getChildren
().
clear
();
buildTreeFromList
(
cos
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
cos
,
view
,
root
,
chunkCounter
);
}
}
public
Series
<
String
,
Number
>
createErrorSeries
()
{
Series
<
String
,
Number
>
series
=
new
Series
<>();
if
(
model
==
null
)
{
return
series
;
}
Map
<
ErrorId
,
ErrorStat
>
errorStats
=
getErrorStats
();
for
(
ErrorStat
es
:
errorStats
.
values
())
{
series
.
getData
().
add
(
new
Data
<>(
es
.
getErrorId
().
toString
(),
es
.
getCount
()));
}
return
series
;
}
public
String
getFileName
()
{
return
model
.
getFileName
();
}
public
void
fillTreeViewWithErrorBuildings
()
{
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
buildingsView
.
getRoot
();
if
(
model
==
null
)
{
return
;
}
if
(
root
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
root
.
getChildren
().
clear
();
List
<
Building
>
errorBuildings
=
new
ArrayList
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
if
(
b
.
containsAnyError
())
{
errorBuildings
.
add
(
b
);
}
}
resetFeatureChunks
();
buildBuildingTreeFromList
(
errorBuildings
,
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
errorBuildings
,
buildingsView
,
root
,
buildingChunkNr
);
}
public
void
fillTreeViewWithErrorVegetation
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getVegetationView
(),
model
.
getVegetation
(),
vegetationChunkNr
);
}
public
void
fillTreeViewWithErrorBridges
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getBridgeView
(),
model
.
getBridges
(),
bridgeChunkNr
);
}
public
void
fillTreeViewWithErrorLand
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getTerrainView
(),
model
.
getLand
(),
landChunkNr
);
}
public
void
fillTreeViewWithErrorCityFurniture
(){
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getCityFurnitureView
(),
model
.
getCityFurniture
(),
cityFurnitureChunkNr
);
}
public
void
fillTreeViewWithErrorOtherObjects
(){
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getOtherObjectsView
(),
model
.
getGenericCityObjects
(),
otherObjectsChunkNr
);
}
public
void
fillTreeViewWithErrorTransportation
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getTransportationView
(),
model
.
getTransportation
(),
transportationChunkNr
);
}
public
void
fillTreeViewWithErrorWater
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getWaterView
(),
model
.
getWater
(),
waterChunkNr
);
}
private
void
fillTreeViewWithErrorCityObjects
(
TreeView
<
Renderable
>
treeView
,
List
<?
extends
CityObject
>
objects
,
AtomicInteger
chunkCounter
)
{
TreeItem
<
Renderable
>
root
=
treeView
.
getRoot
();
if
(
root
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
root
.
getChildren
().
clear
();
List
<
CityObject
>
errorObjects
=
new
ArrayList
<>();
for
(
CityObject
co
:
objects
)
{
if
(
co
.
containsAnyError
())
{
errorObjects
.
add
(
co
);
}
}
buildTreeFromList
(
errorObjects
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
errorObjects
,
treeView
,
root
,
chunkCounter
);
}
public
void
fillTreeViewFromFeatures
(
FeatureType
selectedTab
)
{
if
(
model
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
switch
(
selectedTab
)
{
case
BUILDING:
buildBuildings
(
model
);
updateTree
(
mainWindow
.
getBuildingsView
().
getRoot
());
break
;
case
VEGETATION:
buildVegetation
(
model
.
getVegetation
());
updateTree
(
mainWindow
.
getVegetationView
().
getRoot
());
break
;
case
BRIDGE:
buildBridges
(
model
);
updateTree
(
mainWindow
.
getBridgeView
().
getRoot
());
break
;
case
LAND:
buildLand
(
model
);
updateTree
(
mainWindow
.
getTerrainView
().
getRoot
());
break
;
case
TRANSPORTATION:
buildTransportation
(
model
.
getTransportation
());
updateTree
(
mainWindow
.
getTransportationView
().
getRoot
());
break
;
case
WATER:
buildWater
(
model
);
updateTree
(
mainWindow
.
getWaterView
().
getRoot
());
break
;
case
CITY_FURNITURE:
buildCityFurniture
(
model
);
updateTree
(
mainWindow
.
getCityFurnitureView
().
getRoot
());
break
;
return
stats
;
}
private
void
addErrorStats
(
Map
<
ErrorId
,
ErrorStat
>
stats
,
List
<?
extends
CityObject
>
cos
)
{
List
<
CheckError
>
errors
=
new
ArrayList
<>();
for
(
CityObject
co
:
cos
)
{
co
.
collectContainedErrors
(
errors
);
}
Set
<
CheckError
>
filteredErrors
=
new
HashSet
<>(
errors
);
for
(
CheckError
error
:
filteredErrors
)
{
ErrorStat
stat
=
stats
.
computeIfAbsent
(
error
.
getErrorId
(),
ErrorStat:
:
new
);
stat
.
incrementCount
();
}
}
public
void
export
(
Building
b
)
{
if
(
model
==
null
)
{
return
;
}
CityDoctorModel
newModel
=
new
CityDoctorModel
(
model
.
getParserConfig
(),
model
.
getFile
());
newModel
.
setCityModel
(
new
CityModel
());
newModel
.
addBuilding
(
b
);
FileChooser
fc
=
new
FileChooser
();
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"CityGML"
,
"*.gml"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"OFF - Object File Format"
,
"*.off"
));
File
dir
=
new
File
(
Settings
.
get
(
Settings
.
LAST_OPEN_FOLDER
,
""
));
if
(
dir
.
exists
()
&&
dir
.
isDirectory
())
{
fc
.
setInitialDirectory
(
dir
);
}
else
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
""
);
}
File
f
=
fc
.
showSaveDialog
(
mainWindow
.
getMainStage
());
if
(
f
!=
null
)
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
f
.
getParent
());
try
{
newModel
.
saveAs
(
f
.
getAbsolutePath
(),
true
);
}
catch
(
CityDoctorWriteException
e
)
{
logger
.
error
(
e
);
}
}
}
public
void
showWorld
()
{
if
(
model
!=
null
)
{
renderer
.
render
(
model
);
}
}
public
void
storeModel
(
File
f
,
boolean
saveQualityAde
)
throws
CityDoctorWriteException
{
if
(
model
==
null
)
{
return
;
}
model
.
saveAs
(
f
.
getAbsolutePath
(),
saveQualityAde
);
}
public
void
searchFeature
(
String
searchString
,
FeatureType
selectedTab
)
{
if
(
model
==
null
||
searchString
==
null
||
searchString
.
trim
().
isEmpty
())
{
return
;
}
mainWindow
.
unselectEverything
();
resetFeatureChunks
();
if
(
selectedTab
==
FeatureType
.
BUILDING
)
{
List
<
Building
>
foundBuildings
=
filterFeatures
(
searchString
,
model
.
getBuildings
());
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
buildingsView
.
getRoot
();
root
.
getChildren
().
clear
();
buildBuildingTreeFromList
(
foundBuildings
,
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
foundBuildings
,
buildingsView
,
root
,
buildingChunkNr
);
}
else
{
TreeView
<
Renderable
>
view
;
List
<?
extends
CityObject
>
cos
;
AtomicInteger
chunkCounter
;
switch
(
selectedTab
)
{
case
VEGETATION:
view
=
mainWindow
.
getVegetationView
();
cos
=
filterFeatures
(
searchString
,
model
.
getVegetation
());
chunkCounter
=
vegetationChunkNr
;
break
;
case
BRIDGE:
view
=
mainWindow
.
getBridgeView
();
cos
=
filterFeatures
(
searchString
,
model
.
getBridges
());
chunkCounter
=
bridgeChunkNr
;
break
;
case
TRANSPORTATION:
view
=
mainWindow
.
getTransportationView
();
cos
=
filterFeatures
(
searchString
,
model
.
getTransportation
());
chunkCounter
=
transportationChunkNr
;
break
;
case
WATER:
view
=
mainWindow
.
getWaterView
();
cos
=
filterFeatures
(
searchString
,
model
.
getWater
());
chunkCounter
=
waterChunkNr
;
break
;
case
LAND:
view
=
mainWindow
.
getTerrainView
();
cos
=
filterFeatures
(
searchString
,
model
.
getLand
());
chunkCounter
=
landChunkNr
;
break
;
case
CITY_FURNITURE:
view
=
mainWindow
.
getCityFurnitureView
();
cos
=
filterFeatures
(
searchString
,
model
.
getCityFurniture
());
chunkCounter
=
cityFurnitureChunkNr
;
break
;
case
GENERIC_CITY_OBJECT:
view
=
mainWindow
.
getOtherObjectsView
();
cos
=
filterFeatures
(
searchString
,
model
.
getGenericCityObjects
());
chunkCounter
=
otherObjectsChunkNr
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab"
);
}
TreeItem
<
Renderable
>
root
=
view
.
getRoot
();
root
.
getChildren
().
clear
();
buildTreeFromList
(
cos
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
cos
,
view
,
root
,
chunkCounter
);
}
}
private
<
T
extends
CityObject
>
List
<
T
>
filterFeatures
(
String
searchString
,
List
<
T
>
features
)
{
List
<
T
>
foundFeatures
=
new
ArrayList
<>();
for
(
T
t
:
features
)
{
if
(
t
.
getGmlId
().
getGmlString
().
contains
(
searchString
))
{
foundFeatures
.
add
(
t
);
}
}
return
foundFeatures
;
}
public
void
resetSearch
(
FeatureType
selectedTab
)
{
if
(
model
==
null
)
{
return
;
}
resetFeatureChunks
();
if
(
selectedTab
==
FeatureType
.
BUILDING
)
{
// buildings are handled differently, because of surface and building
// installations
TreeItem
<
Renderable
>
root
=
mainWindow
.
getBuildingsView
().
getRoot
();
if
(
root
!=
null
)
{
root
.
getChildren
().
clear
();
buildBuildingTreeFromList
(
model
.
getBuildings
(),
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
model
.
getBuildings
(),
mainWindow
.
getBuildingsView
(),
root
,
buildingChunkNr
);
}
}
else
{
TreeView
<
Renderable
>
view
;
List
<?
extends
CityObject
>
cos
;
AtomicInteger
chunkCounter
;
switch
(
selectedTab
)
{
case
VEGETATION:
view
=
mainWindow
.
getVegetationView
();
cos
=
model
.
getVegetation
();
chunkCounter
=
vegetationChunkNr
;
break
;
case
BRIDGE:
view
=
mainWindow
.
getBridgeView
();
cos
=
model
.
getBridges
();
chunkCounter
=
bridgeChunkNr
;
break
;
case
TRANSPORTATION:
view
=
mainWindow
.
getTransportationView
();
cos
=
model
.
getTransportation
();
chunkCounter
=
transportationChunkNr
;
break
;
case
WATER:
view
=
mainWindow
.
getWaterView
();
cos
=
model
.
getWater
();
chunkCounter
=
waterChunkNr
;
break
;
case
LAND:
view
=
mainWindow
.
getTerrainView
();
cos
=
model
.
getLand
();
chunkCounter
=
landChunkNr
;
break
;
case
CITY_FURNITURE:
view
=
mainWindow
.
getCityFurnitureView
();
cos
=
model
.
getCityFurniture
();
chunkCounter
=
cityFurnitureChunkNr
;
break
;
case
GENERIC_CITY_OBJECT:
view
=
mainWindow
.
getOtherObjectsView
();
cos
=
model
.
getGenericCityObjects
();
chunkCounter
=
otherObjectsChunkNr
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab"
);
}
TreeItem
<
Renderable
>
root
=
view
.
getRoot
();
root
.
getChildren
().
clear
();
buildTreeFromList
(
cos
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
cos
,
view
,
root
,
chunkCounter
);
}
}
public
Series
<
String
,
Number
>
createErrorSeries
()
{
Series
<
String
,
Number
>
series
=
new
Series
<>();
if
(
model
==
null
)
{
return
series
;
}
Map
<
ErrorId
,
ErrorStat
>
errorStats
=
getErrorStats
();
for
(
ErrorStat
es
:
errorStats
.
values
())
{
series
.
getData
().
add
(
new
Data
<>(
es
.
getErrorId
().
toString
(),
es
.
getCount
()));
}
return
series
;
}
public
String
getFileName
()
{
return
model
.
getFileName
();
}
public
void
fillTreeViewWithErrorBuildings
()
{
TreeView
<
Renderable
>
buildingsView
=
mainWindow
.
getBuildingsView
();
TreeItem
<
Renderable
>
root
=
buildingsView
.
getRoot
();
if
(
model
==
null
)
{
return
;
}
if
(
root
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
root
.
getChildren
().
clear
();
List
<
Building
>
errorBuildings
=
new
ArrayList
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
if
(
b
.
containsAnyError
())
{
errorBuildings
.
add
(
b
);
}
}
resetFeatureChunks
();
buildBuildingTreeFromList
(
errorBuildings
,
root
);
updateTree
(
root
);
addMoreButtonToBuildingsIfNecessary
(
errorBuildings
,
buildingsView
,
root
,
buildingChunkNr
);
}
public
void
fillTreeViewWithErrorVegetation
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getVegetationView
(),
model
.
getVegetation
(),
vegetationChunkNr
);
}
public
void
fillTreeViewWithErrorBridges
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getBridgeView
(),
model
.
getBridges
(),
bridgeChunkNr
);
}
public
void
fillTreeViewWithErrorLand
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getTerrainView
(),
model
.
getLand
(),
landChunkNr
);
}
public
void
fillTreeViewWithErrorCityFurniture
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getCityFurnitureView
(),
model
.
getCityFurniture
(),
cityFurnitureChunkNr
);
}
public
void
fillTreeViewWithErrorOtherObjects
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getOtherObjectsView
(),
model
.
getGenericCityObjects
(),
otherObjectsChunkNr
);
}
public
void
fillTreeViewWithErrorTransportation
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getTransportationView
(),
model
.
getTransportation
(),
transportationChunkNr
);
}
public
void
fillTreeViewWithErrorWater
()
{
if
(
model
==
null
)
{
return
;
}
fillTreeViewWithErrorCityObjects
(
mainWindow
.
getWaterView
(),
model
.
getWater
(),
waterChunkNr
);
}
private
void
fillTreeViewWithErrorCityObjects
(
TreeView
<
Renderable
>
treeView
,
List
<?
extends
CityObject
>
objects
,
AtomicInteger
chunkCounter
)
{
TreeItem
<
Renderable
>
root
=
treeView
.
getRoot
();
if
(
root
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
root
.
getChildren
().
clear
();
List
<
CityObject
>
errorObjects
=
new
ArrayList
<>();
for
(
CityObject
co
:
objects
)
{
if
(
co
.
containsAnyError
())
{
errorObjects
.
add
(
co
);
}
}
buildTreeFromList
(
errorObjects
,
root
,
chunkCounter
);
updateTree
(
root
);
addMoreButtonIfNecessary
(
errorObjects
,
treeView
,
root
,
chunkCounter
);
}
public
void
fillTreeViewFromFeatures
(
FeatureType
selectedTab
)
{
if
(
model
==
null
)
{
return
;
}
mainWindow
.
resetSearchBar
();
switch
(
selectedTab
)
{
case
BUILDING:
buildBuildings
(
model
);
updateTree
(
mainWindow
.
getBuildingsView
().
getRoot
());
break
;
case
VEGETATION:
buildVegetation
(
model
.
getVegetation
());
updateTree
(
mainWindow
.
getVegetationView
().
getRoot
());
break
;
case
BRIDGE:
buildBridges
(
model
);
updateTree
(
mainWindow
.
getBridgeView
().
getRoot
());
break
;
case
LAND:
buildLand
(
model
);
updateTree
(
mainWindow
.
getTerrainView
().
getRoot
());
break
;
case
TRANSPORTATION:
buildTransportation
(
model
.
getTransportation
());
updateTree
(
mainWindow
.
getTransportationView
().
getRoot
());
break
;
case
WATER:
buildWater
(
model
);
updateTree
(
mainWindow
.
getWaterView
().
getRoot
());
break
;
case
CITY_FURNITURE:
buildCityFurniture
(
model
);
updateTree
(
mainWindow
.
getCityFurnitureView
().
getRoot
());
break
;
case
GENERIC_CITY_OBJECT:
buildOtherCityObjects
(
model
);
updateTree
(
mainWindow
.
getOtherObjectsView
().
getRoot
());
break
;
default
:
throw
new
IllegalStateException
();
}
}
public
CityDoctorModel
getModel
()
{
return
model
;
}
public
void
showView
(
View
v
)
{
v
.
fireOnShowEvent
(
model
,
currentChecker
,
mainWindow
);
}
public
void
askAndSave
()
{
boolean
saveWithQualityAde
=
true
;
if
(
model
.
isValidated
())
{
ButtonType
yesBtn
=
ButtonType
.
YES
;
ButtonType
noBtn
=
ButtonType
.
NO
;
Dialog
<
ButtonType
>
dialog
=
new
Dialog
<>();
dialog
.
setTitle
(
"Save with QualityADE?"
);
dialog
.
setContentText
(
"Save with QualityADE information?"
);
dialog
.
getDialogPane
().
getButtonTypes
().
add
(
yesBtn
);
dialog
.
getDialogPane
().
getButtonTypes
().
add
(
noBtn
);
Optional
<
ButtonType
>
result
=
dialog
.
showAndWait
();
if
(
result
.
isPresent
()
&&
result
.
get
()
==
ButtonType
.
NO
)
{
saveWithQualityAde
=
false
;
}
}
FileChooser
fc
=
new
FileChooser
();
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"CityGML"
,
"*.gml"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"OFF - Object File Format"
,
"*.off"
));
File
dir
=
new
File
(
Settings
.
get
(
Settings
.
LAST_OPEN_FOLDER
,
""
));
if
(
dir
.
exists
()
&&
dir
.
isDirectory
())
{
fc
.
setInitialDirectory
(
dir
);
}
else
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
""
);
}
File
f
=
fc
.
showSaveDialog
(
mainWindow
.
getMainStage
());
if
(
f
!=
null
)
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
f
.
getParent
());
try
{
storeModel
(
f
,
saveWithQualityAde
);
}
catch
(
CityDoctorWriteException
e
)
{
mainWindow
.
showExceptionDialog
(
e
);
}
}
}
public
void
delete
(
TreeItem
<
Renderable
>
selectedItem
)
{
if
(
model
==
null
)
{
return
;
}
Renderable
render
=
selectedItem
.
getValue
();
if
(
render
instanceof
BuildingNode
node
)
{
model
.
getBuildings
().
remove
(
node
.
getBuilding
());
mainWindow
.
getBuildingsView
().
getRoot
().
getChildren
().
remove
(
selectedItem
);
}
}
public
void
errorFilterIndexChanged
(
Number
newV
)
{
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
mainWindow
.
unselectEverything
();
if
(
newV
.
intValue
()
==
0
)
{
fillTreeViewFromFeatures
(
mainWindow
.
getSelectedTab
());
}
else
if
(
newV
.
intValue
()
==
1
)
{
switch
(
mainWindow
.
getSelectedTab
())
{
case
BUILDING:
fillTreeViewWithErrorBuildings
();
break
;
case
VEGETATION:
fillTreeViewWithErrorVegetation
();
break
;
case
BRIDGE:
fillTreeViewWithErrorBridges
();
break
;
case
LAND:
fillTreeViewWithErrorLand
();
break
;
case
TRANSPORTATION:
fillTreeViewWithErrorTransportation
();
break
;
case
WATER:
fillTreeViewWithErrorWater
();
break
;
case
CITY_FURNITURE:
fillTreeViewWithErrorCityFurniture
();
break
;
default
:
throw
new
IllegalStateException
();
}
}
public
CityDoctorModel
getModel
()
{
return
model
;
}
public
void
showView
(
View
v
)
{
v
.
fireOnShowEvent
(
model
,
currentChecker
,
mainWindow
);
}
public
void
askAndSave
()
{
boolean
saveWithQualityAde
=
true
;
if
(
model
.
isValidated
())
{
ButtonType
yesBtn
=
ButtonType
.
YES
;
ButtonType
noBtn
=
ButtonType
.
NO
;
Dialog
<
ButtonType
>
dialog
=
new
Dialog
<>();
dialog
.
setTitle
(
"Save with QualityADE?"
);
dialog
.
setContentText
(
"Save with QualityADE information?"
);
dialog
.
getDialogPane
().
getButtonTypes
().
add
(
yesBtn
);
dialog
.
getDialogPane
().
getButtonTypes
().
add
(
noBtn
);
Optional
<
ButtonType
>
result
=
dialog
.
showAndWait
();
if
(
result
.
isPresent
()
&&
result
.
get
()
==
ButtonType
.
NO
)
{
saveWithQualityAde
=
false
;
}
}
FileChooser
fc
=
new
FileChooser
();
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"CityGML"
,
"*.gml"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"OFF - Object File Format"
,
"*.off"
));
File
dir
=
new
File
(
Settings
.
get
(
Settings
.
LAST_OPEN_FOLDER
,
""
));
if
(
dir
.
exists
()
&&
dir
.
isDirectory
())
{
fc
.
setInitialDirectory
(
dir
);
}
else
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
""
);
}
File
f
=
fc
.
showSaveDialog
(
mainWindow
.
getMainStage
());
if
(
f
!=
null
)
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
f
.
getParent
());
try
{
storeModel
(
f
,
saveWithQualityAde
);
}
catch
(
CityDoctorWriteException
e
)
{
mainWindow
.
showExceptionDialog
(
e
);
}
}
}
public
void
delete
(
TreeItem
<
Renderable
>
selectedItem
)
{
if
(
model
==
null
)
{
return
;
}
Renderable
render
=
selectedItem
.
getValue
();
if
(
render
instanceof
BuildingNode
node
)
{
model
.
getBuildings
().
remove
(
node
.
getBuilding
());
mainWindow
.
getBuildingsView
().
getRoot
().
getChildren
().
remove
(
selectedItem
);
}
}
public
void
errorFilterIndexChanged
(
Number
newV
)
{
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
mainWindow
.
unselectEverything
();
if
(
newV
.
intValue
()
==
0
)
{
fillTreeViewFromFeatures
(
mainWindow
.
getSelectedTab
());
}
else
if
(
newV
.
intValue
()
==
1
)
{
switch
(
mainWindow
.
getSelectedTab
())
{
case
BUILDING:
fillTreeViewWithErrorBuildings
();
break
;
case
VEGETATION:
fillTreeViewWithErrorVegetation
();
break
;
case
BRIDGE:
fillTreeViewWithErrorBridges
();
break
;
case
LAND:
fillTreeViewWithErrorLand
();
break
;
case
TRANSPORTATION:
fillTreeViewWithErrorTransportation
();
break
;
case
WATER:
fillTreeViewWithErrorWater
();
break
;
case
CITY_FURNITURE:
fillTreeViewWithErrorCityFurniture
();
break
;
case
GENERIC_CITY_OBJECT:
fillTreeViewWithErrorOtherObjects
();
break
;
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab: "
+
mainWindow
.
getSelectedTab
());
}
}
else
{
throw
new
IllegalStateException
(
"Unknown filter index selected: "
+
newV
);
}
}
public
ParserConfiguration
getCurrentConfig
()
{
return
currentConfig
;
}
default
:
throw
new
IllegalStateException
(
"Unknown selected feature tab: "
+
mainWindow
.
getSelectedTab
());
}
}
else
{
throw
new
IllegalStateException
(
"Unknown filter index selected: "
+
newV
);
}
}
public
ParserConfiguration
getCurrentConfig
()
{
return
currentConfig
;
}
}
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java
View file @
9e161477
...
...
@@ -80,937 +80,937 @@ import javafx.stage.Stage;
public
class
MainWindow
extends
Application
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
MainWindow
.
class
);
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
MainWindow
.
class
);
private
static
final
double
CAMERA_TRANSLATE_Z
=
-
100.0
;
private
static
final
double
CAMERA_INITIAL_X_ANGLE
=
20.0
;
private
static
final
double
CAMERA_INITIAL_Y_ANGLE
=
120.0
;
private
static
final
double
CAMERA_TRANSLATE_Z
=
-
100.0
;
private
static
final
double
CAMERA_INITIAL_X_ANGLE
=
20.0
;
private
static
final
double
CAMERA_INITIAL_Y_ANGLE
=
120.0
;
@FXML
private
TreeView
<
Renderable
>
buildingsView
;
@FXML
private
TreeView
<
Renderable
>
buildingsView
;
@FXML
private
TreeView
<
Renderable
>
vegetationView
;
@FXML
private
TreeView
<
Renderable
>
vegetationView
;
@FXML
private
TreeView
<
Renderable
>
transView
;
@FXML
private
TreeView
<
Renderable
>
transView
;
@FXML
private
TreeView
<
Renderable
>
bridgeView
;
@FXML
private
TreeView
<
Renderable
>
bridgeView
;
@FXML
private
TreeView
<
Renderable
>
waterView
;
@FXML
private
TreeView
<
Renderable
>
waterView
;
@FXML
private
TreeView
<
Renderable
>
terrainView
;
@FXML
private
TreeView
<
Renderable
>
terrainView
;
@FXML
private
TreeView
<
Renderable
>
cityFurnitureView
;
@FXML
private
TreeView
<
Renderable
>
cityFurnitureView
;
@FXML
TreeView
<
Renderable
>
otherObjectsView
;
@FXML
TreeView
<
Renderable
>
otherObjectsView
;
@FXML
private
TreeView
<
Renderable
>
polygonView
;
@FXML
private
TreeView
<
Renderable
>
polygonView
;
@FXML
private
TreeView
<
Renderable
>
edgeView
;
@FXML
private
TreeView
<
Renderable
>
edgeView
;
@FXML
private
TreeView
<
Renderable
>
vertexView
;
@FXML
private
TreeView
<
Renderable
>
vertexView
;
@FXML
private
Pane
meshView
;
@FXML
private
Pane
meshView
;
@FXML
private
SplitPane
mainContainer
;
@FXML
private
SplitPane
mainContainer
;
@FXML
private
TabPane
detailsTabPane
;
@FXML
private
TabPane
detailsTabPane
;
@FXML
private
TabPane
featurePane
;
@FXML
private
TabPane
featurePane
;
@FXML
private
TextField
searchField
;
@FXML
private
TextField
searchField
;
@FXML
private
TreeView
<
Renderable
>
errorView
;
@FXML
private
TreeView
<
Renderable
>
errorView
;
@FXML
private
Button
clearBtn
;
@FXML
private
Button
clearBtn
;
@FXML
private
Button
searchBtn
;
@FXML
private
Button
searchBtn
;
@FXML
private
ToggleButton
allButton
;
@FXML
private
ToggleButton
allButton
;
@FXML
private
ToggleButton
errorButton
;
@FXML
private
ToggleButton
errorButton
;
@FXML
private
ComboBox
<
String
>
showCityObjectsCombo
;
@FXML
private
ComboBox
<
String
>
showCityObjectsCombo
;
@FXML
private
HBox
viewPane
;
@FXML
private
HBox
viewPane
;
@FXML
private
ListView
<
String
>
globalErrorsView
;
@FXML
private
ListView
<
String
>
globalErrorsView
;
@FXML
private
BorderPane
mainPane
;
@FXML
private
BorderPane
mainPane
;
@FXML
private
HBox
viewButtonBox
;
@FXML
private
HBox
viewButtonBox
;
@FXML
private
ComboBox
<
Locale
>
languageSelector
;
@FXML
private
ComboBox
<
Locale
>
languageSelector
;
@FXML
private
Tab
buildingsTab
;
@FXML
private
Tab
buildingsTab
;
@FXML
private
Tab
vegetationTab
;
@FXML
private
Tab
vegetationTab
;
@FXML
private
Tab
transportationTab
;
@FXML
private
Tab
transportationTab
;
@FXML
private
Tab
bridgeTab
;
@FXML
private
Tab
bridgeTab
;
@FXML
private
Tab
waterTab
;
@FXML
private
Tab
waterTab
;
@FXML
private
Tab
terrainTab
;
@FXML
private
Tab
terrainTab
;
@FXML
private
Tab
cityFurnitureTab
;
@FXML
private
Tab
cityFurnitureTab
;
@FXML
private
Tab
otherObjectsTab
;
@FXML
private
Tab
otherObjectsTab
;
@FXML
private
Tab
errorsTab
;
@FXML
private
Tab
errorsTab
;
@FXML
private
Tab
polygonsTab
;
@FXML
private
Tab
polygonsTab
;
@FXML
private
Tab
edgesTab
;
@FXML
private
Tab
edgesTab
;
@FXML
private
Tab
verticesTab
;
@FXML
private
Tab
verticesTab
;
@FXML
private
Tab
logTab
;
@FXML
private
Tab
logTab
;
@FXML
private
Tab
globalErrorsTab
;
@FXML
private
Tab
globalErrorsTab
;
@FXML
private
Label
viewLabel
;
@FXML
private
Label
viewLabel
;
@FXML
private
Label
showLabel
;
@FXML
private
Label
showLabel
;
@FXML
private
Label
searchLabel
;
@FXML
private
Label
searchLabel
;
@FXML
private
Label
memoryLabel
;
@FXML
private
Label
memoryLabel
;
@FXML
private
ProgressBar
memoryBar
;
@FXML
private
ProgressBar
memoryBar
;
@FXML
private
Label
memoryConsumptionLabel
;
@FXML
private
Label
memoryConsumptionLabel
;
@FXML
private
Label
availableLabel
;
@FXML
private
Label
availableLabel
;
private
Group
meshGroup
;
private
Group
meshGroup
;
private
Group
world
;
private
PerspectiveCamera
camera
;
private
Rotate
cameraXRotation
=
new
Rotate
();
private
Rotate
cameraZRotation
=
new
Rotate
();
private
Group
world
;
private
PerspectiveCamera
camera
;
private
Rotate
cameraXRotation
=
new
Rotate
();
private
Rotate
cameraZRotation
=
new
Rotate
();
private
double
dragX
;
private
double
dragY
;
private
double
dragX
;
private
double
dragY
;
private
double
cameraXRot
=
CAMERA_INITIAL_X_ANGLE
;
private
double
cameraYRot
=
CAMERA_INITIAL_Y_ANGLE
;
private
double
translateZ
=
CAMERA_TRANSLATE_Z
;
private
double
[]
clickStart
=
new
double
[
2
];
private
double
cameraXRot
=
CAMERA_INITIAL_X_ANGLE
;
private
double
cameraYRot
=
CAMERA_INITIAL_Y_ANGLE
;
private
double
translateZ
=
CAMERA_TRANSLATE_Z
;
private
double
[]
clickStart
=
new
double
[
2
];
@FXML
private
TextArea
logArea
;
@FXML
private
ToolBar
viewBar
;
private
Stage
stage
;
private
ExceptionDialog
exceptionDialog
;
private
Renderer
renderer
;
private
CityDoctorController
controller
;
private
HighlightController
highlightController
;
private
FeatureType
selectedTab
=
FeatureType
.
BUILDING
;
private
MainToolBar
mainToolBar
;
private
SubScene
geomScene
;
private
static
boolean
loadFileAtStartup
=
false
;
private
static
String
inputFile
;
private
static
String
xmlOutput
;
private
static
String
pdfOutput
;
private
static
ValidationConfiguration
config
;
private
VertexClickHandler
clickHandler
;
private
ChangeListener
<
Number
>
filterChangeListener
;
public
static
void
main
(
String
[]
args
)
{
setLocaleFromSettings
();
ArgumentParser
argParser
=
new
ArgumentParser
(
args
);
inputFile
=
CityDoctorValidation
.
getInputFile
(
argParser
,
true
);
if
(
inputFile
!=
null
)
{
loadFileAtStartup
=
true
;
xmlOutput
=
CityDoctorValidation
.
getXmlOutput
(
argParser
);
pdfOutput
=
CityDoctorValidation
.
getPdfOutput
(
argParser
);
try
{
config
=
CityDoctorValidation
.
getValidationConfig
(
argParser
,
true
);
}
catch
(
FileNotFoundException
e
)
{
Platform
.
runLater
(()
->
{
List
<
String
>
configFiles
=
argParser
.
getValues
(
"config"
);
Alert
alert
=
new
Alert
(
AlertType
.
ERROR
);
alert
.
setContentText
(
Localization
.
getText
(
"MainWindow.missingConfig"
)
+
configFiles
);
alert
.
showAndWait
();
});
System
.
exit
(
4
);
}
}
Application
.
launch
(
args
);
}
private
static
void
setLocaleFromSettings
()
{
String
localeString
=
Settings
.
get
(
Settings
.
LANGUAGE
);
if
(
localeString
!=
null
)
{
try
{
Locale
loc
=
new
Locale
(
localeString
);
Locale
.
setDefault
(
loc
);
}
catch
(
Exception
e
)
{
logger
.
warn
(
"Could not set language to {}, using system language"
,
localeString
);
}
}
}
@Override
public
void
start
(
Stage
stage
)
throws
IOException
{
this
.
stage
=
stage
;
stage
.
getIcons
().
add
(
new
Image
(
MainWindow
.
class
.
getResourceAsStream
(
"icons/citydoctor_logo.png"
)));
FXMLLoader
loader
=
new
FXMLLoader
(
MainWindow
.
class
.
getResource
(
"MainWindow.fxml"
));
loader
.
setController
(
this
);
BorderPane
bp
=
loader
.
load
();
highlightController
=
new
HighlightController
(
world
);
renderer
=
new
Renderer
(
this
,
highlightController
);
clickHandler
=
new
VertexClickHandler
(
errorView
,
renderer
,
stage
);
controller
=
new
CityDoctorController
(
this
,
highlightController
,
renderer
);
mainToolBar
=
new
MainToolBar
(
stage
,
controller
,
featurePane
,
renderer
,
this
);
viewPane
.
getChildren
().
add
(
mainToolBar
.
getToolBar
());
HBox
.
setHgrow
(
mainToolBar
.
getToolBar
(),
Priority
.
ALWAYS
);
ValidationView
valView
=
new
ValidationView
(
this
,
controller
);
ViewRegistration
.
registerView
(
valView
);
setupViews
(
valView
);
createLanguageSelector
();
setLabelsInCorrectLanguage
();
Scene
scene
=
new
Scene
(
bp
,
1280
,
800
);
createDropTarget
(
scene
,
valView
);
String
version
=
Localization
.
getText
(
Localization
.
VERSION
);
stage
.
setTitle
(
"CityDoctor "
+
version
);
stage
.
setScene
(
scene
);
stage
.
show
();
checkForStartupLoading
();
memoryBar
.
setOnMouseClicked
(
me
->
System
.
gc
());
Timer
timer
=
new
Timer
(
true
);
// check memory every second
TimerTask
task
=
new
TimerTask
()
{
Runtime
runtime
=
Runtime
.
getRuntime
();
@Override
public
void
run
()
{
long
totalMemory
=
runtime
.
totalMemory
();
long
freeMemory
=
runtime
.
freeMemory
();
long
usedMemory
=
totalMemory
-
freeMemory
;
double
percentage
=
usedMemory
/
(
double
)
totalMemory
;
if
(
totalMemory
/
1024
/
1024
>=
1024
)
{
// gb
double
totalMemoryGb
=
totalMemory
/
(
1024
d
*
1024
d
*
1024
d
);
double
usedMemoryGb
=
usedMemory
/
(
1024
d
*
1024
d
*
1024
d
);
String
memoryString
=
String
.
format
(
"%.1f GB / %.1f GB"
,
usedMemoryGb
,
totalMemoryGb
);
Platform
.
runLater
(()
->
{
memoryConsumptionLabel
.
setText
(
memoryString
);
memoryBar
.
setProgress
(
percentage
);
});
}
else
if
(
totalMemory
/
1024
>=
1024
)
{
// mb
double
totalMemoryMb
=
totalMemory
/
(
1024
d
*
1024
d
);
double
usedMemoryMb
=
usedMemory
/
(
1024
d
*
1024
d
);
String
memoryString
=
String
.
format
(
"%.1f MB / %.1f MB"
,
usedMemoryMb
,
totalMemoryMb
);
Platform
.
runLater
(()
->
{
memoryConsumptionLabel
.
setText
(
memoryString
);
memoryBar
.
setProgress
(
percentage
);
});
}
}
};
timer
.
schedule
(
task
,
0
,
1000
);
}
private
void
createDropTarget
(
Scene
scene
,
ValidationView
valView
)
{
setDragOverInteraction
(
scene
,
valView
);
scene
.
setOnDragDropped
(
event
->
{
if
(
ViewRegistration
.
getCurrentActiveView
()
!=
valView
)
{
return
;
}
Dragboard
db
=
event
.
getDragboard
();
boolean
success
=
false
;
if
(
db
.
hasFiles
()
&&
db
.
getFiles
().
size
()
==
1
)
{
File
f
=
db
.
getFiles
().
get
(
0
);
Thread
t
=
new
Thread
(()
->
{
try
{
controller
.
loadCityGml
(
f
.
getAbsolutePath
(),
8
,
(
ProgressListener
)
null
,
false
);
}
catch
(
Exception
e
)
{
if
(
logger
.
isErrorEnabled
())
{
logger
.
error
(
Localization
.
getText
(
"OpenFileDialog.loadFailed"
),
e
);
}
Platform
.
runLater
(()
->
{
ExceptionDialog
exDialog
=
new
ExceptionDialog
();
exDialog
.
show
(
e
);
});
}
});
t
.
start
();
success
=
true
;
}
// let the source know whether the string was successfully transferred and used
event
.
setDropCompleted
(
success
);
event
.
consume
();
});
}
private
void
setDragOverInteraction
(
Scene
scene
,
ValidationView
valView
)
{
scene
.
setOnDragOver
(
event
->
{
if
(
ViewRegistration
.
getCurrentActiveView
()
!=
valView
)
{
return
;
}
if
(
event
.
getGestureSource
()
!=
scene
&&
event
.
getDragboard
().
hasFiles
()
&&
event
.
getDragboard
().
getFiles
().
size
()
==
1
)
{
// allow for both copying and moving, whatever user chooses
event
.
acceptTransferModes
(
TransferMode
.
LINK
);
}
event
.
consume
();
});
}
private
void
setLabelsInCorrectLanguage
()
{
buildingsTab
.
setText
(
Localization
.
getText
(
"MainWindow.buildingsTab"
));
vegetationTab
.
setText
(
Localization
.
getText
(
"MainWindow.vegetationTab"
));
transportationTab
.
setText
(
Localization
.
getText
(
"MainWindow.transportationTab"
));
bridgeTab
.
setText
(
Localization
.
getText
(
"MainWindow.bridgeTab"
));
waterTab
.
setText
(
Localization
.
getText
(
"MainWindow.waterTab"
));
terrainTab
.
setText
(
Localization
.
getText
(
"MainWindow.terrainTab"
));
cityFurnitureTab
.
setText
(
Localization
.
getText
(
"MainWindow.cityfurnitureTab"
));
otherObjectsTab
.
setText
(
Localization
.
getText
(
"MainWindow.otherObjectsTab"
));
viewLabel
.
setText
(
Localization
.
getText
(
"MainWindow.viewLabel"
));
showLabel
.
setText
(
Localization
.
getText
(
"MainWindow.showLabel"
));
searchLabel
.
setText
(
Localization
.
getText
(
"MainWindow.searchLabel"
));
searchBtn
.
setText
(
Localization
.
getText
(
"MainWindow.searchBtn"
));
clearBtn
.
setText
(
Localization
.
getText
(
"MainWindow.clearBtn"
));
errorsTab
.
setText
(
Localization
.
getText
(
"MainWindow.errorsTab"
));
polygonsTab
.
setText
(
Localization
.
getText
(
"MainWindow.polygonsTab"
));
edgesTab
.
setText
(
Localization
.
getText
(
"MainWindow.edgesTab"
));
verticesTab
.
setText
(
Localization
.
getText
(
"MainWindow.verticesTab"
));
logTab
.
setText
(
Localization
.
getText
(
"MainWindow.logTab"
));
globalErrorsTab
.
setText
(
Localization
.
getText
(
"MainWindow.globalErrorsTab"
));
memoryLabel
.
setText
(
Localization
.
getText
(
"MainWindow.memoryLabel"
));
availableLabel
.
setText
(
String
.
format
(
"%s %.1f GB"
,
Localization
.
getText
(
"MainWindow.availableLabel"
),
Runtime
.
getRuntime
().
maxMemory
()
/
1024
d
/
1024
d
/
1024
d
));
}
private
void
createLanguageSelector
()
{
languageSelector
.
setButtonCell
(
new
LanguageSelectorCell
());
languageSelector
.
setCellFactory
(
view
->
new
LanguageSelectorCell
());
languageSelector
.
getItems
().
add
(
Locale
.
GERMAN
);
languageSelector
.
getItems
().
add
(
Locale
.
ENGLISH
);
if
(
Locale
.
getDefault
().
getLanguage
().
equals
(
Locale
.
GERMAN
.
getLanguage
()))
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
GERMAN
);
}
else
if
(
Locale
.
getDefault
().
getLanguage
().
equals
(
Locale
.
ENGLISH
.
getLanguage
()))
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
ENGLISH
);
}
else
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
ENGLISH
);
Settings
.
set
(
Settings
.
LANGUAGE
,
Locale
.
ENGLISH
.
getLanguage
());
}
languageSelector
.
getSelectionModel
().
selectedItemProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
Alert
alert
=
new
Alert
(
AlertType
.
CONFIRMATION
,
Localization
.
getText
(
"MainWindow.languageChange"
),
ButtonType
.
OK
);
alert
.
showAndWait
();
Settings
.
set
(
Settings
.
LANGUAGE
,
newV
.
getLanguage
());
});
}
private
void
checkForStartupLoading
()
{
if
(
loadFileAtStartup
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.loadGivenFile"
));
Thread
t
=
new
Thread
(()
->
{
try
{
// wait a bit for the gui to show
Thread
.
sleep
(
500
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
}
try
{
controller
.
loadCityGml
(
inputFile
,
config
.
getNumberOfRoundingPlaces
(),
null
,
config
.
isXmlValidation
());
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedLoading"
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.checking"
));
controller
.
startChecks
(
config
,
null
);
if
(
xmlOutput
!=
null
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.writeXml"
));
controller
.
writeXmlReport
(
new
File
(
xmlOutput
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedXml"
));
}
if
(
pdfOutput
!=
null
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.writePdf"
));
controller
.
writePdfReport
(
new
File
(
pdfOutput
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedPdf"
));
}
}
catch
(
CityGmlParseException
|
InvalidGmlFileException
e
)
{
logger
.
error
(
Localization
.
getText
(
"MainWindow.loadFailed"
),
e
.
getMessage
());
}
});
t
.
start
();
}
}
private
void
setupViews
(
ValidationView
valView
)
{
ToggleGroup
group
=
new
ToggleGroup
();
for
(
View
v
:
ViewRegistration
.
getRegisteredViews
())
{
RadioButton
radioButton
=
new
RadioButton
();
radioButton
.
getStyleClass
().
remove
(
"radio-button"
);
radioButton
.
getStyleClass
().
add
(
"toggle-button"
);
ImageView
view
=
new
ImageView
(
v
.
getViewLogo
());
view
.
setFitHeight
(
32
);
view
.
setFitWidth
(
32
);
radioButton
.
setGraphic
(
view
);
group
.
getToggles
().
add
(
radioButton
);
if
(
v
==
valView
)
{
ViewRegistration
.
setCurrentActiveView
(
valView
);
group
.
selectToggle
(
radioButton
);
}
viewButtonBox
.
getChildren
().
add
(
radioButton
);
radioButton
.
selectedProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(
Boolean
.
TRUE
.
equals
(
newV
))
{
showView
(
v
);
ViewRegistration
.
setCurrentActiveView
(
v
);
}
else
{
v
.
onHide
();
}
});
}
}
private
void
showView
(
View
v
)
{
viewPane
.
getChildren
().
clear
();
controller
.
showView
(
v
);
Optional
<
HBox
>
toolbar
=
v
.
getToolbar
();
if
(
toolbar
.
isPresent
())
{
viewPane
.
getChildren
().
add
(
toolbar
.
get
());
HBox
.
setHgrow
(
toolbar
.
get
(),
Priority
.
ALWAYS
);
}
else
{
HBox
placeHolderToolbar
=
new
HBox
();
placeHolderToolbar
.
setMaxHeight
(
Double
.
MAX_VALUE
);
viewPane
.
getChildren
().
add
(
placeHolderToolbar
);
HBox
.
setHgrow
(
placeHolderToolbar
,
Priority
.
ALWAYS
);
}
mainPane
.
setCenter
(
v
.
getMainScreen
());
}
public
void
initialize
()
{
GuiLogger
.
setTextArea
(
logArea
);
loadFrameConfig
();
setup3dView
();
setupTrees
();
setupSearchField
();
setupSearchButtons
();
setupShowCityComboBox
();
detailsTabPane
.
getSelectionModel
().
selectedIndexProperty
()
.
addListener
((
ov
,
oldI
,
newI
)
->
Platform
.
runLater
(()
->
{
if
(
newI
.
intValue
()
==
0
&&
errorView
.
getSelectionModel
().
getSelectedItem
()
!=
null
)
{
// the first tab is selected, meaning the error tab
// redisplay the selected error
errorView
.
getSelectionModel
().
getSelectedItem
().
getValue
().
visit
(
renderer
);
}
}));
}
private
void
setupShowCityComboBox
()
{
showCityObjectsCombo
.
getItems
().
addAll
(
Localization
.
getText
(
"MainWindow.all"
),
Localization
.
getText
(
"MainWindow.withErrors"
));
showCityObjectsCombo
.
getSelectionModel
().
selectFirst
();
showCityObjectsCombo
.
setCellFactory
(
param
->
new
ListCell
<>()
{
@Override
public
void
updateItem
(
String
item
,
boolean
empty
)
{
super
.
updateItem
(
item
,
empty
);
if
(
item
!=
null
)
{
setText
(
item
);
if
(
item
.
contentEquals
(
Localization
.
getText
(
"MainWindow.withErrors"
)))
{
setTextFill
(
Color
.
RED
);
}
}
else
{
setText
(
null
);
}
}
});
filterChangeListener
=
setupFilterSelectionListener
();
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
addListener
(
filterChangeListener
);
}
public
void
resetFilterComboBox
()
{
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
removeListener
(
filterChangeListener
);
showCityObjectsCombo
.
getSelectionModel
().
selectFirst
();
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
addListener
(
filterChangeListener
);
}
private
ChangeListener
<
Number
>
setupFilterSelectionListener
()
{
return
(
obs
,
oldV
,
newV
)
->
controller
.
errorFilterIndexChanged
(
newV
);
}
private
void
setupSearchButtons
()
{
searchBtn
.
setOnAction
(
ae
->
controller
.
searchFeature
(
searchField
.
getText
(),
selectedTab
));
clearBtn
.
setOnAction
(
ae
->
{
if
(
searchField
.
getText
().
isEmpty
())
{
// do not reset search if nothing has bee searched
return
;
}
controller
.
resetSearch
(
selectedTab
);
searchField
.
setText
(
""
);
});
}
private
void
setupSearchField
()
{
searchField
.
textProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(
newV
.
isEmpty
())
{
controller
.
resetSearch
(
selectedTab
);
}
});
featurePane
.
getSelectionModel
().
selectedIndexProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(!
searchField
.
getText
().
isEmpty
())
{
resetSearchBar
();
controller
.
resetSearch
(
selectedTab
);
}
int
index
=
newV
.
intValue
();
switch
(
index
)
{
case
0
:
selectedTab
=
FeatureType
.
BUILDING
;
break
;
case
1
:
selectedTab
=
FeatureType
.
VEGETATION
;
break
;
case
2
:
selectedTab
=
FeatureType
.
TRANSPORTATION
;
break
;
case
3
:
selectedTab
=
FeatureType
.
BRIDGE
;
break
;
case
4
:
selectedTab
=
FeatureType
.
WATER
;
break
;
case
5
:
selectedTab
=
FeatureType
.
LAND
;
break
;
case
6
:
selectedTab
=
FeatureType
.
CITY_FURNITURE
;
break
;
case
7
:
selectedTab
=
FeatureType
.
GENERIC_CITY_OBJECT
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown tab index: "
+
index
);
}
});
}
public
void
resetSearchBar
()
{
searchField
.
setText
(
""
);
}
private
void
loadFrameConfig
()
{
stage
.
setMaximized
(
Boolean
.
valueOf
(
Settings
.
get
(
Settings
.
MAXIMIZED
,
Boolean
.
FALSE
.
toString
())));
stage
.
maximizedProperty
()
.
addListener
((
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
MAXIMIZED
,
Boolean
.
toString
(
newV
)));
String
widthString
=
Settings
.
get
(
Settings
.
FRAME_WIDTH
);
if
(
widthString
!=
null
)
{
stage
.
setWidth
(
Double
.
parseDouble
(
widthString
));
}
stage
.
widthProperty
().
addListener
(
(
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
FRAME_WIDTH
,
Double
.
toString
(
newV
.
doubleValue
())));
String
heightString
=
Settings
.
get
(
Settings
.
FRAME_HEIGHT
);
if
(
heightString
!=
null
)
{
stage
.
setHeight
(
Double
.
parseDouble
(
heightString
));
}
stage
.
heightProperty
().
addListener
(
(
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
FRAME_HEIGHT
,
Double
.
toString
(
newV
.
doubleValue
())));
}
public
void
showExceptionDialog
(
Throwable
e
)
{
if
(
exceptionDialog
==
null
)
{
exceptionDialog
=
new
ExceptionDialog
();
}
exceptionDialog
.
show
(
e
);
}
private
void
setupTrees
()
{
setupSelectListener
(
errorView
);
errorView
.
setRoot
(
new
TreeItem
<>());
errorView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
buildingsView
.
setShowRoot
(
true
);
setupSelectListener
(
buildingsView
);
buildingsView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
ContextMenu
cMenu
=
new
ContextMenu
();
MenuItem
mi
=
new
MenuItem
(
Localization
.
getText
(
"MainWindow.export"
));
mi
.
setOnAction
(
ea
->
{
Renderable
render
=
buildingsView
.
getSelectionModel
().
getSelectedItem
().
getValue
();
if
(
render
instanceof
BuildingNode
node
)
{
controller
.
export
(
node
.
getBuilding
());
}
});
cMenu
.
getItems
().
add
(
mi
);
MenuItem
deleteMi
=
new
MenuItem
(
"Delete"
);
deleteMi
.
setOnAction
(
ae
->
controller
.
delete
(
buildingsView
.
getSelectionModel
().
getSelectedItem
()));
cMenu
.
getItems
().
add
(
deleteMi
);
buildingsView
.
setContextMenu
(
cMenu
);
vegetationView
.
setShowRoot
(
true
);
setupSelectListener
(
vegetationView
);
vegetationView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
transView
.
setShowRoot
(
true
);
setupSelectListener
(
transView
);
transView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
bridgeView
.
setShowRoot
(
true
);
setupSelectListener
(
bridgeView
);
bridgeView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
waterView
.
setShowRoot
(
true
);
setupSelectListener
(
waterView
);
waterView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
terrainView
.
setShowRoot
(
true
);
setupSelectListener
(
terrainView
);
terrainView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
cityFurnitureView
.
setShowRoot
(
true
);
setupSelectListener
(
cityFurnitureView
);
cityFurnitureView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
otherObjectsView
.
setShowRoot
(
true
);
setupSelectListener
(
otherObjectsView
);
otherObjectsView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
vertexView
);
vertexView
.
setRoot
(
new
TreeItem
<>());
vertexView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
polygonView
);
polygonView
.
setRoot
(
new
TreeItem
<>());
polygonView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
edgeView
);
edgeView
.
setRoot
(
new
TreeItem
<>());
edgeView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
}
private
void
setupSelectListener
(
TreeView
<
Renderable
>
view
)
{
view
.
getSelectionModel
().
selectedItemProperty
().
addListener
((
obs
,
oldI
,
newI
)
->
{
if
(
newI
!=
null
)
{
newI
.
getValue
().
visit
(
renderer
);
}
});
}
private
void
setup3dView
()
{
Group
root
=
new
Group
();
geomScene
=
new
SubScene
(
root
,
500
,
300
,
true
,
SceneAntialiasing
.
BALANCED
);
geomScene
.
heightProperty
().
bind
(
meshView
.
heightProperty
());
geomScene
.
widthProperty
().
bind
(
meshView
.
widthProperty
());
geomScene
.
setFill
(
Color
.
AZURE
);
meshView
.
getChildren
().
add
(
geomScene
);
geomScene
.
addEventFilter
(
MouseEvent
.
MOUSE_PRESSED
,
me
->
{
clickStart
[
0
]
=
me
.
getScreenX
();
clickStart
[
1
]
=
me
.
getScreenY
();
});
geomScene
.
addEventFilter
(
MouseEvent
.
MOUSE_RELEASED
,
me
->
{
if
(
Math
.
abs
(
clickStart
[
0
]
-
me
.
getScreenX
())
>
3
||
Math
.
abs
(
clickStart
[
1
]
-
me
.
getScreenY
())
>
3
)
{
// skip when mouse moved too much
return
;
}
Node
node
=
me
.
getPickResult
().
getIntersectedNode
();
if
(
node
!=
null
)
{
Object
o
=
node
.
getUserData
();
if
(
o
instanceof
ClickDispatcher
cd
)
{
cd
.
click
(
me
,
clickHandler
);
}
}
});
world
=
new
Group
();
root
.
getChildren
().
add
(
world
);
meshGroup
=
new
Group
();
world
.
getChildren
().
add
(
meshGroup
);
AmbientLight
al
=
new
AmbientLight
(
Color
.
WHITE
);
root
.
getChildren
().
add
(
al
);
buildCamera
();
cameraXRotation
.
setAxis
(
Rotate
.
X_AXIS
);
cameraZRotation
.
setAxis
(
Rotate
.
Z_AXIS
);
world
.
getTransforms
().
add
(
cameraXRotation
);
world
.
getTransforms
().
add
(
cameraZRotation
);
root
.
getChildren
().
add
(
camera
);
geomScene
.
setCamera
(
camera
);
setupMeshViewControls
();
}
private
void
setupMeshViewControls
()
{
meshView
.
setOnMousePressed
(
me
->
{
if
(
me
.
getButton
()
==
MouseButton
.
PRIMARY
)
{
dragX
=
me
.
getScreenX
();
dragY
=
me
.
getScreenY
();
}
});
meshView
.
setOnScroll
(
se
->
{
if
(
se
.
getDeltaY
()
<
0
)
{
translateZ
+=
translateZ
*
0.05
;
}
else
{
translateZ
-=
translateZ
*
0.05
;
}
camera
.
setTranslateZ
(
translateZ
);
highlightController
.
changeScaling
(
translateZ
);
});
meshView
.
setOnMouseDragged
(
me
->
{
if
(
me
.
getButton
()
==
MouseButton
.
PRIMARY
)
{
double
deltaX
=
me
.
getScreenX
()
-
dragX
;
double
deltaY
=
me
.
getScreenY
()
-
dragY
;
dragX
=
me
.
getScreenX
();
dragY
=
me
.
getScreenY
();
cameraXRot
+=
(
deltaX
/
3
d
)
%
360
;
cameraYRot
+=
(
deltaY
/
3
d
)
%
360
;
cameraZRotation
.
setAngle
(
cameraXRot
);
cameraXRotation
.
setAngle
(
cameraYRot
);
}
});
}
private
void
buildCamera
()
{
camera
=
new
PerspectiveCamera
(
true
);
camera
.
setNearClip
(
0.1
);
camera
.
setFarClip
(
10000
d
);
camera
.
setTranslateZ
(
translateZ
);
cameraZRotation
.
setAngle
(
cameraXRot
);
cameraXRotation
.
setAngle
(
cameraYRot
);
}
public
void
addFileNameToTitle
(
String
fileName
)
{
String
version
=
Localization
.
getText
(
Localization
.
VERSION
);
stage
.
setTitle
(
"CityDoctor "
+
version
+
" - "
+
fileName
);
}
public
TreeView
<
Renderable
>
getBuildingsView
()
{
return
buildingsView
;
}
public
TreeView
<
Renderable
>
getVegetationView
()
{
return
vegetationView
;
}
public
TreeView
<
Renderable
>
getTransportationView
()
{
return
transView
;
}
public
TreeView
<
Renderable
>
getBridgeView
()
{
return
bridgeView
;
}
public
TreeView
<
Renderable
>
getWaterView
()
{
return
waterView
;
}
public
TreeView
<
Renderable
>
getTerrainView
()
{
return
terrainView
;
}
public
TreeView
<
Renderable
>
getCityFurnitureView
()
{
return
cityFurnitureView
;
}
public
TreeView
<
Renderable
>
getOtherObjectsView
(){
return
otherObjectsView
;
}
public
TreeView
<
Renderable
>
getPolygonsView
()
{
return
polygonView
;
}
public
TreeView
<
Renderable
>
getEdgeView
()
{
return
edgeView
;
}
public
TreeView
<
Renderable
>
getVertexView
()
{
return
vertexView
;
}
public
Button
getCheckButton
()
{
return
mainToolBar
.
getCheckButton
();
}
public
ToggleButton
getGridButton
()
{
return
mainToolBar
.
getGridButton
();
}
public
Group
getMeshGroup
()
{
return
meshGroup
;
}
public
ToggleButton
getCullingButton
()
{
return
mainToolBar
.
getCullingButton
();
}
public
Button
getWriteReportButton
()
{
return
mainToolBar
.
getWriteReportButton
();
}
public
TreeView
<
Renderable
>
getErrorTree
()
{
return
errorView
;
}
public
Stage
getMainStage
()
{
return
stage
;
}
public
void
unselectEverything
()
{
buildingsView
.
getSelectionModel
().
clearSelection
();
vegetationView
.
getSelectionModel
().
clearSelection
();
transView
.
getSelectionModel
().
clearSelection
();
waterView
.
getSelectionModel
().
clearSelection
();
terrainView
.
getSelectionModel
().
clearSelection
();
cityFurnitureView
.
getSelectionModel
().
clearSelection
();
otherObjectsView
.
getSelectionModel
().
clearSelection
();
bridgeView
.
getSelectionModel
().
clearSelection
();
polygonView
.
getSelectionModel
().
clearSelection
();
edgeView
.
getSelectionModel
().
clearSelection
();
vertexView
.
getSelectionModel
().
clearSelection
();
errorView
.
getSelectionModel
().
clearSelection
();
}
public
ToggleButton
getLod1Btn
()
{
return
mainToolBar
.
getLod1Btn
();
}
public
ToggleButton
getLod2Btn
()
{
return
mainToolBar
.
getLod2Btn
();
}
public
ToggleButton
getLod3Btn
()
{
return
mainToolBar
.
getLod3Btn
();
}
public
ToggleButton
getLod4Btn
()
{
return
mainToolBar
.
getLod4Btn
();
}
public
Button
getWorldBtn
()
{
return
mainToolBar
.
getWorldBtn
();
}
public
Button
getSaveBtn
()
{
return
mainToolBar
.
getSaveBtn
();
}
public
SplitPane
getMainContainer
()
{
return
mainContainer
;
}
public
ListView
<
String
>
getGlobalErrorsView
()
{
return
globalErrorsView
;
}
public
void
takeViewScreenshot
()
throws
IOException
{
WritableImage
snapshot
=
geomScene
.
snapshot
(
null
,
null
);
File
outputFile
=
new
File
(
"img.png"
);
BufferedImage
bImage
=
SwingFXUtils
.
fromFXImage
(
snapshot
,
null
);
ImageIO
.
write
(
bImage
,
"png"
,
outputFile
);
}
public
void
zoomOutForBoundingBox
(
BoundingBox
b
)
{
double
longestSide
=
b
.
getDiagonalLength
()
*
0.4
;
double
d
=
longestSide
/
Math
.
tan
(
Math
.
toRadians
(
30
)
/
2
);
translateZ
=
-
d
;
camera
.
setTranslateZ
(
translateZ
);
highlightController
.
changeScaling
(-
translateZ
);
}
public
MainToolBar
getMainToolbar
()
{
return
mainToolBar
;
}
public
void
clearHighlights
()
{
highlightController
.
clearHighlights
();
}
public
CityDoctorController
getController
()
{
return
controller
;
}
public
Button
getOpenBtn
()
{
return
mainToolBar
.
getOpenBtn
();
}
public
VertexClickHandler
getClickHandler
()
{
return
clickHandler
;
}
public
FeatureType
getSelectedTab
()
{
return
selectedTab
;
}
@FXML
private
TextArea
logArea
;
@FXML
private
ToolBar
viewBar
;
private
Stage
stage
;
private
ExceptionDialog
exceptionDialog
;
private
Renderer
renderer
;
private
CityDoctorController
controller
;
private
HighlightController
highlightController
;
private
FeatureType
selectedTab
=
FeatureType
.
BUILDING
;
private
MainToolBar
mainToolBar
;
private
SubScene
geomScene
;
private
static
boolean
loadFileAtStartup
=
false
;
private
static
String
inputFile
;
private
static
String
xmlOutput
;
private
static
String
pdfOutput
;
private
static
ValidationConfiguration
config
;
private
VertexClickHandler
clickHandler
;
private
ChangeListener
<
Number
>
filterChangeListener
;
public
static
void
main
(
String
[]
args
)
{
setLocaleFromSettings
();
ArgumentParser
argParser
=
new
ArgumentParser
(
args
);
inputFile
=
CityDoctorValidation
.
getInputFile
(
argParser
,
true
);
if
(
inputFile
!=
null
)
{
loadFileAtStartup
=
true
;
xmlOutput
=
CityDoctorValidation
.
getXmlOutput
(
argParser
);
pdfOutput
=
CityDoctorValidation
.
getPdfOutput
(
argParser
);
try
{
config
=
CityDoctorValidation
.
getValidationConfig
(
argParser
,
true
);
}
catch
(
FileNotFoundException
e
)
{
Platform
.
runLater
(()
->
{
List
<
String
>
configFiles
=
argParser
.
getValues
(
"config"
);
Alert
alert
=
new
Alert
(
AlertType
.
ERROR
);
alert
.
setContentText
(
Localization
.
getText
(
"MainWindow.missingConfig"
)
+
configFiles
);
alert
.
showAndWait
();
});
System
.
exit
(
4
);
}
}
Application
.
launch
(
args
);
}
private
static
void
setLocaleFromSettings
()
{
String
localeString
=
Settings
.
get
(
Settings
.
LANGUAGE
);
if
(
localeString
!=
null
)
{
try
{
Locale
loc
=
new
Locale
(
localeString
);
Locale
.
setDefault
(
loc
);
}
catch
(
Exception
e
)
{
logger
.
warn
(
"Could not set language to {}, using system language"
,
localeString
);
}
}
}
@Override
public
void
start
(
Stage
stage
)
throws
IOException
{
this
.
stage
=
stage
;
stage
.
getIcons
().
add
(
new
Image
(
MainWindow
.
class
.
getResourceAsStream
(
"icons/citydoctor_logo.png"
)));
FXMLLoader
loader
=
new
FXMLLoader
(
MainWindow
.
class
.
getResource
(
"MainWindow.fxml"
));
loader
.
setController
(
this
);
BorderPane
bp
=
loader
.
load
();
highlightController
=
new
HighlightController
(
world
);
renderer
=
new
Renderer
(
this
,
highlightController
);
clickHandler
=
new
VertexClickHandler
(
errorView
,
renderer
,
stage
);
controller
=
new
CityDoctorController
(
this
,
highlightController
,
renderer
);
mainToolBar
=
new
MainToolBar
(
stage
,
controller
,
featurePane
,
renderer
,
this
);
viewPane
.
getChildren
().
add
(
mainToolBar
.
getToolBar
());
HBox
.
setHgrow
(
mainToolBar
.
getToolBar
(),
Priority
.
ALWAYS
);
ValidationView
valView
=
new
ValidationView
(
this
,
controller
);
ViewRegistration
.
registerView
(
valView
);
setupViews
(
valView
);
createLanguageSelector
();
setLabelsInCorrectLanguage
();
Scene
scene
=
new
Scene
(
bp
,
1280
,
800
);
createDropTarget
(
scene
,
valView
);
String
version
=
Localization
.
getText
(
Localization
.
VERSION
);
stage
.
setTitle
(
"CityDoctor "
+
version
);
stage
.
setScene
(
scene
);
stage
.
show
();
checkForStartupLoading
();
memoryBar
.
setOnMouseClicked
(
me
->
System
.
gc
());
Timer
timer
=
new
Timer
(
true
);
// check memory every second
TimerTask
task
=
new
TimerTask
()
{
Runtime
runtime
=
Runtime
.
getRuntime
();
@Override
public
void
run
()
{
long
totalMemory
=
runtime
.
totalMemory
();
long
freeMemory
=
runtime
.
freeMemory
();
long
usedMemory
=
totalMemory
-
freeMemory
;
double
percentage
=
usedMemory
/
(
double
)
totalMemory
;
if
(
totalMemory
/
1024
/
1024
>=
1024
)
{
// gb
double
totalMemoryGb
=
totalMemory
/
(
1024
d
*
1024
d
*
1024
d
);
double
usedMemoryGb
=
usedMemory
/
(
1024
d
*
1024
d
*
1024
d
);
String
memoryString
=
String
.
format
(
"%.1f GB / %.1f GB"
,
usedMemoryGb
,
totalMemoryGb
);
Platform
.
runLater
(()
->
{
memoryConsumptionLabel
.
setText
(
memoryString
);
memoryBar
.
setProgress
(
percentage
);
});
}
else
if
(
totalMemory
/
1024
>=
1024
)
{
// mb
double
totalMemoryMb
=
totalMemory
/
(
1024
d
*
1024
d
);
double
usedMemoryMb
=
usedMemory
/
(
1024
d
*
1024
d
);
String
memoryString
=
String
.
format
(
"%.1f MB / %.1f MB"
,
usedMemoryMb
,
totalMemoryMb
);
Platform
.
runLater
(()
->
{
memoryConsumptionLabel
.
setText
(
memoryString
);
memoryBar
.
setProgress
(
percentage
);
});
}
}
};
timer
.
schedule
(
task
,
0
,
1000
);
}
private
void
createDropTarget
(
Scene
scene
,
ValidationView
valView
)
{
setDragOverInteraction
(
scene
,
valView
);
scene
.
setOnDragDropped
(
event
->
{
if
(
ViewRegistration
.
getCurrentActiveView
()
!=
valView
)
{
return
;
}
Dragboard
db
=
event
.
getDragboard
();
boolean
success
=
false
;
if
(
db
.
hasFiles
()
&&
db
.
getFiles
().
size
()
==
1
)
{
File
f
=
db
.
getFiles
().
get
(
0
);
Thread
t
=
new
Thread
(()
->
{
try
{
controller
.
loadCityGml
(
f
.
getAbsolutePath
(),
8
,
(
ProgressListener
)
null
,
false
);
}
catch
(
Exception
e
)
{
if
(
logger
.
isErrorEnabled
())
{
logger
.
error
(
Localization
.
getText
(
"OpenFileDialog.loadFailed"
),
e
);
}
Platform
.
runLater
(()
->
{
ExceptionDialog
exDialog
=
new
ExceptionDialog
();
exDialog
.
show
(
e
);
});
}
});
t
.
start
();
success
=
true
;
}
// let the source know whether the string was successfully transferred and used
event
.
setDropCompleted
(
success
);
event
.
consume
();
});
}
private
void
setDragOverInteraction
(
Scene
scene
,
ValidationView
valView
)
{
scene
.
setOnDragOver
(
event
->
{
if
(
ViewRegistration
.
getCurrentActiveView
()
!=
valView
)
{
return
;
}
if
(
event
.
getGestureSource
()
!=
scene
&&
event
.
getDragboard
().
hasFiles
()
&&
event
.
getDragboard
().
getFiles
().
size
()
==
1
)
{
// allow for both copying and moving, whatever user chooses
event
.
acceptTransferModes
(
TransferMode
.
LINK
);
}
event
.
consume
();
});
}
private
void
setLabelsInCorrectLanguage
()
{
buildingsTab
.
setText
(
Localization
.
getText
(
"MainWindow.buildingsTab"
));
vegetationTab
.
setText
(
Localization
.
getText
(
"MainWindow.vegetationTab"
));
transportationTab
.
setText
(
Localization
.
getText
(
"MainWindow.transportationTab"
));
bridgeTab
.
setText
(
Localization
.
getText
(
"MainWindow.bridgeTab"
));
waterTab
.
setText
(
Localization
.
getText
(
"MainWindow.waterTab"
));
terrainTab
.
setText
(
Localization
.
getText
(
"MainWindow.terrainTab"
));
cityFurnitureTab
.
setText
(
Localization
.
getText
(
"MainWindow.cityfurnitureTab"
));
otherObjectsTab
.
setText
(
Localization
.
getText
(
"MainWindow.otherObjectsTab"
));
viewLabel
.
setText
(
Localization
.
getText
(
"MainWindow.viewLabel"
));
showLabel
.
setText
(
Localization
.
getText
(
"MainWindow.showLabel"
));
searchLabel
.
setText
(
Localization
.
getText
(
"MainWindow.searchLabel"
));
searchBtn
.
setText
(
Localization
.
getText
(
"MainWindow.searchBtn"
));
clearBtn
.
setText
(
Localization
.
getText
(
"MainWindow.clearBtn"
));
errorsTab
.
setText
(
Localization
.
getText
(
"MainWindow.errorsTab"
));
polygonsTab
.
setText
(
Localization
.
getText
(
"MainWindow.polygonsTab"
));
edgesTab
.
setText
(
Localization
.
getText
(
"MainWindow.edgesTab"
));
verticesTab
.
setText
(
Localization
.
getText
(
"MainWindow.verticesTab"
));
logTab
.
setText
(
Localization
.
getText
(
"MainWindow.logTab"
));
globalErrorsTab
.
setText
(
Localization
.
getText
(
"MainWindow.globalErrorsTab"
));
memoryLabel
.
setText
(
Localization
.
getText
(
"MainWindow.memoryLabel"
));
availableLabel
.
setText
(
String
.
format
(
"%s %.1f GB"
,
Localization
.
getText
(
"MainWindow.availableLabel"
),
Runtime
.
getRuntime
().
maxMemory
()
/
1024
d
/
1024
d
/
1024
d
));
}
private
void
createLanguageSelector
()
{
languageSelector
.
setButtonCell
(
new
LanguageSelectorCell
());
languageSelector
.
setCellFactory
(
view
->
new
LanguageSelectorCell
());
languageSelector
.
getItems
().
add
(
Locale
.
GERMAN
);
languageSelector
.
getItems
().
add
(
Locale
.
ENGLISH
);
if
(
Locale
.
getDefault
().
getLanguage
().
equals
(
Locale
.
GERMAN
.
getLanguage
()))
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
GERMAN
);
}
else
if
(
Locale
.
getDefault
().
getLanguage
().
equals
(
Locale
.
ENGLISH
.
getLanguage
()))
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
ENGLISH
);
}
else
{
languageSelector
.
getSelectionModel
().
select
(
Locale
.
ENGLISH
);
Settings
.
set
(
Settings
.
LANGUAGE
,
Locale
.
ENGLISH
.
getLanguage
());
}
languageSelector
.
getSelectionModel
().
selectedItemProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
Alert
alert
=
new
Alert
(
AlertType
.
CONFIRMATION
,
Localization
.
getText
(
"MainWindow.languageChange"
),
ButtonType
.
OK
);
alert
.
showAndWait
();
Settings
.
set
(
Settings
.
LANGUAGE
,
newV
.
getLanguage
());
});
}
private
void
checkForStartupLoading
()
{
if
(
loadFileAtStartup
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.loadGivenFile"
));
Thread
t
=
new
Thread
(()
->
{
try
{
// wait a bit for the gui to show
Thread
.
sleep
(
500
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
}
try
{
controller
.
loadCityGml
(
inputFile
,
config
.
getNumberOfRoundingPlaces
(),
null
,
config
.
isXmlValidation
());
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedLoading"
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.checking"
));
controller
.
startChecks
(
config
,
null
);
if
(
xmlOutput
!=
null
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.writeXml"
));
controller
.
writeXmlReport
(
new
File
(
xmlOutput
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedXml"
));
}
if
(
pdfOutput
!=
null
)
{
logger
.
info
(
Localization
.
getText
(
"MainWindow.writePdf"
));
controller
.
writePdfReport
(
new
File
(
pdfOutput
));
logger
.
info
(
Localization
.
getText
(
"MainWindow.finishedPdf"
));
}
}
catch
(
CityGmlParseException
|
InvalidGmlFileException
e
)
{
logger
.
error
(
Localization
.
getText
(
"MainWindow.loadFailed"
),
e
.
getMessage
());
}
});
t
.
start
();
}
}
private
void
setupViews
(
ValidationView
valView
)
{
ToggleGroup
group
=
new
ToggleGroup
();
for
(
View
v
:
ViewRegistration
.
getRegisteredViews
())
{
RadioButton
radioButton
=
new
RadioButton
();
radioButton
.
getStyleClass
().
remove
(
"radio-button"
);
radioButton
.
getStyleClass
().
add
(
"toggle-button"
);
ImageView
view
=
new
ImageView
(
v
.
getViewLogo
());
view
.
setFitHeight
(
32
);
view
.
setFitWidth
(
32
);
radioButton
.
setGraphic
(
view
);
group
.
getToggles
().
add
(
radioButton
);
if
(
v
==
valView
)
{
ViewRegistration
.
setCurrentActiveView
(
valView
);
group
.
selectToggle
(
radioButton
);
}
viewButtonBox
.
getChildren
().
add
(
radioButton
);
radioButton
.
selectedProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(
Boolean
.
TRUE
.
equals
(
newV
))
{
showView
(
v
);
ViewRegistration
.
setCurrentActiveView
(
v
);
}
else
{
v
.
onHide
();
}
});
}
}
private
void
showView
(
View
v
)
{
viewPane
.
getChildren
().
clear
();
controller
.
showView
(
v
);
Optional
<
HBox
>
toolbar
=
v
.
getToolbar
();
if
(
toolbar
.
isPresent
())
{
viewPane
.
getChildren
().
add
(
toolbar
.
get
());
HBox
.
setHgrow
(
toolbar
.
get
(),
Priority
.
ALWAYS
);
}
else
{
HBox
placeHolderToolbar
=
new
HBox
();
placeHolderToolbar
.
setMaxHeight
(
Double
.
MAX_VALUE
);
viewPane
.
getChildren
().
add
(
placeHolderToolbar
);
HBox
.
setHgrow
(
placeHolderToolbar
,
Priority
.
ALWAYS
);
}
mainPane
.
setCenter
(
v
.
getMainScreen
());
}
public
void
initialize
()
{
GuiLogger
.
setTextArea
(
logArea
);
loadFrameConfig
();
setup3dView
();
setupTrees
();
setupSearchField
();
setupSearchButtons
();
setupShowCityComboBox
();
detailsTabPane
.
getSelectionModel
().
selectedIndexProperty
()
.
addListener
((
ov
,
oldI
,
newI
)
->
Platform
.
runLater
(()
->
{
if
(
newI
.
intValue
()
==
0
&&
errorView
.
getSelectionModel
().
getSelectedItem
()
!=
null
)
{
// the first tab is selected, meaning the error tab
// redisplay the selected error
errorView
.
getSelectionModel
().
getSelectedItem
().
getValue
().
visit
(
renderer
);
}
}));
}
private
void
setupShowCityComboBox
()
{
showCityObjectsCombo
.
getItems
().
addAll
(
Localization
.
getText
(
"MainWindow.all"
),
Localization
.
getText
(
"MainWindow.withErrors"
));
showCityObjectsCombo
.
getSelectionModel
().
selectFirst
();
showCityObjectsCombo
.
setCellFactory
(
param
->
new
ListCell
<>()
{
@Override
public
void
updateItem
(
String
item
,
boolean
empty
)
{
super
.
updateItem
(
item
,
empty
);
if
(
item
!=
null
)
{
setText
(
item
);
if
(
item
.
contentEquals
(
Localization
.
getText
(
"MainWindow.withErrors"
)))
{
setTextFill
(
Color
.
RED
);
}
}
else
{
setText
(
null
);
}
}
});
filterChangeListener
=
setupFilterSelectionListener
();
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
addListener
(
filterChangeListener
);
}
public
void
resetFilterComboBox
()
{
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
removeListener
(
filterChangeListener
);
showCityObjectsCombo
.
getSelectionModel
().
selectFirst
();
showCityObjectsCombo
.
getSelectionModel
().
selectedIndexProperty
().
addListener
(
filterChangeListener
);
}
private
ChangeListener
<
Number
>
setupFilterSelectionListener
()
{
return
(
obs
,
oldV
,
newV
)
->
controller
.
errorFilterIndexChanged
(
newV
);
}
private
void
setupSearchButtons
()
{
searchBtn
.
setOnAction
(
ae
->
controller
.
searchFeature
(
searchField
.
getText
(),
selectedTab
));
clearBtn
.
setOnAction
(
ae
->
{
if
(
searchField
.
getText
().
isEmpty
())
{
// do not reset search if nothing has bee searched
return
;
}
controller
.
resetSearch
(
selectedTab
);
searchField
.
setText
(
""
);
});
}
private
void
setupSearchField
()
{
searchField
.
textProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(
newV
.
isEmpty
())
{
controller
.
resetSearch
(
selectedTab
);
}
});
featurePane
.
getSelectionModel
().
selectedIndexProperty
().
addListener
((
obs
,
oldV
,
newV
)
->
{
if
(!
searchField
.
getText
().
isEmpty
())
{
resetSearchBar
();
controller
.
resetSearch
(
selectedTab
);
}
int
index
=
newV
.
intValue
();
switch
(
index
)
{
case
0
:
selectedTab
=
FeatureType
.
BUILDING
;
break
;
case
1
:
selectedTab
=
FeatureType
.
VEGETATION
;
break
;
case
2
:
selectedTab
=
FeatureType
.
TRANSPORTATION
;
break
;
case
3
:
selectedTab
=
FeatureType
.
BRIDGE
;
break
;
case
4
:
selectedTab
=
FeatureType
.
WATER
;
break
;
case
5
:
selectedTab
=
FeatureType
.
LAND
;
break
;
case
6
:
selectedTab
=
FeatureType
.
CITY_FURNITURE
;
break
;
case
7
:
selectedTab
=
FeatureType
.
GENERIC_CITY_OBJECT
;
break
;
default
:
throw
new
IllegalStateException
(
"Unknown tab index: "
+
index
);
}
});
}
public
void
resetSearchBar
()
{
searchField
.
setText
(
""
);
}
private
void
loadFrameConfig
()
{
stage
.
setMaximized
(
Boolean
.
valueOf
(
Settings
.
get
(
Settings
.
MAXIMIZED
,
Boolean
.
FALSE
.
toString
())));
stage
.
maximizedProperty
()
.
addListener
((
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
MAXIMIZED
,
Boolean
.
toString
(
newV
)));
String
widthString
=
Settings
.
get
(
Settings
.
FRAME_WIDTH
);
if
(
widthString
!=
null
)
{
stage
.
setWidth
(
Double
.
parseDouble
(
widthString
));
}
stage
.
widthProperty
().
addListener
(
(
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
FRAME_WIDTH
,
Double
.
toString
(
newV
.
doubleValue
())));
String
heightString
=
Settings
.
get
(
Settings
.
FRAME_HEIGHT
);
if
(
heightString
!=
null
)
{
stage
.
setHeight
(
Double
.
parseDouble
(
heightString
));
}
stage
.
heightProperty
().
addListener
(
(
obs
,
oldV
,
newV
)
->
Settings
.
set
(
Settings
.
FRAME_HEIGHT
,
Double
.
toString
(
newV
.
doubleValue
())));
}
public
void
showExceptionDialog
(
Throwable
e
)
{
if
(
exceptionDialog
==
null
)
{
exceptionDialog
=
new
ExceptionDialog
();
}
exceptionDialog
.
show
(
e
);
}
private
void
setupTrees
()
{
setupSelectListener
(
errorView
);
errorView
.
setRoot
(
new
TreeItem
<>());
errorView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
buildingsView
.
setShowRoot
(
true
);
setupSelectListener
(
buildingsView
);
buildingsView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
ContextMenu
cMenu
=
new
ContextMenu
();
MenuItem
mi
=
new
MenuItem
(
Localization
.
getText
(
"MainWindow.export"
));
mi
.
setOnAction
(
ea
->
{
Renderable
render
=
buildingsView
.
getSelectionModel
().
getSelectedItem
().
getValue
();
if
(
render
instanceof
BuildingNode
node
)
{
controller
.
export
(
node
.
getBuilding
());
}
});
cMenu
.
getItems
().
add
(
mi
);
MenuItem
deleteMi
=
new
MenuItem
(
"Delete"
);
deleteMi
.
setOnAction
(
ae
->
controller
.
delete
(
buildingsView
.
getSelectionModel
().
getSelectedItem
()));
cMenu
.
getItems
().
add
(
deleteMi
);
buildingsView
.
setContextMenu
(
cMenu
);
vegetationView
.
setShowRoot
(
true
);
setupSelectListener
(
vegetationView
);
vegetationView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
transView
.
setShowRoot
(
true
);
setupSelectListener
(
transView
);
transView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
bridgeView
.
setShowRoot
(
true
);
setupSelectListener
(
bridgeView
);
bridgeView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
waterView
.
setShowRoot
(
true
);
setupSelectListener
(
waterView
);
waterView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
terrainView
.
setShowRoot
(
true
);
setupSelectListener
(
terrainView
);
terrainView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
cityFurnitureView
.
setShowRoot
(
true
);
setupSelectListener
(
cityFurnitureView
);
cityFurnitureView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
otherObjectsView
.
setShowRoot
(
true
);
setupSelectListener
(
otherObjectsView
);
otherObjectsView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
vertexView
);
vertexView
.
setRoot
(
new
TreeItem
<>());
vertexView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
polygonView
);
polygonView
.
setRoot
(
new
TreeItem
<>());
polygonView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
setupSelectListener
(
edgeView
);
edgeView
.
setRoot
(
new
TreeItem
<>());
edgeView
.
setCellFactory
(
param
->
new
RenderableTreeCell
());
}
private
void
setupSelectListener
(
TreeView
<
Renderable
>
view
)
{
view
.
getSelectionModel
().
selectedItemProperty
().
addListener
((
obs
,
oldI
,
newI
)
->
{
if
(
newI
!=
null
)
{
newI
.
getValue
().
visit
(
renderer
);
}
});
}
private
void
setup3dView
()
{
Group
root
=
new
Group
();
geomScene
=
new
SubScene
(
root
,
500
,
300
,
true
,
SceneAntialiasing
.
BALANCED
);
geomScene
.
heightProperty
().
bind
(
meshView
.
heightProperty
());
geomScene
.
widthProperty
().
bind
(
meshView
.
widthProperty
());
geomScene
.
setFill
(
Color
.
AZURE
);
meshView
.
getChildren
().
add
(
geomScene
);
geomScene
.
addEventFilter
(
MouseEvent
.
MOUSE_PRESSED
,
me
->
{
clickStart
[
0
]
=
me
.
getScreenX
();
clickStart
[
1
]
=
me
.
getScreenY
();
});
geomScene
.
addEventFilter
(
MouseEvent
.
MOUSE_RELEASED
,
me
->
{
if
(
Math
.
abs
(
clickStart
[
0
]
-
me
.
getScreenX
())
>
3
||
Math
.
abs
(
clickStart
[
1
]
-
me
.
getScreenY
())
>
3
)
{
// skip when mouse moved too much
return
;
}
Node
node
=
me
.
getPickResult
().
getIntersectedNode
();
if
(
node
!=
null
)
{
Object
o
=
node
.
getUserData
();
if
(
o
instanceof
ClickDispatcher
cd
)
{
cd
.
click
(
me
,
clickHandler
);
}
}
});
world
=
new
Group
();
root
.
getChildren
().
add
(
world
);
meshGroup
=
new
Group
();
world
.
getChildren
().
add
(
meshGroup
);
AmbientLight
al
=
new
AmbientLight
(
Color
.
WHITE
);
root
.
getChildren
().
add
(
al
);
buildCamera
();
cameraXRotation
.
setAxis
(
Rotate
.
X_AXIS
);
cameraZRotation
.
setAxis
(
Rotate
.
Z_AXIS
);
world
.
getTransforms
().
add
(
cameraXRotation
);
world
.
getTransforms
().
add
(
cameraZRotation
);
root
.
getChildren
().
add
(
camera
);
geomScene
.
setCamera
(
camera
);
setupMeshViewControls
();
}
private
void
setupMeshViewControls
()
{
meshView
.
setOnMousePressed
(
me
->
{
if
(
me
.
getButton
()
==
MouseButton
.
PRIMARY
)
{
dragX
=
me
.
getScreenX
();
dragY
=
me
.
getScreenY
();
}
});
meshView
.
setOnScroll
(
se
->
{
if
(
se
.
getDeltaY
()
<
0
)
{
translateZ
+=
translateZ
*
0.05
;
}
else
{
translateZ
-=
translateZ
*
0.05
;
}
camera
.
setTranslateZ
(
translateZ
);
highlightController
.
changeScaling
(
translateZ
);
});
meshView
.
setOnMouseDragged
(
me
->
{
if
(
me
.
getButton
()
==
MouseButton
.
PRIMARY
)
{
double
deltaX
=
me
.
getScreenX
()
-
dragX
;
double
deltaY
=
me
.
getScreenY
()
-
dragY
;
dragX
=
me
.
getScreenX
();
dragY
=
me
.
getScreenY
();
cameraXRot
+=
(
deltaX
/
3
d
)
%
360
;
cameraYRot
+=
(
deltaY
/
3
d
)
%
360
;
cameraZRotation
.
setAngle
(
cameraXRot
);
cameraXRotation
.
setAngle
(
cameraYRot
);
}
});
}
private
void
buildCamera
()
{
camera
=
new
PerspectiveCamera
(
true
);
camera
.
setNearClip
(
0.1
);
camera
.
setFarClip
(
10000
d
);
camera
.
setTranslateZ
(
translateZ
);
cameraZRotation
.
setAngle
(
cameraXRot
);
cameraXRotation
.
setAngle
(
cameraYRot
);
}
public
void
addFileNameToTitle
(
String
fileName
)
{
String
version
=
Localization
.
getText
(
Localization
.
VERSION
);
stage
.
setTitle
(
"CityDoctor "
+
version
+
" - "
+
fileName
);
}
public
TreeView
<
Renderable
>
getBuildingsView
()
{
return
buildingsView
;
}
public
TreeView
<
Renderable
>
getVegetationView
()
{
return
vegetationView
;
}
public
TreeView
<
Renderable
>
getTransportationView
()
{
return
transView
;
}
public
TreeView
<
Renderable
>
getBridgeView
()
{
return
bridgeView
;
}
public
TreeView
<
Renderable
>
getWaterView
()
{
return
waterView
;
}
public
TreeView
<
Renderable
>
getTerrainView
()
{
return
terrainView
;
}
public
TreeView
<
Renderable
>
getCityFurnitureView
()
{
return
cityFurnitureView
;
}
public
TreeView
<
Renderable
>
getOtherObjectsView
()
{
return
otherObjectsView
;
}
public
TreeView
<
Renderable
>
getPolygonsView
()
{
return
polygonView
;
}
public
TreeView
<
Renderable
>
getEdgeView
()
{
return
edgeView
;
}
public
TreeView
<
Renderable
>
getVertexView
()
{
return
vertexView
;
}
public
Button
getCheckButton
()
{
return
mainToolBar
.
getCheckButton
();
}
public
ToggleButton
getGridButton
()
{
return
mainToolBar
.
getGridButton
();
}
public
Group
getMeshGroup
()
{
return
meshGroup
;
}
public
ToggleButton
getCullingButton
()
{
return
mainToolBar
.
getCullingButton
();
}
public
Button
getWriteReportButton
()
{
return
mainToolBar
.
getWriteReportButton
();
}
public
TreeView
<
Renderable
>
getErrorTree
()
{
return
errorView
;
}
public
Stage
getMainStage
()
{
return
stage
;
}
public
void
unselectEverything
()
{
buildingsView
.
getSelectionModel
().
clearSelection
();
vegetationView
.
getSelectionModel
().
clearSelection
();
transView
.
getSelectionModel
().
clearSelection
();
waterView
.
getSelectionModel
().
clearSelection
();
terrainView
.
getSelectionModel
().
clearSelection
();
cityFurnitureView
.
getSelectionModel
().
clearSelection
();
otherObjectsView
.
getSelectionModel
().
clearSelection
();
bridgeView
.
getSelectionModel
().
clearSelection
();
polygonView
.
getSelectionModel
().
clearSelection
();
edgeView
.
getSelectionModel
().
clearSelection
();
vertexView
.
getSelectionModel
().
clearSelection
();
errorView
.
getSelectionModel
().
clearSelection
();
}
public
ToggleButton
getLod1Btn
()
{
return
mainToolBar
.
getLod1Btn
();
}
public
ToggleButton
getLod2Btn
()
{
return
mainToolBar
.
getLod2Btn
();
}
public
ToggleButton
getLod3Btn
()
{
return
mainToolBar
.
getLod3Btn
();
}
public
ToggleButton
getLod4Btn
()
{
return
mainToolBar
.
getLod4Btn
();
}
public
Button
getWorldBtn
()
{
return
mainToolBar
.
getWorldBtn
();
}
public
Button
getSaveBtn
()
{
return
mainToolBar
.
getSaveBtn
();
}
public
SplitPane
getMainContainer
()
{
return
mainContainer
;
}
public
ListView
<
String
>
getGlobalErrorsView
()
{
return
globalErrorsView
;
}
public
void
takeViewScreenshot
()
throws
IOException
{
WritableImage
snapshot
=
geomScene
.
snapshot
(
null
,
null
);
File
outputFile
=
new
File
(
"img.png"
);
BufferedImage
bImage
=
SwingFXUtils
.
fromFXImage
(
snapshot
,
null
);
ImageIO
.
write
(
bImage
,
"png"
,
outputFile
);
}
public
void
zoomOutForBoundingBox
(
BoundingBox
b
)
{
double
longestSide
=
b
.
getDiagonalLength
()
*
0.4
;
double
d
=
longestSide
/
Math
.
tan
(
Math
.
toRadians
(
30
)
/
2
);
translateZ
=
-
d
;
camera
.
setTranslateZ
(
translateZ
);
highlightController
.
changeScaling
(-
translateZ
);
}
public
MainToolBar
getMainToolbar
()
{
return
mainToolBar
;
}
public
void
clearHighlights
()
{
highlightController
.
clearHighlights
();
}
public
CityDoctorController
getController
()
{
return
controller
;
}
public
Button
getOpenBtn
()
{
return
mainToolBar
.
getOpenBtn
();
}
public
VertexClickHandler
getClickHandler
()
{
return
clickHandler
;
}
public
FeatureType
getSelectedTab
()
{
return
selectedTab
;
}
}
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