Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
85cf93b6
Commit
85cf93b6
authored
4 years ago
by
Matthias Betz
Browse files
Options
Download
Email Patches
Plain Diff
reworked check engine now working on requirements
parent
35577785
master
107-opengl-view
dev
dev_bht
dev_cpp_code_conversion
dev_gui_features
dev_gui_features_zip_loading
dev_visitor_rework
3.17.1
3.17.0
3.16.0
3.15.0
3.14.1
3.14.0
3.13.1
3.13.0
3.12.0
3.11.0
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.0
3.8.0
archive/dev_gui_features_zip_loading
archive/dev_citygml3
archive/dev_GUI
archive/darmstadt
Pipeline
#2108
passed with stage
in 3 minutes and 6 seconds
Changes
66
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java
+4
-1
...c/main/java/de/hft/stuttgart/citydoctor2/check/Check.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java
+7
-8
...main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java
+1
-1
...in/java/de/hft/stuttgart/citydoctor2/check/Checkable.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java
+12
-8
.../de/hft/stuttgart/citydoctor2/check/DefaultParameter.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java
+6
-7
...main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java
+136
-0
.../java/de/hft/stuttgart/citydoctor2/check/Requirement.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementType.java
+1
-1
...a/de/hft/stuttgart/citydoctor2/check/RequirementType.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java
+1
-1
...ft/stuttgart/citydoctor2/check/error/NotCeilingError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java
+1
-1
.../hft/stuttgart/citydoctor2/check/error/NotFloorError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java
+1
-1
...hft/stuttgart/citydoctor2/check/error/NotGroundError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java
+1
-1
...e/hft/stuttgart/citydoctor2/check/error/NotWallError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java
+1
-1
...ft/stuttgart/citydoctor2/check/error/SchematronError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java
+1
-1
...art/citydoctor2/check/error/SurfaceUnfragmentedError.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java
+4
-0
.../hft/stuttgart/citydoctor2/datastructure/BoundingBox.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/CovarianceMatrix.java
+6
-0
...a/de/hft/stuttgart/citydoctor2/math/CovarianceMatrix.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java
+1
-1
...in/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java
+47
-7
...ft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
+78
-56
...main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/GlobalParameters.java
+31
-0
.../de/hft/stuttgart/citydoctor2/check/GlobalParameters.java
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/RequirementConfiguration.java
+2
-5
...stuttgart/citydoctor2/check/RequirementConfiguration.java
with
342 additions
and
101 deletions
+342
-101
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Check.java
+
4
-
1
View file @
85cf93b6
...
...
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError
;
import
de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding
;
...
...
@@ -98,6 +99,8 @@ public abstract class Check {
public
List
<
CheckId
>
getDependencies
()
{
return
Collections
.
emptyList
();
}
public
abstract
Set
<
Requirement
>
appliesToRequirements
();
/**
* Getter for the check id.
...
...
@@ -111,7 +114,7 @@ public abstract class Check {
*
* @return the check type
*/
public
abstract
Check
Type
getType
();
public
abstract
Requirement
Type
getType
();
/**
* Checks whether the check can be executed on this checkable, meaning the
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckId.java
+
7
-
8
View file @
85cf93b6
...
...
@@ -44,14 +44,13 @@ public class CheckId implements Serializable {
public
static
final
CheckId
C_GE_P_HOLE_OUTSIDE
=
new
CheckId
(
"C_GE_P_HOLE_OUTSIDE"
);
public
static
final
CheckId
IS_CEILING
=
new
CheckId
(
"IS_CEILING"
);
public
static
final
CheckId
C_GE_P_INNER_RINGS_NESTED
=
new
CheckId
(
"C_GE_P_INNER_RINGS_NESTED"
);
public
static
final
CheckId
C_SEM_BS_NOT_CEILING
=
new
CheckId
(
"C_SEM_BS_NOT_CEILING"
);
public
static
final
CheckId
C_SEM_BS_NOT_FLOOR
=
new
CheckId
(
"C_SEM_BS_NOT_FLOOR"
);
public
static
final
CheckId
C_SEM_BS_NOT_GROUND
=
new
CheckId
(
"C_SEM_BS_NOT_GROUND"
);
public
static
final
CheckId
C_SEM_F_MISSING_ID
=
new
CheckId
(
"C_SEM_F_MISSING_ID"
);
public
static
final
CheckId
C_SEM_BS_GROUND_NOT_FRAGMENTED
=
new
CheckId
(
"C_SEM_BS_GROUND_NOT_FRAGMENTED"
);
public
static
final
CheckId
C_SEM_BS_IS_WALL
=
new
CheckId
(
"C_SEM_BS_IS_WALL"
);
public
static
final
CheckId
C_SEM_SCHEMATRON
=
new
CheckId
(
"C_SEM_SCHEMATRON"
);
public
static
final
CheckId
C_SEM_BS_ROOF_NOT_FRAGMENTED
=
new
CheckId
(
"C_SEM_BS_ROOF_NOT_FRAGMENTED"
);
public
static
final
CheckId
C_SE_BS_IS_CEILING
=
new
CheckId
(
"C_SE_BS_IS_CEILING"
);
public
static
final
CheckId
C_SE_BS_IS_FLOOR
=
new
CheckId
(
"C_SE_BS_IS_FLOOR"
);
public
static
final
CheckId
C_SE_BS_IS_GROUND
=
new
CheckId
(
"C_SE_BS_IS_GROUND"
);
public
static
final
CheckId
C_SE_BS_GROUND_NOT_FRAGMENTED
=
new
CheckId
(
"C_SE_BS_GROUND_NOT_FRAGMENTED"
);
public
static
final
CheckId
C_SE_BS_IS_WALL
=
new
CheckId
(
"C_SE_BS_IS_WALL"
);
public
static
final
CheckId
C_SE_SCHEMATRON
=
new
CheckId
(
"C_SE_SCHEMATRON"
);
public
static
final
CheckId
C_SE_BS_ROOF_UNFRAGMENTED
=
new
CheckId
(
"C_SE_BS_ROOF_UNFRAGMENTED"
);
public
static
final
CheckId
C_GE_S_NOT_CLOSED
=
new
CheckId
(
"C_GE_S_NOT_CLOSED"
);
public
static
final
CheckId
C_GE_P_ORIENTATION_RINGS_SAME
=
new
CheckId
(
"C_GE_P_ORIENTATION_RINGS_SAME"
);
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Checkable.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -31,7 +31,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
/**
* Interface to indicate that this object can be checked by Checks.
*
* @author Matthias Betz
- 12bema1bif@hft-stuttgart.de
* @author Matthias Betz
*
*/
public
abstract
class
Checkable
implements
Serializable
{
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/DefaultParameter.java
+
12
-
8
View file @
85cf93b6
...
...
@@ -18,6 +18,8 @@
*/
package
de.hft.stuttgart.citydoctor2.check
;
import
java.io.Serializable
;
/**
* Describes a parameter for a check including the default value as a String.
* All values are a String as they are passed to the check as a Map<String,
...
...
@@ -26,15 +28,17 @@ package de.hft.stuttgart.citydoctor2.check;
* @author Matthias Betz
*
*/
public
class
DefaultParameter
{
public
class
DefaultParameter
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
4587211298078974066L
;
private
String
name
;
private
String
defaultV
alue
;
private
String
v
alue
;
private
Unit
unitType
;
public
DefaultParameter
(
String
name
,
String
defaultValue
,
Unit
unitType
)
{
this
.
name
=
name
;
this
.
defaultV
alue
=
defaultValue
;
this
.
v
alue
=
defaultValue
;
this
.
unitType
=
unitType
;
}
...
...
@@ -56,8 +60,8 @@ public class DefaultParameter {
*
* @return the defaultValue
*/
public
String
get
Default
Value
()
{
return
defaultV
alue
;
public
String
getValue
()
{
return
v
alue
;
}
/*
...
...
@@ -68,10 +72,10 @@ public class DefaultParameter {
@Override
public
String
toString
()
{
StringBuilder
builder
=
new
StringBuilder
();
builder
.
append
(
"
Check
Parameter [name="
);
builder
.
append
(
"
Default
Parameter [name="
);
builder
.
append
(
name
);
builder
.
append
(
",
defaultV
alue="
);
builder
.
append
(
defaultV
alue
);
builder
.
append
(
",
v
alue="
);
builder
.
append
(
v
alue
);
builder
.
append
(
"]"
);
return
builder
.
toString
();
}
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/ErrorId.java
+
6
-
7
View file @
85cf93b6
...
...
@@ -56,13 +56,12 @@ public class ErrorId implements Serializable {
public
static
final
ErrorId
GE_P_ORIENTATION_RINGS_SAME
=
new
ErrorId
(
"GE_P_ORIENTATION_RINGS_SAME"
);
public
static
final
ErrorId
GE_S_NOT_CLOSED
=
new
ErrorId
(
"GE_S_NOT_CLOSED"
);
public
static
final
ErrorId
GE_S_TOO_FEW_POLYGONS
=
new
ErrorId
(
"GE_S_TOO_FEW_POLYGONS"
);
public
static
final
ErrorId
SEM_F_MISSING_ID
=
new
ErrorId
(
"SEM_F_MISSING_ID"
);
public
static
final
ErrorId
SEM_BS_NOT_CEILING
=
new
ErrorId
(
"SEM_BS_NOT_CEILING"
);
public
static
final
ErrorId
SEM_BS_NOT_WALL
=
new
ErrorId
(
"SEM_BS_NOT_WALL"
);
public
static
final
ErrorId
SEM_BS_NOT_FLOOR
=
new
ErrorId
(
"SEM_BS_NOT_FLOOR"
);
public
static
final
ErrorId
SEM_BS_NOT_GROUND
=
new
ErrorId
(
"SEM_BS_NOT_GROUND"
);
public
static
final
ErrorId
SEM_SCHEMATRON_ERROR
=
new
ErrorId
(
"SEM_SCHEMATRON_ERROR"
);
public
static
final
ErrorId
SEM_BS_UNFRAGMENTED
=
new
ErrorId
(
"SEM_BS_UNFRAGMENTED"
);
public
static
final
ErrorId
SE_BS_NOT_CEILING
=
new
ErrorId
(
"SE_BS_NOT_CEILING"
);
public
static
final
ErrorId
SE_BS_NOT_WALL
=
new
ErrorId
(
"SE_BS_NOT_WALL"
);
public
static
final
ErrorId
SE_BS_NOT_FLOOR
=
new
ErrorId
(
"SE_BS_NOT_FLOOR"
);
public
static
final
ErrorId
SE_BS_NOT_GROUND
=
new
ErrorId
(
"SE_BS_NOT_GROUND"
);
public
static
final
ErrorId
SE_SCHEMATRON_ERROR
=
new
ErrorId
(
"SE_SCHEMATRON_ERROR"
);
public
static
final
ErrorId
SE_BS_UNFRAGMENTED
=
new
ErrorId
(
"SE_BS_UNFRAGMENTED"
);
public
static
final
ErrorId
GE_P_DEGENERATED_POLYGON
=
new
ErrorId
(
"GE_P_DEGENERATED_POLYGON"
);
private
String
name
;
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/Requirement.java
0 → 100644
+
136
-
0
View file @
85cf93b6
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.check
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
public
class
Requirement
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
590639811553512803L
;
private
static
final
String
DISTANCE_TOLERANCE
=
"distanceTolerance"
;
private
static
final
String
ANGLE_TOLERANCE
=
"angleTolerance"
;
private
static
final
String
TYPE_STRING
=
"type"
;
private
static
final
String
DEGENERATED_POLYGON_TOLERANCE
=
"degeneratedPolygonTolerance"
;
private
static
final
String
LOWER_ANGLE_NAME
=
"lowerAngle"
;
private
static
final
String
UPPER_ANGLE_NAME
=
"upperAngle"
;
public
static
final
Requirement
R_GE_R_TOO_FEW_POINTS
=
new
Requirement
(
"R_GE_R_TOO_FEW_POINTS"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_R_NOT_CLOSED
=
new
Requirement
(
"R_GE_R_NOT_CLOSED"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_R_CONSECUTIVE_POINTS_SAME
=
new
Requirement
(
"R_GE_R_CONSECUTIVE_POINTS_SAME"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_R_SELF_INTERSECTION
=
new
Requirement
(
"R_GE_R_SELF_INTERSECTION"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_NON_PLANAR
=
new
Requirement
(
"R_GE_P_NON_PLANAR"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_INTERIOR_DISCONNECTED
=
new
Requirement
(
"R_GE_P_INTERIOR_DISCONNECTED"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_INTERSECTING_RINGS
=
new
Requirement
(
"R_GE_P_INTERSECTING_RINGS"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_HOLE_OUTSIDE
=
new
Requirement
(
"R_GE_P_HOLE_OUTSIDE"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_ORIENTATION_RINGS_SAME
=
new
Requirement
(
"R_GE_P_ORIENTATION_RINGS_SAME"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_P_INNER_RINGS_NESTED
=
new
Requirement
(
"R_GE_P_INNER_RINGS_NESTED"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_TOO_FEW_POLYGONS
=
new
Requirement
(
"R_GE_S_TOO_FEW_POLYGONS"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_NOT_CLOSED
=
new
Requirement
(
"R_GE_S_NOT_CLOSED"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_NON_MANIFOLD_EDGE
=
new
Requirement
(
"R_GE_S_NON_MANIFOLD_EDGE"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_POLYGON_WRONG_ORIENTATION
=
new
Requirement
(
"R_GE_S_POLYGON_WRONG_ORIENTATION"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION
=
new
Requirement
(
"R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_NON_MANIFOLD_VERTEX
=
new
Requirement
(
"R_GE_S_NON_MANIFOLD_VERTEX"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_SELF_INTERSECTION
=
new
Requirement
(
"R_GE_S_SELF_INTERSECTION"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_GE_S_MULTIPLE_CONNECTED_COMPONENTS
=
new
Requirement
(
"R_GE_S_MULTIPLE_CONNECTED_COMPONENTS"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_SE_ATTRIBUTES_EXISTING
=
new
Requirement
(
"R_SE_ATTRIBUTES_EXISTING"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_ATTRIBUTES_CORRECT
=
new
Requirement
(
"R_SE_ATTRIBUTES_CORRECT"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_GE_R_NULL_AREA
=
new
Requirement
(
"R_GE_R_NULL_AREA"
,
RequirementType
.
GEOMETRY
);
public
static
final
Requirement
R_SE_BS_GROUND_UNFRAGMENTED
=
new
Requirement
(
"R_SE_BS_GROUND_UNFRAGMENTED"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_BS_ROOF_UNFRAGMENTED
=
new
Requirement
(
"R_SE_BS_GROUND_UNFRAGMENTED"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_BS_IS_CEILING
=
new
Requirement
(
"R_SE_BS_IS_CEILING"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_BS_IS_FLOOR
=
new
Requirement
(
"R_SE_BS_IS_FLOOR"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_BS_IS_WALL
=
new
Requirement
(
"R_SE_BS_IS_WALL"
,
RequirementType
.
SEMANTIC
);
public
static
final
Requirement
R_SE_BS_IS_GROUND
=
new
Requirement
(
"R_SE_BS_IS_GROUND"
,
RequirementType
.
SEMANTIC
);
static
{
// fill requirements with default parameters
ArrayList
<
DefaultParameter
>
defaultParameters
=
new
ArrayList
<>();
defaultParameters
.
add
(
new
DefaultParameter
(
TYPE_STRING
,
"distance"
,
Unit
.
NONE
));
defaultParameters
.
add
(
new
DefaultParameter
(
DISTANCE_TOLERANCE
,
"0.01"
,
Unit
.
METER
));
defaultParameters
.
add
(
new
DefaultParameter
(
ANGLE_TOLERANCE
,
"1"
,
Unit
.
DEGREE
));
defaultParameters
.
add
(
new
DefaultParameter
(
DEGENERATED_POLYGON_TOLERANCE
,
"0.00000"
,
Unit
.
METER
));
R_GE_P_NON_PLANAR
.
parameters
=
Collections
.
unmodifiableList
(
defaultParameters
);
defaultParameters
=
new
ArrayList
<>();
defaultParameters
.
add
(
new
DefaultParameter
(
LOWER_ANGLE_NAME
,
"45"
,
Unit
.
DEGREE
));
defaultParameters
.
add
(
new
DefaultParameter
(
UPPER_ANGLE_NAME
,
"135"
,
Unit
.
DEGREE
));
R_SE_BS_IS_WALL
.
parameters
=
Collections
.
unmodifiableList
(
defaultParameters
);
}
private
String
id
;
private
RequirementType
type
;
private
List
<
DefaultParameter
>
parameters
;
public
Requirement
(
String
id
,
RequirementType
type
)
{
this
.
id
=
id
;
this
.
type
=
type
;
parameters
=
Collections
.
emptyList
();
}
public
String
getId
()
{
return
id
;
}
public
List
<
DefaultParameter
>
getDefaultParameter
()
{
return
parameters
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
id
==
null
)
?
0
:
id
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
Requirement
other
=
(
Requirement
)
obj
;
if
(
id
==
null
)
{
if
(
other
.
id
!=
null
)
return
false
;
}
else
if
(!
id
.
equals
(
other
.
id
))
return
false
;
return
true
;
}
@Override
public
String
toString
()
{
return
id
;
}
public
RequirementType
getType
()
{
return
type
;
}
}
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/
Check
Type.java
→
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/
Requirement
Type.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -26,7 +26,7 @@ package de.hft.stuttgart.citydoctor2.check;
* @author Matthias Betz
*
*/
public
enum
Check
Type
{
public
enum
Requirement
Type
{
GEOMETRY
,
SEMANTIC
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotCeilingError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -79,7 +79,7 @@ public class NotCeilingError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_BS_NOT_CEILING
;
return
ErrorId
.
SE_BS_NOT_CEILING
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotFloorError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -77,7 +77,7 @@ public class NotFloorError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_BS_NOT_FLOOR
;
return
ErrorId
.
SE_BS_NOT_FLOOR
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotGroundError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -79,7 +79,7 @@ public class NotGroundError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_BS_NOT_GROUND
;
return
ErrorId
.
SE_BS_NOT_GROUND
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/NotWallError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -82,7 +82,7 @@ public class NotWallError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_BS_NOT_WALL
;
return
ErrorId
.
SE_BS_NOT_WALL
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SchematronError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -94,7 +94,7 @@ public class SchematronError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_SCHEMATRON_ERROR
;
return
ErrorId
.
SE_SCHEMATRON_ERROR
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/check/error/SurfaceUnfragmentedError.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -77,7 +77,7 @@ public class SurfaceUnfragmentedError implements CheckError {
@Override
public
ErrorId
getErrorId
()
{
return
ErrorId
.
SE
M
_BS_UNFRAGMENTED
;
return
ErrorId
.
SE_BS_UNFRAGMENTED
;
}
@Override
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/BoundingBox.java
+
4
-
0
View file @
85cf93b6
...
...
@@ -42,6 +42,10 @@ public class BoundingBox {
public
static
BoundingBox
of
(
List
<
Polygon
>
polygons
)
{
return
BoundingBoxCalculator
.
calculateBoundingBox
(
polygons
);
}
public
static
BoundingBox
ofPoints
(
List
<?
extends
Vector3d
>
points
)
{
return
BoundingBoxCalculator
.
calculateBoundingBoxFromPoints
(
points
);
}
/**
* Creates an axis aligned bounding box of the whole model.
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/CovarianceMatrix.java
+
6
-
0
View file @
85cf93b6
...
...
@@ -56,6 +56,12 @@ public class CovarianceMatrix {
covValues
[
1
][
2
]
+=
ydiff
*
zdiff
;
covValues
[
2
][
2
]
+=
zdiff
*
zdiff
;
}
covValues
[
0
][
0
]
/=
vertices
.
size
();
covValues
[
0
][
1
]
/=
vertices
.
size
();
covValues
[
0
][
2
]
/=
vertices
.
size
();
covValues
[
1
][
1
]
/=
vertices
.
size
();
covValues
[
1
][
2
]
/=
vertices
.
size
();
covValues
[
2
][
2
]
/=
vertices
.
size
();
// the covariance matrix is symmetric, so we can fill in the remaining values
covValues
[
1
][
0
]
=
covValues
[
0
][
1
];
covValues
[
2
][
0
]
=
covValues
[
0
][
2
];
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Matrix3x3d.java
+
1
-
1
View file @
85cf93b6
...
...
@@ -135,7 +135,7 @@ public class Matrix3x3d {
/**
* Multiplies this matrix with a 3-dim vector.
*
* @param
o
the
r the
vector
* @param the
multiplied
vector
* @return the result stored in a new vector
*/
public
Vector3d
mult
(
Vector3d
other
)
{
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/utils/BoundingBoxCalculator.java
+
47
-
7
View file @
85cf93b6
...
...
@@ -63,17 +63,20 @@ public class BoundingBoxCalculator {
for
(
Vertex
v
:
p
.
getExteriorRing
().
getVertices
())
{
if
(
v
.
getX
()
<
lowX
)
{
lowX
=
v
.
getX
();
}
else
if
(
v
.
getX
()
>
highX
)
{
}
if
(
v
.
getX
()
>
highX
)
{
highX
=
v
.
getX
();
}
if
(
v
.
getY
()
<
lowY
)
{
lowY
=
v
.
getY
();
}
else
if
(
v
.
getY
()
>
highY
)
{
}
if
(
v
.
getY
()
>
highY
)
{
highY
=
v
.
getY
();
}
if
(
v
.
getZ
()
<
lowZ
)
{
lowZ
=
v
.
getZ
();
}
else
if
(
v
.
getZ
()
>
highZ
)
{
}
if
(
v
.
getZ
()
>
highZ
)
{
highZ
=
v
.
getZ
();
}
}
...
...
@@ -92,7 +95,7 @@ public class BoundingBoxCalculator {
*/
public
static
BoundingBox
calculateBoundingBox
(
CityDoctorModel
model
)
{
Vector3d
low
=
new
Vector3d
(
Double
.
MAX_VALUE
,
Double
.
MAX_VALUE
,
Double
.
MAX_VALUE
);
Vector3d
high
=
new
Vector3d
(
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
);
Vector3d
high
=
new
Vector3d
(
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
);
findMinMax
(
low
,
high
,
model
.
getBuildings
());
findMinMax
(
low
,
high
,
model
.
getBridges
());
...
...
@@ -107,6 +110,40 @@ public class BoundingBoxCalculator {
return
BoundingBox
.
of
(
result
);
}
public
static
BoundingBox
calculateBoundingBoxFromPoints
(
List
<?
extends
Vector3d
>
points
)
{
double
lowX
=
Double
.
MAX_VALUE
;
double
highX
=
Double
.
NEGATIVE_INFINITY
;
double
lowY
=
Double
.
MAX_VALUE
;
double
highY
=
Double
.
NEGATIVE_INFINITY
;
double
lowZ
=
Double
.
MAX_VALUE
;
double
highZ
=
Double
.
NEGATIVE_INFINITY
;
// only need to check exterior rings
for
(
Vector3d
v
:
points
)
{
if
(
v
.
getX
()
<
lowX
)
{
lowX
=
v
.
getX
();
}
if
(
v
.
getX
()
>
highX
)
{
highX
=
v
.
getX
();
}
if
(
v
.
getY
()
<
lowY
)
{
lowY
=
v
.
getY
();
}
if
(
v
.
getY
()
>
highY
)
{
highY
=
v
.
getY
();
}
if
(
v
.
getZ
()
<
lowZ
)
{
lowZ
=
v
.
getZ
();
}
if
(
v
.
getZ
()
>
highZ
)
{
highZ
=
v
.
getZ
();
}
}
Vector3d
[]
result
=
new
Vector3d
[
2
];
result
[
0
]
=
new
Vector3d
(
lowX
,
lowY
,
lowZ
);
result
[
1
]
=
new
Vector3d
(
highX
,
highY
,
highZ
);
return
BoundingBox
.
of
(
result
);
}
private
static
void
findMinMax
(
Vector3d
low
,
Vector3d
high
,
List
<?
extends
CityObject
>
features
)
{
for
(
CityObject
co
:
features
)
{
findMinMax
(
low
,
high
,
co
);
...
...
@@ -121,17 +158,20 @@ public class BoundingBoxCalculator {
for
(
Vertex
v
:
geom
.
getVertices
())
{
if
(
v
.
getX
()
<
low
.
getX
())
{
low
.
setX
(
v
.
getX
());
}
else
if
(
v
.
getX
()
>
high
.
getX
())
{
}
if
(
v
.
getX
()
>
high
.
getX
())
{
high
.
setX
(
v
.
getX
());
}
if
(
v
.
getY
()
<
low
.
getY
())
{
low
.
setY
(
v
.
getY
());
}
else
if
(
v
.
getY
()
>
high
.
getY
())
{
}
if
(
v
.
getY
()
>
high
.
getY
())
{
high
.
setY
(
v
.
getY
());
}
if
(
v
.
getZ
()
<
low
.
getZ
())
{
low
.
setZ
(
v
.
getZ
());
}
else
if
(
v
.
getZ
()
>
high
.
getZ
())
{
}
if
(
v
.
getZ
()
>
high
.
getZ
())
{
high
.
setZ
(
v
.
getZ
());
}
}
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
+
78
-
56
View file @
85cf93b6
...
...
@@ -241,7 +241,7 @@ public class Checker {
ValidationPlan
plan
=
new
ValidationPlan
();
List
<
Checking
>
filter
=
createFilter
();
for
(
Entry
<
CheckId
,
Check
Configuration
>
e
:
config
.
get
Check
s
().
entrySet
())
{
for
(
Entry
<
String
,
Requirement
Configuration
>
e
:
config
.
get
Requirement
s
().
entrySet
())
{
RequirementId
reqId
=
mapToRequirement
(
e
.
getKey
());
if
(
reqId
==
null
)
{
continue
;
...
...
@@ -250,12 +250,12 @@ public class Checker {
req
.
setName
(
reqId
);
req
.
setEnabled
(
e
.
getValue
().
isEnabled
());
plan
.
getRequirements
().
add
(
req
);
CheckPrototype
proto
=
Checks
.
getCheckPrototypeForId
(
e
.
getKey
());
Map
<
String
,
String
>
parameters
=
e
.
getValue
().
getParameters
();
Map
<
String
,
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
>
reqs
=
Checks
.
getAvailableRequirements
();
if
(
parameters
!=
null
)
{
for
(
Entry
<
String
,
String
>
param
:
parameters
.
entrySet
())
{
Parameter
p
=
new
Parameter
();
DefaultParameter
defaultP
=
getDefaultParameter
(
param
.
getKey
(),
proto
);
DefaultParameter
defaultP
=
getDefaultParameter
(
param
.
getKey
(),
reqs
);
if
(
defaultP
!=
null
)
{
p
.
setUom
(
defaultP
.
getUnitType
().
getGmlRepresentation
());
}
...
...
@@ -292,10 +292,14 @@ public class Checker {
return
plan
;
}
private
DefaultParameter
getDefaultParameter
(
String
key
,
CheckPrototype
proto
)
{
for
(
DefaultParameter
param
:
proto
.
getDefaultParameter
())
{
if
(
param
.
getName
().
equals
(
key
))
{
return
param
;
private
DefaultParameter
getDefaultParameter
(
String
key
,
Map
<
String
,
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
>
reqs
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
requirement
=
reqs
.
get
(
key
);
if
(
requirement
!=
null
)
{
for
(
DefaultParameter
param
:
requirement
.
getDefaultParameter
())
{
if
(
param
.
getName
().
equals
(
key
))
{
return
param
;
}
}
}
return
null
;
...
...
@@ -382,43 +386,10 @@ public class Checker {
}
}
private
RequirementId
mapToRequirement
(
CheckId
key
)
{
switch
(
key
.
getName
())
{
case
"C_GE_R_TOO_FEW_POINTS"
:
return
RequirementId
.
R_GE_R_TOO_FEW_POINTS
;
case
"C_GE_R_NOT_CLOSED"
:
return
RequirementId
.
R_GE_R_NOT_CLOSED
;
case
"C_GE_R_DUPLICATE_POINT"
:
return
RequirementId
.
R_GE_R_CONSECUTIVE_POINTS_SAME
;
case
"C_GE_R_SELF_INTERSECTION"
:
return
RequirementId
.
R_GE_R_SELF_INTERSECTION
;
case
"C_GE_P_INTERIOR_DISCONNECTED"
:
return
RequirementId
.
R_GE_P_INTERIOR_DISCONNECTED
;
case
"C_GE_P_INTERSECTING_RINGS"
:
return
RequirementId
.
R_GE_P_INTERSECTING_RINGS
;
case
"C_GE_P_NON_PLANAR"
:
return
RequirementId
.
R_GE_P_NON_PLANAR
;
case
"C_GE_S_TOO_FEW_POLYGONS"
:
return
RequirementId
.
R_GE_S_TOO_FEW_POLYGONS
;
case
"C_GE_S_NON_MANIFOLD_EDGE"
:
return
RequirementId
.
R_GE_S_NON_MANIFOLD_EDGE
;
case
"C_GE_S_POLYGON_WRONG_ORIENTATION"
:
return
RequirementId
.
R_GE_S_POLYGON_WRONG_ORIENTATION
;
case
"C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION"
:
return
RequirementId
.
R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION
;
case
"C_GE_S_NON_MANIFOLD_VERTEX"
:
return
RequirementId
.
R_GE_S_NON_MANIFOLD_VERTEX
;
case
"C_GE_S_SELF_INTERSECTION"
:
return
RequirementId
.
R_GE_S_SELF_INTERSECTION
;
case
"C_GE_P_HOLE_OUTSIDE"
:
return
RequirementId
.
R_GE_P_HOLE_OUTSIDE
;
case
"C_GE_P_INNER_RINGS_NESTED"
:
return
RequirementId
.
R_GE_P_INNER_RINGS_NESTED
;
case
"C_GE_S_NOT_CLOSED"
:
return
RequirementId
.
R_GE_S_NOT_CLOSED
;
case
"C_GE_S_MULTIPLE_CONNECTED_COMPONENTS"
:
return
RequirementId
.
R_GE_S_MULTIPLE_CONNECTED_COMPONENTS
;
default
:
private
RequirementId
mapToRequirement
(
String
requirementName
)
{
try
{
return
RequirementId
.
valueOf
(
requirementName
);
}
catch
(
IllegalArgumentException
e
)
{
return
null
;
}
}
...
...
@@ -557,20 +528,71 @@ public class Checker {
}
private
List
<
Check
>
collectEnabledChecksAndInit
(
ParserConfiguration
parserConfig
,
ValidationConfiguration
config
)
{
List
<
Check
>
checks
=
new
ArrayList
<>();
for
(
Entry
<
CheckId
,
CheckConfiguration
>
e
:
config
.
getChecks
().
entrySet
())
{
if
(
e
.
getValue
().
isEnabled
())
{
Check
c
=
checkConfig
.
getCheckForId
(
e
.
getKey
());
Map
<
String
,
String
>
parameters
=
new
HashMap
<>();
parameters
.
putAll
(
e
.
getValue
().
getParameters
());
parameters
.
put
(
"numberOfRoundingPlaces"
,
""
+
config
.
getNumberOfRoundingPlaces
());
parameters
.
put
(
"minVertexDistance"
,
""
+
config
.
getMinVertexDistance
());
// initialize checks with parameters
c
.
init
(
parameters
,
parserConfig
);
checks
.
add
(
c
);
Set
<
CheckId
>
enabledCheck
=
new
HashSet
<>();
Map
<
CheckId
,
Map
<
String
,
String
>>
parameterMap
=
new
HashMap
<>();
for
(
Entry
<
String
,
RequirementConfiguration
>
e
:
config
.
getRequirements
().
entrySet
())
{
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
req
=
Checks
.
getAvailableRequirements
().
get
(
e
.
getKey
());
if
(
req
==
null
)
{
logger
.
warn
(
"Could not find any check that satisfies requirement {}, it will not be checked"
,
e
.
getKey
());
}
else
{
if
(
e
.
getValue
().
isEnabled
())
{
// this requirement is enabled
for
(
CheckPrototype
proto
:
Checks
.
getCheckPrototypes
())
{
if
(
proto
.
checksRequirements
().
contains
(
req
))
{
// this requirement is checked by this check
// put all requirement parameter in the map
parameterMap
.
compute
(
proto
.
getCheckId
(),
(
k
,
v
)
->
{
if
(
v
==
null
)
{
v
=
new
HashMap
<>();
v
.
put
(
GlobalParameters
.
NUMBER_OF_ROUNDING_PLACES
,
config
.
getNumberOfRoundingPlacesAsString
());
v
.
put
(
GlobalParameters
.
MIN_VERTEX_DISTANCE
,
config
.
getMinVertexDistanceAsString
());
}
v
.
putAll
(
e
.
getValue
().
getParameters
());
return
v
;
});
enabledCheck
.
add
(
proto
.
getCheckId
());
collectDependencyChecks
(
proto
,
enabledCheck
);
}
}
}
}
}
fillParameterMapsWithDefaultParameter
(
enabledCheck
,
parameterMap
);
ArrayList
<
Check
>
checkList
=
new
ArrayList
<>();
for
(
CheckId
id
:
enabledCheck
)
{
Check
c
=
checkConfig
.
getCheckForId
(
id
);
c
.
init
(
parameterMap
.
get
(
id
),
parserConfig
);
checkList
.
add
(
c
);
}
return
checkList
;
}
private
void
fillParameterMapsWithDefaultParameter
(
Set
<
CheckId
>
enabledCheck
,
Map
<
CheckId
,
Map
<
String
,
String
>>
parameterMap
)
{
for
(
CheckId
id
:
enabledCheck
)
{
CheckPrototype
proto
=
Checks
.
getCheckPrototypeForId
(
id
);
Map
<
String
,
String
>
map
=
parameterMap
.
computeIfAbsent
(
id
,
k
->
new
HashMap
<>());
for
(
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
req
:
proto
.
checksRequirements
())
{
if
(
proto
.
checksRequirements
().
contains
(
req
))
{
for
(
DefaultParameter
param
:
req
.
getDefaultParameter
())
{
map
.
computeIfAbsent
(
param
.
getName
(),
k
->
param
.
getValue
());
}
}
}
}
}
private
void
collectDependencyChecks
(
CheckPrototype
proto
,
Set
<
CheckId
>
enabledChecks
)
{
enabledChecks
.
addAll
(
proto
.
getDependencies
());
for
(
CheckId
id
:
proto
.
getDependencies
())
{
if
(
enabledChecks
.
contains
(
id
))
{
continue
;
}
CheckPrototype
depProto
=
Checks
.
getCheckPrototypeForId
(
id
);
collectDependencyChecks
(
depProto
,
enabledChecks
);
}
return
checks
;
}
private
void
checkCityModel
(
CityDoctorModel
model
,
ProgressListener
l
)
{
...
...
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/GlobalParameters.java
0 → 100644
+
31
-
0
View file @
85cf93b6
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.check
;
public
class
GlobalParameters
{
private
GlobalParameters
()
{
}
public
static
final
String
SCHEMATRON_PATH
=
"schematronPath"
;
public
static
final
String
MIN_VERTEX_DISTANCE
=
"minVertexDistance"
;
public
static
final
String
NUMBER_OF_ROUNDING_PLACES
=
"numberOfRoundingPlaces"
;
}
This diff is collapsed.
Click to expand it.
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/
Check
Configuration.java
→
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/
Requirement
Configuration.java
+
2
-
5
View file @
85cf93b6
...
...
@@ -29,7 +29,7 @@ import java.util.Map;
* @author Matthias Betz
*
*/
public
class
Check
Configuration
implements
Serializable
{
public
class
Requirement
Configuration
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
1258195428669813888L
;
...
...
@@ -59,10 +59,7 @@ public class CheckConfiguration implements Serializable {
}
return
parameters
;
}
/**
* @param parameters Sets the parameters of this check.
*/
public
void
setParameters
(
Map
<
String
,
String
>
parameters
)
{
this
.
parameters
=
parameters
;
}
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
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
Menu
Explore
Projects
Groups
Snippets