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
a5a82382
Commit
a5a82382
authored
Jul 31, 2024
by
Riegel
Browse files
Open Source release of CityDoctor-GUI
parent
7a22ca9c
Pipeline
#10028
failed with stage
in 7 seconds
Changes
126
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/FilterPane.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citydoctor2.check.ExcludeFilterConfiguration
;
import
de.hft.stuttgart.citydoctor2.check.FilterConfiguration
;
import
de.hft.stuttgart.citydoctor2.check.IncludeFilterConfiguration
;
import
de.hft.stuttgart.citydoctor2.datastructure.FeatureType
;
import
de.hft.stuttgart.citydoctor2.gui.filter.TypeFilterSelection
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
javafx.fxml.FXML
;
import
javafx.fxml.FXMLLoader
;
import
javafx.scene.control.Button
;
import
javafx.scene.control.ComboBox
;
import
javafx.scene.control.ScrollPane
;
import
javafx.scene.control.TextField
;
import
javafx.scene.image.Image
;
import
javafx.scene.image.ImageView
;
import
javafx.scene.layout.HBox
;
import
javafx.scene.layout.VBox
;
public
class
FilterPane
{
@FXML
private
VBox
inclFeatureBox
;
@FXML
private
ImageView
addInclFeatureView
;
@FXML
private
VBox
inclMatchBox
;
@FXML
private
ImageView
addInclMatchView
;
@FXML
private
Button
addInclFeatureBtn
;
@FXML
private
Button
addInclMatchBtn
;
@FXML
private
VBox
exclFeatureBox
;
@FXML
private
ImageView
addExclFeatureView
;
@FXML
private
VBox
exclMatchBox
;
@FXML
private
ImageView
addExclMatchView
;
@FXML
private
Button
addExclFeatureBtn
;
@FXML
private
Button
addExclMatchBtn
;
private
ScrollPane
pane
;
private
Image
deleteImg
;
private
List
<
ComboBox
<
TypeFilterSelection
>>
includeTypeBoxes
=
new
ArrayList
<>();
private
List
<
TextField
>
includeMatcherFields
=
new
ArrayList
<>();
private
List
<
TextField
>
excludeMatcherFields
=
new
ArrayList
<>();
private
List
<
ComboBox
<
TypeFilterSelection
>>
excludeTypeBoxes
=
new
ArrayList
<>();
private
List
<
TypeFilterSelection
>
availableFilters
;
public
FilterPane
()
throws
IOException
{
FXMLLoader
fxmlLoader
=
new
FXMLLoader
(
FilterPane
.
class
.
getResource
(
"FilterPane.fxml"
));
fxmlLoader
.
setController
(
this
);
pane
=
fxmlLoader
.
load
();
}
public
void
initialize
()
{
loadImages
();
availableFilters
=
new
ArrayList
<>();
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
BUILDING
,
Localization
.
getText
(
"FilterPane.buildings"
)));
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
BRIDGE
,
Localization
.
getText
(
"FilterPane.bridges"
)));
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
LAND
,
Localization
.
getText
(
"FilterPane.landUse"
)));
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
TRANSPORTATION
,
Localization
.
getText
(
"FilterPane.transportation"
)));
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
VEGETATION
,
Localization
.
getText
(
"FilterPane.vegetation"
)));
availableFilters
.
add
(
new
TypeFilterSelection
(
FeatureType
.
WATER
,
Localization
.
getText
(
"FilterPane.water"
)));
setupIncludeFeatureButton
();
setupIncludeMatchButton
();
setupExcludeFeatureButton
();
setupExcludeMatchButton
();
}
private
void
setupExcludeMatchButton
()
{
addExclMatchBtn
.
setOnAction
(
ae
->
addExcludeMatchField
());
}
private
TextField
addExcludeMatchField
()
{
TextField
tf
=
new
TextField
();
tf
.
setPrefWidth
(
400
);
excludeMatcherFields
.
add
(
tf
);
HBox
box
=
new
HBox
(
10
);
box
.
getChildren
().
add
(
tf
);
ImageView
imgView
=
new
ImageView
(
deleteImg
);
imgView
.
setFitHeight
(
25
);
imgView
.
setFitWidth
(
25
);
box
.
getChildren
().
add
(
imgView
);
imgView
.
setOnMouseClicked
(
me2
->
{
excludeMatcherFields
.
remove
(
tf
);
exclMatchBox
.
getChildren
().
remove
(
box
);
});
exclMatchBox
.
getChildren
().
add
(
box
);
return
tf
;
}
private
void
setupExcludeFeatureButton
()
{
addExclFeatureBtn
.
setOnAction
(
ae
->
addExcludeTypeFilterBox
());
}
private
ComboBox
<
TypeFilterSelection
>
addExcludeTypeFilterBox
()
{
ComboBox
<
TypeFilterSelection
>
cBox
=
new
ComboBox
<>();
cBox
.
setPrefWidth
(
400
);
cBox
.
getItems
().
addAll
(
availableFilters
);
cBox
.
getSelectionModel
().
select
(
0
);
excludeTypeBoxes
.
add
(
cBox
);
HBox
box
=
new
HBox
(
10
);
box
.
getChildren
().
add
(
cBox
);
ImageView
imgView
=
new
ImageView
(
deleteImg
);
imgView
.
setFitHeight
(
25
);
imgView
.
setFitWidth
(
25
);
box
.
getChildren
().
add
(
imgView
);
imgView
.
setOnMouseClicked
(
me2
->
{
excludeTypeBoxes
.
remove
(
cBox
);
exclFeatureBox
.
getChildren
().
remove
(
box
);
});
exclFeatureBox
.
getChildren
().
add
(
box
);
return
cBox
;
}
private
void
setupIncludeMatchButton
()
{
addInclMatchBtn
.
setOnAction
(
ae
->
addIncludeMatchField
());
}
private
TextField
addIncludeMatchField
()
{
TextField
tf
=
new
TextField
();
tf
.
setPrefWidth
(
400
);
includeMatcherFields
.
add
(
tf
);
HBox
box
=
new
HBox
(
10
);
box
.
getChildren
().
add
(
tf
);
ImageView
imgView
=
new
ImageView
(
deleteImg
);
imgView
.
setFitHeight
(
25
);
imgView
.
setFitWidth
(
25
);
box
.
getChildren
().
add
(
imgView
);
imgView
.
setOnMouseClicked
(
me2
->
{
includeMatcherFields
.
remove
(
tf
);
inclMatchBox
.
getChildren
().
remove
(
box
);
});
inclMatchBox
.
getChildren
().
add
(
box
);
return
tf
;
}
public
void
applyFilterConfig
(
FilterConfiguration
filter
)
{
includeMatcherFields
.
clear
();
inclMatchBox
.
getChildren
().
clear
();
includeTypeBoxes
.
clear
();
inclFeatureBox
.
getChildren
().
clear
();
excludeMatcherFields
.
clear
();
exclMatchBox
.
getChildren
().
clear
();
excludeTypeBoxes
.
clear
();
exclFeatureBox
.
getChildren
().
clear
();
applyExcludeFilters
(
filter
);
applyIncludeFilters
(
filter
);
}
private
void
applyIncludeFilters
(
FilterConfiguration
filter
)
{
IncludeFilterConfiguration
include
=
filter
.
getInclude
();
if
(
include
!=
null
)
{
for
(
String
s
:
include
.
getIds
())
{
addIncludeMatchField
().
setText
(
s
);
}
for
(
FeatureType
type
:
include
.
getTypes
())
{
ComboBox
<
TypeFilterSelection
>
box
=
addIncludeTypeFilterBox
();
for
(
TypeFilterSelection
tfs
:
box
.
getItems
())
{
if
(
tfs
.
getType
()
==
type
)
{
box
.
getSelectionModel
().
select
(
tfs
);
}
}
}
}
}
private
void
applyExcludeFilters
(
FilterConfiguration
filter
)
{
ExcludeFilterConfiguration
exclude
=
filter
.
getExclude
();
if
(
exclude
!=
null
)
{
for
(
String
s
:
exclude
.
getIds
())
{
addExcludeMatchField
().
setText
(
s
);
}
for
(
FeatureType
type
:
exclude
.
getTypes
())
{
ComboBox
<
TypeFilterSelection
>
box
=
addExcludeTypeFilterBox
();
for
(
TypeFilterSelection
tfs
:
box
.
getItems
())
{
if
(
tfs
.
getType
()
==
type
)
{
box
.
getSelectionModel
().
select
(
tfs
);
}
}
}
}
}
private
void
setupIncludeFeatureButton
()
{
addInclFeatureBtn
.
setOnAction
(
ae
->
addIncludeTypeFilterBox
());
}
private
ComboBox
<
TypeFilterSelection
>
addIncludeTypeFilterBox
()
{
ComboBox
<
TypeFilterSelection
>
cBox
=
new
ComboBox
<>();
cBox
.
setPrefWidth
(
400
);
cBox
.
getItems
().
addAll
(
availableFilters
);
cBox
.
getSelectionModel
().
select
(
0
);
includeTypeBoxes
.
add
(
cBox
);
HBox
box
=
new
HBox
(
10
);
box
.
getChildren
().
add
(
cBox
);
ImageView
imgView
=
new
ImageView
(
deleteImg
);
imgView
.
setFitHeight
(
25
);
imgView
.
setFitWidth
(
25
);
box
.
getChildren
().
add
(
imgView
);
imgView
.
setOnMouseClicked
(
me2
->
{
includeTypeBoxes
.
remove
(
cBox
);
inclFeatureBox
.
getChildren
().
remove
(
box
);
});
inclFeatureBox
.
getChildren
().
add
(
box
);
return
cBox
;
}
public
FilterConfiguration
getConfiguration
()
{
IncludeFilterConfiguration
includeFilters
=
new
IncludeFilterConfiguration
();
List
<
FeatureType
>
featureTypes
=
new
ArrayList
<>();
for
(
ComboBox
<
TypeFilterSelection
>
box
:
includeTypeBoxes
)
{
featureTypes
.
add
(
box
.
getSelectionModel
().
getSelectedItem
().
getType
());
}
includeFilters
.
setTypes
(
featureTypes
);
List
<
String
>
ids
=
new
ArrayList
<>();
for
(
TextField
tf
:
includeMatcherFields
)
{
ids
.
add
(
tf
.
getText
());
}
includeFilters
.
setIds
(
ids
);
ExcludeFilterConfiguration
excludeFilters
=
new
ExcludeFilterConfiguration
();
List
<
FeatureType
>
excludeFeatureTypes
=
new
ArrayList
<>();
for
(
ComboBox
<
TypeFilterSelection
>
box
:
excludeTypeBoxes
)
{
excludeFeatureTypes
.
add
(
box
.
getSelectionModel
().
getSelectedItem
().
getType
());
}
excludeFilters
.
setTypes
(
excludeFeatureTypes
);
List
<
String
>
excludeIds
=
new
ArrayList
<>();
for
(
TextField
tf
:
excludeMatcherFields
)
{
excludeIds
.
add
(
tf
.
getText
());
}
excludeFilters
.
setIds
(
excludeIds
);
FilterConfiguration
fConfig
=
new
FilterConfiguration
();
fConfig
.
setInclude
(
includeFilters
);
fConfig
.
setExclude
(
excludeFilters
);
return
fConfig
;
}
private
void
loadImages
()
{
try
{
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/Add.png"
))
{
Image
img
=
new
Image
(
inStream
);
addInclFeatureView
.
setImage
(
img
);
addInclMatchView
.
setImage
(
img
);
addExclFeatureView
.
setImage
(
img
);
addExclMatchView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/Delete.png"
))
{
deleteImg
=
new
Image
(
inStream
);
}
}
catch
(
IOException
e
)
{
// ignore close exception
}
}
public
ScrollPane
getPane
()
{
return
pane
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/GlobalParameter.java
0 → 100644
View file @
a5a82382
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.Serializable
;
import
de.hft.stuttgart.citydoctor2.check.Unit
;
public
class
GlobalParameter
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1423983452743345752L
;
private
String
name
;
private
String
value
;
private
Unit
unit
;
public
GlobalParameter
(
String
name
,
String
value
,
Unit
unit
)
{
super
();
this
.
name
=
name
;
this
.
value
=
value
;
this
.
unit
=
unit
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getValue
()
{
return
value
;
}
public
void
setValue
(
String
value
)
{
this
.
value
=
value
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
name
==
null
)
?
0
:
name
.
hashCode
());
result
=
prime
*
result
+
((
unit
==
null
)
?
0
:
unit
.
hashCode
());
result
=
prime
*
result
+
((
value
==
null
)
?
0
:
value
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
GlobalParameter
other
=
(
GlobalParameter
)
obj
;
if
(
name
==
null
)
{
if
(
other
.
name
!=
null
)
return
false
;
}
else
if
(!
name
.
equals
(
other
.
name
))
return
false
;
if
(
unit
!=
other
.
unit
)
return
false
;
if
(
value
==
null
)
{
if
(
other
.
value
!=
null
)
return
false
;
}
else
if
(!
value
.
equals
(
other
.
value
))
return
false
;
return
true
;
}
@Override
public
String
toString
()
{
return
"GlobalParameter [name="
+
name
+
", value="
+
value
+
", unit="
+
unit
+
"]"
;
}
public
Unit
getUnit
()
{
return
unit
;
}
public
void
setUnit
(
Unit
unit
)
{
this
.
unit
=
unit
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/HighlightController.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.util.List
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType
;
import
de.hft.stuttgart.citydoctor2.math.Triangle3d
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
javafx.application.Platform
;
import
javafx.geometry.Point3D
;
import
javafx.scene.Group
;
import
javafx.scene.Node
;
import
javafx.scene.paint.Color
;
import
javafx.scene.paint.PhongMaterial
;
import
javafx.scene.shape.Cylinder
;
import
javafx.scene.shape.Sphere
;
import
javafx.scene.transform.Rotate
;
import
javafx.scene.transform.Translate
;
public
class
HighlightController
{
private
double
scale
;
private
Group
points
;
private
Group
edges
;
private
Group
highlights
;
public
HighlightController
(
Group
world
)
{
highlights
=
new
Group
();
points
=
new
Group
();
edges
=
new
Group
();
highlights
.
getChildren
().
add
(
edges
);
highlights
.
getChildren
().
add
(
points
);
Platform
.
runLater
(()
->
world
.
getChildren
().
add
(
highlights
));
}
public
void
clearHighlights
()
{
points
.
getChildren
().
clear
();
edges
.
getChildren
().
clear
();
}
public
void
changeScaling
(
double
translateZ
)
{
scale
=
Math
.
abs
(
translateZ
);
scale
=
Math
.
min
(
150
,
scale
);
scale
=
Math
.
max
(
10
,
scale
);
scale
=
scale
*
0.01
;
for
(
Node
n
:
points
.
getChildren
())
{
n
.
setScaleX
(
scale
);
n
.
setScaleY
(
scale
);
n
.
setScaleZ
(
scale
);
}
double
edgeSize
=
scale
/
10
;
for
(
Node
n
:
edges
.
getChildren
())
{
if
(
n
instanceof
Cylinder
)
{
Cylinder
cy
=
(
Cylinder
)
n
;
cy
.
setRadius
(
edgeSize
);
}
}
}
public
void
highlight
(
Polygon
p
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
addHighlight
(
p
,
currentTriGeom
,
Color
.
RED
,
Color
.
BLUE
);
}
private
void
addHighlight
(
Polygon
p
,
TriangulatedGeometry
currentTriGeom
,
Color
extColor
,
Color
intColor
)
{
if
(
currentTriGeom
==
null
||
p
==
null
)
{
return
;
}
addHighlight
(
p
.
getExteriorRing
(),
currentTriGeom
,
extColor
);
for
(
LinearRing
intRing
:
p
.
getInnerRings
())
{
addHighlight
(
intRing
,
currentTriGeom
,
intColor
);
}
}
public
void
highlight
(
LinearRing
ring
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
if
(
ring
.
getType
()
==
LinearRingType
.
EXTERIOR
)
{
addHighlight
(
ring
,
currentTriGeom
,
Color
.
RED
);
}
else
{
addHighlight
(
ring
,
currentTriGeom
,
Color
.
BLUE
);
}
}
public
void
highlight
(
List
<
LinearRing
>
rings
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
for
(
LinearRing
lr
:
rings
)
{
if
(
lr
.
getType
()
==
LinearRingType
.
EXTERIOR
)
{
addHighlight
(
lr
,
currentTriGeom
,
Color
.
RED
);
}
else
{
addHighlight
(
lr
,
currentTriGeom
,
Color
.
BLUE
);
}
}
}
private
void
addHighlight
(
LinearRing
ring
,
TriangulatedGeometry
currentTriGeom
,
Color
pointColor
)
{
if
(
currentTriGeom
==
null
||
ring
==
null
)
{
return
;
}
Vector3d
movedBy
=
currentTriGeom
.
getMovedBy
();
for
(
Vertex
v
:
ring
.
getVertices
())
{
highlightPoint
(
movedBy
,
v
,
pointColor
);
}
for
(
int
i
=
0
;
i
<
ring
.
getVertices
().
size
()
-
1
;
i
++)
{
Vertex
v1
=
ring
.
getVertices
().
get
(
i
+
0
);
Vertex
v2
=
ring
.
getVertices
().
get
(
i
+
1
);
highlightEdge
(
v1
,
v2
,
movedBy
);
}
}
public
void
highlight
(
Edge
e
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
addHighlight
(
e
,
currentTriGeom
);
}
private
void
addHighlight
(
Edge
e
,
TriangulatedGeometry
currentTriGeom
)
{
if
(
currentTriGeom
==
null
||
e
==
null
)
{
return
;
}
Vector3d
movedBy
=
currentTriGeom
.
getMovedBy
();
highlightEdge
(
e
.
getFrom
(),
e
.
getTo
(),
movedBy
);
highlightPoint
(
movedBy
,
e
.
getFrom
(),
Color
.
RED
);
highlightPoint
(
movedBy
,
e
.
getTo
(),
Color
.
RED
);
}
public
void
highlight
(
Vertex
v
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
addHighlight
(
v
,
currentTriGeom
,
Color
.
RED
);
}
public
void
addHighlight
(
Vertex
v
,
TriangulatedGeometry
currentTriGeom
,
Color
c
)
{
if
(
currentTriGeom
==
null
||
v
==
null
)
{
return
;
}
Vector3d
movedBy
=
currentTriGeom
.
getMovedBy
();
highlightPoint
(
movedBy
,
v
,
c
);
}
private
void
highlightPoint
(
Vector3d
movedBy
,
Vertex
v
,
Color
color
)
{
Sphere
sp
=
new
Sphere
(
0.5
);
sp
.
setMaterial
(
new
PhongMaterial
(
color
));
sp
.
setTranslateX
(
v
.
getX
()
-
movedBy
.
getX
());
sp
.
setTranslateY
(
v
.
getY
()
-
movedBy
.
getY
());
sp
.
setTranslateZ
(
v
.
getZ
()
-
movedBy
.
getZ
());
sp
.
setScaleX
(
scale
);
sp
.
setScaleY
(
scale
);
sp
.
setScaleZ
(
scale
);
sp
.
setUserData
(
new
VertexClickDispatcher
(
v
));
points
.
getChildren
().
add
(
sp
);
}
private
void
highlightEdge
(
Vector3d
v1
,
Vector3d
v2
,
Vector3d
movedBy
)
{
Point3D
origin
=
new
Point3D
(
v1
.
getX
()
-
movedBy
.
getX
(),
v1
.
getY
()
-
movedBy
.
getY
(),
v1
.
getZ
()
-
movedBy
.
getZ
());
Point3D
target
=
new
Point3D
(
v2
.
getX
()
-
movedBy
.
getX
(),
v2
.
getY
()
-
movedBy
.
getY
(),
v2
.
getZ
()
-
movedBy
.
getZ
());
Point3D
yAxis
=
new
Point3D
(
0
,
1
,
0
);
Point3D
diff
=
target
.
subtract
(
origin
);
double
height
=
diff
.
magnitude
();
Point3D
mid
=
target
.
midpoint
(
origin
);
Translate
moveToMidpoint
=
new
Translate
(
mid
.
getX
(),
mid
.
getY
(),
mid
.
getZ
());
Point3D
axisOfRotation
=
diff
.
crossProduct
(
yAxis
);
double
angle
=
Math
.
acos
(
diff
.
normalize
().
dotProduct
(
yAxis
));
Rotate
rotateAroundCenter
=
new
Rotate
(-
Math
.
toDegrees
(
angle
),
axisOfRotation
);
Cylinder
cy
=
new
Cylinder
(
scale
/
10
,
height
);
cy
.
setMaterial
(
new
PhongMaterial
(
Color
.
ORANGE
));
cy
.
getTransforms
().
addAll
(
moveToMidpoint
,
rotateAroundCenter
);
edges
.
getChildren
().
add
(
cy
);
}
public
void
highlightEdges
(
List
<
Edge
>
errorEdges
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
for
(
Edge
e
:
errorEdges
)
{
addHighlight
(
e
,
currentTriGeom
);
}
}
public
void
highlightPolygons
(
List
<
List
<
Polygon
>>
components
,
TriangulatedGeometry
currentTriGeom
)
{
clearHighlights
();
for
(
int
i
=
0
;
i
<
components
.
size
();
i
++)
{
Color
extColor
;
Color
intColor
;
// select some color pairs for exterior and inner rings
switch
(
i
%
3
)
{
case
1
:
extColor
=
Color
.
GREEN
;
intColor
=
Color
.
YELLOW
;
break
;
case
2
:
extColor
=
Color
.
BROWN
;
intColor
=
Color
.
VIOLET
;
break
;
default
:
extColor
=
Color
.
RED
;
intColor
=
Color
.
BLUE
;
}
List
<
Polygon
>
component
=
components
.
get
(
i
);
for
(
Polygon
p
:
component
)
{
addHighlight
(
p
,
currentTriGeom
,
extColor
,
intColor
);
}
}
}
public
void
addHighlight
(
Polygon
p
,
TriangulatedGeometry
currentTriGeom
)
{
addHighlight
(
p
,
currentTriGeom
,
Color
.
RED
,
Color
.
BLUE
);
}
public
void
highlight
(
Triangle3d
t
,
TriangulatedGeometry
currentTriGeom
)
{
highlightEdge
(
t
.
getP1
(),
t
.
getP2
(),
currentTriGeom
.
getMovedBy
());
highlightEdge
(
t
.
getP2
(),
t
.
getP3
(),
currentTriGeom
.
getMovedBy
());
highlightEdge
(
t
.
getP3
(),
t
.
getP1
(),
currentTriGeom
.
getMovedBy
());
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LanguageSelectorCell.java
0 → 100644
View file @
a5a82382
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.Map
;
import
javafx.scene.control.ListCell
;
import
javafx.scene.image.Image
;
import
javafx.scene.image.ImageView
;
public
class
LanguageSelectorCell
extends
ListCell
<
Locale
>
{
private
static
Map
<
String
,
Image
>
imageCache
=
new
HashMap
<>();
@Override
protected
void
updateItem
(
Locale
item
,
boolean
empty
)
{
super
.
updateItem
(
item
,
empty
);
if
(
item
==
null
||
empty
)
{
setGraphic
(
null
);
}
else
{
String
country
=
item
.
getLanguage
().
toLowerCase
(
Locale
.
US
);
Image
iconRef
=
imageCache
.
computeIfAbsent
(
country
,
key
->
{
String
iconPath
=
"icons/icon_"
+
country
+
".png"
;
return
new
Image
(
MainWindow
.
class
.
getResourceAsStream
(
iconPath
));
});
ImageView
iconImageView
=
new
ImageView
(
iconRef
);
setGraphic
(
iconImageView
);
}
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.ErrorVisitor
;
import
de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError
;
import
de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation
;
import
de.hft.stuttgart.citydoctor2.check.error.NotCeilingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NotFloorError
;
import
de.hft.stuttgart.citydoctor2.check.error.NotGroundError
;
import
de.hft.stuttgart.citydoctor2.check.error.NotWallError
;
import
de.hft.stuttgart.citydoctor2.check.error.NullAreaError
;
import
de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonWithoutSurfaceError
;
import
de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError
;
import
de.hft.stuttgart.citydoctor2.check.error.SchematronError
;
import
de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError
;
import
de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError
;
import
de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError
;
import
de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError
;
import
de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
javafx.scene.paint.Color
;
public
class
ListErrorVisitor
implements
ErrorVisitor
{
private
HighlightController
controller
;
private
TriangulatedGeometry
geom
;
public
ListErrorVisitor
(
HighlightController
controller
)
{
this
.
controller
=
controller
;
}
public
void
setGeometry
(
TriangulatedGeometry
geom
)
{
this
.
geom
=
geom
;
}
@Override
public
void
visit
(
PolygonHoleOutsideError
err
)
{
List
<
LinearRing
>
highlightedRings
=
new
ArrayList
<>();
highlightedRings
.
add
(
err
.
getPolygon
().
getExteriorRing
());
highlightedRings
.
addAll
(
err
.
getHolesOutside
());
controller
.
highlight
(
highlightedRings
,
geom
);
}
@Override
public
void
visit
(
NonManifoldEdgeError
err
)
{
controller
.
highlightEdges
(
err
.
getEdges
(),
geom
);
}
@Override
public
void
visit
(
MultipleConnectedComponentsError
err
)
{
controller
.
highlightPolygons
(
err
.
getComponents
(),
geom
);
}
@Override
public
void
visit
(
NestedRingError
err
)
{
List
<
LinearRing
>
highlightedRings
=
new
ArrayList
<>();
highlightedRings
.
add
(
err
.
getPolygon
().
getExteriorRing
());
highlightedRings
.
add
(
err
.
getInnerRing
());
controller
.
highlight
(
highlightedRings
,
geom
);
}
@Override
public
void
visit
(
NonManifoldVertexError
err
)
{
controller
.
highlightPolygons
(
err
.
getComponents
(),
geom
);
controller
.
addHighlight
(
err
.
getVertex
(),
geom
,
Color
.
BLUEVIOLET
);
}
@Override
public
void
visit
(
PolygonWrongOrientationError
err
)
{
controller
.
highlightEdges
(
err
.
getEdges
(),
geom
);
}
@Override
public
void
visit
(
PolygonSameOrientationError
err
)
{
List
<
LinearRing
>
highlightedRings
=
new
ArrayList
<>();
highlightedRings
.
add
(
err
.
getPolygon
().
getExteriorRing
());
highlightedRings
.
add
(
err
.
getInnerRing
());
controller
.
highlight
(
highlightedRings
,
geom
);
}
@Override
public
void
visit
(
SolidNotClosedError
err
)
{
controller
.
highlightEdges
(
err
.
getErrorEdges
(),
geom
);
}
@Override
public
void
visit
(
DependenciesNotMetError
err
)
{
// don't display
}
@Override
public
void
visit
(
UnknownCheckError
err
)
{
// don't display
}
@Override
public
void
visit
(
RingNotClosedError
err
)
{
controller
.
highlight
(
err
.
getRing
(),
geom
);
}
@Override
public
void
visit
(
ConsecutivePointSameError
err
)
{
controller
.
highlight
(
err
.
getRing
(),
geom
);
controller
.
addHighlight
(
err
.
getVertex1
(),
geom
,
Color
.
BLACK
);
controller
.
addHighlight
(
err
.
getVertex2
(),
geom
,
Color
.
BLACK
);
}
@Override
public
void
visit
(
AllPolygonsWrongOrientationError
err
)
{
// don't display
}
@Override
public
void
visit
(
PolygonInteriorDisconnectedError
err
)
{
controller
.
highlight
(
err
.
getConnectedRings
(),
geom
);
}
@Override
public
void
visit
(
NullAreaError
err
)
{
// don't display
}
@Override
public
void
visit
(
RingTooFewPointsError
err
)
{
controller
.
highlight
(
err
.
getRing
(),
geom
);
}
@Override
public
void
visit
(
NonPlanarPolygonNormalsDeviation
err
)
{
controller
.
highlight
(
err
.
getPolygon
(),
geom
);
}
@Override
public
void
visit
(
NonPlanarPolygonDistancePlaneError
err
)
{
controller
.
highlight
(
err
.
getPolygon
(),
geom
);
controller
.
addHighlight
(
err
.
getVertex
(),
geom
,
Color
.
BLACK
);
}
@Override
public
void
visit
(
PolygonIntersectingRingsError
err
)
{
List
<
LinearRing
>
rings
=
new
ArrayList
<>();
rings
.
add
(
err
.
getIntersectingRings
().
getValue0
());
rings
.
add
(
err
.
getIntersectingRings
().
getValue1
());
controller
.
highlight
(
rings
,
geom
);
}
@Override
public
void
visit
(
SolidSelfIntError
err
)
{
// nothing to display for now
}
@Override
public
void
visit
(
TooFewPolygonsError
err
)
{
// don't display
}
@Override
public
void
visit
(
RingDuplicatePointError
err
)
{
controller
.
highlight
(
err
.
getRing
(),
geom
);
controller
.
addHighlight
(
err
.
getVertex1
(),
geom
,
Color
.
BLACK
);
controller
.
addHighlight
(
err
.
getVertex2
(),
geom
,
Color
.
BLACK
);
}
@Override
public
void
visit
(
RingEdgeIntersectionError
err
)
{
List
<
Edge
>
list
=
new
ArrayList
<>();
list
.
add
(
err
.
getEdge1
());
list
.
add
(
err
.
getEdge2
());
controller
.
highlightEdges
(
list
,
geom
);
controller
.
addHighlight
(
new
Vertex
(
err
.
getIntersection
()),
geom
,
Color
.
BLACK
);
}
@Override
public
void
visit
(
PointTouchesEdgeError
err
)
{
controller
.
highlight
(
err
.
getEdge
(),
geom
);
controller
.
addHighlight
(
err
.
getVertex
(),
geom
,
Color
.
BLACK
);
}
@Override
public
void
visit
(
CheckError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
NotCeilingError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
NotFloorError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
NotWallError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
NotGroundError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
SchematronError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
SurfaceUnfragmentedError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
DegeneratedRingError
err
)
{
controller
.
highlight
(
err
.
getRing
(),
geom
);
}
@Override
public
void
visit
(
AttributeMissingError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
AttributeValueWrongError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
AttributeInvalidError
err
)
{
// nothing to display
}
@Override
public
void
visit
(
PolygonWithoutSurfaceError
err
)
{
controller
.
highlight
(
err
.
getPolygon
(),
geom
);
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/LoadingInfoDialog.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.IOException
;
import
javafx.fxml.FXMLLoader
;
import
javafx.scene.Scene
;
import
javafx.scene.layout.VBox
;
import
javafx.stage.Modality
;
import
javafx.stage.Stage
;
import
javafx.stage.StageStyle
;
import
javafx.stage.Window
;
public
class
LoadingInfoDialog
{
private
Stage
stage
;
public
LoadingInfoDialog
(
Window
parent
)
throws
IOException
{
FXMLLoader
loader
=
new
FXMLLoader
(
LoadingInfoDialog
.
class
.
getResource
(
"CreateRenderDataDialog.fxml"
));
loader
.
setController
(
this
);
VBox
box
=
loader
.
load
();
stage
=
new
Stage
(
StageStyle
.
UNDECORATED
);
Scene
scene
=
new
Scene
(
box
);
scene
.
setFill
(
null
);
stage
.
setScene
(
scene
);
stage
.
initOwner
(
parent
);
stage
.
initModality
(
Modality
.
APPLICATION_MODAL
);
}
public
void
show
()
{
stage
.
show
();
}
public
void
hide
()
{
stage
.
hide
();
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainToolBar.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
de.hft.stuttgart.citydoctor2.gui.tree.Renderable
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
javafx.fxml.FXML
;
import
javafx.fxml.FXMLLoader
;
import
javafx.scene.control.Button
;
import
javafx.scene.control.Tab
;
import
javafx.scene.control.TabPane
;
import
javafx.scene.control.ToggleButton
;
import
javafx.scene.control.Tooltip
;
import
javafx.scene.control.TreeView
;
import
javafx.scene.image.Image
;
import
javafx.scene.image.ImageView
;
import
javafx.scene.layout.HBox
;
import
javafx.stage.Stage
;
public
class
MainToolBar
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
MainToolBar
.
class
);
@FXML
private
Button
saveBtn
;
@FXML
private
ImageView
saveView
;
@FXML
private
Button
openBtn
;
@FXML
private
ImageView
openImageView
;
@FXML
private
Button
checkBtn
;
@FXML
private
ImageView
checkImageView
;
@FXML
private
Button
showWorldBtn
;
@FXML
private
ImageView
showWorldImageView
;
@FXML
private
Button
schematronBtn
;
@FXML
private
ImageView
schematronImgView
;
@FXML
private
ToggleButton
lod1Btn
;
@FXML
private
ImageView
lod1View
;
@FXML
private
ToggleButton
lod2Btn
;
@FXML
private
ImageView
lod2View
;
@FXML
private
ToggleButton
lod3Btn
;
@FXML
private
ImageView
lod3View
;
@FXML
private
ToggleButton
lod4Btn
;
@FXML
private
ImageView
lod4View
;
@FXML
private
Button
aboutBtn
;
@FXML
private
ImageView
aboutImgView
;
@FXML
private
ToggleButton
gridButton
;
@FXML
private
ToggleButton
cullingButton
;
@FXML
private
ImageView
cullingImageView
;
@FXML
private
ImageView
gridImageView
;
@FXML
private
Button
reportBtn
;
@FXML
private
ImageView
reportImageView
;
private
OpenFileDialog
fileDialog
;
private
CheckDialog
checkDialog
;
private
WriteReportDialog
writeDialog
;
private
AboutDialog
aboutDialog
;
private
CityDoctorController
controller
;
private
TabPane
featurePane
;
private
Stage
stage
;
private
Renderer
renderer
;
private
MainWindow
mainWindow
;
private
HBox
toolBar
;
public
MainToolBar
(
Stage
stage
,
CityDoctorController
controller
,
TabPane
featurePane
,
Renderer
renderer
,
MainWindow
mainWindow
)
throws
IOException
{
this
.
controller
=
controller
;
this
.
featurePane
=
featurePane
;
this
.
renderer
=
renderer
;
this
.
stage
=
stage
;
this
.
mainWindow
=
mainWindow
;
FXMLLoader
loader
=
new
FXMLLoader
(
MainToolBar
.
class
.
getResource
(
"MainToolBar.fxml"
));
loader
.
setController
(
this
);
toolBar
=
loader
.
load
();
fileDialog
=
new
OpenFileDialog
(
stage
,
controller
);
}
public
void
initialize
()
{
openBtn
.
setOnAction
(
ae
->
fileDialog
.
show
());
setupSaveBtn
();
setupCheckButton
();
setupLodButtons
();
setupAboutButton
();
setupReportButton
();
loadImages
();
gridButton
.
setOnAction
(
ae
->
renderer
.
showWireFrame
(
gridButton
.
isSelected
()));
gridButton
.
setTooltip
(
new
Tooltip
(
Localization
.
getText
(
"MainToolBar.wireframe"
)));
cullingButton
.
setOnAction
(
ae
->
renderer
.
enableCulling
(
cullingButton
.
isSelected
()));
cullingButton
.
setTooltip
(
new
Tooltip
(
Localization
.
getText
(
"MainToolBar.culling"
)));
showWorldBtn
.
setOnAction
(
ar
->
{
Tab
selectedItem
=
featurePane
.
getSelectionModel
().
getSelectedItem
();
if
(
selectedItem
.
getContent
()
instanceof
TreeView
)
{
@SuppressWarnings
(
"unchecked"
)
TreeView
<
Renderable
>
content
=
(
TreeView
<
Renderable
>)
selectedItem
.
getContent
();
content
.
getSelectionModel
().
clearSelection
();
}
controller
.
showWorld
();
});
}
private
void
loadImages
()
{
try
{
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/openFolderIcon.png"
))
{
Image
img
=
new
Image
(
inStream
);
openImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/check32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
checkImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/wireframe32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
gridImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/Culling.png"
))
{
Image
img
=
new
Image
(
inStream
);
cullingImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/error_stat32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
reportImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/scene.png"
))
{
Image
img
=
new
Image
(
inStream
);
showWorldImageView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/lod1_32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
lod1View
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/lod2_32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
lod2View
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/lod3_32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
lod3View
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/lod4_32x32.png"
))
{
Image
img
=
new
Image
(
inStream
);
lod4View
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/about.png"
))
{
Image
img
=
new
Image
(
inStream
);
aboutImgView
.
setImage
(
img
);
}
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/save.png"
))
{
Image
img
=
new
Image
(
inStream
);
saveView
.
setImage
(
img
);
}
}
catch
(
IOException
e
)
{
// ignore close exception
}
}
private
void
setupReportButton
()
{
reportBtn
.
setDisable
(
true
);
reportBtn
.
setTooltip
(
new
Tooltip
(
Localization
.
getText
(
"MainToolBar.writeReports"
)));
reportBtn
.
setOnAction
(
ae
->
{
if
(
writeDialog
==
null
)
{
try
{
writeDialog
=
new
WriteReportDialog
(
stage
,
controller
,
mainWindow
);
}
catch
(
IOException
e
)
{
logger
.
catching
(
e
);
mainWindow
.
showExceptionDialog
(
e
);
}
}
if
(
writeDialog
!=
null
)
{
// writeDialog can be null if creation of said dialog fails
writeDialog
.
show
();
}
});
}
private
void
setupAboutButton
()
{
aboutBtn
.
setOnAction
(
ae
->
{
if
(
aboutDialog
==
null
)
{
try
{
aboutDialog
=
new
AboutDialog
(
stage
);
aboutDialog
.
show
();
}
catch
(
IOException
e
)
{
logger
.
error
(
"Could not load about dialog."
,
e
);
}
}
else
{
aboutDialog
.
show
();
}
});
}
private
void
setupLodButtons
()
{
lod1Btn
.
setOnAction
(
ae
->
{
if
(
lod1Btn
.
isSelected
())
{
renderer
.
enableLod1
();
}
else
{
renderer
.
disableLod1
();
}
});
lod2Btn
.
setOnAction
(
ae
->
{
if
(
lod2Btn
.
isSelected
())
{
renderer
.
enableLod2
();
}
else
{
renderer
.
disableLod2
();
}
});
lod3Btn
.
setOnAction
(
ae
->
{
if
(
lod3Btn
.
isSelected
())
{
renderer
.
enableLod3
();
}
else
{
renderer
.
disableLod3
();
}
});
lod4Btn
.
setOnAction
(
ae
->
{
if
(
lod4Btn
.
isSelected
())
{
renderer
.
enableLod4
();
}
else
{
renderer
.
disableLod4
();
}
});
}
private
void
setupSaveBtn
()
{
saveBtn
.
setOnAction
(
ae
->
controller
.
askAndSave
());
}
private
void
setupCheckButton
()
{
checkBtn
.
setDisable
(
true
);
checkBtn
.
setTooltip
(
new
Tooltip
(
Localization
.
getText
(
"MainToolBar.executeChecks"
)));
checkBtn
.
setOnAction
(
ae
->
{
if
(
checkDialog
==
null
)
{
try
{
checkDialog
=
new
CheckDialog
(
mainWindow
,
stage
,
controller
);
}
catch
(
IOException
e
)
{
mainWindow
.
showExceptionDialog
(
e
);
logger
.
catching
(
e
);
}
}
checkDialog
.
show
();
});
}
public
Button
getCheckButton
()
{
return
checkBtn
;
}
public
ToggleButton
getGridButton
()
{
return
gridButton
;
}
public
ToggleButton
getCullingButton
()
{
return
cullingButton
;
}
public
Button
getWriteReportButton
()
{
return
reportBtn
;
}
public
ToggleButton
getLod1Btn
()
{
return
lod1Btn
;
}
public
ToggleButton
getLod2Btn
()
{
return
lod2Btn
;
}
public
ToggleButton
getLod3Btn
()
{
return
lod3Btn
;
}
public
ToggleButton
getLod4Btn
()
{
return
lod4Btn
;
}
public
Button
getWorldBtn
()
{
return
showWorldBtn
;
}
public
Button
getSaveBtn
()
{
return
saveBtn
;
}
public
HBox
getToolBar
()
{
return
toolBar
;
}
public
Button
getOpenBtn
()
{
return
openBtn
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.awt.image.BufferedImage
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Optional
;
import
java.util.Timer
;
import
java.util.TimerTask
;
import
javax.imageio.ImageIO
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
de.hft.stuttgart.citydoctor2.CityDoctorValidation
;
import
de.hft.stuttgart.citydoctor2.check.ValidationConfiguration
;
import
de.hft.stuttgart.citydoctor2.datastructure.BoundingBox
;
import
de.hft.stuttgart.citydoctor2.datastructure.FeatureType
;
import
de.hft.stuttgart.citydoctor2.gui.logger.GuiLogger
;
import
de.hft.stuttgart.citydoctor2.gui.tree.BuildingNode
;
import
de.hft.stuttgart.citydoctor2.gui.tree.Renderable
;
import
de.hft.stuttgart.citydoctor2.gui.tree.RenderableTreeCell
;
import
de.hft.stuttgart.citydoctor2.parameter.ArgumentParser
;
import
de.hft.stuttgart.citydoctor2.parser.CityGmlParseException
;
import
de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException
;
import
de.hft.stuttgart.citydoctor2.parser.ProgressListener
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
javafx.application.Application
;
import
javafx.application.Platform
;
import
javafx.beans.value.ChangeListener
;
import
javafx.embed.swing.SwingFXUtils
;
import
javafx.fxml.FXML
;
import
javafx.fxml.FXMLLoader
;
import
javafx.scene.AmbientLight
;
import
javafx.scene.Group
;
import
javafx.scene.Node
;
import
javafx.scene.PerspectiveCamera
;
import
javafx.scene.Scene
;
import
javafx.scene.SceneAntialiasing
;
import
javafx.scene.SubScene
;
import
javafx.scene.control.Alert
;
import
javafx.scene.control.Alert.AlertType
;
import
javafx.scene.control.Button
;
import
javafx.scene.control.ButtonType
;
import
javafx.scene.control.ComboBox
;
import
javafx.scene.control.ContextMenu
;
import
javafx.scene.control.Label
;
import
javafx.scene.control.ListCell
;
import
javafx.scene.control.ListView
;
import
javafx.scene.control.MenuItem
;
import
javafx.scene.control.ProgressBar
;
import
javafx.scene.control.RadioButton
;
import
javafx.scene.control.SplitPane
;
import
javafx.scene.control.Tab
;
import
javafx.scene.control.TabPane
;
import
javafx.scene.control.TextArea
;
import
javafx.scene.control.TextField
;
import
javafx.scene.control.ToggleButton
;
import
javafx.scene.control.ToggleGroup
;
import
javafx.scene.control.ToolBar
;
import
javafx.scene.control.TreeItem
;
import
javafx.scene.control.TreeView
;
import
javafx.scene.image.Image
;
import
javafx.scene.image.ImageView
;
import
javafx.scene.image.WritableImage
;
import
javafx.scene.input.Dragboard
;
import
javafx.scene.input.MouseButton
;
import
javafx.scene.input.MouseEvent
;
import
javafx.scene.input.TransferMode
;
import
javafx.scene.layout.BorderPane
;
import
javafx.scene.layout.HBox
;
import
javafx.scene.layout.Pane
;
import
javafx.scene.layout.Priority
;
import
javafx.scene.paint.Color
;
import
javafx.scene.transform.Rotate
;
import
javafx.stage.Stage
;
public
class
MainWindow
extends
Application
{
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
;
@FXML
private
TreeView
<
Renderable
>
buildingsView
;
@FXML
private
TreeView
<
Renderable
>
vegetationView
;
@FXML
private
TreeView
<
Renderable
>
transView
;
@FXML
private
TreeView
<
Renderable
>
bridgeView
;
@FXML
private
TreeView
<
Renderable
>
waterView
;
@FXML
private
TreeView
<
Renderable
>
terrainView
;
@FXML
private
TreeView
<
Renderable
>
polygonView
;
@FXML
private
TreeView
<
Renderable
>
edgeView
;
@FXML
private
TreeView
<
Renderable
>
vertexView
;
@FXML
private
Pane
meshView
;
@FXML
private
SplitPane
mainContainer
;
@FXML
private
TabPane
detailsTabPane
;
@FXML
private
TabPane
featurePane
;
@FXML
private
TextField
searchField
;
@FXML
private
TreeView
<
Renderable
>
errorView
;
@FXML
private
Button
clearBtn
;
@FXML
private
Button
searchBtn
;
@FXML
private
ToggleButton
allButton
;
@FXML
private
ToggleButton
errorButton
;
@FXML
private
ComboBox
<
String
>
showCityObjectsCombo
;
@FXML
private
HBox
viewPane
;
@FXML
private
ListView
<
String
>
globalErrorsView
;
@FXML
private
BorderPane
mainPane
;
@FXML
private
HBox
viewButtonBox
;
@FXML
private
ComboBox
<
Locale
>
languageSelector
;
@FXML
private
Tab
buildingsTab
;
@FXML
private
Tab
vegetationTab
;
@FXML
private
Tab
transportationTab
;
@FXML
private
Tab
bridgeTab
;
@FXML
private
Tab
waterTab
;
@FXML
private
Tab
terrainTab
;
@FXML
private
Tab
errorsTab
;
@FXML
private
Tab
polygonsTab
;
@FXML
private
Tab
edgesTab
;
@FXML
private
Tab
verticesTab
;
@FXML
private
Tab
logTab
;
@FXML
private
Tab
globalErrorsTab
;
@FXML
private
Label
viewLabel
;
@FXML
private
Label
showLabel
;
@FXML
private
Label
searchLabel
;
@FXML
private
Label
memoryLabel
;
@FXML
private
ProgressBar
memoryBar
;
@FXML
private
Label
memoryConsumptionLabel
;
@FXML
private
Label
availableLabel
;
private
Group
meshGroup
;
private
Group
world
;
private
PerspectiveCamera
camera
;
private
Rotate
cameraXRotation
=
new
Rotate
();
private
Rotate
cameraZRotation
=
new
Rotate
();
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
];
@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"
));
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
<
String
>()
{
@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
;
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
)
{
BuildingNode
node
=
(
BuildingNode
)
render
;
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
());
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
)
{
ClickDispatcher
cd
=
(
ClickDispatcher
)
o
;
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
>
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
();
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
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ModelProvider.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
public
class
ModelProvider
{
private
CityDoctorController
controller
;
public
ModelProvider
(
CityDoctorController
controller
)
{
this
.
controller
=
controller
;
}
public
CityDoctorModel
getModel
()
{
return
controller
.
getModel
();
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/OpenFileDialog.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.File
;
import
java.io.IOException
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
javafx.application.Platform
;
import
javafx.event.Event
;
import
javafx.fxml.FXML
;
import
javafx.fxml.FXMLLoader
;
import
javafx.scene.Scene
;
import
javafx.scene.control.Button
;
import
javafx.scene.control.CheckBox
;
import
javafx.scene.control.Label
;
import
javafx.scene.control.ProgressBar
;
import
javafx.scene.control.TextField
;
import
javafx.scene.control.TextFormatter
;
import
javafx.scene.control.TitledPane
;
import
javafx.scene.image.Image
;
import
javafx.scene.input.KeyCode
;
import
javafx.scene.input.KeyEvent
;
import
javafx.scene.layout.VBox
;
import
javafx.stage.FileChooser
;
import
javafx.stage.FileChooser.ExtensionFilter
;
import
javafx.stage.Modality
;
import
javafx.stage.Stage
;
import
javafx.stage.Window
;
public
class
OpenFileDialog
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
OpenFileDialog
.
class
);
private
Stage
stage
;
@FXML
private
Button
loadBtn
;
@FXML
private
Button
cancelBtn
;
@FXML
private
Button
selectBtn
;
@FXML
private
TextField
precisionField
;
@FXML
private
TextField
pathField
;
@FXML
private
ProgressBar
progress
;
@FXML
private
CheckBox
useValidationBox
;
@FXML
private
Label
fileLabel
;
@FXML
private
TitledPane
settingsPane
;
@FXML
private
Label
roundingPlacesLabel
;
@FXML
private
Label
xmlValidationLabel
;
@FXML
private
Label
lowMemoryLabel
;
@FXML
private
CheckBox
lowMemoryBox
;
private
CityDoctorController
controller
;
private
ExceptionDialog
exDialog
;
private
FileChooser
fc
;
public
OpenFileDialog
(
Window
parent
,
CityDoctorController
controller
)
throws
IOException
{
FXMLLoader
loader
=
new
FXMLLoader
(
OpenFileDialog
.
class
.
getResource
(
"OpenFileDialog.fxml"
));
loader
.
setController
(
this
);
VBox
box
=
loader
.
load
();
this
.
controller
=
controller
;
stage
=
new
Stage
();
stage
.
getIcons
().
add
(
new
Image
(
MainWindow
.
class
.
getResourceAsStream
(
"icons/CityDoctor-Logo-rot_klein.jpg"
)));
stage
.
setScene
(
new
Scene
(
box
));
stage
.
initOwner
(
parent
);
stage
.
initModality
(
Modality
.
APPLICATION_MODAL
);
stage
.
setTitle
(
"Open File"
);
stage
.
getScene
().
addEventFilter
(
KeyEvent
.
KEY_PRESSED
,
(
KeyEvent
event
)
->
{
if
(
event
.
getCode
()
==
KeyCode
.
ESCAPE
)
{
stage
.
close
();
}
});
}
public
void
initialize
()
{
cancelBtn
.
setOnAction
(
ae
->
stage
.
close
());
setupPrecisionField
();
setupLoadButton
();
setupSelectButton
();
applyLanguageToControls
();
}
private
void
applyLanguageToControls
()
{
fileLabel
.
setText
(
Localization
.
getText
(
"OpenFileDialog.fileLabel"
));
selectBtn
.
setText
(
Localization
.
getText
(
"OpenFileDialog.selectBtn"
));
loadBtn
.
setText
(
Localization
.
getText
(
"OpenFileDialog.loadBtn"
));
settingsPane
.
setText
(
Localization
.
getText
(
"OpenFileDialog.settingsPane"
));
roundingPlacesLabel
.
setText
(
Localization
.
getText
(
"OpenFileDialog.roundingPlacesLabel"
));
xmlValidationLabel
.
setText
(
Localization
.
getText
(
"OpenFileDialog.xmlValidationLabel"
));
cancelBtn
.
setText
(
Localization
.
getText
(
"OpenFileDialog.cancelBtn"
));
lowMemoryLabel
.
setText
(
Localization
.
getText
(
"OpenFileDialog.lowMemoryLabel"
));
}
private
void
setupSelectButton
()
{
selectBtn
.
setOnAction
(
ae
->
{
if
(
fc
==
null
)
{
fc
=
new
FileChooser
();
fc
.
setTitle
(
Localization
.
getText
(
"OpenFileDialog.select"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
"GML/XML"
,
"*.gml"
,
"*.xml"
));
fc
.
getExtensionFilters
().
add
(
new
ExtensionFilter
(
Localization
.
getText
(
"MainWindow.all"
),
"*.*"
));
}
File
dir
=
new
File
(
Settings
.
get
(
Settings
.
LAST_OPEN_FOLDER
,
""
));
if
(
dir
.
exists
()
&&
dir
.
isDirectory
())
{
fc
.
setInitialDirectory
(
dir
);
}
else
{
String
userDir
=
System
.
getProperty
(
"user.dir"
);
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
userDir
);
fc
.
setInitialDirectory
(
new
File
(
userDir
));
}
File
f
=
fc
.
showOpenDialog
(
stage
);
if
(
f
!=
null
)
{
Settings
.
set
(
Settings
.
LAST_OPEN_FOLDER
,
f
.
getParent
());
pathField
.
setText
(
f
.
getAbsolutePath
());
}
});
}
private
void
setupLoadButton
()
{
loadBtn
.
setOnAction
(
ae
->
{
int
numberOfRoundingPlaces
=
Integer
.
parseInt
(
precisionField
.
getText
());
boolean
useValidation
=
useValidationBox
.
isSelected
();
boolean
lowMemory
=
lowMemoryBox
.
isSelected
();
String
path
=
pathField
.
getText
();
cancelBtn
.
setDisable
(
true
);
loadBtn
.
setDisable
(
true
);
pathField
.
setDisable
(
true
);
selectBtn
.
setDisable
(
true
);
stage
.
setOnCloseRequest
(
Event:
:
consume
);
Thread
t
=
new
Thread
(()
->
{
try
{
controller
.
loadCityGml
(
path
,
numberOfRoundingPlaces
,
progress:
:
setProgress
,
useValidation
,
lowMemory
);
Platform
.
runLater
(()
->
stage
.
close
());
}
catch
(
Exception
e
)
{
if
(
logger
.
isErrorEnabled
())
{
logger
.
error
(
Localization
.
getText
(
"OpenFileDialog.loadFailed"
),
e
);
}
Platform
.
runLater
(()
->
{
if
(
exDialog
==
null
)
{
exDialog
=
new
ExceptionDialog
();
}
exDialog
.
show
(
e
);
});
}
finally
{
selectBtn
.
setDisable
(
false
);
pathField
.
setDisable
(
false
);
cancelBtn
.
setDisable
(
false
);
loadBtn
.
setDisable
(
false
);
stage
.
setOnCloseRequest
(
null
);
}
});
t
.
start
();
});
}
private
void
setupPrecisionField
()
{
TextFormatter
<
String
>
formatter
=
new
TextFormatter
<>(
change
->
{
if
(!
change
.
isContentChange
())
{
return
change
;
}
String
text
=
change
.
getControlNewText
();
try
{
Integer
.
parseInt
(
text
);
return
change
;
}
catch
(
NumberFormatException
e
)
{
return
null
;
}
});
precisionField
.
setTextFormatter
(
formatter
);
}
public
void
show
()
{
Platform
.
runLater
(()
->
{
progress
.
setProgress
(
0
d
);
stage
.
showAndWait
();
});
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/PolygonClickDispatcher.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
javafx.scene.input.MouseEvent
;
public
class
PolygonClickDispatcher
implements
ClickDispatcher
{
private
Polygon
p
;
public
PolygonClickDispatcher
(
Polygon
p
)
{
this
.
p
=
p
;
}
@Override
public
void
click
(
MouseEvent
me
,
ClickHandler
handler
)
{
handler
.
onPolygonClick
(
p
,
me
);
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Renderer.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding
;
import
de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface
;
import
de.hft.stuttgart.citydoctor2.datastructure.BoundingBox
;
import
de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement
;
import
de.hft.stuttgart.citydoctor2.datastructure.BridgeObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Building
;
import
de.hft.stuttgart.citydoctor2.datastructure.Installation
;
import
de.hft.stuttgart.citydoctor2.datastructure.BuildingPart
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Lod
;
import
de.hft.stuttgart.citydoctor2.datastructure.Opening
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.ReliefObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.TinObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.TransportationObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vegetation
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.datastructure.WaterObject
;
import
de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter
;
import
de.hft.stuttgart.citydoctor2.gui.tree.EdgeNode
;
import
de.hft.stuttgart.citydoctor2.gui.tree.ErrorItemVisitor
;
import
de.hft.stuttgart.citydoctor2.gui.tree.ErrorNode
;
import
de.hft.stuttgart.citydoctor2.gui.tree.LinearRingNode
;
import
de.hft.stuttgart.citydoctor2.gui.tree.PolygonNode
;
import
de.hft.stuttgart.citydoctor2.gui.tree.Renderable
;
import
de.hft.stuttgart.citydoctor2.gui.tree.VertexNode
;
import
de.hft.stuttgart.citydoctor2.math.Triangle3d
;
import
javafx.application.Platform
;
import
javafx.scene.control.TreeItem
;
import
javafx.scene.paint.Color
;
import
javafx.scene.shape.CullFace
;
import
javafx.scene.shape.DrawMode
;
public
class
Renderer
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
Renderer
.
class
);
private
TriangulatedGeometry
currentTriGeom
;
private
Geometry
currentGeometry
;
private
CullFace
currentCulling
=
CullFace
.
BACK
;
private
DrawMode
currentDrawMode
=
DrawMode
.
FILL
;
private
MainWindow
mainWindow
;
private
HighlightController
highlightController
;
private
ListErrorVisitor
errVisitor
;
private
LoadingInfoDialog
loadingDialog
;
private
List
<
ViewFilter
>
lodFilters
=
new
ArrayList
<>();
private
Runnable
refresher
;
private
Runnable
errorUpdater
;
public
Renderer
(
MainWindow
mainWindow
,
HighlightController
highlightController
)
throws
IOException
{
this
.
mainWindow
=
mainWindow
;
this
.
highlightController
=
highlightController
;
loadingDialog
=
new
LoadingInfoDialog
(
mainWindow
.
getMainStage
());
errVisitor
=
new
ListErrorVisitor
(
highlightController
);
setupLodFilters
();
}
private
void
setupLodFilters
()
{
lodFilters
.
add
(
new
ViewFilter
()
{
@Override
public
boolean
useGeometry
(
CityObject
co
,
Geometry
geom
)
{
return
geom
.
getLod
()
==
Lod
.
LOD1
;
}
});
lodFilters
.
add
(
new
ViewFilter
()
{
@Override
public
boolean
useGeometry
(
CityObject
co
,
Geometry
geom
)
{
return
geom
.
getLod
()
==
Lod
.
LOD2
;
}
});
lodFilters
.
add
(
new
ViewFilter
()
{
@Override
public
boolean
useGeometry
(
CityObject
co
,
Geometry
geom
)
{
return
geom
.
getLod
()
==
Lod
.
LOD3
;
}
});
lodFilters
.
add
(
new
ViewFilter
()
{
@Override
protected
boolean
useGeometry
(
CityObject
co
,
Geometry
geom
)
{
return
geom
.
getLod
()
==
Lod
.
LOD0
;
}
});
lodFilters
.
add
(
new
ViewFilter
()
{
@Override
public
boolean
useGeometry
(
CityObject
co
,
Geometry
geom
)
{
return
geom
.
getLod
()
==
Lod
.
LOD4
;
}
});
}
public
void
enableLod1
()
{
lodFilters
.
get
(
0
).
enable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
disableLod1
()
{
lodFilters
.
get
(
0
).
disable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
enableLod2
()
{
lodFilters
.
get
(
1
).
enable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
disableLod2
()
{
lodFilters
.
get
(
1
).
disable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
enableLod3
()
{
lodFilters
.
get
(
2
).
enable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
disableLod3
()
{
lodFilters
.
get
(
2
).
disable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
enableLod4
()
{
lodFilters
.
get
(
3
).
enable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
disableLod4
()
{
lodFilters
.
get
(
3
).
disable
();
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
render
(
Building
building
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupBuildingPolygons
=
setupBuildingPolygons
(
building
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupBuildingPolygons
));
render
(
setupBuildingPolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
building
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupBuildingPolygons
(
Building
b
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
b
,
polygons
);
for
(
BoundarySurface
bs
:
b
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
}
for
(
Installation
bi
:
b
.
getBuildingInstallations
())
{
addPolygons
(
bi
,
polygons
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
}
}
for
(
BuildingPart
bp
:
b
.
getBuildingParts
())
{
polygons
.
addAll
(
setupBuildingPartPolygons
(
bp
));
}
return
polygons
;
}
public
void
render
(
BuildingPart
bp
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupBuildingPartPolygons
=
setupBuildingPartPolygons
(
bp
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupBuildingPartPolygons
));
render
(
setupBuildingPartPolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
bp
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupBuildingPartPolygons
(
BuildingPart
bp
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
bp
,
polygons
);
for
(
BoundarySurface
bs
:
bp
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
}
for
(
Installation
bi
:
bp
.
getBuildingInstallations
())
{
addPolygons
(
bi
,
polygons
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
}
}
return
polygons
;
}
public
void
render
(
BridgeObject
bridge
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupBridgePolygons
=
setupBridgePolygons
(
bridge
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupBridgePolygons
));
render
(
setupBridgePolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
bridge
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupBridgePolygons
(
BridgeObject
bridge
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
bridge
,
polygons
);
for
(
BoundarySurface
bs
:
bridge
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
}
for
(
BridgeConstructiveElement
consElement
:
bridge
.
getConstructiveElements
())
{
addPolygons
(
consElement
,
polygons
);
for
(
BoundarySurface
bs
:
consElement
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
}
}
for
(
Installation
inst
:
bridge
.
getBridgeInstallations
())
{
addPolygons
(
inst
,
polygons
);
for
(
BoundarySurface
bs
:
inst
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
}
}
return
polygons
;
}
public
void
render
(
CityObject
co
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupCityObjectPolygons
=
setupCityObjectPolygons
(
co
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupCityObjectPolygons
));
render
(
setupCityObjectPolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
co
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
public
void
render
(
ReliefObject
relief
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupCityObjectPolygons
=
setupReliefPolygons
(
relief
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupCityObjectPolygons
));
render
(
setupCityObjectPolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
relief
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupReliefPolygons
(
ReliefObject
relief
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
relief
,
polygons
);
for
(
TinObject
tin
:
relief
.
getComponents
())
{
addPolygons
(
tin
,
polygons
);
}
return
polygons
;
}
public
void
render
(
Installation
bi
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupCityObjectPolygons
=
setupBuildingInstallationPolygons
(
bi
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupCityObjectPolygons
));
render
(
setupCityObjectPolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
bi
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupBuildingInstallationPolygons
(
Installation
bi
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
bi
,
polygons
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
}
return
polygons
;
}
public
void
render
(
BoundarySurface
bs
)
{
refresher
=
()
->
{
Set
<
ConcretePolygon
>
setupBoundarySurfacePolygons
=
setupBoundarySurfacePolygons
(
bs
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
setupBoundarySurfacePolygons
));
render
(
setupBoundarySurfacePolygons
);
Platform
.
runLater
(()
->
{
errorUpdater
=
()
->
displayErrors
(
bs
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
Set
<
ConcretePolygon
>
setupBoundarySurfacePolygons
(
BoundarySurface
bs
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
bs
,
polygons
);
for
(
Opening
op
:
bs
.
getOpenings
())
{
addPolygons
(
op
,
polygons
);
}
return
polygons
;
}
private
Set
<
ConcretePolygon
>
setupCityObjectPolygons
(
CityObject
co
)
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
addPolygons
(
co
,
polygons
);
return
polygons
;
}
private
void
addPolygons
(
CityObject
co
,
Set
<
ConcretePolygon
>
polygons
)
{
for
(
Geometry
geom
:
co
.
getGeometries
())
{
boolean
used
=
false
;
for
(
ViewFilter
filter
:
lodFilters
)
{
if
(
filter
.
allowedToUse
(
co
,
geom
))
{
used
=
true
;
break
;
}
}
if
(
used
)
{
addConcretePolygons
(
polygons
,
geom
);
}
}
}
private
void
displayErrors
(
Checkable
c
)
{
if
(!
c
.
isValidated
())
{
return
;
}
List
<
CheckError
>
errors
=
new
ArrayList
<>();
c
.
collectContainedErrors
(
errors
);
// filter out duplicate errors (polygon can be contained in multiple geometries)
Set
<
CheckError
>
errorSet
=
new
HashSet
<>(
errors
);
for
(
CheckError
err
:
errorSet
)
{
ErrorNode
node
=
new
ErrorNode
(
err
);
TreeItem
<
Renderable
>
errItem
=
new
TreeItem
<>(
node
);
ErrorItemVisitor
visitor
=
new
ErrorItemVisitor
(
errItem
);
err
.
accept
(
visitor
);
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
add
(
errItem
);
}
}
public
void
render
(
Geometry
geom
)
{
refresher
=
()
->
{
Platform
.
runLater
(
this
::
clearGeometryTrees
);
currentTriGeom
=
TriangulatedGeometry
.
of
(
geom
);
if
(
geom
.
getEdges
()
==
null
&&
currentGeometry
!=
null
)
{
// if there are no edges available low memory mode is enabled
// clear the old geometry of all meta information
currentGeometry
.
clearMetaInformation
();
}
errVisitor
.
setGeometry
(
currentTriGeom
);
Platform
.
runLater
(()
->
{
setupRenderState
();
if
(
geom
.
getEdges
()
==
null
)
{
// create edges and vertices so they can be listed in the gui
geom
.
prepareForChecking
();
// remember the geometry, so it can be cleared if another is displayed
currentGeometry
=
geom
;
}
addGeometryDataToView
(
geom
);
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
geom
.
getPolygons
()));
errorUpdater
=
()
->
displayErrors
(
geom
);
errorUpdater
.
run
();
});
};
refresher
.
run
();
}
private
void
addGeometryDataToView
(
Geometry
geom
)
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
addPolygonToView
(
p
);
}
for
(
Edge
e
:
geom
.
getEdges
())
{
addEdgeToView
(
e
);
}
for
(
Vertex
v
:
geom
.
getVertices
())
{
addVertexToView
(
v
);
}
}
private
void
addVertexToView
(
Vertex
v
)
{
Renderable
cf
=
new
VertexNode
(
v
);
TreeItem
<
Renderable
>
ti
=
new
TreeItem
<>(
cf
);
mainWindow
.
getVertexView
().
getRoot
().
getChildren
().
add
(
ti
);
}
private
void
addEdgeToView
(
Edge
e
)
{
EdgeNode
cf
=
new
EdgeNode
(
e
);
TreeItem
<
Renderable
>
ti
=
new
TreeItem
<>(
cf
);
mainWindow
.
getEdgeView
().
getRoot
().
getChildren
().
add
(
ti
);
}
private
void
addPolygonToView
(
Polygon
p
)
{
CheckStatus
cs
=
determineCheckStatus
(
p
);
PolygonNode
cf
=
new
PolygonNode
(
p
,
cs
);
TreeItem
<
Renderable
>
ti
=
new
TreeItem
<>(
cf
);
mainWindow
.
getPolygonsView
().
getRoot
().
getChildren
().
add
(
ti
);
// add linear rings
CheckStatus
csRing
=
determineCheckStatus
(
p
.
getExteriorRing
());
Renderable
ccRing
=
new
LinearRingNode
(
p
.
getExteriorRing
(),
csRing
);
TreeItem
<
Renderable
>
tiRing
=
new
TreeItem
<>(
ccRing
);
ti
.
getChildren
().
add
(
tiRing
);
for
(
Vertex
v
:
p
.
getExteriorRing
().
getVertices
())
{
VertexNode
vn
=
new
VertexNode
(
v
);
TreeItem
<
Renderable
>
tiV
=
new
TreeItem
<>(
vn
);
tiRing
.
getChildren
().
add
(
tiV
);
}
for
(
LinearRing
lr
:
p
.
getInnerRings
())
{
CheckStatus
csInteriorRing
=
determineCheckStatus
(
lr
);
Renderable
ccInteriorRing
=
new
LinearRingNode
(
lr
,
csInteriorRing
);
TreeItem
<
Renderable
>
tiInteriorRing
=
new
TreeItem
<>(
ccInteriorRing
);
ti
.
getChildren
().
add
(
tiInteriorRing
);
for
(
Vertex
v
:
lr
.
getVertices
())
{
VertexNode
vn
=
new
VertexNode
(
v
);
TreeItem
<
Renderable
>
tiV
=
new
TreeItem
<>(
vn
);
tiRing
.
getChildren
().
add
(
tiV
);
}
}
}
private
CheckStatus
determineCheckStatus
(
Checkable
c
)
{
if
(!
c
.
isValidated
())
{
return
CheckStatus
.
NOT_CHECKED
;
}
if
(
c
.
containsAnyError
())
{
return
CheckStatus
.
ERROR
;
}
return
CheckStatus
.
OK
;
}
private
void
render
(
Collection
<?
extends
Polygon
>
polygons
)
{
Platform
.
runLater
(
this
::
clearGeometryTrees
);
currentTriGeom
=
TriangulatedGeometry
.
of
(
polygons
);
errVisitor
.
setGeometry
(
currentTriGeom
);
setupRenderState
();
}
private
void
clearGeometryTrees
()
{
highlightController
.
clearHighlights
();
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getPolygonsView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getEdgeView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getVertexView
().
getRoot
().
getChildren
().
clear
();
}
public
void
renderBuildings
(
List
<
Building
>
objects
)
{
errorUpdater
=
null
;
refresher
=
()
->
{
Platform
.
runLater
(()
->
{
loadingDialog
.
show
();
clearGeometryTrees
();
});
Thread
t
=
new
Thread
(()
->
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
for
(
Building
b
:
objects
)
{
collectPolygons
(
polygons
,
b
);
for
(
BuildingPart
bp
:
b
.
getBuildingParts
())
{
collectPolygons
(
polygons
,
bp
);
}
}
currentTriGeom
=
TriangulatedGeometry
.
of
(
polygons
);
errVisitor
.
setGeometry
(
currentTriGeom
);
Platform
.
runLater
(()
->
{
setupRenderState
();
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
polygons
));
loadingDialog
.
hide
();
});
});
t
.
setUncaughtExceptionHandler
((
thread
,
e
)
->
{
Platform
.
runLater
(()
->
loadingDialog
.
hide
());
logger
.
catching
(
e
);
});
t
.
start
();
};
refresher
.
run
();
}
public
void
render
(
CityDoctorModel
model
)
{
errorUpdater
=
null
;
refresher
=
()
->
{
Platform
.
runLater
(()
->
{
loadingDialog
.
show
();
clearGeometryTrees
();
});
Thread
t
=
new
Thread
(()
->
{
currentTriGeom
=
TriangulatedGeometry
.
of
(
model
,
lodFilters
);
errVisitor
.
setGeometry
(
currentTriGeom
);
Platform
.
runLater
(()
->
{
setupRenderState
();
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
model
));
loadingDialog
.
hide
();
});
});
t
.
setUncaughtExceptionHandler
((
thread
,
e
)
->
{
Platform
.
runLater
(()
->
loadingDialog
.
hide
());
logger
.
catching
(
e
);
});
t
.
start
();
};
refresher
.
run
();
}
public
void
renderVegetation
(
List
<
Vegetation
>
vegetation
)
{
renderCityObjects
(
vegetation
,
Color
.
LIGHTGREEN
);
}
public
void
renderTransportation
(
List
<
TransportationObject
>
transportation
)
{
renderCityObjects
(
transportation
,
Color
.
YELLOW
);
}
public
void
renderBridges
(
List
<
BridgeObject
>
bridges
)
{
renderCityObjects
(
bridges
,
Color
.
CORAL
);
}
public
void
renderWater
(
List
<
WaterObject
>
water
)
{
renderCityObjects
(
water
,
Color
.
LIGHTSKYBLUE
);
}
public
void
renderTerrain
(
List
<
CityObject
>
land
)
{
renderLandObjects
(
land
,
Color
.
BROWN
);
}
private
void
renderLandObjects
(
List
<
CityObject
>
cos
,
Color
baseColor
)
{
errorUpdater
=
null
;
refresher
=
()
->
{
Platform
.
runLater
(()
->
{
loadingDialog
.
show
();
clearGeometryTrees
();
});
Thread
t
=
new
Thread
(()
->
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
for
(
CityObject
co
:
cos
)
{
addPolygons
(
co
,
polygons
);
if
(
co
instanceof
ReliefObject
)
{
ReliefObject
relief
=
(
ReliefObject
)
co
;
for
(
TinObject
tin
:
relief
.
getComponents
())
{
addPolygons
(
tin
,
polygons
);
}
}
}
currentTriGeom
=
TriangulatedGeometry
.
of
(
polygons
,
baseColor
);
errVisitor
.
setGeometry
(
currentTriGeom
);
Platform
.
runLater
(()
->
{
setupRenderState
();
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
polygons
));
loadingDialog
.
hide
();
});
});
t
.
setUncaughtExceptionHandler
((
thread
,
e
)
->
Platform
.
runLater
(()
->
loadingDialog
.
hide
()));
t
.
start
();
};
refresher
.
run
();
}
public
void
renderCityObjects
(
List
<?
extends
CityObject
>
cos
,
Color
baseColor
)
{
errorUpdater
=
null
;
refresher
=
()
->
{
Platform
.
runLater
(()
->
{
loadingDialog
.
show
();
clearGeometryTrees
();
});
Thread
t
=
new
Thread
(()
->
{
Set
<
ConcretePolygon
>
polygons
=
new
HashSet
<>();
for
(
CityObject
co
:
cos
)
{
addPolygons
(
co
,
polygons
);
}
currentTriGeom
=
TriangulatedGeometry
.
of
(
polygons
,
baseColor
);
errVisitor
.
setGeometry
(
currentTriGeom
);
Platform
.
runLater
(()
->
{
setupRenderState
();
mainWindow
.
zoomOutForBoundingBox
(
BoundingBox
.
of
(
polygons
));
loadingDialog
.
hide
();
});
});
t
.
setUncaughtExceptionHandler
((
thread
,
e
)
->
Platform
.
runLater
(()
->
loadingDialog
.
hide
()));
t
.
start
();
};
refresher
.
run
();
}
private
void
collectPolygons
(
Set
<
ConcretePolygon
>
polygons
,
AbstractBuilding
ab
)
{
addPolygons
(
ab
,
polygons
);
for
(
Installation
bi
:
ab
.
getBuildingInstallations
())
{
addPolygons
(
bi
,
polygons
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
addPolygons
(
o
,
polygons
);
}
}
}
for
(
BoundarySurface
bs
:
ab
.
getBoundarySurfaces
())
{
addPolygons
(
bs
,
polygons
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
addPolygons
(
o
,
polygons
);
}
}
}
private
void
addConcretePolygons
(
Set
<
ConcretePolygon
>
polygons
,
Geometry
geom
)
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
polygons
.
add
(
p
.
getOriginal
());
}
}
private
void
setupRenderState
()
{
currentTriGeom
.
setCullFace
(
currentCulling
);
currentTriGeom
.
setDrawMode
(
currentDrawMode
);
Platform
.
runLater
(()
->
{
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
mainWindow
.
getMeshGroup
().
getChildren
().
addAll
(
currentTriGeom
.
getMeshes
());
});
mainWindow
.
getGridButton
().
setDisable
(
false
);
mainWindow
.
getCullingButton
().
setDisable
(
false
);
}
public
void
showWireFrame
(
boolean
show
)
{
if
(
currentTriGeom
!=
null
)
{
if
(
show
)
{
currentDrawMode
=
DrawMode
.
LINE
;
}
else
{
currentDrawMode
=
DrawMode
.
FILL
;
}
currentTriGeom
.
setDrawMode
(
currentDrawMode
);
}
}
public
void
enableCulling
(
boolean
enable
)
{
if
(
currentTriGeom
!=
null
)
{
if
(
enable
)
{
currentCulling
=
CullFace
.
BACK
;
}
else
{
currentCulling
=
CullFace
.
NONE
;
}
currentTriGeom
.
setCullFace
(
currentCulling
);
}
}
public
void
clearCurrentRender
()
{
// don't render anything
Platform
.
runLater
(()
->
{
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
clearGeometryTrees
();
});
}
public
void
highlight
(
Polygon
p
)
{
highlightController
.
highlight
(
p
,
currentTriGeom
);
}
public
void
highlight
(
LinearRing
lr
)
{
highlightController
.
highlight
(
lr
,
currentTriGeom
);
}
public
void
highlight
(
Edge
e
)
{
highlightController
.
highlight
(
e
,
currentTriGeom
);
}
public
void
highlight
(
Vertex
v
)
{
highlightController
.
highlight
(
v
,
currentTriGeom
);
}
public
void
highlight
(
List
<
LinearRing
>
highlightedRings
)
{
highlightController
.
highlight
(
highlightedRings
,
currentTriGeom
);
}
public
void
highlightEdges
(
List
<
Edge
>
edges
)
{
highlightController
.
highlightEdges
(
edges
,
currentTriGeom
);
}
public
void
highlightPolygons
(
List
<
List
<
Polygon
>>
components
)
{
highlightController
.
highlightPolygons
(
components
,
currentTriGeom
);
}
public
void
addHighlight
(
Vertex
vertex
,
Color
c
)
{
highlightController
.
addHighlight
(
vertex
,
currentTriGeom
,
c
);
}
public
void
highlight
(
CheckError
err
)
{
err
.
accept
(
errVisitor
);
}
public
void
refresh
()
{
if
(
refresher
!=
null
)
{
refresher
.
run
();
}
}
public
void
updateErrors
()
{
if
(
errorUpdater
!=
null
)
{
errorUpdater
.
run
();
}
}
public
void
clearHighlights
()
{
highlightController
.
clearHighlights
();
}
public
void
addHighlight
(
Polygon
p
)
{
highlightController
.
addHighlight
(
p
,
currentTriGeom
);
}
public
void
addHighlight
(
Triangle3d
t
)
{
highlightController
.
highlight
(
t
,
currentTriGeom
);
}
public
void
reset
()
{
errorUpdater
=
null
;
refresher
=
null
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/Settings.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.BufferedReader
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.util.Properties
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
public
class
Settings
{
private
static
Logger
logger
=
LogManager
.
getLogger
(
Settings
.
class
);
public
static
final
String
LAST_OPEN_FOLDER
=
"lastOpenFolder"
;
public
static
final
String
MAXIMIZED
=
"maximized"
;
public
static
final
String
FRAME_HEIGHT
=
"frameHeight"
;
public
static
final
String
FRAME_WIDTH
=
"frameWidth"
;
public
static
final
String
FRAME_X
=
"frameX"
;
public
static
final
String
FRAME_Y
=
"frameY"
;
public
static
final
String
LANGUAGE
=
"language"
;
private
static
Properties
props
;
static
{
props
=
new
Properties
();
File
propFile
=
new
File
(
"GUISettings.properties"
);
if
(
propFile
.
exists
())
{
try
(
BufferedReader
bis
=
new
BufferedReader
(
new
FileReader
(
propFile
)))
{
props
.
load
(
bis
);
}
catch
(
IOException
e
)
{
logger
.
error
(
"Failed to load settings"
,
e
);
}
}
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(()
->
{
try
(
BufferedWriter
bw
=
new
BufferedWriter
(
new
FileWriter
(
propFile
)))
{
props
.
store
(
bw
,
"GUI configuration"
);
}
catch
(
IOException
e
)
{
logger
.
error
(
"Failed to save settings"
,
e
);
}
}));
}
private
Settings
()
{
}
public
static
String
get
(
String
name
)
{
return
props
.
getProperty
(
name
);
}
public
static
void
set
(
String
name
,
String
value
)
{
props
.
setProperty
(
name
,
value
);
}
public
static
String
get
(
String
name
,
String
defaultV
)
{
return
props
.
getProperty
(
name
,
defaultV
);
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TableEditCell.java
0 → 100644
View file @
a5a82382
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.gui
;
import
javafx.event.Event
;
import
javafx.scene.control.ContentDisplay
;
import
javafx.scene.control.TableCell
;
import
javafx.scene.control.TableColumn
;
import
javafx.scene.control.TableColumn.CellEditEvent
;
import
javafx.scene.control.TablePosition
;
import
javafx.scene.control.TableView
;
import
javafx.scene.control.TextField
;
import
javafx.scene.input.KeyCode
;
import
javafx.scene.input.KeyEvent
;
import
javafx.util.StringConverter
;
public
class
TableEditCell
<
S
,
T
>
extends
TableCell
<
S
,
T
>
{
// Text field for editing
private
final
TextField
textField
=
new
TextField
();
// Converter for converting the text in the text field to the user type, and
// vice-versa:
private
final
StringConverter
<
T
>
converter
;
public
TableEditCell
(
StringConverter
<
T
>
converter
)
{
this
.
converter
=
converter
;
itemProperty
().
addListener
((
obx
,
oldItem
,
newItem
)
->
{
if
(
newItem
==
null
)
{
setText
(
null
);
}
else
{
setText
(
converter
.
toString
(
newItem
));
}
});
setGraphic
(
textField
);
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
textField
.
setOnAction
(
evt
->
commitEdit
(
this
.
converter
.
fromString
(
textField
.
getText
())));
textField
.
focusedProperty
().
addListener
((
obs
,
wasFocused
,
isNowFocused
)
->
{
if
(
Boolean
.
FALSE
.
equals
(
isNowFocused
))
{
commitEdit
(
this
.
converter
.
fromString
(
textField
.
getText
()));
}
});
textField
.
addEventFilter
(
KeyEvent
.
KEY_PRESSED
,
event
->
{
if
(
event
.
getCode
()
==
KeyCode
.
ESCAPE
)
{
textField
.
setText
(
converter
.
toString
(
getItem
()));
cancelEdit
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
RIGHT
)
{
getTableView
().
getSelectionModel
().
selectRightCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
LEFT
)
{
getTableView
().
getSelectionModel
().
selectLeftCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
UP
)
{
getTableView
().
getSelectionModel
().
selectAboveCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
DOWN
)
{
getTableView
().
getSelectionModel
().
selectBelowCell
();
event
.
consume
();
}
});
}
/**
* Convenience converter that does nothing (converts Strings to themselves and
* vice-versa...).
*/
public
static
final
StringConverter
<
String
>
IDENTITY_CONVERTER
=
new
StringConverter
<
String
>()
{
@Override
public
String
toString
(
String
object
)
{
return
object
;
}
@Override
public
String
fromString
(
String
string
)
{
return
string
;
}
};
/**
* Convenience method for creating an EditCell for a String value.
*
* @return
*/
public
static
<
S
>
TableEditCell
<
S
,
String
>
createStringEditCell
()
{
return
new
TableEditCell
<>(
IDENTITY_CONVERTER
);
}
// set the text of the text field and display the graphic
@Override
public
void
startEdit
()
{
super
.
startEdit
();
textField
.
setText
(
converter
.
toString
(
getItem
()));
setContentDisplay
(
ContentDisplay
.
GRAPHIC_ONLY
);
textField
.
requestFocus
();
}
// revert to text display
@Override
public
void
cancelEdit
()
{
super
.
cancelEdit
();
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
}
// commits the edit. Update property if possible and revert to text display
@Override
public
void
commitEdit
(
T
item
)
{
// This block is necessary to support commit on losing focus, because the
// baked-in mechanism
// sets our editing state to false before we can intercept the loss of focus.
// The default commitEdit(...) method simply bails if we are not editing...
if
(!
isEditing
()
&&
!
item
.
equals
(
getItem
()))
{
TableView
<
S
>
table
=
getTableView
();
if
(
table
!=
null
)
{
TableColumn
<
S
,
T
>
column
=
getTableColumn
();
CellEditEvent
<
S
,
T
>
event
=
new
CellEditEvent
<>(
table
,
new
TablePosition
<>(
table
,
getIndex
(),
column
),
TableColumn
.
editCommitEvent
(),
item
);
Event
.
fireEvent
(
column
,
event
);
}
}
super
.
commitEdit
(
item
);
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
}
}
\ No newline at end of file
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TreeEditCell.java
0 → 100644
View file @
a5a82382
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.gui
;
import
javafx.event.Event
;
import
javafx.scene.control.ContentDisplay
;
import
javafx.scene.control.TextField
;
import
javafx.scene.control.TreeTableCell
;
import
javafx.scene.control.TreeTableColumn
;
import
javafx.scene.control.TreeTableColumn.CellEditEvent
;
import
javafx.scene.control.TreeTablePosition
;
import
javafx.scene.control.TreeTableView
;
import
javafx.scene.input.KeyCode
;
import
javafx.scene.input.KeyEvent
;
import
javafx.util.StringConverter
;
public
class
TreeEditCell
<
S
,
T
>
extends
TreeTableCell
<
S
,
T
>
{
// Text field for editing
private
final
TextField
textField
=
new
TextField
();
// Converter for converting the text in the text field to the user type, and
// vice-versa:
private
final
StringConverter
<
T
>
converter
;
public
TreeEditCell
(
StringConverter
<
T
>
converter
)
{
this
.
converter
=
converter
;
itemProperty
().
addListener
((
obx
,
oldItem
,
newItem
)
->
{
if
(
newItem
==
null
)
{
setText
(
null
);
}
else
{
setText
(
converter
.
toString
(
newItem
));
}
});
setGraphic
(
textField
);
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
textField
.
setOnAction
(
evt
->
commitEdit
(
this
.
converter
.
fromString
(
textField
.
getText
())));
textField
.
focusedProperty
().
addListener
((
obs
,
wasFocused
,
isNowFocused
)
->
{
if
(
Boolean
.
FALSE
.
equals
(
isNowFocused
))
{
commitEdit
(
this
.
converter
.
fromString
(
textField
.
getText
()));
}
});
textField
.
addEventFilter
(
KeyEvent
.
KEY_PRESSED
,
event
->
{
if
(
event
.
getCode
()
==
KeyCode
.
ESCAPE
)
{
textField
.
setText
(
converter
.
toString
(
getItem
()));
cancelEdit
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
RIGHT
)
{
getTreeTableView
().
getSelectionModel
().
selectRightCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
LEFT
)
{
getTreeTableView
().
getSelectionModel
().
selectLeftCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
UP
)
{
getTreeTableView
().
getSelectionModel
().
selectAboveCell
();
event
.
consume
();
}
else
if
(
event
.
getCode
()
==
KeyCode
.
DOWN
)
{
getTreeTableView
().
getSelectionModel
().
selectBelowCell
();
event
.
consume
();
}
});
}
// set the text of the text field and display the graphic
@Override
public
void
startEdit
()
{
super
.
startEdit
();
textField
.
setText
(
converter
.
toString
(
getItem
()));
setContentDisplay
(
ContentDisplay
.
GRAPHIC_ONLY
);
textField
.
requestFocus
();
}
// revert to text display
@Override
public
void
cancelEdit
()
{
super
.
cancelEdit
();
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
}
// commits the edit. Update property if possible and revert to text display
@Override
public
void
commitEdit
(
T
item
)
{
// This block is necessary to support commit on losing focus, because the
// baked-in mechanism
// sets our editing state to false before we can intercept the loss of focus.
// The default commitEdit(...) method simply bails if we are not editing...
if
(!
isEditing
()
&&
!
item
.
equals
(
getItem
()))
{
TreeTableView
<
S
>
table
=
getTreeTableView
();
if
(
table
!=
null
)
{
TreeTableColumn
<
S
,
T
>
column
=
getTableColumn
();
CellEditEvent
<
S
,
T
>
event
=
new
CellEditEvent
<>(
table
,
new
TreeTablePosition
<>(
table
,
getIndex
(),
column
),
TreeTableColumn
.
editCommitEvent
(),
item
);
Event
.
fireEvent
(
column
,
event
);
}
}
super
.
commitEdit
(
item
);
setContentDisplay
(
ContentDisplay
.
TEXT_ONLY
);
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/TriangulatedGeometry.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface
;
import
de.hft.stuttgart.citydoctor2.datastructure.BoundarySurfaceType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Building
;
import
de.hft.stuttgart.citydoctor2.datastructure.Installation
;
import
de.hft.stuttgart.citydoctor2.datastructure.BuildingPart
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.Opening
;
import
de.hft.stuttgart.citydoctor2.datastructure.OpeningType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter
;
import
de.hft.stuttgart.citydoctor2.math.Triangle3d
;
import
de.hft.stuttgart.citydoctor2.math.UnitVector3d
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon
;
import
javafx.scene.paint.Color
;
import
javafx.scene.paint.PhongMaterial
;
import
javafx.scene.shape.CullFace
;
import
javafx.scene.shape.DrawMode
;
import
javafx.scene.shape.MeshView
;
import
javafx.scene.shape.TriangleMesh
;
import
javafx.scene.shape.VertexFormat
;
public
class
TriangulatedGeometry
{
private
static
final
PhongMaterial
GRID_MAT
=
new
PhongMaterial
(
Color
.
BLACK
);
// random vector for calculating normal angles, for color determination
private
static
final
UnitVector3d
AXIS
=
new
Vector3d
(
19
,
0.8
,
1.5
).
normalize
();
private
Vector3d
movedBy
;
private
List
<
MeshView
>
meshes
;
private
List
<
PhongMaterial
>
materials
;
public
static
TriangulatedGeometry
of
(
Geometry
geom
)
{
return
of
(
geom
.
getPolygons
());
}
public
static
TriangulatedGeometry
of
(
Collection
<?
extends
Polygon
>
polygons
,
Color
basePolygonColor
)
{
TriangulatedGeometry
triGeom
=
new
TriangulatedGeometry
();
triGeom
.
materials
=
new
ArrayList
<>();
triGeom
.
meshes
=
new
ArrayList
<>();
List
<
Vector3d
>
points
=
new
ArrayList
<>();
for
(
Polygon
p
:
polygons
)
{
for
(
Vertex
v
:
p
.
getExteriorRing
().
getVertices
())
{
points
.
add
(
v
);
}
}
triGeom
.
movedBy
=
triGeom
.
findCenter
(
points
);
addPolygonDataToTriGeom
(
polygons
,
basePolygonColor
,
triGeom
);
return
triGeom
;
}
private
static
void
addPolygonDataToTriGeom
(
Collection
<?
extends
Polygon
>
polygons
,
Color
basePolygonColor
,
TriangulatedGeometry
triGeom
)
{
for
(
Polygon
p
:
polygons
)
{
TesselatedPolygon
tp
=
p
.
tesselate
();
TriangleMesh
triMesh
=
new
TriangleMesh
(
VertexFormat
.
POINT_TEXCOORD
);
Map
<
Vector3d
,
Integer
>
indexMap
=
new
HashMap
<>();
List
<
Vector3d
>
vertices
=
new
ArrayList
<>();
int
index
=
0
;
for
(
Triangle3d
t
:
tp
.
getTriangles
())
{
index
=
triGeom
.
filterDuplicates
(
triMesh
,
indexMap
,
vertices
,
index
,
t
.
getP1
());
index
=
triGeom
.
filterDuplicates
(
triMesh
,
indexMap
,
vertices
,
index
,
t
.
getP2
());
index
=
triGeom
.
filterDuplicates
(
triMesh
,
indexMap
,
vertices
,
index
,
t
.
getP3
());
}
for
(
Vector3d
point
:
vertices
)
{
float
x
=
(
float
)
(
point
.
getX
()
-
triGeom
.
movedBy
.
getX
());
float
y
=
(
float
)
(
point
.
getY
()
-
triGeom
.
movedBy
.
getY
());
float
z
=
(
float
)
(
point
.
getZ
()
-
triGeom
.
movedBy
.
getZ
());
triMesh
.
getPoints
().
addAll
(
x
,
y
,
z
);
}
triMesh
.
getTexCoords
().
addAll
(
0
,
0
);
MeshView
view
=
new
MeshView
(
triMesh
);
view
.
setUserData
(
new
PolygonClickDispatcher
(
p
));
PhongMaterial
mat
=
triGeom
.
calculateMaterial
(
p
,
basePolygonColor
);
triGeom
.
materials
.
add
(
mat
);
triGeom
.
meshes
.
add
(
view
);
}
}
public
static
TriangulatedGeometry
of
(
CityDoctorModel
model
,
List
<
ViewFilter
>
filters
)
{
List
<
Vector3d
>
points
=
new
ArrayList
<>();
addPointsFromBuildings
(
model
.
getBuildings
(),
points
);
addPointsFromCityObject
(
model
.
getBridges
(),
points
);
addPointsFromCityObject
(
model
.
getLand
(),
points
);
addPointsFromCityObject
(
model
.
getTransportation
(),
points
);
addPointsFromCityObject
(
model
.
getVegetation
(),
points
);
addPointsFromCityObject
(
model
.
getWater
(),
points
);
TriangulatedGeometry
triGeom
=
new
TriangulatedGeometry
();
triGeom
.
materials
=
new
ArrayList
<>();
triGeom
.
meshes
=
new
ArrayList
<>();
triGeom
.
movedBy
=
triGeom
.
findCenter
(
points
);
addPolygonDataFromBuildings
(
model
.
getBuildings
(),
triGeom
,
filters
);
addPolygonDataFromCityObjects
(
model
.
getBridges
(),
triGeom
,
Color
.
CORAL
,
filters
);
addPolygonDataFromCityObjects
(
model
.
getLand
(),
triGeom
,
Color
.
BROWN
,
filters
);
addPolygonDataFromCityObjects
(
model
.
getTransportation
(),
triGeom
,
Color
.
YELLOW
,
filters
);
addPolygonDataFromCityObjects
(
model
.
getVegetation
(),
triGeom
,
Color
.
LIGHTGREEN
,
filters
);
addPolygonDataFromCityObjects
(
model
.
getWater
(),
triGeom
,
Color
.
LIGHTSKYBLUE
,
filters
);
return
triGeom
;
}
private
static
void
addPolygonDataFromBuildings
(
List
<
Building
>
buildings
,
TriangulatedGeometry
triGeom
,
List
<
ViewFilter
>
filters
)
{
for
(
Building
b
:
buildings
)
{
addPolygonData
(
b
,
triGeom
,
Color
.
WHITE
,
filters
);
addPolygonDataFromBoundarySurfaces
(
b
.
getBoundarySurfaces
(),
triGeom
,
filters
);
addPolygonDataFromCityObjects
(
b
.
getBuildingInstallations
(),
triGeom
,
Color
.
WHITE
,
filters
);
for
(
Installation
bi
:
b
.
getBuildingInstallations
())
{
addPolygonDataFromCityObjects
(
bi
.
getBoundarySurfaces
(),
triGeom
,
Color
.
WHITE
,
filters
);
}
for
(
BuildingPart
bp
:
b
.
getBuildingParts
())
{
addPolygonData
(
bp
,
triGeom
,
Color
.
WHITE
,
filters
);
addPolygonDataFromBoundarySurfaces
(
bp
.
getBoundarySurfaces
(),
triGeom
,
filters
);
addPolygonDataFromCityObjects
(
bp
.
getBuildingInstallations
(),
triGeom
,
Color
.
WHITE
,
filters
);
}
}
}
private
static
void
addPolygonDataFromBoundarySurfaces
(
List
<
BoundarySurface
>
boundarySurfaces
,
TriangulatedGeometry
triGeom
,
List
<
ViewFilter
>
filters
)
{
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
addPolygonData
(
bs
,
triGeom
,
Color
.
WHITE
,
filters
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
addPolygonData
(
o
,
triGeom
,
Color
.
WHITE
,
filters
);
}
}
}
private
static
void
addPolygonDataFromCityObjects
(
List
<?
extends
CityObject
>
cos
,
TriangulatedGeometry
triGeom
,
Color
color
,
List
<
ViewFilter
>
filters
)
{
for
(
CityObject
co
:
cos
)
{
addPolygonData
(
co
,
triGeom
,
color
,
filters
);
}
}
private
static
void
addPolygonData
(
CityObject
co
,
TriangulatedGeometry
triGeom
,
Color
color
,
List
<
ViewFilter
>
filters
)
{
for
(
Geometry
geom
:
co
.
getGeometries
())
{
if
(
isGeometryFiltered
(
co
,
geom
,
filters
))
{
continue
;
}
List
<
Polygon
>
polygons
=
new
ArrayList
<>();
for
(
Polygon
p
:
geom
.
getPolygons
())
{
if
(
p
.
isLink
())
{
continue
;
}
polygons
.
add
(
p
);
}
addPolygonDataToTriGeom
(
polygons
,
color
,
triGeom
);
}
}
private
static
boolean
isGeometryFiltered
(
CityObject
co
,
Geometry
geom
,
List
<
ViewFilter
>
filters
)
{
for
(
ViewFilter
filter
:
filters
)
{
if
(
filter
.
allowedToUse
(
co
,
geom
))
{
return
false
;
}
}
return
true
;
}
private
static
void
addPointsFromBuildings
(
List
<
Building
>
buildings
,
List
<
Vector3d
>
points
)
{
for
(
Building
b
:
buildings
)
{
addPoints
(
b
,
points
);
for
(
BuildingPart
bp
:
b
.
getBuildingParts
())
{
addPoints
(
bp
,
points
);
addPointsFromCityObject
(
bp
.
getBoundarySurfaces
(),
points
);
addPointsFromCityObject
(
bp
.
getBuildingInstallations
(),
points
);
}
addPointsFromCityObject
(
b
.
getBoundarySurfaces
(),
points
);
addPointsFromCityObject
(
b
.
getBuildingInstallations
(),
points
);
}
}
private
static
void
addPointsFromCityObject
(
List
<?
extends
CityObject
>
cos
,
List
<
Vector3d
>
points
)
{
for
(
CityObject
co
:
cos
)
{
addPoints
(
co
,
points
);
}
}
private
static
void
addPoints
(
CityObject
co
,
List
<
Vector3d
>
points
)
{
for
(
Geometry
geom
:
co
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
if
(
p
.
isLink
())
{
continue
;
}
for
(
Vertex
v
:
p
.
getExteriorRing
().
getVertices
())
{
points
.
add
(
v
);
}
}
}
}
public
static
TriangulatedGeometry
of
(
Collection
<?
extends
Polygon
>
polygons
)
{
return
of
(
polygons
,
Color
.
WHITE
);
}
private
int
filterDuplicates
(
TriangleMesh
triMesh
,
Map
<
Vector3d
,
Integer
>
indexMap
,
List
<
Vector3d
>
vertices
,
int
index
,
Vector3d
v
)
{
Integer
vertexIndex
=
indexMap
.
get
(
v
);
if
(
vertexIndex
==
null
)
{
indexMap
.
put
(
v
,
index
);
vertices
.
add
(
v
);
vertexIndex
=
index
;
index
++;
}
triMesh
.
getFaces
().
addAll
(
vertexIndex
,
0
);
return
index
;
}
private
PhongMaterial
calculateMaterial
(
Polygon
p
,
Color
baseColor
)
{
Vector3d
normal
=
p
.
calculateNormalNormalized
();
BoundarySurface
bs
=
p
.
getPartOfSurface
();
if
(
bs
!=
null
)
{
if
(
bs
.
getType
()
==
BoundarySurfaceType
.
ROOF
)
{
baseColor
=
Color
.
RED
;
}
else
if
(
bs
.
getType
()
==
BoundarySurfaceType
.
GROUND
)
{
baseColor
=
Color
.
KHAKI
;
}
}
baseColor
=
determineColorDependingOnParentType
(
p
,
baseColor
);
double
cos
=
normal
.
dot
(
AXIS
);
double
acos
=
Math
.
acos
(
cos
);
// normalize to range [0.3, 0.9]
acos
=
acos
/
Math
.
PI
;
acos
=
acos
*
0.6
+
0.3
;
Color
derivedColor
=
baseColor
.
deriveColor
(
0
,
1.0
,
acos
,
1.0
);
return
new
PhongMaterial
(
derivedColor
);
}
private
Color
determineColorDependingOnParentType
(
Polygon
p
,
Color
baseColor
)
{
p
=
p
.
getOriginal
();
Polygon
p1
=
p
.
getLinkedFromPolygon
();
baseColor
=
changeBaseColorIfPolygonHasOpeningParent
(
p1
,
baseColor
);
baseColor
=
changeBaseColorIfPolygonHasOpeningParent
(
p
,
baseColor
);
return
baseColor
;
}
private
Color
changeBaseColorIfPolygonHasOpeningParent
(
Polygon
p
,
Color
baseColor
)
{
if
(
p
==
null
)
{
return
baseColor
;
}
CityObject
parent
=
p
.
getParent
().
getParent
();
if
(
parent
instanceof
Opening
)
{
Opening
op
=
(
Opening
)
parent
;
if
(
op
.
getType
()
==
OpeningType
.
DOOR
)
{
baseColor
=
Color
.
ORANGE
;
}
else
{
baseColor
=
Color
.
TEAL
;
}
}
return
baseColor
;
}
private
Vector3d
findCenter
(
List
<
Vector3d
>
points
)
{
double
xMin
=
Double
.
MAX_VALUE
;
double
yMin
=
Double
.
MAX_VALUE
;
double
zMin
=
Double
.
MAX_VALUE
;
double
xMax
=
Double
.
NEGATIVE_INFINITY
;
double
yMax
=
Double
.
NEGATIVE_INFINITY
;
double
zMax
=
Double
.
NEGATIVE_INFINITY
;
for
(
Vector3d
point
:
points
)
{
if
(
point
.
getX
()
<
xMin
)
{
xMin
=
point
.
getX
();
}
if
(
point
.
getX
()
>
xMax
)
{
xMax
=
point
.
getX
();
}
if
(
point
.
getY
()
<
yMin
)
{
yMin
=
point
.
getY
();
}
if
(
point
.
getY
()
>
yMax
)
{
yMax
=
point
.
getY
();
}
if
(
point
.
getZ
()
<
zMin
)
{
zMin
=
point
.
getZ
();
}
if
(
point
.
getZ
()
>
zMax
)
{
zMax
=
point
.
getZ
();
}
}
// center
double
x
=
(
xMax
-
xMin
)
/
2
+
xMin
;
double
y
=
(
yMax
-
yMin
)
/
2
+
yMin
;
double
z
=
(
zMax
-
zMin
)
/
2
+
zMin
;
return
new
Vector3d
(
x
,
y
,
z
);
}
public
Vector3d
getMovedBy
()
{
return
movedBy
;
}
public
void
setCullFace
(
CullFace
currentCulling
)
{
for
(
MeshView
mesh
:
meshes
)
{
mesh
.
setCullFace
(
currentCulling
);
}
}
public
void
setDrawMode
(
DrawMode
currentDrawMode
)
{
if
(
currentDrawMode
==
DrawMode
.
LINE
)
{
for
(
MeshView
mesh
:
meshes
)
{
mesh
.
setDrawMode
(
currentDrawMode
);
mesh
.
setMaterial
(
GRID_MAT
);
}
}
else
if
(
currentDrawMode
==
DrawMode
.
FILL
)
{
for
(
int
i
=
0
;
i
<
meshes
.
size
();
i
++)
{
MeshView
mesh
=
meshes
.
get
(
i
);
mesh
.
setDrawMode
(
currentDrawMode
);
mesh
.
setMaterial
(
materials
.
get
(
i
));
}
}
}
public
List
<
MeshView
>
getMeshes
()
{
return
meshes
;
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ValidationView.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.Optional
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
de.hft.stuttgart.citydoctor2.check.Checker
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
javafx.application.Platform
;
import
javafx.scene.Node
;
import
javafx.scene.image.Image
;
import
javafx.scene.layout.HBox
;
public
class
ValidationView
extends
View
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
ValidationView
.
class
);
private
Image
viewLogo
;
private
MainWindow
mainWindow
;
private
CityDoctorController
controller
;
public
ValidationView
(
MainWindow
mainWindow
,
CityDoctorController
controller
)
{
this
.
mainWindow
=
mainWindow
;
this
.
controller
=
controller
;
try
(
InputStream
inStream
=
MainWindow
.
class
.
getResourceAsStream
(
"icons/error_stat32x32.png"
))
{
viewLogo
=
new
Image
(
inStream
);
}
catch
(
IOException
e
)
{
logger
.
catching
(
e
);
}
}
@Override
public
Node
getMainScreen
()
{
return
mainWindow
.
getMainContainer
();
}
@Override
public
Optional
<
HBox
>
getToolbar
()
{
return
Optional
.
of
(
mainWindow
.
getMainToolbar
().
getToolBar
());
}
@Override
public
void
onHide
()
{
Platform
.
runLater
(()
->
{
mainWindow
.
unselectEverything
();
mainWindow
.
getMeshGroup
().
getChildren
().
clear
();
mainWindow
.
clearHighlights
();
mainWindow
.
getErrorTree
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getPolygonsView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getVertexView
().
getRoot
().
getChildren
().
clear
();
mainWindow
.
getEdgeView
().
getRoot
().
getChildren
().
clear
();
});
}
@Override
public
void
onShow
(
CityDoctorModel
model
,
Checker
checker
)
{
if
(
model
==
null
)
{
return
;
}
controller
.
buildTrees
();
controller
.
updateFeatureTrees
();
}
@Override
public
Image
getViewLogo
()
{
return
viewLogo
;
}
@Override
public
void
initializeView
(
MainWindow
mainWindow
)
{
// already initialized
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickDispatcher.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
javafx.scene.input.MouseEvent
;
public
class
VertexClickDispatcher
implements
ClickDispatcher
{
private
Vertex
v
;
public
VertexClickDispatcher
(
Vertex
v
)
{
this
.
v
=
v
;
}
@Override
public
void
click
(
MouseEvent
me
,
ClickHandler
handler
)
{
handler
.
onVertexClick
(
v
,
me
);
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/VertexClickHandler.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
org.locationtech.proj4j.ProjCoordinate
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.gui.tree.Renderable
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
javafx.scene.control.ContextMenu
;
import
javafx.scene.control.CustomMenuItem
;
import
javafx.scene.control.Label
;
import
javafx.scene.control.MenuItem
;
import
javafx.scene.control.TreeView
;
import
javafx.scene.input.MouseButton
;
import
javafx.scene.input.MouseEvent
;
import
javafx.stage.Stage
;
public
class
VertexClickHandler
implements
ClickHandler
{
private
TreeView
<
Renderable
>
errorView
;
private
Renderer
renderer
;
private
Stage
stage
;
private
ParserConfiguration
config
;
public
VertexClickHandler
(
TreeView
<
Renderable
>
errorView
,
Renderer
renderer
,
Stage
stage
)
{
this
.
errorView
=
errorView
;
this
.
renderer
=
renderer
;
this
.
stage
=
stage
;
}
public
void
setConfig
(
ParserConfiguration
config
)
{
this
.
config
=
config
;
}
@Override
public
void
onPolygonClick
(
Polygon
p
,
MouseEvent
me
)
{
if
(
me
.
getButton
()
==
MouseButton
.
PRIMARY
)
{
errorView
.
getSelectionModel
().
clearSelection
();
renderer
.
highlight
(
p
);
}
else
if
(
me
.
getButton
()
==
MouseButton
.
SECONDARY
)
{
MenuItem
mi
=
new
MenuItem
(
p
.
getGmlId
().
getGmlString
());
ContextMenu
cMenu
=
new
ContextMenu
(
mi
);
cMenu
.
show
(
stage
,
me
.
getScreenX
(),
me
.
getScreenY
());
}
}
@Override
public
void
onVertexClick
(
Vertex
v
,
MouseEvent
me
)
{
if
(
me
.
getButton
()
==
MouseButton
.
SECONDARY
)
{
MenuItem
mi1
=
new
CustomMenuItem
(
new
Label
(
"Vertex"
));
double
x
=
v
.
getX
();
double
y
=
v
.
getY
();
if
(
config
.
getOriginalTransform
()
!=
null
)
{
ProjCoordinate
p1
=
new
ProjCoordinate
();
ProjCoordinate
p2
=
new
ProjCoordinate
();
p1
.
x
=
v
.
getX
();
p1
.
y
=
v
.
getY
();
config
.
getOriginalTransform
().
transform
(
p1
,
p2
);
x
=
p2
.
x
;
y
=
p2
.
y
;
}
MenuItem
mi2
=
new
MenuItem
(
"x = "
+
x
);
MenuItem
mi3
=
new
MenuItem
(
"y = "
+
y
);
MenuItem
mi4
=
new
MenuItem
(
"z = "
+
v
.
getZ
());
ContextMenu
cMenu
=
new
ContextMenu
(
mi1
,
mi2
,
mi3
,
mi4
);
cMenu
.
show
(
stage
,
me
.
getScreenX
(),
me
.
getScreenY
());
}
}
}
CityDoctorParent/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/View.java
0 → 100644
View file @
a5a82382
package
de.hft.stuttgart.citydoctor2.gui
;
import
java.util.Optional
;
import
de.hft.stuttgart.citydoctor2.check.Checker
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
javafx.scene.Node
;
import
javafx.scene.image.Image
;
import
javafx.scene.layout.HBox
;
public
abstract
class
View
{
private
boolean
firstTime
=
true
;
public
abstract
Optional
<
HBox
>
getToolbar
();
public
abstract
Node
getMainScreen
();
public
abstract
Image
getViewLogo
();
public
abstract
void
initializeView
(
MainWindow
mainWindow
);
public
void
fireOnShowEvent
(
CityDoctorModel
model
,
Checker
checker
,
MainWindow
mainWindow
)
{
if
(
firstTime
)
{
firstTime
=
false
;
initializeView
(
mainWindow
);
}
onShow
(
model
,
checker
);
}
public
abstract
void
onHide
();
public
abstract
void
onShow
(
CityDoctorModel
model
,
Checker
checker
);
}
Prev
1
2
3
4
5
6
7
Next
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