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
9de70078
Commit
9de70078
authored
Jun 10, 2026
by
Luna Riegel
Browse files
Feat: Add UtilityLines connection checks
parent
1b5f851b
Pipeline
#12412
failed with stage
in 59 seconds
Changes
17
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/AbstractErrorVisitor.java
View file @
9de70078
...
...
@@ -8,6 +8,8 @@ import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import
de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.check.error.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
...
...
@@ -216,4 +218,12 @@ public abstract class AbstractErrorVisitor implements ErrorVisitor {
@Override
public
void
visit
(
FeatureCollisionError
err
){
}
@Override
public
void
visit
(
FloatingUtilityError
err
)
{
}
@Override
public
void
visit
(
MisalignedConnectionError
err
)
{
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java
View file @
9de70078
...
...
@@ -58,7 +58,8 @@ public record CheckId(String name) implements Serializable {
public
static
final
CheckId
C_SE_POLYGON_WITHOUT_SURFACE
=
new
CheckId
(
"C_SE_POLYGON_WITHOUT_SURFACE"
);
public
static
final
CheckId
C_TO_FEATURE_COLLISION
=
new
CheckId
(
"C_TO_FEATURE_COLLISION"
);
public
static
final
CheckId
C_TO_UTILITY_LINES_DISCONNECTED
=
new
CheckId
(
"C_TO_UTILITY_LINES_DISCONNECTED"
);
public
static
final
CheckId
C_TO_UTILITY_CONNECTION_MISALIGNED
=
new
CheckId
(
"C_TO_UTILITY_CONNECTION_MISALIGNED"
);
public
static
final
CheckId
C_TO_FLOATING_UTILITY
=
new
CheckId
(
"C_TO_FLOATING_UTILITY"
);
@Override
public
boolean
equals
(
Object
obj
)
{
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java
View file @
9de70078
...
...
@@ -68,7 +68,7 @@ public record ErrorId(String name) implements Serializable {
public
static
final
ErrorId
SE_POLYGON_WITHOUT_SURFACE
=
new
ErrorId
(
"SE_POLYGON_WITHOUT_SURFACE"
);
public
static
final
ErrorId
SC_SCHEMA_VALIDATION
=
new
ErrorId
(
"SC_SCHEMA_VALIDATION"
);
public
static
final
ErrorId
TO_FEATURE_COLLISION
=
new
ErrorId
(
"TO_FEATURE_COLLISION"
);
public
static
final
ErrorId
TO_FLOATING_UTILITY
=
new
ErrorId
(
"TO_FLOATING_UTILITY"
);
@Override
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorVisitor.java
View file @
9de70078
...
...
@@ -26,6 +26,8 @@ import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import
de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.check.error.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
...
...
@@ -70,90 +72,94 @@ import de.hft.stuttgart.citydoctor2.check.error.XMLValidationError;
*/
public
interface
ErrorVisitor
{
public
void
visit
(
RingError
err
);
void
visit
(
RingError
err
);
public
void
visit
(
PolygonError
err
);
void
visit
(
PolygonError
err
);
public
void
visit
(
RingSelfIntersectionError
err
);
void
visit
(
RingSelfIntersectionError
err
);
public
void
visit
(
PlanarityError
err
);
void
visit
(
PlanarityError
err
);
public
void
visit
(
PolygonHoleOutsideError
err
);
void
visit
(
PolygonHoleOutsideError
err
);
public
void
visit
(
NonManifoldEdgeError
err
);
void
visit
(
NonManifoldEdgeError
err
);
public
void
visit
(
MultipleConnectedComponentsError
err
);
void
visit
(
MultipleConnectedComponentsError
err
);
public
void
visit
(
NestedRingError
err
);
void
visit
(
NestedRingError
err
);
public
void
visit
(
NonManifoldVertexError
err
);
void
visit
(
NonManifoldVertexError
err
);
public
void
visit
(
PolygonWrongOrientationError
err
);
void
visit
(
PolygonWrongOrientationError
err
);
public
void
visit
(
PolygonSameOrientationError
err
);
void
visit
(
PolygonSameOrientationError
err
);
public
void
visit
(
SolidNotClosedError
err
);
void
visit
(
SolidNotClosedError
err
);
public
void
visit
(
DependenciesNotMetError
err
);
void
visit
(
DependenciesNotMetError
err
);
public
void
visit
(
UnknownCheckError
err
);
void
visit
(
UnknownCheckError
err
);
public
void
visit
(
RingNotClosedError
err
);
void
visit
(
RingNotClosedError
err
);
public
void
visit
(
ConsecutivePointSameError
err
);
void
visit
(
ConsecutivePointSameError
err
);
public
void
visit
(
AllPolygonsWrongOrientationError
err
);
void
visit
(
AllPolygonsWrongOrientationError
err
);
public
void
visit
(
PolygonInteriorDisconnectedError
err
);
void
visit
(
PolygonInteriorDisconnectedError
err
);
public
void
visit
(
NullAreaError
err
);
void
visit
(
NullAreaError
err
);
public
void
visit
(
RingTooFewPointsError
err
);
void
visit
(
RingTooFewPointsError
err
);
public
void
visit
(
NonPlanarPolygonNormalsDeviation
err
);
void
visit
(
NonPlanarPolygonNormalsDeviation
err
);
public
void
visit
(
NonPlanarPolygonDistancePlaneError
err
);
void
visit
(
NonPlanarPolygonDistancePlaneError
err
);
public
void
visit
(
PolygonIntersectingRingsError
err
);
void
visit
(
PolygonIntersectingRingsError
err
);
public
void
visit
(
SolidSelfIntError
err
);
void
visit
(
SolidSelfIntError
err
);
public
void
visit
(
TooFewPolygonsError
err
);
void
visit
(
TooFewPolygonsError
err
);
public
void
visit
(
RingDuplicatePointError
err
);
void
visit
(
RingDuplicatePointError
err
);
public
void
visit
(
RingEdgeIntersectionError
err
);
void
visit
(
RingEdgeIntersectionError
err
);
public
void
visit
(
PointTouchesEdgeError
err
);
void
visit
(
PointTouchesEdgeError
err
);
public
void
visit
(
NotCeilingError
err
);
void
visit
(
NotCeilingError
err
);
public
void
visit
(
NotFloorError
err
);
void
visit
(
NotFloorError
err
);
public
void
visit
(
NotWallError
err
);
void
visit
(
NotWallError
err
);
public
void
visit
(
NotGroundError
err
);
void
visit
(
NotGroundError
err
);
public
void
visit
(
SchematronError
err
);
void
visit
(
SchematronError
err
);
public
void
visit
(
SurfaceUnfragmentedError
err
);
void
visit
(
SurfaceUnfragmentedError
err
);
public
void
visit
(
DegeneratedRingError
err
);
void
visit
(
DegeneratedRingError
err
);
public
void
visit
(
AttributeMissingError
err
);
void
visit
(
AttributeMissingError
err
);
public
void
visit
(
AttributeValueWrongError
err
);
void
visit
(
AttributeValueWrongError
err
);
public
void
visit
(
AttributeInvalidError
err
);
void
visit
(
AttributeInvalidError
err
);
public
void
visit
(
PolygonWithoutSurfaceError
err
);
void
visit
(
PolygonWithoutSurfaceError
err
);
public
void
visit
(
CheckError
err
);
void
visit
(
CheckError
err
);
public
void
visit
(
SolidError
err
);
void
visit
(
SolidError
err
);
public
void
visit
(
XMLValidationError
err
);
void
visit
(
XMLValidationError
err
);
public
void
visit
(
FeatureCollisionError
err
);
void
visit
(
FeatureCollisionError
err
);
void
visit
(
FloatingUtilityError
err
);
void
visit
(
MisalignedConnectionError
err
);
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java
View file @
9de70078
...
...
@@ -72,6 +72,7 @@ public class Requirement implements Serializable {
public
static
final
Requirement
R_TO_FEATURE_COLLISION
=
new
Requirement
(
"R_TO_FEATURE_COLLISION"
,
RequirementType
.
TOPOLOGY
);
public
static
final
Requirement
R_TO_UTILITY_LINES_DISCONNECTED
=
new
Requirement
(
"R_TO_UTILITY_LINES_DISCONNECTED"
,
RequirementType
.
TOPOLOGY
);
static
{
// fill requirements with default parameters
ArrayList
<
DefaultParameter
>
defaultParameters
=
new
ArrayList
<>();
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/FloatingUtilityError.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.check.error
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.ErrorId
;
import
de.hft.stuttgart.citydoctor2.check.ErrorReport
;
import
de.hft.stuttgart.citydoctor2.check.ErrorType
;
import
de.hft.stuttgart.citydoctor2.check.ErrorVisitor
;
import
de.hft.stuttgart.citydoctor2.check.HealingMethod
;
import
de.hft.stuttgart.citydoctor2.check.ModificationListener
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlElement
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlId
;
public
class
FloatingUtilityError
implements
CheckError
{
private
Geometry
subjectGeom
;
private
GmlId
subjectGmlId
;
public
FloatingUtilityError
(
CityObject
co
,
Geometry
subjectGeom
)
{
this
.
subjectGeom
=
subjectGeom
;
this
.
subjectGmlId
=
co
.
getGmlId
();
}
@Override
public
ErrorType
getType
()
{
return
ErrorType
.
ERROR
;
}
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
TO_FLOATING_UTILITY
;
}
@Override
public
GmlElement
getFeature
()
{
return
subjectGeom
;
}
public
Geometry
getSubjectGeom
(){
return
subjectGeom
;
}
@Override
public
void
accept
(
ErrorVisitor
errorVisitor
)
{
errorVisitor
.
visit
(
this
);
}
@Override
public
boolean
accept
(
HealingMethod
method
,
ModificationListener
l
)
{
return
false
;
}
@Override
public
void
report
(
ErrorReport
report
)
{
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/MisalignedConnectionError.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.check.error
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.ErrorId
;
import
de.hft.stuttgart.citydoctor2.check.ErrorReport
;
import
de.hft.stuttgart.citydoctor2.check.ErrorType
;
import
de.hft.stuttgart.citydoctor2.check.ErrorVisitor
;
import
de.hft.stuttgart.citydoctor2.check.HealingMethod
;
import
de.hft.stuttgart.citydoctor2.check.ModificationListener
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlElement
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlId
;
public
class
MisalignedConnectionError
implements
CheckError
{
private
MisalignmentType
misType
;
private
ErrorType
errType
;
private
Geometry
subjectGeom
;
private
GmlId
subjectGmlId
;
private
GmlId
candidateGmlId
;
//TODO: ADD
public
enum
MisalignmentType
{
ASYMMETRIC_ROTATION
,
SHEARED
,
HANGING
,
UNKNOWN
}
public
MisalignedConnectionError
(
Geometry
subjectGeom
,
CityObject
subject
,
GmlId
candidateGmlId
,
MisalignmentType
misType
,
ErrorType
errType
)
{
this
.
subjectGeom
=
subjectGeom
;
this
.
subjectGmlId
=
subject
.
getGmlId
();
this
.
candidateGmlId
=
candidateGmlId
;
this
.
misType
=
misType
;
this
.
errType
=
errType
;
}
@Override
public
ErrorType
getType
()
{
return
errType
;
}
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
TO_FLOATING_UTILITY
;
}
@Override
public
GmlElement
getFeature
()
{
return
subjectGeom
;
}
public
Geometry
getSubjectGeom
()
{
return
subjectGeom
;
}
public
GmlId
getSubjectGmlId
()
{
return
subjectGmlId
;
}
public
GmlId
getCandidateGmlId
()
{
return
candidateGmlId
;
}
@Override
public
void
accept
(
ErrorVisitor
errorVisitor
)
{
errorVisitor
.
visit
(
this
);
}
public
String
getMisalignmentType
()
{
return
misType
.
toString
();
}
@Override
public
boolean
accept
(
HealingMethod
method
,
ModificationListener
l
)
{
return
false
;
}
@Override
public
void
report
(
ErrorReport
report
)
{
}
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/Checks.java
View file @
9de70078
...
...
@@ -25,6 +25,7 @@ import java.util.Map;
import
java.util.ServiceLoader
;
import
de.hft.stuttgart.citydoctor2.checks.topology.FeatureCollisionCheck
;
import
de.hft.stuttgart.citydoctor2.checks.topology.MisalignedUtilityConnectionCheck
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
...
...
@@ -116,7 +117,7 @@ public class Checks {
//topology checks
publish
(
new
FeatureCollisionCheck
());
publish
(
new
MisalignedUtilityConnectionCheck
());
// load checks from service loader
ServiceLoader
<
Check
>
checkLoader
=
ServiceLoader
.
load
(
Check
.
class
);
for
(
Check
c
:
checkLoader
)
{
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/topology/FloatingUtilityCheck.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.checks.topology
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckResult
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor
;
import
de.hft.stuttgart.citydoctor2.check.ErrorType
;
import
de.hft.stuttgart.citydoctor2.check.GlobalParameters
;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
import
de.hft.stuttgart.citydoctor2.check.RequirementType
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.util.ConnectionAlignmentType
;
import
de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil
;
import
de.hft.stuttgart.citydoctor2.checks.util.UtilityNetworkUtils
;
import
de.hft.stuttgart.citydoctor2.database.CityObjectCache
;
import
de.hft.stuttgart.citydoctor2.datastructure.AbstractLinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Building
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GeometryType
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.math.Plane
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.Pair
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
public
class
FloatingUtilityCheck
extends
Check
{
private
static
final
List
<
CheckId
>
dependencies
;
static
{
ArrayList
<
CheckId
>
deps
=
new
ArrayList
<>();
deps
.
add
(
CheckId
.
C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION
);
deps
.
add
(
CheckId
.
C_TO_FLOATING_UTILITY
);
dependencies
=
Collections
.
unmodifiableList
(
deps
);
ArrayList
<
Class
<?
extends
Checkable
>>
classes
=
new
ArrayList
<>();
classes
.
add
(
LinearRing
.
class
);
}
private
double
epsilon
=
Checks
.
MIN_VERTEX_DISTANCE_DEFAULT
;
private
double
searchRadius
=
Checks
.
MIN_VERTEX_DISTANCE_DEFAULT
;
private
CityObjectCache
cache
;
@Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
Set
.
of
(
Requirement
.
R_TO_UTILITY_LINES_DISCONNECTED
);
}
@Override
public
CheckId
getCheckId
()
{
return
CheckId
.
C_TO_FLOATING_UTILITY
;
}
@Override
public
RequirementType
getType
()
{
return
RequirementType
.
TOPOLOGY
;
}
@Override
public
Check
createNewInstance
()
{
return
new
FloatingUtilityCheck
();
}
@Override
public
void
init
(
Map
<
CheckId
,
Map
<
String
,
String
>>
params
,
ParserConfiguration
config
,
CityObjectCache
cache
)
{
Map
<
String
,
String
>
localParameters
=
params
.
get
(
getCheckId
());
if
(
localParameters
==
null
)
{
// no parameters
return
;
}
String
epsilonString
=
localParameters
.
get
(
GlobalParameters
.
MIN_VERTEX_DISTANCE
);
if
(
epsilonString
!=
null
)
{
epsilon
=
Double
.
parseDouble
(
epsilonString
);
}
this
.
cache
=
cache
;
}
@Override
public
void
check
(
Building
b
)
{
checkUtilityLinesConnections
(
b
);
}
@Override
public
void
check
(
OtherConstructionObject
oco
)
{
checkUtilityLinesConnections
(
oco
);
}
private
void
checkUtilityLinesConnections
(
CityObject
subject
){
Collection
<
CityObject
>
candidates
=
cache
.
getCandidates
(
subject
,
searchRadius
);
if
(
candidates
.
isEmpty
())
{
FloatingUtilityError
err
=
new
FloatingUtilityError
(
subject
,
subject
.
getHighestLodGeometry
());
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
));
return
;
}
List
<
Geometry
>
subjGeoms
=
new
ArrayList
<>();
subject
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
geom
)
{
subjGeoms
.
add
(
geom
);
}
});
for
(
Geometry
geom
:
subjGeoms
)
{
for
(
CityObject
candidate
:
candidates
){
}
}
boolean
misalignedConnections
=
false
;
boolean
freeFloating
=
false
;
for
(
Geometry
sGeo
:
subjGeoms
)
{
final
boolean
[]
connected
=
{
false
};
final
boolean
[]
misalignment
=
{
false
};
for
(
CityObject
candidate
:
candidates
)
{
candidate
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
cGeo
)
{
if
(
sGeo
.
getLod
()
!=
cGeo
.
getLod
()){
return
;
}
List
<
Pair
<
Vertex
,
Vertex
>>
pairs
=
getVertexPairs
(
sGeo
,
cGeo
);
if
(
pairs
.
size
()
<
3
)
{
if
(!
pairs
.
isEmpty
())
{
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignedConnectionError
.
MisalignmentType
.
HANGING
,
ErrorType
.
ERROR
)));
}
}
else
{
switch
(
checkConnectionAlignment
(
sGeo
,
cGeo
,
pairs
))
{
case
ALIGNED:
connected
[
0
]
=
true
;
break
;
case
ASYMMETRIC_ROTATION:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignedConnectionError
.
MisalignmentType
.
ASYMMETRIC_ROTATION
,
ErrorType
.
ERROR
)));
misalignment
[
0
]
=
true
;
break
;
case
SHEARED:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignedConnectionError
.
MisalignmentType
.
SHEARED
,
ErrorType
.
ERROR
)));
misalignment
[
0
]
=
true
;
break
;
case
UNKNOWN:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
WARNING
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignedConnectionError
.
MisalignmentType
.
UNKNOWN
,
ErrorType
.
WARNING
)));
misalignment
[
0
]
=
true
;
break
;
}
}
}
});
if
(!
connected
[
0
])
{
// Geometry has no connections and is "floating in space"
freeFloating
=
true
;
FloatingUtilityError
err
=
new
FloatingUtilityError
(
subject
,
sGeo
);
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
));
}
else
if
(
misalignment
[
0
])
{
misalignedConnections
=
true
;
}
}
}
if
(!
misalignedConnections
&&
!
freeFloating
)
{
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
}
}
private
List
<
Pair
<
Vertex
,
Vertex
>>
getVertexPairs
(
Geometry
subject
,
Geometry
candidate
){
if
(
candidate
.
getVertices
()
==
null
){
candidate
.
prepareForChecking
();
}
List
<
Vertex
>
subjectVerts
=
subject
.
getVertices
();
List
<
Pair
<
Vertex
,
Vertex
>>
connectionPairs
=
new
ArrayList
<>();
for
(
Vertex
cVert
:
candidate
.
getVertices
())
{
for
(
Vertex
sVert
:
subjectVerts
)
{
if
(
sVert
.
equalsWithEpsilon
(
cVert
,
searchRadius
)){
connectionPairs
.
add
(
new
Pair
<>(
sVert
,
cVert
));
}
}
}
return
connectionPairs
;
}
private
ConnectionAlignmentType
checkConnectionAlignment
(
Geometry
subject
,
Geometry
candidate
,
List
<
Pair
<
Vertex
,
Vertex
>>
pairs
){
ConcretePolygon
sPoly
=
new
ConcretePolygon
();
LinearRing
sRing
=
new
LinearRing
(
AbstractLinearRing
.
LinearRingType
.
EXTERIOR
);
sPoly
.
setParent
(
new
Geometry
(
GeometryType
.
MULTI_SURFACE
,
subject
.
getLod
(),
Geometry
.
Orientation
.
INWARD
));
ArrayList
<
Vertex
>
sPairVerts
=
new
ArrayList
<>();
ArrayList
<
Vertex
>
cPairVerts
=
new
ArrayList
<>();
sPoly
.
setExteriorRing
(
sRing
);
pairs
.
forEach
(
pair
->
{
sPairVerts
.
add
(
pair
.
getValue0
());
cPairVerts
.
add
(
pair
.
getValue1
());
sRing
.
addVertex
(
pair
.
getValue0
());
});
Plane
connectionPlane
=
Plane
.
of
(
sPoly
);
List
<
Vertex
>
subjConVerts
=
UtilityNetworkUtils
.
edgeLoopSelection
(
subject
,
sPairVerts
,
connectionPlane
,
searchRadius
);
List
<
Vertex
>
candConVerts
=
UtilityNetworkUtils
.
edgeLoopSelection
(
candidate
,
cPairVerts
,
connectionPlane
,
searchRadius
);
if
(
subjConVerts
.
isEmpty
()
&&
candConVerts
.
isEmpty
())
{
// No missed vertices near connection, connection of features is aligned
return
ConnectionAlignmentType
.
ALIGNED
;
}
Vertex
subjCentroid
=
UtilityNetworkUtils
.
getCentroid
(
subjConVerts
);
Vertex
candCentroid
=
UtilityNetworkUtils
.
getCentroid
(
candConVerts
);
if
(
subjCentroid
.
equalsWithEpsilon
(
candCentroid
,
searchRadius
))
{
if
(
subjConVerts
.
size
()
==
candConVerts
.
size
()){
// Connection plane centroids of both features equal, and are missing equal number of connection vertices
// -> both features likely of same shape but with a roll, yaw or pitch mismatch
return
ConnectionAlignmentType
.
ASYMMETRIC_ROTATION
;
}
else
{
// The form of both features differs, and they are connected by some vertex pairs
// Uncertain if erroneous, add warning
return
ConnectionAlignmentType
.
UNKNOWN
;
}
}
else
{
// Centroids are misaligned, connection is sheared off along the connection plane
return
ConnectionAlignmentType
.
SHEARED
;
}
}
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/topology/MisalignedUtilityConnectionCheck.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.checks.topology
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckResult
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor
;
import
de.hft.stuttgart.citydoctor2.check.ErrorType
;
import
de.hft.stuttgart.citydoctor2.check.GlobalParameters
;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
import
de.hft.stuttgart.citydoctor2.check.RequirementType
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError.MisalignmentType
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.util.ConnectionAlignmentType
;
import
de.hft.stuttgart.citydoctor2.checks.util.UtilityNetworkUtils
;
import
de.hft.stuttgart.citydoctor2.database.CityObjectCache
;
import
de.hft.stuttgart.citydoctor2.datastructure.AbstractLinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Building
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GeometryType
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.math.Plane
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.Pair
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
public
class
MisalignedUtilityConnectionCheck
extends
Check
{
private
static
final
List
<
CheckId
>
dependencies
;
static
{
ArrayList
<
CheckId
>
deps
=
new
ArrayList
<>();
deps
.
add
(
CheckId
.
C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION
);
dependencies
=
Collections
.
unmodifiableList
(
deps
);
ArrayList
<
Class
<?
extends
Checkable
>>
classes
=
new
ArrayList
<>();
classes
.
add
(
LinearRing
.
class
);
}
private
double
epsilon
=
Checks
.
MIN_VERTEX_DISTANCE_DEFAULT
;
private
double
searchRadius
=
Checks
.
MIN_VERTEX_DISTANCE_DEFAULT
;
private
CityObjectCache
cache
;
@Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
Set
.
of
(
Requirement
.
R_TO_UTILITY_LINES_DISCONNECTED
);
}
@Override
public
CheckId
getCheckId
()
{
return
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
;
}
@Override
public
RequirementType
getType
()
{
return
RequirementType
.
TOPOLOGY
;
}
@Override
public
Check
createNewInstance
()
{
return
new
MisalignedUtilityConnectionCheck
();
}
@Override
public
void
init
(
Map
<
CheckId
,
Map
<
String
,
String
>>
params
,
ParserConfiguration
config
,
CityObjectCache
cache
)
{
Map
<
String
,
String
>
localParameters
=
params
.
get
(
getCheckId
());
if
(
localParameters
==
null
)
{
// no parameters
return
;
}
String
epsilonString
=
localParameters
.
get
(
GlobalParameters
.
MIN_VERTEX_DISTANCE
);
if
(
epsilonString
!=
null
)
{
epsilon
=
Double
.
parseDouble
(
epsilonString
);
}
this
.
cache
=
cache
;
}
@Override
public
void
check
(
Building
b
)
{
checkUtilityLinesConnections
(
b
);
}
@Override
public
void
check
(
OtherConstructionObject
oco
)
{
checkUtilityLinesConnections
(
oco
);
}
private
void
checkUtilityLinesConnections
(
CityObject
subject
){
Collection
<
CityObject
>
candidates
=
cache
.
getCandidates
(
subject
,
epsilon
);
if
(
candidates
.
isEmpty
())
{
FloatingUtilityError
err
=
new
FloatingUtilityError
(
subject
,
subject
.
getHighestLodGeometry
());
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
));
return
;
}
List
<
Geometry
>
subjGeoms
=
new
ArrayList
<>();
subject
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
geom
)
{
subjGeoms
.
add
(
geom
);
}
});
boolean
misalignedConnections
=
false
;
boolean
freeFloating
=
false
;
for
(
Geometry
sGeo
:
subjGeoms
)
{
final
boolean
[]
connected
=
{
false
};
final
boolean
[]
misalignment
=
{
false
};
for
(
CityObject
candidate
:
candidates
)
{
candidate
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
cGeo
)
{
if
(
sGeo
.
getLod
()
!=
cGeo
.
getLod
()){
return
;
}
List
<
Pair
<
Vertex
,
Vertex
>>
pairs
=
getVertexPairs
(
sGeo
,
cGeo
);
if
(
pairs
.
size
()
<
3
)
{
if
(!
pairs
.
isEmpty
())
{
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignedConnectionError
.
MisalignmentType
.
HANGING
,
ErrorType
.
ERROR
)));
}
}
else
{
switch
(
checkConnectionAlignment
(
sGeo
,
cGeo
,
pairs
))
{
case
ALIGNED:
connected
[
0
]
=
true
;
break
;
case
ASYMMETRIC_ROTATION:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignmentType
.
ASYMMETRIC_ROTATION
,
ErrorType
.
ERROR
)));
misalignment
[
0
]
=
true
;
break
;
case
SHEARED:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
ERROR
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignmentType
.
SHEARED
,
ErrorType
.
ERROR
)));
misalignment
[
0
]
=
true
;
break
;
case
UNKNOWN:
subject
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_TO_UTILITY_CONNECTION_MISALIGNED
,
ResultStatus
.
WARNING
,
new
MisalignedConnectionError
(
sGeo
,
subject
,
candidate
.
getGmlId
(),
MisalignmentType
.
UNKNOWN
,
ErrorType
.
WARNING
)));
misalignment
[
0
]
=
true
;
break
;
}
}
}
});
if
(!
connected
[
0
])
{
// Geometry has no connections and is "floating in space"
freeFloating
=
true
;
FloatingUtilityError
err
=
new
FloatingUtilityError
(
subject
,
sGeo
);
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
));
}
else
if
(
misalignment
[
0
])
{
misalignedConnections
=
true
;
}
}
}
if
(!
misalignedConnections
&&
!
freeFloating
)
{
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
}
}
private
List
<
Pair
<
Vertex
,
Vertex
>>
getVertexPairs
(
Geometry
subject
,
Geometry
candidate
){
if
(
candidate
.
getVertices
()
==
null
){
candidate
.
prepareForChecking
();
}
List
<
Vertex
>
subjectVerts
=
subject
.
getVertices
();
List
<
Pair
<
Vertex
,
Vertex
>>
connectionPairs
=
new
ArrayList
<>();
for
(
Vertex
cVert
:
candidate
.
getVertices
())
{
for
(
Vertex
sVert
:
subjectVerts
)
{
if
(
sVert
.
equalsWithEpsilon
(
cVert
,
searchRadius
)){
connectionPairs
.
add
(
new
Pair
<>(
sVert
,
cVert
));
}
}
}
return
connectionPairs
;
}
private
ConnectionAlignmentType
checkConnectionAlignment
(
Geometry
subject
,
Geometry
candidate
,
List
<
Pair
<
Vertex
,
Vertex
>>
pairs
){
ConcretePolygon
sPoly
=
new
ConcretePolygon
();
LinearRing
sRing
=
new
LinearRing
(
AbstractLinearRing
.
LinearRingType
.
EXTERIOR
);
sPoly
.
setParent
(
new
Geometry
(
GeometryType
.
MULTI_SURFACE
,
subject
.
getLod
(),
Geometry
.
Orientation
.
INWARD
));
ArrayList
<
Vertex
>
sPairVerts
=
new
ArrayList
<>();
ArrayList
<
Vertex
>
cPairVerts
=
new
ArrayList
<>();
sPoly
.
setExteriorRing
(
sRing
);
pairs
.
forEach
(
pair
->
{
sPairVerts
.
add
(
pair
.
getValue0
());
cPairVerts
.
add
(
pair
.
getValue1
());
sRing
.
addVertex
(
pair
.
getValue0
());
});
Plane
connectionPlane
=
Plane
.
of
(
sPoly
);
List
<
Vertex
>
subjConVerts
=
UtilityNetworkUtils
.
edgeLoopSelection
(
subject
,
sPairVerts
,
connectionPlane
,
searchRadius
);
List
<
Vertex
>
candConVerts
=
UtilityNetworkUtils
.
edgeLoopSelection
(
candidate
,
cPairVerts
,
connectionPlane
,
searchRadius
);
if
(
subjConVerts
.
isEmpty
()
&&
candConVerts
.
isEmpty
())
{
// No missed vertices near connection, connection of features is aligned
return
ConnectionAlignmentType
.
ALIGNED
;
}
Vertex
subjCentroid
=
UtilityNetworkUtils
.
getCentroid
(
subjConVerts
);
Vertex
candCentroid
=
UtilityNetworkUtils
.
getCentroid
(
candConVerts
);
if
(
subjCentroid
.
equalsWithEpsilon
(
candCentroid
,
searchRadius
))
{
if
(
subjConVerts
.
size
()
==
candConVerts
.
size
()){
// Connection plane centroids of both features equal, and are missing equal number of connection vertices
// -> both features likely of same shape but with a roll, yaw or pitch mismatch
return
ConnectionAlignmentType
.
ASYMMETRIC_ROTATION
;
}
else
{
// The form of both features differs, and they are connected by some vertex pairs
// Uncertain if erroneous, add warning
return
ConnectionAlignmentType
.
UNKNOWN
;
}
}
else
{
// Centroids are misaligned, connection is sheared off along the connection plane
return
ConnectionAlignmentType
.
SHEARED
;
}
}
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/topology/UtilityConnectionAngleCheck.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.checks.topology
;
import
de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor
;
import
de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.utils.PolygonIntersection
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.function.Predicate
;
public
class
UtilityConnectionAngleCheck
{
// private void checkUtilityLinesConnections(CityObject subject){
// Collection<CityObject> candidates = cache.getCandidates(subject, epsilon);
// List<Geometry> subjGeoms = new ArrayList<>();
// subject.accept(new CheckableUtilsVisitor() {
// @Override
// public void check(Geometry geom) {
// subjGeoms.add(geom);
// }
// });
// boolean disconnected = true;
// for (Geometry sGeo : subjGeoms) {
// for (CityObject candidate : candidates) {
// candidate.accept(new CheckableUtilsVisitor() {
// @Override
// public void check(Geometry cGeo) {
// if(sGeo.getLod() != cGeo.getLod()){
// return;
// }
// List<PolygonIntersection> intersections = getIntersections(sGeo, cGeo);
// if(intersections.isEmpty()){
// return;
// }
// List<Vector3d> intersectionPoints = extractIntersectionPoints(intersections);
// if(intersectionPoints.isEmpty()){
// return;
// }
//
// }
// });
//
//
// }
// }
//
// }
//
// private List<PolygonIntersection> getIntersections(Geometry subjectGeom, Geometry candidateGeom) {
// List<PolygonIntersection> intersections = SelfIntersectionUtil
// .calculateGeometryIntersections(subjectGeom, candidateGeom, epsilon);
// intersections = intersections.stream()
// .filter(sect -> sect.getType() != PolygonIntersection.IntersectionType.NONE)
// .toList();
// if (intersections.isEmpty()) {
// return Collections.emptyList();
// }
// return intersections;
// }
//
// private List<Vector3d> extractIntersectionPoints(List<PolygonIntersection> intersections) {
// List<Vector3d> intersectionPoints = new ArrayList<>();
// for (PolygonIntersection intersection : intersections) {
// intersection.getLines().forEach(line -> {
// intersectionPoints.add(line.getPointA());
// intersectionPoints.add(line.getPointB());
// });
// }
// List<Vector3d> points = deduplicatePoints(intersectionPoints);
// if (points.isEmpty()||points.size() < 3) {
// return Collections.emptyList();
// }
// return points;
// }
//
// private List<Vector3d> deduplicatePoints(Collection<Vector3d> points) {
// Predicate<Vector3d> duplicateFilter = new Predicate<Vector3d>() {
// List<Vector3d> distinctPoints = new ArrayList<>();
// @Override
// public boolean test(Vector3d v) {
// for(Vector3d dPoint : distinctPoints){
// if(dPoint.equalsWithEpsilon(v, epsilon)){
// return false;
// }
// }
// distinctPoints.add(v);
// return true;
// }
// };
// return points.stream().filter(duplicateFilter).toList();
// }
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/topology/UtilityLinesDisconnectedCheck.java
deleted
100644 → 0
View file @
1b5f851b
package
de.hft.stuttgart.citydoctor2.checks.topology
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
import
de.hft.stuttgart.citydoctor2.check.RequirementType
;
import
java.util.Set
;
public
class
UtilityLinesDisconnectedCheck
extends
Check
{
@Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
Set
.
of
(
Requirement
.
R_TO_UTILITY_LINES_DISCONNECTED
);
}
@Override
public
CheckId
getCheckId
()
{
return
CheckId
.
C_TO_UTILITY_LINES_DISCONNECTED
;
}
@Override
public
RequirementType
getType
()
{
return
RequirementType
.
TOPOLOGY
;
}
@Override
public
Check
createNewInstance
()
{
return
new
UtilityLinesDisconnectedCheck
();
}
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/ConnectionAlignmentType.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.checks.util
;
public
enum
ConnectionAlignmentType
{
ALIGNED
,
ASYMMETRIC_ROTATION
,
SHEARED
,
UNKNOWN
}
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/UtilityNetworkUtils.java
0 → 100644
View file @
9de70078
package
de.hft.stuttgart.citydoctor2.checks.util
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.math.Plane
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
public
class
UtilityNetworkUtils
{
public
static
List
<
Vertex
>
radialSelectVertices
(
Geometry
geom
,
Plane
plane
,
double
searchRadius
){
List
<
Vertex
>
vertices
=
new
ArrayList
<>();
geom
.
getVertices
().
forEach
(
vertex
->
{
if
(
plane
.
getDistance
(
vertex
)
<=
searchRadius
)
{
vertices
.
add
(
vertex
);
}
});
return
vertices
;
}
public
static
List
<
Vertex
>
edgeLoopSelection
(
Geometry
geom
,
List
<
Vertex
>
seedPoints
,
Plane
loopPlane
,
double
searchRadius
){
List
<
Vertex
>
unboundPoints
=
radialSelectVertices
(
geom
,
loopPlane
,
searchRadius
);
unboundPoints
.
removeAll
(
seedPoints
);
return
edgeLoopCrawl
(
geom
,
seedPoints
,
unboundPoints
);
}
private
static
List
<
Vertex
>
edgeLoopCrawl
(
Geometry
geom
,
List
<
Vertex
>
seedPoints
,
List
<
Vertex
>
unboundPoints
){
List
<
Vertex
>
fixedPoints
=
new
ArrayList
<>(
seedPoints
);
List
<
Vertex
>
freePoints
=
new
ArrayList
<>(
unboundPoints
);
List
<
Vertex
>
caughtPoints
=
new
ArrayList
<>();
for
(
Vertex
fix:
fixedPoints
){
for
(
Vertex
free:
freePoints
){
Edge
edge
=
geom
.
getEdge
(
fix
,
free
);
if
(
edge
!=
null
)
{
caughtPoints
.
add
(
free
);
}
}
freePoints
.
removeAll
(
caughtPoints
);
}
if
(
caughtPoints
.
isEmpty
()){
return
Collections
.
emptyList
();
}
else
if
(
freePoints
.
isEmpty
()){
return
caughtPoints
;
}
else
{
List
<
Vertex
>
loopPoints
=
new
ArrayList
<>(
caughtPoints
);
loopPoints
.
addAll
(
edgeLoopCrawl
(
geom
,
caughtPoints
,
freePoints
));
return
loopPoints
;
}
}
public
static
Vertex
getCentroid
(
Collection
<
Vertex
>
vertices
)
{
Vertex
centroid
=
new
Vertex
(
0
,
0
,
0
);
vertices
.
forEach
(
centroid:
:
plus
);
centroid
.
mult
(((
double
)
1
/
vertices
.
size
()));
return
centroid
;
}
}
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/GlobalErrorVisitor.java
View file @
9de70078
...
...
@@ -10,6 +10,8 @@ import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import
de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.check.error.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
...
...
@@ -234,4 +236,13 @@ public class GlobalErrorVisitor implements ErrorVisitor {
public
void
visit
(
FeatureCollisionError
err
){
}
@Override
public
void
visit
(
MisalignedConnectionError
err
)
{
}
@Override
public
void
visit
(
FloatingUtilityError
err
)
{
}
}
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/ListErrorVisitor.java
View file @
9de70078
...
...
@@ -12,6 +12,8 @@ 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.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
...
...
@@ -312,4 +314,14 @@ public class ListErrorVisitor implements ErrorVisitor {
//TODO: Implement handling of error here
}
@Override
public
void
visit
(
FloatingUtilityError
err
){
//TODO: Implement highlighting
}
@Override
public
void
visit
(
MisalignedConnectionError
err
){
//TODO: Implement highlighting
}
}
CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/tree/ErrorItemVisitor.java
View file @
9de70078
...
...
@@ -13,6 +13,8 @@ import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import
de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.check.error.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.check.error.FloatingUtilityError
;
import
de.hft.stuttgart.citydoctor2.check.error.MisalignedConnectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError
;
...
...
@@ -493,4 +495,29 @@ public class ErrorItemVisitor extends AbstractErrorVisitor {
//TODO: Implement handling of error here
// Will require new Error Node-type that is capable of rendering 2 CityObjects
}
@Override
public
void
visit
(
MisalignedConnectionError
err
)
{
TextNode
subTypeTextNode
=
new
TextNode
(
"MisalignedConnection"
);
TreeItem
<
Renderable
>
subTypeItem
=
new
TreeItem
<>(
subTypeTextNode
);
TopologyErrorNode
subjectGeoNode
=
new
TopologyErrorNode
(
err
.
getSubjectGeom
().
getDisplayText
(),
renderer
->
renderer
.
highlightTopoErrorGeometry
(
err
.
getSubjectGeom
(),
false
));
TreeItem
<
Renderable
>
subjectGeoItem
=
new
TreeItem
<>(
subjectGeoNode
);
TextNode
misAlignTypeTextNode
=
new
TextNode
(
err
.
getMisalignmentType
());
TreeItem
<
Renderable
>
misAlignTypeItem
=
new
TreeItem
<>(
misAlignTypeTextNode
);
subjectGeoItem
.
getChildren
().
add
(
misAlignTypeItem
);
root
.
getChildren
().
add
(
subTypeItem
);
root
.
getChildren
().
add
(
subjectGeoItem
);
//TODO: Proper handling of error here
}
@Override
public
void
visit
(
FloatingUtilityError
err
)
{
TextNode
subTypeTextNode
=
new
TextNode
(
"FloatingUtility"
);
TreeItem
<
Renderable
>
subTypeItem
=
new
TreeItem
<>(
subTypeTextNode
);
root
.
getChildren
().
add
(
subTypeItem
);
//TODO: Proper handling of error here
}
}
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