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
d1ff5020
Commit
d1ff5020
authored
May 24, 2025
by
Beuster
Browse files
Merge remote-tracking branch 'origin/dev' into dev_cpp_code_conversion
parents
06ad5a8e
b50c5f13
Pipeline
#11130
passed with stage
in 1 minute and 28 seconds
Changes
179
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Building.java
View file @
d1ff5020
...
...
@@ -18,16 +18,10 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
org.citygml4j.core.model.building.BuildingInstallation
;
import
org.citygml4j.core.model.building.BuildingInstallationProperty
;
import
org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
java.io.Serial
;
import
java.util.ArrayList
;
...
...
@@ -44,13 +38,6 @@ public class Building extends AbstractBuilding {
return
buildingParts
;
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
super
.
reCreateGeometries
(
factory
,
config
);
for
(
BuildingPart
bp
:
buildingParts
)
{
bp
.
reCreateGeometries
(
factory
,
config
);
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
...
...
@@ -58,7 +45,7 @@ public class Building extends AbstractBuilding {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -68,50 +55,6 @@ public class Building extends AbstractBuilding {
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
BuildingPart
bp
:
buildingParts
)
{
bp
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
BuildingPart
bp
:
buildingParts
)
{
bp
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
BuildingPart
bp
:
buildingParts
)
{
if
(
bp
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
BuildingPart
bp
:
buildingParts
)
{
if
(
bp
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
public
void
addBuildingPart
(
BuildingPart
buildingPart
)
{
buildingParts
.
add
(
buildingPart
);
}
...
...
@@ -138,42 +81,4 @@ public class Building extends AbstractBuilding {
setCityGmlBuilding
(
gmlB
);
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
BuildingPart
part
:
buildingParts
)
{
part
.
clearMetaInformation
();
}
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
BuildingPart
part
:
buildingParts
)
{
part
.
prepareForChecking
();
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
Building
originalBuilding
=
(
Building
)
original
;
for
(
BuildingPart
originalBp
:
originalBuilding
.
buildingParts
)
{
buildingParts
.
add
(
handler
.
getCopyInstance
(
originalBp
));
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
BuildingPart
bp
:
buildingParts
)
{
handler
.
addInstance
(
bp
);
}
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
Building
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingPart.java
View file @
d1ff5020
...
...
@@ -18,9 +18,6 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
java.io.Serial
;
public
class
BuildingPart
extends
AbstractBuilding
{
...
...
@@ -57,22 +54,4 @@ public class BuildingPart extends AbstractBuilding {
return
"BuildingPart [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
BuildingPart
originalPart
=
(
BuildingPart
)
original
;
parent
=
handler
.
getCopyInstance
(
originalPart
.
parent
);
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
handler
.
addInstance
(
parent
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
BuildingPart
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingRoom.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.citygml4j.core.model.building.BuildingFurnitureProperty
;
import
java.io.Serial
;
...
...
@@ -42,27 +41,13 @@ public class BuildingRoom extends AbstractRoom {
return
parent
;
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
BuildingRoom
oRoom
=
(
BuildingRoom
)
original
;
parent
=
handler
.
getCopyInstance
(
oRoom
.
getParent
());
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
getParent
().
getTopLevelCityObject
();
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
handler
.
addInstance
(
parent
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
BuildingRoom
();
public
Color
getRenderColor
()
{
return
parent
.
getRenderColor
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingRoomFurniture.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
org.citygml4j.core.model.building.BuildingFurniture
;
import
java.io.Serial
;
...
...
@@ -15,10 +14,5 @@ public class BuildingRoomFurniture extends AbstractFurniture {
super
.
setGmlObject
(
gmlObject
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
BuildingRoomFurniture
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BuildingUnit.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
java.io.Serial
;
import
java.util.ArrayList
;
...
...
@@ -20,112 +14,14 @@ public class BuildingUnit extends AbstractBuildingSubdivision {
private
final
List
<
Storey
>
storeys
=
new
ArrayList
<>();
@Override
public
Copyable
createCopyInstance
()
{
return
new
BuildingUnit
();
}
@Override
public
void
unsetGmlGeometries
()
{
super
.
unsetGmlGeometries
();
for
(
Storey
storey
:
storeys
)
{
storey
.
unsetGmlGeometries
();
}
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
super
.
reCreateGeometries
(
factory
,
config
);
for
(
Storey
storey
:
storeys
)
{
storey
.
reCreateGeometries
(
factory
,
config
);
}
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
CheckableVisitor
c
)
{
super
.
accept
(
c
);
for
(
Storey
storey
:
storeys
)
{
storey
.
accept
(
c
);
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
Storey
storey
:
storeys
)
{
storey
.
collectContainedErrors
(
errors
);
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
Storey
storey
:
storeys
)
{
storey
.
clearAllContainedCheckResults
();
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
Storey
storey
:
storeys
)
{
if
(
storey
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
Storey
storey
:
storeys
)
{
if
(
storey
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
Storey
storey
:
storeys
)
{
storey
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
Storey
storey
:
storeys
)
{
storey
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
Storey
storey
:
storeys
)
{
storey
.
collectInstances
(
handler
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
BuildingUnit
originalBu
=
(
BuildingUnit
)
original
;
for
(
Storey
storey
:
originalBu
.
storeys
)
{
storeys
.
add
(
handler
.
getCopyInstance
(
storey
));
}
this
.
abs
=
originalBu
.
abs
;
}
public
List
<
Storey
>
getStoreys
()
{
return
storeys
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java
View file @
d1ff5020
...
...
@@ -18,8 +18,7 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.AbstractCheck
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
...
...
@@ -147,7 +146,7 @@ public class CityDoctorModel {
folder
.
mkdirs
();
createFeatureStream
().
forEach
(
co
->
{
Map
<
Lod
,
Set
<
Polygon
>>
polygonMap
=
new
EnumMap
<>(
Lod
.
class
);
Check
c
=
new
AbstractCheck
()
{
Check
ableUtilsVisitor
c
=
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
geom
)
{
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityFurniture.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.Check
ableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.citygml4j.core.model.core.AbstractCityObject
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
...
...
@@ -22,7 +21,7 @@ public class CityFurniture extends CityObject {
private
org
.
citygml4j
.
core
.
model
.
cityfurniture
.
CityFurniture
cgmlCityFurniture
;
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -35,6 +34,11 @@ public class CityFurniture extends CityObject {
return
cgmlCityFurniture
;
}
@Override
public
Color
getRenderColor
()
{
return
Color
.
THISTLE
;
}
public
void
setGmlObject
(
org
.
citygml4j
.
core
.
model
.
cityfurniture
.
CityFurniture
gmlCityFurniture
)
{
cgmlCityFurniture
=
gmlCityFurniture
;
}
...
...
@@ -47,6 +51,9 @@ public class CityFurniture extends CityObject {
cgmlCityFurniture
.
setLod1Solid
(
null
);
cgmlCityFurniture
.
setLod2Solid
(
null
);
cgmlCityFurniture
.
setLod3Solid
(
null
);
cgmlCityFurniture
.
getDeprecatedProperties
().
setLod1Geometry
(
null
);
cgmlCityFurniture
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
cgmlCityFurniture
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
cgmlCityFurniture
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
...
...
@@ -56,7 +63,7 @@ public class CityFurniture extends CityObject {
}
@Override
public
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
public
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
...
...
@@ -116,15 +123,4 @@ public class CityFurniture extends CityObject {
return
FeatureType
.
CITY_FURNITURE
;
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
CityFurniture
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
CityFurniture
originalCF
=
(
CityFurniture
)
original
;
cgmlCityFurniture
=
originalCF
.
cgmlCityFurniture
;
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityObject.java
View file @
d1ff5020
...
...
@@ -18,12 +18,11 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
de.hft.stuttgart.citydoctor2.utils.visitors.GmlGeometryRebuilder
;
import
de.hft.stuttgart.citydoctor2.utils.visitors.UnsetGeometriesVisitor
;
import
javafx.scene.paint.Color
;
import
org.citygml4j.core.model.core.AbstractCityObject
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
...
...
@@ -44,20 +43,30 @@ public abstract class CityObject extends GmlElement {
@Serial
private
static
final
long
serialVersionUID
=
651712070755024188L
;
private
final
List
<
Geometry
>
geometryList
=
new
ArrayList
<>();
private
final
List
<
GenericAttribute
>
genericAttributeList
=
new
ArrayList
<>();
/**
* Recreates the CityGML4j geometry in this object's datastructure using the CityDoctor geometries.
* The original CityGML4j geometry is deleted after parsing to reduce the memory overhead of {@link CityObject CityObjects}.
* <p/>
* Recreation of the geometries is needed for writing validation results to the QualityADE, as well as for the export
* of repaired geometries from CityDoctor's internal datastructure.
* @param factory the GeometryFactory used for creation of CityGml4j geometry objects
* @param config the configuration settings of the parser
*/
public
final
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
this
.
accept
(
new
GmlGeometryRebuilder
(
factory
,
config
));
}
/**
* Recreates the CityGML4j geometry in this object. The CityGML4j geometry is
* deleted from the data structure as was mapped to the city doctor data
* structure. For writing CityGML files the geometry has to be restored. Also
* maps changes to geometry back to CityGML4j
* Rebuilds the CityGML4j geometries of this object.
*
* @param factory needed to create CityGML4j data structures
* @param config contains information whether a city doctor point was
* transformed to a different coordinate system. It would need to
* be transformed to the original coordinate system
* @param factory the GeometryFactory used for creation of CityGml4j geometry objects
* @param config the configuration settings of the parser
*/
public
abstract
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
);
public
abstract
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
);
/**
* Getter for the CityGML4j data object
...
...
@@ -67,29 +76,58 @@ public abstract class CityObject extends GmlElement {
public
abstract
AbstractCityObject
getGmlObject
();
/**
* Remove the CityGML4j geometries from th
e data structure to save memory
.
* Remove the CityGML4j geometries from th
is CityObject to reduce memory overhead
.
*/
public
abstract
void
unsetGmlGeometries
();
/**
* Removes all CityGML4J geometries from this CityObject and child objects of its datastructure to reduce
* the memory overhead.
*/
public
final
void
clearGmlGeometries
()
{
this
.
accept
(
new
UnsetGeometriesVisitor
());
}
/**
* Adds a Geometry to this object.
* @param geom the Geometry to add.
*/
public
void
addGeometry
(
Geometry
geom
)
{
Objects
.
requireNonNull
(
geom
);
geometryList
.
add
(
geom
);
geom
.
setParent
(
this
);
}
/**
* Returns all Geometries of this object.
* @return a list of the Geometries.
*/
public
List
<
Geometry
>
getGeometries
()
{
return
geometryList
;
}
/**
* Removes a Geometry from this object.
* @param lod the {@link Lod} of the Geometry.
*/
public
void
removeGeometry
(
Lod
lod
)
{
geometryList
.
removeIf
(
geom
->
geom
.
getLod
()
==
lod
);
}
/**
* Removes a Geometry from this object.
* @param lod the {@link Lod} of the Geometry.
* @param type the {@link GeometryType} of the Geometry.
*/
public
void
removeGeometry
(
Lod
lod
,
GeometryType
type
)
{
geometryList
.
removeIf
(
geom
->
geom
.
getLod
()
==
lod
&&
geom
.
getType
()
==
type
);
}
/**
* Returns the Geometry with the highest LOD of this object. If multiple Geometries share the highest LOD, the one
* that was added first will be returned.
* @return the Geometry with the highest LOD
*/
public
Geometry
getHighestLodGeometry
()
{
Geometry
highestLodGeometry
=
null
;
Lod
highestLod
=
null
;
...
...
@@ -103,22 +141,51 @@ public abstract class CityObject extends GmlElement {
}
/**
* Returns the top-level CityObject (
like
Building
or
Tunnel) belonging to this object.
* Returns the top-level CityObject (
e.g.
Building
,
Tunnel
, Vegetation etc.
) belonging to this object.
*/
public
abstract
CityObject
getTopLevelCityObject
();
/**
* Returns a String representation of this object for display in the featuretab TreeViews in the format of
* "[FeatureType] Gml-ID"
* @return the String representation.
*/
public
String
getDisplayText
()
{
return
String
.
format
(
"[%s] %s"
,
this
.
getClass
().
getSimpleName
(),
this
.
getGmlId
().
toString
());
}
/**
* Returns the color for rendering of this object's polygons.
* @return color for this object
*/
public
Color
getRenderColor
()
{
return
Color
.
WHITE
;
}
/**
* Adds a GenericAttribute to this object.
* @param genericAttribute the attribute to add.
*/
public
void
addGenericAttribute
(
GenericAttribute
genericAttribute
)
{
genericAttributeList
.
add
(
genericAttribute
);
}
/**
* Returns all GenericAttributes of this object.
* @return a list of the GenericAttributes.
*/
public
List
<
GenericAttribute
>
getGenericAttributes
()
{
return
genericAttributeList
;
}
/**
* Returns the CityGML FeatureType of this object.
* @return this object's FeatureType.
*/
public
abstract
FeatureType
getFeatureType
();
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -128,50 +195,6 @@ public abstract class CityObject extends GmlElement {
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
Geometry
geom
:
geometryList
)
{
if
(
geom
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearCheckResults
();
for
(
Geometry
geom
:
geometryList
)
{
geom
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
Geometry
geom
:
geometryList
)
{
geom
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
Geometry
geom
:
geometryList
)
{
if
(
geom
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
public
Geometry
getGeometry
(
GeometryType
type
,
Lod
lod
)
{
for
(
Geometry
geom
:
geometryList
)
{
if
(
geom
.
getType
()
==
type
&&
geom
.
getLod
()
==
lod
)
{
...
...
@@ -181,33 +204,5 @@ public abstract class CityObject extends GmlElement {
return
null
;
}
@Override
public
void
prepareForChecking
()
{
for
(
Geometry
geom
:
geometryList
)
{
geom
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
for
(
Geometry
geom
:
geometryList
)
{
geom
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
for
(
Geometry
geom
:
geometryList
)
{
handler
.
addInstance
(
geom
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
CityObject
originalCo
=
(
CityObject
)
original
;
for
(
Geometry
geom
:
originalCo
.
geometryList
)
{
geometryList
.
add
(
handler
.
getCopyInstance
(
geom
));
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ConcretePolygon.java
View file @
d1ff5020
...
...
@@ -18,15 +18,12 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator
;
import
de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
java.io.Serial
;
import
java.util.ArrayList
;
...
...
@@ -183,7 +180,8 @@ public class ConcretePolygon extends Polygon {
* citydoctor2.check.Check)
*/
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
CheckableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
...
...
@@ -195,7 +193,6 @@ public class ConcretePolygon extends Polygon {
lr
.
accept
(
c
);
}
}
setValidated
(
true
);
}
@Override
...
...
@@ -215,93 +212,6 @@ public class ConcretePolygon extends Polygon {
return
exterior
.
isRingConnectedViaPoint
(
other
.
getExteriorRing
());
}
/*
* (non-Javadoc)
*
* @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#containsAnyError()
*/
@Override
public
boolean
containsAnyError
()
{
if
(
super
.
containsAnyError
())
{
return
true
;
}
if
(
exterior
!=
null
&&
exterior
.
containsAnyError
())
{
return
true
;
}
if
(
innerRings
!=
null
)
{
for
(
LinearRing
lr
:
innerRings
)
{
if
(
lr
.
containsAnyError
())
{
return
true
;
}
}
}
return
false
;
}
/*
* (non-Javadoc)
*
* @see
* de.hft.stuttgart.citydoctor2.datastructure.Polygon#collectContainedErrors(
* java.util.List)
*/
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
if
(
exterior
!=
null
)
{
exterior
.
collectContainedErrors
(
errors
);
}
if
(
innerRings
!=
null
)
{
for
(
LinearRing
lr
:
innerRings
)
{
lr
.
collectContainedErrors
(
errors
);
}
}
}
/*
* (non-Javadoc)
*
* @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#
* clearAllContainedCheckResults()
*/
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearCheckResults
();
if
(
exterior
!=
null
)
{
exterior
.
clearAllContainedCheckResults
();
}
if
(
innerRings
!=
null
)
{
for
(
LinearRing
lr
:
innerRings
)
{
lr
.
clearAllContainedCheckResults
();
}
}
}
/*
* (non-Javadoc)
*
* @see de.hft.stuttgart.citydoctor2.datastructure.Polygon#containsError(de.hft.
* stuttgart.citydoctor2.check.CheckId)
*/
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
if
(
exterior
!=
null
&&
exterior
.
containsError
(
checkIdentifier
))
{
return
true
;
}
if
(
innerRings
!=
null
)
{
for
(
LinearRing
lr
:
innerRings
)
{
if
(
lr
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
}
return
false
;
}
/*
* (non-Javadoc)
*
...
...
@@ -479,51 +389,10 @@ public class ConcretePolygon extends Polygon {
}
@Override
public
void
prepareForChecking
()
{
parent
.
prepareForChecking
();
}
@Override
public
void
clearMetaInformation
()
{
parent
.
clearMetaInformation
();
public
void
prepareLowMemoryUsageMode
()
{
parent
.
updateEdgesAndVertices
();
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
handler
.
addInstance
(
exterior
);
if
(
innerRings
!=
null
)
{
for
(
LinearRing
lr
:
innerRings
)
{
handler
.
addInstance
(
lr
);
}
}
handler
.
addInstance
(
partOfSurface
);
handler
.
addInstance
(
partfOfInstallation
);
handler
.
addInstance
(
parent
);
handler
.
addInstance
(
linkedFromPolygon
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
ConcretePolygon
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
ConcretePolygon
originalPoly
=
(
ConcretePolygon
)
original
;
exterior
=
handler
.
getCopyInstance
(
originalPoly
.
exterior
);
if
(
originalPoly
.
innerRings
!=
null
)
{
innerRings
=
new
ArrayList
<>(
originalPoly
.
innerRings
.
size
());
for
(
LinearRing
originalRing
:
originalPoly
.
innerRings
)
{
innerRings
.
add
(
handler
.
getCopyInstance
(
originalRing
));
}
}
parent
=
handler
.
getCopyInstance
(
originalPoly
.
parent
);
partfOfInstallation
=
handler
.
getCopyInstance
(
originalPoly
.
partfOfInstallation
);
partOfSurface
=
handler
.
getCopyInstance
(
originalPoly
.
partOfSurface
);
linkedFromPolygon
=
handler
.
getCopyInstance
(
originalPoly
.
linkedFromPolygon
);
}
@Override
public
void
remove
()
{
...
...
@@ -544,6 +413,11 @@ public class ConcretePolygon extends Polygon {
}
return
area
;
}
@Override
public
Color
getRenderColor
()
{
return
parent
.
getRenderColor
();
}
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Edge.java
View file @
d1ff5020
...
...
@@ -18,9 +18,6 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
...
...
@@ -31,7 +28,7 @@ import java.util.List;
*
* @author Matthias Betz
*/
public
class
Edge
implements
Serializable
,
Copyable
{
public
class
Edge
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
-
504694863498128296L
;
...
...
@@ -186,33 +183,7 @@ public class Edge implements Serializable, Copyable {
}
return
null
;
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
handler
.
addInstance
(
from
);
handler
.
addInstance
(
to
);
handler
.
addInstance
(
adjacentPolygons
);
handler
.
addInstance
(
adjacentRings
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
Edge
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
Edge
originalEdge
=
(
Edge
)
original
;
from
=
handler
.
getCopyInstance
(
originalEdge
.
from
);
to
=
handler
.
getCopyInstance
(
originalEdge
.
to
);
numberOfHalfEdges
=
originalEdge
.
numberOfHalfEdges
;
numberOfOppositeHalfEdges
=
originalEdge
.
numberOfOppositeHalfEdges
;
for
(
Polygon
originalPoly
:
originalEdge
.
adjacentPolygons
)
{
adjacentPolygons
.
add
(
handler
.
getCopyInstance
(
originalPoly
));
}
for
(
LinearRing
originalRing
:
originalEdge
.
adjacentRings
)
{
adjacentRings
.
add
(
handler
.
getCopyInstance
(
originalRing
));
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GenericCityObject.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.citygml4j.core.model.core.AbstractCityObject
;
...
...
@@ -36,7 +33,7 @@ public class GenericCityObject extends CityObject {
private
final
List
<
BoundarySurface
>
boundarySurfaceList
=
new
ArrayList
<>();
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -47,7 +44,7 @@ public class GenericCityObject extends CityObject {
}
@Override
public
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
public
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
...
...
@@ -60,23 +57,21 @@ public class GenericCityObject extends CityObject {
setSolidAccordingToLod
(
geom
,
solid
);
}
}
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
reCreateBoundarySurface
(
factory
,
config
,
bs
);
}
removeEmptyBoundarySurfaces
();
}
private
void
reCreateBoundarySurface
(
GeometryFactory
factory
,
ParserConfiguration
config
,
BoundarySurface
bs
)
{
if
(
bs
.
getGeometries
().
isEmpty
())
{
for
(
AbstractSpaceBoundaryProperty
bsp
:
cgmlGos
.
getBoundaries
())
{
if
(
bsp
.
getObject
()
!=
null
&&
bsp
.
getObject
()
==
bs
.
getGmlObject
())
{
logger
.
warn
(
"Found empty boundary surface: {}, removing from generic object"
,
bs
.
getGmlId
());
cgmlGos
.
getBoundaries
().
remove
(
bsp
);
break
;
private
void
removeEmptyBoundarySurfaces
()
{
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
if
(
bs
.
getGeometries
().
isEmpty
())
{
for
(
AbstractSpaceBoundaryProperty
bsp
:
cgmlGos
.
getBoundaries
())
{
if
(
bsp
.
getObject
()
!=
null
&&
bsp
.
getObject
()
==
bs
.
getGmlObject
())
{
logger
.
warn
(
"Found empty boundary surface: {}, removing from feature"
,
bs
.
getGmlId
());
cgmlGos
.
getBoundaries
().
remove
(
bsp
);
break
;
}
}
}
return
;
}
bs
.
reCreateGeometries
(
factory
,
config
);
}
private
void
setMultiSurfaceAccordingToLod
(
Geometry
geom
,
MultiSurface
ms
)
{
...
...
@@ -119,86 +114,9 @@ public class GenericCityObject extends CityObject {
throw
new
IllegalStateException
(
"Cannot add "
+
geom
.
getLod
()
+
" solid to buildings"
);
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
bs
.
collectContainedErrors
(
errors
);
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
bs
.
clearAllContainedCheckResults
();
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
if
(
bs
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
if
(
bs
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
bs
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
bs
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
handler
.
addInstance
(
boundarySurfaceList
);
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
GenericCityObject
originalGos
=
(
GenericCityObject
)
original
;
for
(
BoundarySurface
originalBs
:
originalGos
.
boundarySurfaceList
)
{
boundarySurfaceList
.
add
(
handler
.
getCopyInstance
(
originalBs
));
}
cgmlGos
=
originalGos
.
cgmlGos
;
}
@Override
public
AbstractCityObject
getGmlObject
()
{
return
null
;
return
cgmlGos
;
}
@Override
...
...
@@ -210,16 +128,23 @@ public class GenericCityObject extends CityObject {
return
boundarySurfaceList
;
}
@Override
public
Color
getRenderColor
()
{
return
Color
.
DARKGOLDENROD
;
}
@Override
public
void
unsetGmlGeometries
()
{
cgmlGos
.
setLod1Solid
(
null
);
cgmlGos
.
setLod2Solid
(
null
);
cgmlGos
.
setLod3Solid
(
null
);
cgmlGos
.
setLod0MultiSurface
(
null
);
cgmlGos
.
setLod2MultiSurface
(
null
);
cgmlGos
.
setLod3MultiSurface
(
null
);
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
bs
.
unsetGmlGeometries
();
}
cgmlGos
.
getDeprecatedProperties
().
setLod1Geometry
(
null
);
cgmlGos
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
cgmlGos
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
cgmlGos
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
@Override
...
...
@@ -236,9 +161,4 @@ public class GenericCityObject extends CityObject {
bs
.
setParent
(
this
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
GenericCityObject
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Geometry.java
View file @
d1ff5020
...
...
@@ -18,20 +18,16 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.math.Triangle3d
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon
;
import
de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
de.hft.stuttgart.citydoctor2.utils.SerializablePair
;
import
javafx.scene.paint.Color
;
import
java.io.Serial
;
import
java.util.*
;
import
java.util.Map.Entry
;
/**
* Representation of a geometry containing the polygons and edges
...
...
@@ -207,52 +203,9 @@ public class Geometry extends GmlElement {
+
a
[
0
]
*
b
[
1
]
*
c
[
2
];
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
Polygon
p
:
polygons
)
{
if
(
p
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearCheckResults
();
for
(
Polygon
p
:
polygons
)
{
p
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
Polygon
p
:
polygons
)
{
p
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
Polygon
p
:
polygons
)
{
if
(
p
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -378,13 +331,8 @@ public class Geometry extends GmlElement {
return
false
;
}
@Override
public
void
prepareForChecking
()
{
updateEdgesAndVertices
();
}
@Override
public
void
clearMetaInformation
()
{
public
void
clearMetaData
()
{
if
(
vertices
!=
null
)
{
for
(
Vertex
v
:
vertices
)
{
v
.
clearAdjacentRings
();
...
...
@@ -395,57 +343,7 @@ public class Geometry extends GmlElement {
edgeMap
=
null
;
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
handler
.
addInstance
(
parent
);
handler
.
addInstance
(
polygons
);
handler
.
addInstance
(
edges
);
handler
.
addInstance
(
vertices
);
if
(
edgeMap
!=
null
)
{
for
(
Entry
<
SerializablePair
<
Vertex
,
Vertex
>,
Edge
>
e
:
edgeMap
.
entrySet
())
{
handler
.
addInstance
(
e
.
getKey
().
getValue0
());
handler
.
addInstance
(
e
.
getKey
().
getValue1
());
handler
.
addInstance
(
e
.
getValue
());
}
}
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
Geometry
(
type
,
lod
);
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
Geometry
originalGeometry
=
(
Geometry
)
original
;
for
(
Polygon
originalPoly
:
originalGeometry
.
polygons
)
{
polygons
.
add
(
handler
.
getCopyInstance
(
originalPoly
));
}
if
(
originalGeometry
.
edges
!=
null
)
{
edges
=
new
ArrayList
<>(
originalGeometry
.
edges
.
size
());
for
(
Edge
originalEdge
:
originalGeometry
.
edges
)
{
edges
.
add
(
handler
.
getCopyInstance
(
originalEdge
));
}
}
if
(
originalGeometry
.
edgeMap
!=
null
)
{
edgeMap
=
new
HashMap
<>(
originalGeometry
.
edgeMap
.
size
());
for
(
Entry
<
SerializablePair
<
Vertex
,
Vertex
>,
Edge
>
originalEntry
:
originalGeometry
.
edgeMap
.
entrySet
())
{
Vertex
copyV0
=
handler
.
getCopyInstance
(
originalEntry
.
getKey
().
getValue0
());
Vertex
copyV1
=
handler
.
getCopyInstance
(
originalEntry
.
getKey
().
getValue1
());
SerializablePair
<
Vertex
,
Vertex
>
pair
=
new
SerializablePair
<>(
copyV0
,
copyV1
);
Edge
copyEdge
=
handler
.
getCopyInstance
(
originalEntry
.
getValue
());
edgeMap
.
put
(
pair
,
copyEdge
);
}
}
if
(
originalGeometry
.
vertices
!=
null
)
{
vertices
=
new
ArrayList
<>(
originalGeometry
.
vertices
.
size
());
for
(
Vertex
originalVertex
:
originalGeometry
.
vertices
)
{
vertices
.
add
(
handler
.
getCopyInstance
(
originalVertex
));
}
}
parent
=
handler
.
getCopyInstance
(
originalGeometry
.
parent
);
public
Color
getRenderColor
()
{
return
parent
.
getRenderColor
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/GmlElement.java
View file @
d1ff5020
...
...
@@ -19,8 +19,6 @@
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
java.io.Serial
;
...
...
@@ -29,7 +27,7 @@ import java.io.Serial;
*
* @author Matthias Betz
*/
public
abstract
class
GmlElement
extends
Checkable
implements
Copyable
{
public
abstract
class
GmlElement
extends
Checkable
{
@Serial
private
static
final
long
serialVersionUID
=
-
3242505393303017359L
;
...
...
@@ -52,11 +50,5 @@ public abstract class GmlElement extends Checkable implements Copyable {
return
gmlId
!=
null
&&
!
gmlId
.
isGenerated
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
GmlElement
originalElement
=
(
GmlElement
)
original
;
// generate gml id before copying
gmlId
=
originalElement
.
getGmlId
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/ImplicitGeometryHolder.java
View file @
d1ff5020
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
java.io.Serial
;
import
java.util.List
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
org.citygml4j.core.model.core.ImplicitGeometry
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.math.TransformationMatrix
;
/**
...
...
@@ -58,36 +55,10 @@ public class ImplicitGeometryHolder extends Geometry {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
prototypeGeometry
.
accept
(
c
);
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
return
prototypeGeometry
.
containsError
(
checkIdentifier
);
}
@Override
public
void
clearAllContainedCheckResults
()
{
prototypeGeometry
.
clearAllContainedCheckResults
();
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
prototypeGeometry
.
clearAllContainedCheckResults
();
}
@Override
public
boolean
containsAnyError
()
{
return
prototypeGeometry
.
containsAnyError
();
}
@Override
public
void
prepareForChecking
()
{
this
.
updateEdgesAndVertices
();
prototypeGeometry
.
prepareForChecking
();
}
@Override
public
boolean
isValidated
()
{
return
prototypeGeometry
.
isValidated
();
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Installation.java
View file @
d1ff5020
...
...
@@ -18,16 +18,16 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.citygml4j.core.model.bridge.BridgeInstallation
;
import
org.citygml4j.core.model.construction.AbstractInstallation
;
import
org.citygml4j.core.model.core.AbstractSpaceBoundaryProperty
;
import
org.citygml4j.core.model.tunnel.TunnelInstallation
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
org.xmlobjects.gml.model.geometry.GeometryProperty
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
...
...
@@ -44,13 +44,15 @@ public class Installation extends CityObject {
@Serial
private
static
final
long
serialVersionUID
=
1576237433322680191L
;
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
Installation
.
class
);
private
List
<
BoundarySurface
>
boundarySurfaces
=
new
ArrayList
<>(
4
);
private
AbstractInstallation
gmlBi
;
private
CityObject
parent
;
public
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
public
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
.
getType
()
==
GeometryType
.
MULTI_SURFACE
)
{
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
...
...
@@ -66,8 +68,20 @@ public class Installation extends CityObject {
throw
new
IllegalStateException
(
"BuildingInstallation not have Solid geometries"
);
}
}
removeEmptyBoundarySurfaces
();
}
private
void
removeEmptyBoundarySurfaces
()
{
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
reCreateGeometries
(
factory
,
config
);
if
(
bs
.
getGeometries
().
isEmpty
())
{
for
(
AbstractSpaceBoundaryProperty
bsp
:
gmlBi
.
getBoundaries
())
{
if
(
bsp
.
getObject
()
!=
null
&&
bsp
.
getObject
()
==
bs
.
getGmlObject
())
{
logger
.
warn
(
"Found empty boundary surface: {}, removing from feature"
,
bs
.
getGmlId
());
gmlBi
.
getBoundaries
().
remove
(
bsp
);
break
;
}
}
}
}
}
...
...
@@ -115,7 +129,7 @@ public class Installation extends CityObject {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -125,50 +139,6 @@ public class Installation extends CityObject {
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
if
(
bs
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
if
(
bs
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
public
void
setParent
(
CityObject
parent
)
{
this
.
parent
=
parent
;
}
...
...
@@ -177,21 +147,36 @@ public class Installation extends CityObject {
return
parent
;
}
@Override
public
Color
getRenderColor
()
{
return
parent
.
getRenderColor
().
darker
();
}
public
void
addBoundarySurface
(
BoundarySurface
bs
)
{
boundarySurfaces
.
add
(
bs
);
bs
.
setParent
(
this
);
}
@Override
public
void
unsetGmlGeometries
()
{
if
(
gmlBi
instanceof
org
.
citygml4j
.
core
.
model
.
building
.
BuildingInstallation
localBi
)
{
localBi
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
localBi
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
localBi
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
else
if
(
gmlBi
instanceof
BridgeInstallation
localBi
)
{
removeGeometriesFromBridgeInstallation
(
localBi
);
}
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
unsetGmlGeometries
();
gmlBi
.
setLod0MultiSurface
(
null
);
gmlBi
.
setLod2MultiSurface
(
null
);
gmlBi
.
setLod3MultiSurface
(
null
);
gmlBi
.
setLod1Solid
(
null
);
gmlBi
.
setLod2Solid
(
null
);
gmlBi
.
setLod3Solid
(
null
);
if
(
gmlBi
instanceof
org
.
citygml4j
.
core
.
model
.
building
.
BuildingInstallation
buildingInstallation
)
{
buildingInstallation
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
buildingInstallation
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
buildingInstallation
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
else
if
(
gmlBi
instanceof
BridgeInstallation
bridgeInstallation
)
{
bridgeInstallation
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
bridgeInstallation
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
bridgeInstallation
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
else
if
(
gmlBi
instanceof
TunnelInstallation
tunnelInstallation
)
{
tunnelInstallation
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
tunnelInstallation
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
tunnelInstallation
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
}
...
...
@@ -200,11 +185,6 @@ public class Installation extends CityObject {
return
getParent
().
getTopLevelCityObject
();
}
private
void
removeGeometriesFromBridgeInstallation
(
BridgeInstallation
localBi
)
{
localBi
.
getDeprecatedProperties
().
setLod2Geometry
(
null
);
localBi
.
getDeprecatedProperties
().
setLod3Geometry
(
null
);
localBi
.
getDeprecatedProperties
().
setLod4Geometry
(
null
);
}
public
void
setGmlObject
(
AbstractInstallation
gmlBi
)
{
this
.
gmlBi
=
gmlBi
;
...
...
@@ -242,46 +222,4 @@ public class Installation extends CityObject {
}
return
boundarySurfaces
;
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
clearMetaInformation
();
}
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
bs
.
prepareForChecking
();
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
Installation
originalBi
=
(
Installation
)
original
;
for
(
BoundarySurface
originalBs
:
originalBi
.
boundarySurfaces
)
{
boundarySurfaces
.
add
(
handler
.
getCopyInstance
(
originalBs
));
}
gmlBi
=
originalBi
.
gmlBi
;
parent
=
handler
.
getCopyInstance
(
parent
);
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
BoundarySurface
bs
:
boundarySurfaces
)
{
handler
.
addInstance
(
bs
);
}
handler
.
addInstance
(
parent
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
Installation
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LandObject.java
View file @
d1ff5020
...
...
@@ -18,10 +18,10 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.Check
ableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.citygml4j.core.model.core.AbstractCityObject
;
import
org.citygml4j.core.model.landuse.LandUse
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
...
...
@@ -47,7 +47,7 @@ public class LandObject extends CityObject {
}
@Override
public
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
public
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
.
getType
()
==
GeometryType
.
MULTI_SURFACE
)
{
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
...
...
@@ -63,6 +63,11 @@ public class LandObject extends CityObject {
return
FeatureType
.
LAND
;
}
@Override
public
Color
getRenderColor
()
{
return
Color
.
TAN
;
}
private
void
setMultiSurfaceAccordingToLod
(
Geometry
geom
,
MultiSurface
ms
)
{
switch
(
geom
.
getLod
())
{
case
LOD0:
...
...
@@ -84,7 +89,7 @@ public class LandObject extends CityObject {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
...
...
@@ -119,9 +124,4 @@ public class LandObject extends CityObject {
return
"LandObject [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
LandObject
(
lu
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java
View file @
d1ff5020
...
...
@@ -18,10 +18,8 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.Check
ableVisitor
;
import
de.hft.stuttgart.citydoctor2.math.*
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
java.io.Serial
;
import
java.util.ArrayList
;
...
...
@@ -228,18 +226,13 @@ public class LinearRing extends GmlElement {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearCheckResults
();
}
public
void
setParent
(
Polygon
polygon
)
{
parent
=
polygon
;
}
...
...
@@ -313,37 +306,8 @@ public class LinearRing extends GmlElement {
vertices
.
addAll
(
extRing
);
}
@Override
public
void
prepareForChecking
()
{
parent
.
getParent
().
prepareForChecking
();
}
@Override
public
void
clearMetaInformation
()
{
parent
.
getParent
().
clearMetaInformation
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
LinearRing
originalRing
=
(
LinearRing
)
original
;
type
=
originalRing
.
type
;
parent
=
handler
.
getCopyInstance
(
originalRing
.
parent
);
for
(
Vertex
v
:
originalRing
.
vertices
)
{
vertices
.
add
(
handler
.
getCopyInstance
(
v
));
}
public
void
prepareLowMemoryUsageMode
()
{
parent
.
prepareLowMemoryUsageMode
();
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
for
(
Vertex
v
:
vertices
)
{
handler
.
addInstance
(
v
);
}
handler
.
addInstance
(
parent
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
LinearRing
(
type
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinkedPolygon.java
View file @
d1ff5020
...
...
@@ -19,13 +19,12 @@
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckResult
;
import
de.hft.stuttgart.citydoctor2.check.CheckableVisitor
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
java.io.Serial
;
import
java.util.List
;
...
...
@@ -77,8 +76,8 @@ public class LinkedPolygon extends Polygon {
}
@Override
public
boolean
hasAnyError
()
{
return
poly
.
hasAnyError
();
public
boolean
hasAnyError
WithoutDependencies
()
{
return
poly
.
hasAnyError
WithoutDependencies
();
}
@Override
...
...
@@ -107,7 +106,7 @@ public class LinkedPolygon extends Polygon {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
// linked polygons are not checked
setValidated
(
true
);
}
...
...
@@ -117,16 +116,6 @@ public class LinkedPolygon extends Polygon {
poly
.
addCheckResult
(
cr
);
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
poly
.
collectContainedErrors
(
errors
);
}
@Override
public
boolean
containsAnyError
()
{
return
poly
.
containsAnyError
();
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
return
poly
.
containsError
(
checkIdentifier
);
...
...
@@ -247,24 +236,14 @@ public class LinkedPolygon extends Polygon {
poly
.
anonymize
();
}
@Override
public
void
clearAllContainedCheckResults
()
{
poly
.
clearAllContainedCheckResults
();
}
@Override
public
ConcretePolygon
getOriginal
()
{
return
poly
;
}
@Override
public
void
prepareForChecking
()
{
poly
.
prepareForChecking
();
}
@Override
public
void
clearMetaInformation
()
{
poly
.
clearMetaInformation
();
public
void
prepareLowMemoryUsageMode
()
{
poly
.
prepareLowMemoryUsageMode
();
}
@Override
...
...
@@ -272,24 +251,6 @@ public class LinkedPolygon extends Polygon {
return
false
;
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
handler
.
addInstance
(
parent
);
handler
.
addInstance
(
poly
);
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
LinkedPolygon
();
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
LinkedPolygon
linkedOriginal
=
(
LinkedPolygon
)
original
;
parent
=
handler
.
getCopyInstance
(
linkedOriginal
.
parent
);
poly
=
handler
.
getCopyInstance
(
linkedOriginal
.
poly
);
}
@Override
public
void
remove
()
{
poly
.
remove
();
...
...
@@ -300,4 +261,9 @@ public class LinkedPolygon extends Polygon {
return
poly
.
getArea
();
}
@Override
public
Color
getRenderColor
()
{
return
poly
.
getRenderColor
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Opening.java
View file @
d1ff5020
...
...
@@ -18,11 +18,10 @@
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.Check
ableVisitor
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
javafx.scene.paint.Color
;
import
org.citygml4j.core.model.construction.AbstractFillingSurface
;
import
org.citygml4j.core.model.core.AbstractCityObject
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
...
...
@@ -61,7 +60,7 @@ public class Opening extends CityObject {
this
.
ao
=
ao
;
}
public
void
re
Create
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
public
void
re
build
Geometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
if
(
ao
.
getId
()
!=
null
)
{
ao
.
setId
(
getGmlId
().
getGmlString
());
}
...
...
@@ -115,18 +114,13 @@ public class Opening extends CityObject {
}
@Override
public
void
accept
(
Check
c
)
{
public
void
accept
(
Check
ableVisitor
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearCheckResults
();
}
public
void
unsetGmlGeometries
()
{
ao
.
setLod0MultiSurface
(
null
);
ao
.
setLod1MultiSurface
(
null
);
...
...
@@ -160,24 +154,12 @@ public class Opening extends CityObject {
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
Opening
(
type
);
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
handler
.
addInstance
(
partOf
);
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
Opening
originalOpening
=
(
Opening
)
original
;
partOf
=
handler
.
getCopyInstance
(
originalOpening
.
partOf
);
type
=
originalOpening
.
type
;
featureType
=
originalOpening
.
featureType
;
ao
=
originalOpening
.
ao
;
public
Color
getRenderColor
()
{
return
switch
(
type
)
{
case
DOOR
->
Color
.
ORANGE
;
case
WINDOW
->
Color
.
TEAL
;
default
->
Color
.
BLACK
;
};
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Polygon.java
View file @
d1ff5020
...
...
@@ -20,6 +20,7 @@ package de.hft.stuttgart.citydoctor2.datastructure;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon
;
import
javafx.scene.paint.Color
;
import
java.io.Serial
;
import
java.util.List
;
...
...
@@ -80,8 +81,12 @@ public abstract class Polygon extends GmlElement {
public
abstract
ConcretePolygon
getOriginal
();
public
abstract
void
prepareLowMemoryUsageMode
();
public
abstract
void
remove
();
public
abstract
double
getArea
();
public
abstract
Color
getRenderColor
();
}
\ No newline at end of file
Prev
1
2
3
4
5
6
…
9
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