Commit 1da24add authored by Matthias Betz's avatar Matthias Betz
Browse files

Merge branch 'CheckEngineRework' into 'master'

Check engine rework

See merge request betzms/citydoctor2!4
parents 09470a4d cd494d75
Pipeline #2115 passed with stage
in 2 minutes and 53 seconds
...@@ -23,6 +23,7 @@ import java.util.ArrayList; ...@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError; import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding; import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
...@@ -46,15 +47,16 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; ...@@ -46,15 +47,16 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
* The general check class containing the methods which will be called by check * The general check class containing the methods which will be called by check
* engine. To create a new check override one or more check(...) methods and * engine. To create a new check override one or more check(...) methods and
* implement the {@link Check#getApplicableToClasses()} method by returning a * implement the {@link Check#getApplicableToClasses()} method by returning a
* list of classes you wish to check. CheckResult objects can be attached to * list of classes you wish to check.<br>
* every Checkable. If the check has parameters override the * CheckResult objects can be attached to every Checkable. If the check has
* {@link Check#init(Map, ParserConfiguration)} method to get the value of a * parameters override the {@link Check#init(Map, ParserConfiguration)} method
* parameter if a user has specified one in the validation plan. It will be * to get the value of a parameter if a user has specified one in the validation
* contained in the Map as a string. If you have parameters you will need to * plan. It will be contained in the Map as a string. If you have parameters you
* override the {@link Check#getDefaultParameter()} method as well to declare * will need to override the {@link Check#getDefaultParameter()} method as well
* which parameters you have, which name and default value they have. The name * to declare which parameters you have, which name and default value they have.
* will be the key for the Map in the init method previously mentioned. If your * The name will be the key for the Map in the init method previously
* check has dependencies you can declare them in the * mentioned.<br>
* If your check has dependencies you can declare them in the
* {@link Check#getDependencies()} method. Be sure not to create cyclic * {@link Check#getDependencies()} method. Be sure not to create cyclic
* dependencies as that would result in undefined behavior. * dependencies as that would result in undefined behavior.
* *
...@@ -66,7 +68,7 @@ public abstract class Check { ...@@ -66,7 +68,7 @@ public abstract class Check {
private List<Class<Checkable>> applicableToClasses = new ArrayList<>(2); private List<Class<Checkable>> applicableToClasses = new ArrayList<>(2);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Check() { protected Check() {
Method[] declaredMethods = getClass().getDeclaredMethods(); Method[] declaredMethods = getClass().getDeclaredMethods();
for (Method m : declaredMethods) { for (Method m : declaredMethods) {
if ("check".equals(m.getName())) { if ("check".equals(m.getName())) {
...@@ -98,6 +100,8 @@ public abstract class Check { ...@@ -98,6 +100,8 @@ public abstract class Check {
return Collections.emptyList(); return Collections.emptyList();
} }
public abstract Set<Requirement> appliesToRequirements();
/** /**
* Getter for the check id. * Getter for the check id.
* *
...@@ -110,7 +114,7 @@ public abstract class Check { ...@@ -110,7 +114,7 @@ public abstract class Check {
* *
* @return the check type * @return the check type
*/ */
public abstract CheckType getType(); public abstract RequirementType getType();
/** /**
* Checks whether the check can be executed on this checkable, meaning the * Checks whether the check can be executed on this checkable, meaning the
...@@ -306,7 +310,7 @@ public abstract class Check { ...@@ -306,7 +310,7 @@ public abstract class Check {
* *
* @param params the parameter map containing the parameters for the check in * @param params the parameter map containing the parameters for the check in
* String form. The key should be the same String provided by the * String form. The key should be the same String provided by the
* {@link Check#getDefaultParameter()} method * {@link Requirement#getDefaultParameter()} method
* @param config sometimes there are global parameters which can be used by * @param config sometimes there are global parameters which can be used by
* checks. Those are be stored in this container * checks. Those are be stored in this container
*/ */
...@@ -314,16 +318,6 @@ public abstract class Check { ...@@ -314,16 +318,6 @@ public abstract class Check {
} }
/**
* This methods gives checks the possibility to declare default parameters, used
* primarily in the GUI.
*
* @return a list of default parameters, not null
*/
public List<DefaultParameter> getDefaultParameter() {
return Collections.emptyList();
}
@Override @Override
public String toString() { public String toString() {
return "Check [id=" + getCheckId() + "]"; return "Check [id=" + getCheckId() + "]";
......
...@@ -44,14 +44,13 @@ public class CheckId implements Serializable { ...@@ -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 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 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_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_SE_BS_IS_CEILING = new CheckId("C_SE_BS_IS_CEILING");
public static final CheckId C_SEM_BS_NOT_FLOOR = new CheckId("C_SEM_BS_NOT_FLOOR"); public static final CheckId C_SE_BS_IS_FLOOR = new CheckId("C_SE_BS_IS_FLOOR");
public static final CheckId C_SEM_BS_NOT_GROUND = new CheckId("C_SEM_BS_NOT_GROUND"); public static final CheckId C_SE_BS_IS_GROUND = new CheckId("C_SE_BS_IS_GROUND");
public static final CheckId C_SEM_F_MISSING_ID = new CheckId("C_SEM_F_MISSING_ID"); public static final CheckId C_SE_BS_GROUND_NOT_FRAGMENTED = new CheckId("C_SE_BS_GROUND_NOT_FRAGMENTED");
public static final CheckId C_SEM_BS_GROUND_NOT_FRAGMENTED = new CheckId("C_SEM_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_SEM_BS_IS_WALL = new CheckId("C_SEM_BS_IS_WALL"); public static final CheckId C_SE_SCHEMATRON = new CheckId("C_SE_SCHEMATRON");
public static final CheckId C_SEM_SCHEMATRON = new CheckId("C_SEM_SCHEMATRON"); public static final CheckId C_SE_BS_ROOF_UNFRAGMENTED = new CheckId("C_SE_BS_ROOF_UNFRAGMENTED");
public static final CheckId C_SEM_BS_ROOF_NOT_FRAGMENTED = new CheckId("C_SEM_BS_ROOF_NOT_FRAGMENTED");
public static final CheckId C_GE_S_NOT_CLOSED = new CheckId("C_GE_S_NOT_CLOSED"); 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"); public static final CheckId C_GE_P_ORIENTATION_RINGS_SAME = new CheckId("C_GE_P_ORIENTATION_RINGS_SAME");
......
...@@ -31,7 +31,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlId; ...@@ -31,7 +31,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
/** /**
* Interface to indicate that this object can be checked by Checks. * 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 { public abstract class Checkable implements Serializable {
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
*/ */
package de.hft.stuttgart.citydoctor2.check; package de.hft.stuttgart.citydoctor2.check;
import java.io.Serializable;
/** /**
* Describes a parameter for a check including the default value as a String. * 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, * 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; ...@@ -26,15 +28,17 @@ package de.hft.stuttgart.citydoctor2.check;
* @author Matthias Betz * @author Matthias Betz
* *
*/ */
public class DefaultParameter { public class DefaultParameter implements Serializable {
private static final long serialVersionUID = -4587211298078974066L;
private String name; private String name;
private String defaultValue; private String value;
private Unit unitType; private Unit unitType;
public DefaultParameter(String name, String defaultValue, Unit unitType) { public DefaultParameter(String name, String defaultValue, Unit unitType) {
this.name = name; this.name = name;
this.defaultValue = defaultValue; this.value = defaultValue;
this.unitType = unitType; this.unitType = unitType;
} }
...@@ -56,8 +60,8 @@ public class DefaultParameter { ...@@ -56,8 +60,8 @@ public class DefaultParameter {
* *
* @return the defaultValue * @return the defaultValue
*/ */
public String getDefaultValue() { public String getValue() {
return defaultValue; return value;
} }
/* /*
...@@ -68,10 +72,10 @@ public class DefaultParameter { ...@@ -68,10 +72,10 @@ public class DefaultParameter {
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("CheckParameter [name="); builder.append("DefaultParameter [name=");
builder.append(name); builder.append(name);
builder.append(", defaultValue="); builder.append(", value=");
builder.append(defaultValue); builder.append(value);
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }
......
...@@ -56,14 +56,13 @@ public class ErrorId implements Serializable { ...@@ -56,14 +56,13 @@ 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_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_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 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 SE_BS_NOT_CEILING = new ErrorId("SE_BS_NOT_CEILING");
public static final ErrorId SEM_BS_NOT_CEILING = new ErrorId("SEM_BS_NOT_CEILING"); public static final ErrorId SE_BS_NOT_WALL = new ErrorId("SE_BS_NOT_WALL");
public static final ErrorId SEM_BS_NOT_WALL = new ErrorId("SEM_BS_NOT_WALL"); public static final ErrorId SE_BS_NOT_FLOOR = new ErrorId("SE_BS_NOT_FLOOR");
public static final ErrorId SEM_BS_NOT_FLOOR = new ErrorId("SEM_BS_NOT_FLOOR"); public static final ErrorId SE_BS_NOT_GROUND = new ErrorId("SE_BS_NOT_GROUND");
public static final ErrorId SEM_BS_NOT_GROUND = new ErrorId("SEM_BS_NOT_GROUND"); public static final ErrorId SE_SCHEMATRON_ERROR = new ErrorId("SE_SCHEMATRON_ERROR");
public static final ErrorId SEM_SCHEMATRON_ERROR = new ErrorId("SEM_SCHEMATRON_ERROR"); public static final ErrorId SE_BS_UNFRAGMENTED = new ErrorId("SE_BS_UNFRAGMENTED");
public static final ErrorId SEM_BS_UNFRAGMENTED = new ErrorId("SEM_BS_UNFRAGMENTED"); public static final ErrorId GE_P_DEGENERATED_POLYGON = new ErrorId("GE_P_DEGENERATED_POLYGON");
public static final ErrorId GE_P_TINY_EDGE = new ErrorId("GE_P_TINY_EDGE");
private String name; private String name;
......
/*-
* 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";
private static final String MAX_ANGLE_DEVIATION = "maxAngleDeviation";
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);
defaultParameters.add(new DefaultParameter(MAX_ANGLE_DEVIATION, "1", Unit.DEGREE));
R_SE_BS_ROOF_UNFRAGMENTED.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;
}
}
...@@ -26,7 +26,7 @@ package de.hft.stuttgart.citydoctor2.check; ...@@ -26,7 +26,7 @@ package de.hft.stuttgart.citydoctor2.check;
* @author Matthias Betz * @author Matthias Betz
* *
*/ */
public enum CheckType { public enum RequirementType {
GEOMETRY, SEMANTIC GEOMETRY, SEMANTIC
......
...@@ -64,7 +64,7 @@ public class DegeneratedPolygonError implements CheckError { ...@@ -64,7 +64,7 @@ public class DegeneratedPolygonError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.GE_P_TINY_EDGE; return ErrorId.GE_P_DEGENERATED_POLYGON;
} }
@Override @Override
......
...@@ -79,7 +79,7 @@ public class NotCeilingError implements CheckError { ...@@ -79,7 +79,7 @@ public class NotCeilingError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_BS_NOT_CEILING; return ErrorId.SE_BS_NOT_CEILING;
} }
@Override @Override
......
...@@ -77,7 +77,7 @@ public class NotFloorError implements CheckError { ...@@ -77,7 +77,7 @@ public class NotFloorError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_BS_NOT_FLOOR; return ErrorId.SE_BS_NOT_FLOOR;
} }
@Override @Override
......
...@@ -79,7 +79,7 @@ public class NotGroundError implements CheckError { ...@@ -79,7 +79,7 @@ public class NotGroundError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_BS_NOT_GROUND; return ErrorId.SE_BS_NOT_GROUND;
} }
@Override @Override
......
...@@ -82,7 +82,7 @@ public class NotWallError implements CheckError { ...@@ -82,7 +82,7 @@ public class NotWallError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_BS_NOT_WALL; return ErrorId.SE_BS_NOT_WALL;
} }
@Override @Override
......
...@@ -94,7 +94,7 @@ public class SchematronError implements CheckError { ...@@ -94,7 +94,7 @@ public class SchematronError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_SCHEMATRON_ERROR; return ErrorId.SE_SCHEMATRON_ERROR;
} }
@Override @Override
......
...@@ -77,7 +77,7 @@ public class SurfaceUnfragmentedError implements CheckError { ...@@ -77,7 +77,7 @@ public class SurfaceUnfragmentedError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.SEM_BS_UNFRAGMENTED; return ErrorId.SE_BS_UNFRAGMENTED;
} }
@Override @Override
......
...@@ -43,6 +43,10 @@ public class BoundingBox { ...@@ -43,6 +43,10 @@ public class BoundingBox {
return BoundingBoxCalculator.calculateBoundingBox(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. * Creates an axis aligned bounding box of the whole model.
* *
......
...@@ -56,6 +56,12 @@ public class CovarianceMatrix { ...@@ -56,6 +56,12 @@ public class CovarianceMatrix {
covValues[1][2] += ydiff * zdiff; covValues[1][2] += ydiff * zdiff;
covValues[2][2] += zdiff * 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 // the covariance matrix is symmetric, so we can fill in the remaining values
covValues[1][0] = covValues[0][1]; covValues[1][0] = covValues[0][1];
covValues[2][0] = covValues[0][2]; covValues[2][0] = covValues[0][2];
......
...@@ -135,7 +135,7 @@ public class Matrix3x3d { ...@@ -135,7 +135,7 @@ public class Matrix3x3d {
/** /**
* Multiplies this matrix with a 3-dim vector. * Multiplies this matrix with a 3-dim vector.
* *
* @param other the vector * @param the multiplied vector
* @return the result stored in a new vector * @return the result stored in a new vector
*/ */
public Vector3d mult(Vector3d other) { public Vector3d mult(Vector3d other) {
......
...@@ -55,10 +55,10 @@ public class OrthogonalRegressionPlane { ...@@ -55,10 +55,10 @@ public class OrthogonalRegressionPlane {
double eig2 = eigenvalues.getZ(); double eig2 = eigenvalues.getZ();
Matrix v = ed.getV(); Matrix v = ed.getV();
Matrix eigenVector; Matrix eigenVector;
if (eig0 < eig1 && eig0 < eig2) { if (eig0 <= eig1 && eig0 <= eig2) {
// the first eigenvalue is the lowest // the first eigenvalue is the lowest
eigenVector = v.getMatrix(0, 2, 0, 0); eigenVector = v.getMatrix(0, 2, 0, 0);
} else if (eig1 < eig0 && eig1 < eig2) { } else if (eig1 <= eig0 && eig1 <= eig2) {
// the second eigenvalue is the lowest // the second eigenvalue is the lowest
eigenVector = v.getMatrix(0, 2, 1, 1); eigenVector = v.getMatrix(0, 2, 1, 1);
} else { } else {
......
...@@ -63,17 +63,20 @@ public class BoundingBoxCalculator { ...@@ -63,17 +63,20 @@ public class BoundingBoxCalculator {
for (Vertex v : p.getExteriorRing().getVertices()) { for (Vertex v : p.getExteriorRing().getVertices()) {
if (v.getX() < lowX) { if (v.getX() < lowX) {
lowX = v.getX(); lowX = v.getX();
} else if (v.getX() > highX) { }
if (v.getX() > highX) {
highX = v.getX(); highX = v.getX();
} }
if (v.getY() < lowY) { if (v.getY() < lowY) {
lowY = v.getY(); lowY = v.getY();
} else if (v.getY() > highY) { }
if (v.getY() > highY) {
highY = v.getY(); highY = v.getY();
} }
if (v.getZ() < lowZ) { if (v.getZ() < lowZ) {
lowZ = v.getZ(); lowZ = v.getZ();
} else if (v.getZ() > highZ) { }
if (v.getZ() > highZ) {
highZ = v.getZ(); highZ = v.getZ();
} }
} }
...@@ -92,7 +95,7 @@ public class BoundingBoxCalculator { ...@@ -92,7 +95,7 @@ public class BoundingBoxCalculator {
*/ */
public static BoundingBox calculateBoundingBox(CityDoctorModel model) { public static BoundingBox calculateBoundingBox(CityDoctorModel model) {
Vector3d low = new Vector3d(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 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.getBuildings());
findMinMax(low, high, model.getBridges()); findMinMax(low, high, model.getBridges());
...@@ -107,6 +110,40 @@ public class BoundingBoxCalculator { ...@@ -107,6 +110,40 @@ public class BoundingBoxCalculator {
return BoundingBox.of(result); 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) { private static void findMinMax(Vector3d low, Vector3d high, List<? extends CityObject> features) {
for (CityObject co : features) { for (CityObject co : features) {
findMinMax(low, high, co); findMinMax(low, high, co);
...@@ -121,17 +158,20 @@ public class BoundingBoxCalculator { ...@@ -121,17 +158,20 @@ public class BoundingBoxCalculator {
for (Vertex v : geom.getVertices()) { for (Vertex v : geom.getVertices()) {
if (v.getX() < low.getX()) { if (v.getX() < low.getX()) {
low.setX(v.getX()); low.setX(v.getX());
} else if (v.getX() > high.getX()) { }
if (v.getX() > high.getX()) {
high.setX(v.getX()); high.setX(v.getX());
} }
if (v.getY() < low.getY()) { if (v.getY() < low.getY()) {
low.setY(v.getY()); low.setY(v.getY());
} else if (v.getY() > high.getY()) { }
if (v.getY() > high.getY()) {
high.setY(v.getY()); high.setY(v.getY());
} }
if (v.getZ() < low.getZ()) { if (v.getZ() < low.getZ()) {
low.setZ(v.getZ()); low.setZ(v.getZ());
} else if (v.getZ() > high.getZ()) { }
if (v.getZ() > high.getZ()) {
high.setZ(v.getZ()); high.setZ(v.getZ());
} }
} }
......
...@@ -23,7 +23,6 @@ import java.io.File; ...@@ -23,7 +23,6 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -33,7 +32,6 @@ import java.util.List; ...@@ -33,7 +32,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
...@@ -47,8 +45,6 @@ import javax.xml.transform.stream.StreamSource; ...@@ -47,8 +45,6 @@ import javax.xml.transform.stream.StreamSource;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.citygml4j.factory.GMLGeometryFactory;
import org.citygml4j.model.citygml.core.CityModel;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError; import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
...@@ -60,15 +56,9 @@ import de.hft.stuttgart.citydoctor2.checks.CheckPrototype; ...@@ -60,15 +56,9 @@ import de.hft.stuttgart.citydoctor2.checks.CheckPrototype;
import de.hft.stuttgart.citydoctor2.checks.Checks; import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.checks.SvrlContentHandler; import de.hft.stuttgart.citydoctor2.checks.SvrlContentHandler;
import de.hft.stuttgart.citydoctor2.checks.util.FeatureCheckedListener; import de.hft.stuttgart.citydoctor2.checks.util.FeatureCheckedListener;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel; import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject; import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer; import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException; import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser; import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
...@@ -81,15 +71,10 @@ import de.hft.stuttgart.citydoctor2.reporting.XmlValidationReporter; ...@@ -81,15 +71,10 @@ import de.hft.stuttgart.citydoctor2.reporting.XmlValidationReporter;
import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfReporter; import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfReporter;
import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfStreamReporter; import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfStreamReporter;
import de.hft.stuttgart.citydoctor2.utils.Localization; import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.utils.QualityADEUtils;
import de.hft.stuttgart.quality.model.Validation;
import de.hft.stuttgart.quality.model.jaxb.Checking; import de.hft.stuttgart.quality.model.jaxb.Checking;
import de.hft.stuttgart.quality.model.jaxb.ErrorStatistics;
import de.hft.stuttgart.quality.model.jaxb.FeatureStatistics;
import de.hft.stuttgart.quality.model.jaxb.Parameter; import de.hft.stuttgart.quality.model.jaxb.Parameter;
import de.hft.stuttgart.quality.model.jaxb.Requirement; import de.hft.stuttgart.quality.model.jaxb.Requirement;
import de.hft.stuttgart.quality.model.jaxb.RequirementId; import de.hft.stuttgart.quality.model.jaxb.RequirementId;
import de.hft.stuttgart.quality.model.jaxb.Statistics;
import de.hft.stuttgart.quality.model.jaxb.TopLevelFeatureType; import de.hft.stuttgart.quality.model.jaxb.TopLevelFeatureType;
import de.hft.stuttgart.quality.model.jaxb.ValidationPlan; import de.hft.stuttgart.quality.model.jaxb.ValidationPlan;
import net.sf.saxon.s9api.DOMDestination; import net.sf.saxon.s9api.DOMDestination;
...@@ -235,7 +220,7 @@ public class Checker { ...@@ -235,7 +220,7 @@ public class Checker {
}); });
} }
private static void handleSchematronErrorsForCityObject(List<SchematronError> v, CityObject co) { static void handleSchematronErrorsForCityObject(List<SchematronError> v, CityObject co) {
int count = 0; int count = 0;
for (SchematronError se : v) { for (SchematronError se : v) {
CheckError err; CheckError err;
...@@ -252,11 +237,11 @@ public class Checker { ...@@ -252,11 +237,11 @@ public class Checker {
} }
} }
private ValidationPlan createValidationPlan() { ValidationPlan createValidationPlan() {
ValidationPlan plan = new ValidationPlan(); ValidationPlan plan = new ValidationPlan();
List<Checking> filter = createFilter(); List<Checking> filter = createFilter();
for (Entry<CheckId, CheckConfiguration> e : config.getChecks().entrySet()) { for (Entry<String, RequirementConfiguration> e : config.getRequirements().entrySet()) {
RequirementId reqId = mapToRequirement(e.getKey()); RequirementId reqId = mapToRequirement(e.getKey());
if (reqId == null) { if (reqId == null) {
continue; continue;
...@@ -265,12 +250,12 @@ public class Checker { ...@@ -265,12 +250,12 @@ public class Checker {
req.setName(reqId); req.setName(reqId);
req.setEnabled(e.getValue().isEnabled()); req.setEnabled(e.getValue().isEnabled());
plan.getRequirements().add(req); plan.getRequirements().add(req);
CheckPrototype proto = Checks.getCheckPrototypeForId(e.getKey());
Map<String, String> parameters = e.getValue().getParameters(); Map<String, String> parameters = e.getValue().getParameters();
Map<String, de.hft.stuttgart.citydoctor2.check.Requirement> reqs = Checks.getAvailableRequirements();
if (parameters != null) { if (parameters != null) {
for (Entry<String, String> param : parameters.entrySet()) { for (Entry<String, String> param : parameters.entrySet()) {
Parameter p = new Parameter(); Parameter p = new Parameter();
DefaultParameter defaultP = getDefaultParameter(param.getKey(), proto); DefaultParameter defaultP = getDefaultParameter(param.getKey(), reqs);
if (defaultP != null) { if (defaultP != null) {
p.setUom(defaultP.getUnitType().getGmlRepresentation()); p.setUom(defaultP.getUnitType().getGmlRepresentation());
} }
...@@ -307,12 +292,16 @@ public class Checker { ...@@ -307,12 +292,16 @@ public class Checker {
return plan; return plan;
} }
private DefaultParameter getDefaultParameter(String key, CheckPrototype proto) { private DefaultParameter getDefaultParameter(String key,
for (DefaultParameter param : proto.getDefaultParameter()) { 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)) { if (param.getName().equals(key)) {
return param; return param;
} }
} }
}
return null; return null;
} }
...@@ -397,43 +386,10 @@ public class Checker { ...@@ -397,43 +386,10 @@ public class Checker {
} }
} }
private RequirementId mapToRequirement(CheckId key) { private RequirementId mapToRequirement(String requirementName) {
switch (key.getName()) { try {
case "C_GE_R_TOO_FEW_POINTS": return RequirementId.valueOf(requirementName);
return RequirementId.R_GE_R_TOO_FEW_POINTS; } catch (IllegalArgumentException e) {
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:
return null; return null;
} }
} }
...@@ -475,6 +431,8 @@ public class Checker { ...@@ -475,6 +431,8 @@ public class Checker {
expandTransformer.setDestination(xslt2Transformer); expandTransformer.setDestination(xslt2Transformer);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Document doc = factory.newDocumentBuilder().newDocument(); Document doc = factory.newDocumentBuilder().newDocument();
DOMDestination domDestination = new DOMDestination(doc); DOMDestination domDestination = new DOMDestination(doc);
...@@ -570,20 +528,71 @@ public class Checker { ...@@ -570,20 +528,71 @@ public class Checker {
} }
private List<Check> collectEnabledChecksAndInit(ParserConfiguration parserConfig, ValidationConfiguration config) { private List<Check> collectEnabledChecksAndInit(ParserConfiguration parserConfig, ValidationConfiguration config) {
List<Check> checks = new ArrayList<>(); Set<CheckId> enabledCheck = new HashSet<>();
for (Entry<CheckId, CheckConfiguration> e : config.getChecks().entrySet()) { 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()) { if (e.getValue().isEnabled()) {
Check c = checkConfig.getCheckForId(e.getKey()); // this requirement is enabled
Map<String, String> parameters = new HashMap<>(); for (CheckPrototype proto : Checks.getCheckPrototypes()) {
parameters.putAll(e.getValue().getParameters()); if (proto.checksRequirements().contains(req)) {
parameters.put("numberOfRoundingPlaces", "" + config.getNumberOfRoundingPlaces()); // this requirement is checked by this check
parameters.put("minVertexDistance", "" + config.getMinVertexDistance()); // put all requirement parameter in the map
// initialize checks with parameters parameterMap.compute(proto.getCheckId(), (k, v) -> {
c.init(parameters, parserConfig); if (v == null) {
checks.add(c); 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);
}
}
}
} }
} }
return checks; 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);
}
} }
private void checkCityModel(CityDoctorModel model, ProgressListener l) { private void checkCityModel(CityDoctorModel model, ProgressListener l) {
...@@ -729,88 +738,9 @@ public class Checker { ...@@ -729,88 +738,9 @@ public class Checker {
XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName); XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
PdfStreamReporter pdfReporter = getPdfReporter(config, logoLocation, pdfBos, fileName); PdfStreamReporter pdfReporter = getPdfReporter(config, logoLocation, pdfBos, fileName);
// create quality ade structures
Validation val = new Validation();
val.setValidationDate(ZonedDateTime.now());
val.setValidationSoftware("CityDoctor " + Localization.getText(Localization.VERSION));
Statistics statistics = new Statistics();
FeatureStatistics buildingStatistics = new FeatureStatistics();
statistics.setNumErrorBuildings(buildingStatistics);
FeatureStatistics bridgeStatistics = new FeatureStatistics();
statistics.setNumErrorBridgeObjects(bridgeStatistics);
FeatureStatistics transportationStatistics = new FeatureStatistics();
statistics.setNumErrorTransportation(transportationStatistics);
FeatureStatistics vegetationStatistics = new FeatureStatistics();
statistics.setNumErrorVegetation(vegetationStatistics);
FeatureStatistics landStatistics = new FeatureStatistics();
statistics.setNumErrorLandObjects(landStatistics);
FeatureStatistics waterStatistics = new FeatureStatistics();
statistics.setNumErrorWaterObjects(waterStatistics);
// map for counting individual error counts
Map<ErrorId, AtomicInteger> errorCount = new HashMap<>();
GMLGeometryFactory gmlFactory = new GMLGeometryFactory();
// execute schematron first // execute schematron first
SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile); SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile);
CityGmlConsumer con = new StreamCityGmlConsumer(c, xmlReporter, pdfReporter, handler, config, l);
CityGmlConsumer con = new CityGmlConsumer() {
@Override
public void accept(CityObject co) {
c.checkFeature(xmlReporter, pdfReporter, co);
if (handler != null) {
List<SchematronError> errors = handler.getFeatureErrors().get(co.getGmlId().getGmlString());
if (errors != null) {
handleSchematronErrorsForCityObject(errors, co);
}
}
// remove existing quality ade datastructure if existing
QualityADEUtils.removeValidationResult(co);
// store quality ade datastructures in cityobject
QualityADEUtils.writeQualityAde(co);
// recreate geometry
co.reCreateGeometries(gmlFactory, config.getParserConfiguration());
// store result in statistics
applyToStatistics(buildingStatistics, bridgeStatistics, transportationStatistics,
vegetationStatistics, landStatistics, waterStatistics, co);
// add errors to statistics
List<CheckError> errorList = new ArrayList<>();
co.collectContainedErrors(errorList);
Set<CheckError> errors = new HashSet<>(errorList);
for (CheckError e : errors) {
errorCount.compute(e.getErrorId(), (k, v) -> {
if (v == null) {
return new AtomicInteger(1);
}
v.incrementAndGet();
return v;
});
}
if (l != null) {
l.featureChecked(co);
}
}
@Override
public void accept(CityModel cm) {
QualityADEUtils.removeValidation(cm);
for (Entry<ErrorId, AtomicInteger> e : errorCount.entrySet()) {
ErrorStatistics stats = new ErrorStatistics();
stats.setAmount(e.getValue().get());
stats.setName(QualityADEUtils.mapErrorIdToAdeId(e.getKey()));
statistics.getErrorStatistics().add(stats);
}
val.setStatistics(statistics);
val.setValidationPlan(c.createValidationPlan());
cm.addGenericApplicationPropertyOfCityModel(val);
}
};
// parse and validate // parse and validate
CityGmlParser.streamCityGml(inputFile, config.getParserConfiguration(), con, outputFile); CityGmlParser.streamCityGml(inputFile, config.getParserConfiguration(), con, outputFile);
...@@ -823,33 +753,6 @@ public class Checker { ...@@ -823,33 +753,6 @@ public class Checker {
} }
} }
private static void applyToStatistics(FeatureStatistics buildingStatistics, FeatureStatistics bridgeStatistics,
FeatureStatistics transportationStatistics, FeatureStatistics vegetationStatistics,
FeatureStatistics landStatistics, FeatureStatistics waterStatistics, CityObject co) {
if (co.isValidated()) {
if (co instanceof Building) {
countForFeatureStatistics(buildingStatistics, co);
} else if (co instanceof TransportationObject) {
countForFeatureStatistics(transportationStatistics, co);
} else if (co instanceof BridgeObject) {
countForFeatureStatistics(bridgeStatistics, co);
} else if (co instanceof WaterObject) {
countForFeatureStatistics(waterStatistics, co);
} else if (co instanceof LandObject) {
countForFeatureStatistics(landStatistics, co);
} else if (co instanceof Vegetation) {
countForFeatureStatistics(vegetationStatistics, co);
}
}
}
private static void countForFeatureStatistics(FeatureStatistics featureStatistics, CityObject co) {
featureStatistics.setNumChecked(featureStatistics.getNumChecked() + 1);
if (co.containsAnyError()) {
featureStatistics.setNumErrors(featureStatistics.getNumErrors() + 1);
}
}
private static XmlStreamReporter getXmlReporter(ValidationConfiguration config, BufferedOutputStream xmlBos, private static XmlStreamReporter getXmlReporter(ValidationConfiguration config, BufferedOutputStream xmlBos,
String fileName) { String fileName) {
XmlStreamReporter xmlReporter; XmlStreamReporter xmlReporter;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment