Commit 85cf93b6 authored by Matthias Betz's avatar Matthias Betz
Browse files

reworked check engine now working on requirements

parent 35577785
Pipeline #2108 passed with stage
in 3 minutes and 6 seconds
......@@ -28,6 +28,7 @@ import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -40,7 +41,6 @@ import org.yaml.snakeyaml.representer.Representer;
import de.hft.stuttgart.citydoctor2.checks.CheckPrototype;
import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
/**
* The validation configuration class represented in the yaml configuration
......@@ -52,19 +52,17 @@ import de.hft.stuttgart.citydoctor2.utils.Localization;
*/
public class ValidationConfiguration implements Serializable {
private static final String NUMBER_OF_ROUNDING_PLACES_DEFAULT = "8";
private static final String MIN_VERTEX_DISTANCE_DEFAULT = "0.0001";
private static final long serialVersionUID = -8020055032177740646L;
private static final Logger logger = LogManager.getLogger(ValidationConfiguration.class);
private int numberOfRoundingPlaces = 8;
private double minVertexDistance = 0.0001;
private String schematronFilePath = null;
private Map<String, String> globalParameters;
private boolean xmlValidation = false;
private boolean useStreaming = false;
private FilterConfiguration filter;
private Map<CheckId, CheckConfiguration> checks;
private Map<String, RequirementConfiguration> requirements;
private ParserConfiguration parserConfig;
......@@ -81,19 +79,20 @@ public class ValidationConfiguration implements Serializable {
public static ValidationConfiguration loadStandardValidationConfig() {
ValidationConfiguration config = new ValidationConfiguration();
config.checks = new HashMap<>();
config.requirements = new HashMap<>();
for (CheckPrototype c : Checks.getCheckPrototypes()) {
CheckConfiguration cConfig = new CheckConfiguration();
cConfig.setEnabled(true);
if (!c.getDefaultParameter().isEmpty()) {
Map<String, String> paramMap = new HashMap<>();
for (DefaultParameter param : c.getDefaultParameter()) {
paramMap.put(param.getName(), param.getDefaultValue());
for (Requirement req : c.checksRequirements()) {
RequirementConfiguration reqConfig = new RequirementConfiguration();
reqConfig.setEnabled(true);
for (DefaultParameter param : req.getDefaultParameter()) {
reqConfig.getParameters().put(param.getName(), param.getValue());
}
cConfig.setParameters(paramMap);
config.requirements.put(req.getId(), reqConfig);
}
config.checks.put(c.getCheckId(), cConfig);
}
config.globalParameters = new HashMap<>();
config.globalParameters.put(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, NUMBER_OF_ROUNDING_PLACES_DEFAULT);
config.globalParameters.put(GlobalParameters.MIN_VERTEX_DISTANCE, MIN_VERTEX_DISTANCE_DEFAULT);
return config;
}
......@@ -117,14 +116,6 @@ public class ValidationConfiguration implements Serializable {
this.xmlValidation = xmlValidation;
}
public String getSchematronFilePath() {
return schematronFilePath;
}
public void setSchematronFilePath(String schematronFilePath) {
this.schematronFilePath = schematronFilePath;
}
public boolean isUseStreaming() {
return useStreaming;
}
......@@ -141,88 +132,67 @@ public class ValidationConfiguration implements Serializable {
this.filter = filter;
}
public Map<CheckId, CheckConfiguration> getChecks() {
if (checks == null) {
checks = new HashMap<>();
public Map<String, RequirementConfiguration> getRequirements() {
if (requirements == null) {
requirements = new HashMap<>();
}
return checks;
return requirements;
}
public void setChecks(Map<CheckId, CheckConfiguration> checks) {
this.checks = checks;
public Map<String, String> getGlobalParameters() {
if (globalParameters == null) {
globalParameters = new HashMap<>();
}
return globalParameters;
}
public void setGlobalParameters(Map<String, String> globalParameters) {
this.globalParameters = globalParameters;
}
/**
* Validates the configuration, adds all missing checks as enabled, reenables
* checks that are necessary to perform other checks
* Validates the configuration, adds all missing requirements as enabled.
*
* @return true if it reenabled disabled checks, false otherwise
*/
public boolean validateConfiguration() {
for (CheckPrototype c : Checks.getCheckPrototypes()) {
// enable all checks that are missing in the validation config
checks.computeIfAbsent(c.getCheckId(), id -> {
CheckConfiguration cConfig = new CheckConfiguration();
cConfig.setEnabled(true);
return cConfig;
});
}
boolean reenabledChecks = reenableNecessaryChecks();
if (schematronFilePath != null && !schematronFilePath.isEmpty()) {
File f = new File(schematronFilePath);
if (!f.exists() || !f.isFile()) {
schematronFilePath = null;
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("ValidationConfiguration.missingSchematron"), f.getAbsolutePath());
public void validateConfiguration() {
logger.trace("Validating configuration");
Map<String, Requirement> availableRequirements = Checks.getAvailableRequirements();
for (Entry<String, RequirementConfiguration> entry : requirements.entrySet()) {
Requirement req = availableRequirements.get(entry.getKey());
if (req != null) {
for (DefaultParameter param : req.getDefaultParameter()) {
RequirementConfiguration config = entry.getValue();
config.getParameters().computeIfAbsent(param.getName(), k -> param.getValue());
}
}
}
return reenabledChecks;
}
private boolean reenableNecessaryChecks() {
boolean reenabledChecks = false;
for (java.util.Map.Entry<CheckId, CheckConfiguration> e : checks.entrySet()) {
if (!e.getValue().isEnabled()) {
continue;
}
CheckPrototype c = Checks.getCheckPrototypeForId(e.getKey());
for (CheckId dep : c.getDependencies()) {
CheckConfiguration checkConfig = checks.get(dep);
if (!checkConfig.isEnabled()) {
checkConfig.setEnabled(true);
reenabledChecks = true;
if (logger.isWarnEnabled()) {
logger.warn(Localization.getText("ValidationConfiguration.reenable"), dep, c.getCheckId());
}
for (Requirement req : availableRequirements.values()) {
requirements.computeIfAbsent(req.getId(), id -> {
RequirementConfiguration cConfig = new RequirementConfiguration();
cConfig.setEnabled(true);
for (DefaultParameter param : req.getDefaultParameter()) {
cConfig.getParameters().put(param.getName(), param.getValue());
}
}
insertMissingParametersWithDefaultParameters(e, c);
}
return reenabledChecks;
}
private void insertMissingParametersWithDefaultParameters(java.util.Map.Entry<CheckId, CheckConfiguration> e,
CheckPrototype c) {
for (DefaultParameter param : c.getDefaultParameter()) {
String configuredValue = e.getValue().getParameters().get(param.getName());
if (configuredValue == null) {
e.getValue().getParameters().put(param.getName(), param.getDefaultValue());
}
return cConfig;
});
}
globalParameters.computeIfAbsent(GlobalParameters.MIN_VERTEX_DISTANCE, k -> MIN_VERTEX_DISTANCE_DEFAULT);
globalParameters.computeIfAbsent(GlobalParameters.NUMBER_OF_ROUNDING_PLACES,
k -> NUMBER_OF_ROUNDING_PLACES_DEFAULT);
}
public int getNumberOfRoundingPlaces() {
return numberOfRoundingPlaces;
return Integer.parseInt(globalParameters.get(GlobalParameters.NUMBER_OF_ROUNDING_PLACES));
}
public void setNumberOfRoundingPlaces(int numberOfRoundingPlaces) {
this.numberOfRoundingPlaces = numberOfRoundingPlaces;
public void setNumberOfRoundingPlacesInGlobalParameters(int numberOfRoundingPlaces) {
globalParameters.put(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, Integer.toString(numberOfRoundingPlaces));
}
public ParserConfiguration getParserConfiguration() {
if (parserConfig == null) {
parserConfig = new ParserConfiguration(numberOfRoundingPlaces, xmlValidation);
parserConfig = new ParserConfiguration(getNumberOfRoundingPlaces(), xmlValidation);
}
return parserConfig;
}
......@@ -231,11 +201,31 @@ public class ValidationConfiguration implements Serializable {
this.parserConfig = parserConfig;
}
public void setMinVertexDistance(double minVertexDistance) {
this.minVertexDistance = minVertexDistance;
public void setMinVertexDistanceInGlobalParameters(double minVertexDistance) {
globalParameters.put(GlobalParameters.MIN_VERTEX_DISTANCE, Double.toString(minVertexDistance));
}
public double getMinVertexDistance() {
return minVertexDistance;
return Double.parseDouble(globalParameters.get(GlobalParameters.MIN_VERTEX_DISTANCE));
}
public String getSchematronFilePath() {
return globalParameters.get(GlobalParameters.SCHEMATRON_PATH);
}
public String getNumberOfRoundingPlacesAsString() {
return globalParameters.get(GlobalParameters.NUMBER_OF_ROUNDING_PLACES);
}
public String getMinVertexDistanceAsString() {
return globalParameters.get(GlobalParameters.MIN_VERTEX_DISTANCE);
}
public void setSchematronFilePathInGlobalParameters(String string) {
globalParameters.put(GlobalParameters.SCHEMATRON_PATH, string);
}
public void setRequirements(Map<String, RequirementConfiguration> requirements) {
this.requirements = requirements;
}
}
......@@ -20,6 +20,7 @@ package de.hft.stuttgart.citydoctor2.checks;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -28,9 +29,10 @@ import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
......@@ -68,6 +70,11 @@ public class CheckContainer extends Check {
public CheckContainer(Check check) {
this.check = check;
}
@Override
public Set<Requirement> appliesToRequirements() {
return check.appliesToRequirements();
}
@Override
public void init(Map<String, String> parameters, ParserConfiguration config) {
......@@ -244,7 +251,7 @@ public class CheckContainer extends Check {
}
@Override
public CheckType getType() {
public RequirementType getType() {
return check.getType();
}
......
......@@ -19,11 +19,13 @@
package de.hft.stuttgart.citydoctor2.checks;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter;
import de.hft.stuttgart.citydoctor2.check.Requirement;
/**
* This class is for having a read only access to a check for accessing meta
......@@ -62,8 +64,12 @@ public class CheckPrototype {
return c.getDefaultParameter();
}
public CheckType getType() {
public RequirementType getType() {
return c.getType();
}
public Set<Requirement> checksRequirements() {
return c.appliesToRequirements();
}
}
......@@ -29,15 +29,15 @@ import org.apache.logging.log4j.Logger;
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.checks.geometry.AllPolygonsWrongOrientationCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.DuplicatePointsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.FaceOutCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.HoleOutsideCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.InteriorDisconnectedCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.ManifoldVertexCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.MultipleConnectedComponentCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.NestedRingsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.NonManifoldEdgeCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.NumPointsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.PlanarCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonIntersectingRingsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonSameOrientationCheck;
......@@ -46,6 +46,7 @@ import de.hft.stuttgart.citydoctor2.checks.geometry.RingNotClosedCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.RingSelfIntCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidNotClosedCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidSelfIntCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.TooFewPointsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.TooFewPolygonsCheck;
import de.hft.stuttgart.citydoctor2.checks.semantics.IsCeilingCheck;
import de.hft.stuttgart.citydoctor2.checks.semantics.IsFloorCheck;
......@@ -69,6 +70,8 @@ public class Checks {
private static List<CheckPrototype> checkPrototypes;
private static Map<CheckId, CheckPrototype> prototypeMap;
private static Map<String, Requirement> availableRequirements;
private Map<CheckId, Check> checkMap;
......@@ -78,7 +81,7 @@ public class Checks {
// add new checks here
// ring checks
publish(new NumPointsCheck());
publish(new TooFewPointsCheck());
publish(new RingNotClosedCheck());
publish(new DuplicatePointsCheck());
publish(new RingSelfIntCheck());
......@@ -96,7 +99,7 @@ public class Checks {
publish(new SolidNotClosedCheck());
publish(new NonManifoldEdgeCheck());
publish(new PolygonWrongOrientationCheck());
publish(new FaceOutCheck());
publish(new AllPolygonsWrongOrientationCheck());
publish(new TooFewPolygonsCheck());
publish(new ManifoldVertexCheck());
publish(new SolidSelfIntCheck());
......@@ -128,6 +131,30 @@ public class Checks {
}
}
private static Map<String, Requirement> collectRequirements() {
Map<String, Requirement> requirements = new HashMap<>();
for (CheckPrototype proto : checkPrototypes) {
for (Requirement req : proto.checksRequirements()) {
requirements.put(req.getId(), req);
}
}
return requirements;
}
/**
* Gets all requirements for which there are checks that can verify the
* requirements. This is dependent on the available checks as only the checks
* know which requirements they check.
*
* @return a set of available requirements
*/
public static Map<String, Requirement> getAvailableRequirements() {
if (availableRequirements == null) {
availableRequirements = collectRequirements();
}
return availableRequirements;
}
private static void publish(Check check) {
CheckPrototype prototype = new CheckPrototype(check);
checkPrototypes.add(prototype);
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
......@@ -38,11 +41,12 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
/**
* Checks whether all polygons have the wrong orientation.
*
* @author Matthias Betz - 71bema1mst@hft-stuttgart.de
* @author Matthias Betz
*
*/
public class FaceOutCheck extends Check {
public class AllPolygonsWrongOrientationCheck extends Check {
private static final List<CheckId> dependencies;
......@@ -171,15 +175,20 @@ public class FaceOutCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
public Check createNewInstance() {
return new FaceOutCheck();
return new AllPolygonsWrongOrientationCheck();
}
@Override
......
......@@ -22,16 +22,19 @@ 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.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
......@@ -44,7 +47,7 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
* <dd>
* <dd>CP_CLOSE</dd></dd>
*
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* @author Matthias Betz
*
*/
public class DuplicatePointsCheck extends Check {
......@@ -77,6 +80,11 @@ public class DuplicatePointsCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.asSet(Requirement.R_GE_R_CONSECUTIVE_POINTS_SAME, Requirement.R_GE_R_SELF_INTERSECTION);
}
@Override
public void check(LinearRing lr) {
......@@ -114,8 +122,8 @@ public class DuplicatePointsCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
......@@ -79,10 +82,15 @@ public class HoleOutsideCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_HOLE_OUTSIDE);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -23,14 +23,17 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
......@@ -38,12 +41,18 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.graph.CycleNode;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
/**
* Checks if a polygon is split up into multiple polygons by interior rings
*
* @author Matthias Betz
*
*/
public class InteriorDisconnectedCheck extends Check {
private static final String EPSILON_NAME = "minVertexDistance";
private static final List<CheckId> dependencies;
static {
ArrayList<CheckId> deps = new ArrayList<>();
deps.add(CheckId.C_GE_R_TOO_FEW_POINTS);
......@@ -53,19 +62,17 @@ public class InteriorDisconnectedCheck extends Check {
deps.add(CheckId.C_GE_P_NON_PLANAR);
dependencies = Collections.unmodifiableList(deps);
}
private double epsilon = 0.0001;
@Override
public void init(Map<String, String> params, ParserConfiguration config) {
String epsilonString = params.get(EPSILON_NAME);
if (epsilonString == null) {
epsilon = 0.0001;
} else {
if (epsilonString != null) {
epsilon = Double.parseDouble(epsilonString);
}
}
@Override
public void check(Polygon p) {
if (p.getInnerRings().isEmpty()) {
......@@ -88,7 +95,7 @@ public class InteriorDisconnectedCheck extends Check {
}
}
}
for (CycleNode node : nodeMap.values()) {
if (node.hasMoreThan2CycleDepth(null)) {
// found ring in graph with more than 1 node
......@@ -127,7 +134,7 @@ public class InteriorDisconnectedCheck extends Check {
p.addCheckResult(cr);
return true;
}
}
}
}
......@@ -152,15 +159,20 @@ public class InteriorDisconnectedCheck extends Check {
nodeMap.put(lr, node);
}
}
@Override
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_INTERIOR_DISCONNECTED);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
......@@ -40,7 +43,7 @@ import de.hft.stuttgart.citydoctor2.math.graph.PolygonGraph;
* Checks if the polygons adjacent to a vertex are attached via edges or are
* they discontinuous.
*
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* @author Matthias Betz
*
*/
public class ManifoldVertexCheck extends Check {
......@@ -92,10 +95,15 @@ public class ManifoldVertexCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_NON_MANIFOLD_VERTEX);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
......@@ -38,7 +41,7 @@ import de.hft.stuttgart.citydoctor2.math.graph.PolygonGraph;
/**
* Checks if all parts of a solid are connected or not.
*
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* @author Matthias Betz
*
*/
public class MultipleConnectedComponentCheck extends Check {
......@@ -86,10 +89,15 @@ public class MultipleConnectedComponentCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_MULTIPLE_CONNECTED_COMPONENTS);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,20 +21,30 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
/**
* Checks whether a inner ring is completely contained in another inner ring
* within the same polygon
*
* @author Matthias Betz
*
*/
public class NestedRingsCheck extends Check {
private static final List<CheckId> dependencies;
static {
......@@ -47,7 +57,7 @@ public class NestedRingsCheck extends Check {
deps.add(CheckId.C_GE_P_ORIENTATION_RINGS_SAME);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Polygon p) {
for (LinearRing interiorRing : p.getInnerRings()) {
......@@ -85,10 +95,15 @@ public class NestedRingsCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_INNER_RINGS_NESTED);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
......@@ -37,7 +40,9 @@ import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
* This class detects half edges with more than two neighbors, i.e.
* non-2-manifold geometries
*
* @author dwagner, alam
* @author dwagner
* @author alam
* @author Matthias Betz
*/
public class NonManifoldEdgeCheck extends Check {
......@@ -80,6 +85,11 @@ public class NonManifoldEdgeCheck extends Check {
}
g.addCheckResult(cr);
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_NON_MANIFOLD_EDGE);
}
@Override
public List<CheckId> getDependencies() {
......@@ -87,8 +97,8 @@ public class NonManifoldEdgeCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -22,15 +22,18 @@ 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.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.Unit;
import de.hft.stuttgart.citydoctor2.check.error.NullAreaError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Line3d;
......@@ -106,6 +109,11 @@ public class NullAreaCheck extends Check {
}
return area < 0.0001;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_R_NULL_AREA);
}
@Override
public List<CheckId> getDependencies() {
......@@ -113,8 +121,8 @@ public class NullAreaCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
......
......@@ -22,23 +22,28 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import Jama.EigenvalueDecomposition;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.Unit;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedPolygonError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedPolygonError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.CovarianceMatrix;
import de.hft.stuttgart.citydoctor2.math.Matrix3x3d;
import de.hft.stuttgart.citydoctor2.math.OrthogonalRegressionPlane;
import de.hft.stuttgart.citydoctor2.math.Plane;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
......@@ -48,18 +53,19 @@ import de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon;
/**
* Check class to check for planarity issues
* Check class to check for planarity issues as well as degenerated polygons.
* Checks for regression plane and normal issues.
*
* @author Matthias Betz
*
*/
public class PlanarCheck extends Check {
private static final String DISTANCE = "distance";
private static final String DISTANCE_TOLERANCE = "distanceTolerance";
private static final String ANGLE_TOLERANCE = "angleTolerance";
private static final String TYPE = "type";
private static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance";
public static final String DISTANCE = "distance";
public static final String DISTANCE_TOLERANCE = "distanceTolerance";
public static final String ANGLE_TOLERANCE = "angleTolerance";
public static final String TYPE = "type";
public static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance";
private static final List<CheckId> dependencies;
private static final List<DefaultParameter> defaultParameters;
......@@ -91,6 +97,8 @@ public class PlanarCheck extends Check {
public void init(Map<String, String> parameters, ParserConfiguration config) {
if (parameters.containsKey(TYPE)) {
planarCheckType = parameters.get(TYPE).toLowerCase();
} else {
throw new IllegalStateException("Parameter " + TYPE + " is missing from parameters");
}
if (parameters.containsKey(ANGLE_TOLERANCE)) {
rad = Math.toRadians(Double.parseDouble(parameters.get(ANGLE_TOLERANCE)));
......@@ -115,8 +123,10 @@ public class PlanarCheck extends Check {
} else if ("angle".equals(planarCheckType)) {
// check for tiny edge as well
// store all used points in temporary list
Vector3d eigenvalues = calculatedEigenvalues(p);
if (checkEigenvalues(p, eigenvalues)) {
ArrayList<Vertex> vertices = collectVertices(p);
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
if (checkEigenvalues(p, vertices, ed)) {
// found tiny edge error, abort further checking
return;
}
......@@ -130,13 +140,6 @@ public class PlanarCheck extends Check {
}
}
private Vector3d calculatedEigenvalues(Polygon p) {
ArrayList<Vertex> vertices = collectVertices(p);
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
return OrthogonalRegressionPlane.getEigenvalues(ed);
}
private void planarNormalDeviation(Polygon p) {
TesselatedPolygon tp = JoglTesselator.tesselatePolygon(p);
ArrayList<Vector3d> normals = new ArrayList<>();
......@@ -185,13 +188,13 @@ public class PlanarCheck extends Check {
ArrayList<Vertex> vertices = collectVertices(p);
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed);
if (checkEigenvalues(p, eigenvalues)) {
if (checkEigenvalues(p, vertices, ed)) {
// found tiny edge error, abort further checking
return;
}
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed);
Plane plane = OrthogonalRegressionPlane.calculatePlane(centroid, ed, eigenvalues);
for (Vertex v : vertices) {
double distance = plane.getDistance(v);
......@@ -224,13 +227,25 @@ public class PlanarCheck extends Check {
return vertices;
}
private boolean checkEigenvalues(Polygon p, Vector3d eigenvalues) {
private boolean checkEigenvalues(Polygon p, List<Vertex> points, EigenvalueDecomposition ed) {
Matrix3x3d mat = new Matrix3x3d(ed.getV().getArray());
List<Vector3d> rotatedVertices = new ArrayList<>();
for (Vertex v : points) {
rotatedVertices.add(mat.mult(v));
}
BoundingBox bbox = BoundingBox.ofPoints(rotatedVertices);
int nrOfEigenvaluesBelowTolerance = 0;
for (double d : eigenvalues.getCoordinates()) {
if (d <= degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getWidth() < degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getHeight() < degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getDepth() < degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (nrOfEigenvaluesBelowTolerance >= 2) {
CheckError err = new DegeneratedPolygonError(p);
p.addCheckResult(new CheckResult(this, ResultStatus.ERROR, err));
......@@ -245,8 +260,13 @@ public class PlanarCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_NON_PLANAR);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Polygon2d;
......@@ -38,11 +41,16 @@ import de.hft.stuttgart.citydoctor2.math.Vector2d;
import de.hft.stuttgart.citydoctor2.utils.Pair;
import de.hft.stuttgart.citydoctor2.utils.SerializablePair;
/**
* Checks whether linear rings within a polygon are intersecting with each other
*
* @author Matthias Betz
*
*/
public class PolygonIntersectingRingsCheck extends Check {
private static final List<CheckId> dependencies;
static {
ArrayList<CheckId> deps = new ArrayList<>();
deps.add(CheckId.C_GE_R_TOO_FEW_POINTS);
......@@ -54,7 +62,7 @@ public class PolygonIntersectingRingsCheck extends Check {
deps.add(CheckId.C_GE_P_INNER_RINGS_NESTED);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Polygon p) {
if (p.getInnerRings().isEmpty()) {
......@@ -73,7 +81,7 @@ public class PolygonIntersectingRingsCheck extends Check {
}
p.addCheckResult(cr);
}
public SerializablePair<LinearRing, LinearRing> interiorRingsIntersectWithExterior(Polygon p) {
List<Pair<LinearRing, List<Segment2d>>> ringSegments = projectTo2D(p);
for (int i = 0; i < ringSegments.size() - 1; i++) {
......@@ -124,8 +132,13 @@ public class PolygonIntersectingRingsCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_INTERSECTING_RINGS);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,22 +21,33 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.checks.util.Orientation;
import de.hft.stuttgart.citydoctor2.checks.util.RingOrientationUtil;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Polygon2d;
import de.hft.stuttgart.citydoctor2.math.Ring2d;
/**
* This class checks whether a linear ring and the exterior ring of a polygon
* have the same orientation. A inner ring must be oriented in the opposite
* direction than the exterior ring.
*
* @author Matthias Betz
*
*/
public class PolygonSameOrientationCheck extends Check {
private static final List<CheckId> dependencies;
static {
......@@ -48,7 +59,7 @@ public class PolygonSameOrientationCheck extends Check {
deps.add(CheckId.C_GE_P_NON_PLANAR);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Polygon p) {
if (p.getInnerRings().isEmpty()) {
......@@ -67,7 +78,7 @@ public class PolygonSameOrientationCheck extends Check {
return;
}
}
// no error found, or the method would have terminated previously
CheckResult cr = new CheckResult(this, ResultStatus.OK, null);
p.addCheckResult(cr);
......@@ -80,8 +91,13 @@ public class PolygonSameOrientationCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_ORIENTATION_RINGS_SAME);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,28 +21,32 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
/**
* This class checks the orientation of each face of a solid
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* Checks whether polygons share a edge that is walked more than one time in the
* same direction by two or more polygons indicating that a polygon is oriented wrong.
*
* @author Matthias Betz
*
*/
public class PolygonWrongOrientationCheck extends Check {
private static final List<CheckId> dependencies;
static {
ArrayList<CheckId> deps = new ArrayList<>();
deps.add(CheckId.C_GE_R_TOO_FEW_POINTS);
......@@ -57,19 +61,19 @@ public class PolygonWrongOrientationCheck extends Check {
deps.add(CheckId.C_GE_S_NON_MANIFOLD_EDGE);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Geometry g) {
// only for solids
if (g.getType() != GeometryType.SOLID) {
return;
}
List<Edge> faultyEdges = new ArrayList<>();
for (Edge edge : g.getEdges()) {
if (edge.getNumberOfHalfEdges() != edge.getNumberOppositeHalfEdges()) {
faultyEdges.add(edge);
}
}
}
CheckResult cr;
if (faultyEdges.isEmpty()) {
......@@ -80,15 +84,20 @@ public class PolygonWrongOrientationCheck extends Check {
}
g.addCheckResult(cr);
}
@Override
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_POLYGON_WRONG_ORIENTATION);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,22 +21,25 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
/**
* CP_CLOSE checks the closeness a linear ring. A linear ring must end where it
* C_GE_R_NOT_CLOSED checks the closeness a linear ring. A linear ring must end where it
* started.
*
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* @author Matthias Betz
*
*/
public class RingNotClosedCheck extends Check {
......@@ -69,8 +72,13 @@ public class RingNotClosedCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_R_NOT_CLOSED);
}
@Override
......
......@@ -22,16 +22,19 @@ 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.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
......@@ -40,6 +43,13 @@ import de.hft.stuttgart.citydoctor2.math.DistanceResult;
import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
/**
* Checks whether a ring self intersects. Also checks if a point is too close to
* an edge of the ring.
*
* @author Matthias Betz
*
*/
public class RingSelfIntCheck extends Check {
private static final String EPSILON_NAME = "minVertexDistance";
......@@ -138,8 +148,13 @@ public class RingSelfIntCheck extends Check {
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_R_SELF_INTERSECTION);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
......@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
......@@ -37,8 +40,9 @@ import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
* This class detects half edges without neighbor, i.e. holes in solid
* geometries
*
* @author dwagner, alam
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de
* @author dwagner
* @author alam
* @author Matthias Betz
*/
public class SolidNotClosedCheck extends Check {
......@@ -87,10 +91,15 @@ public class SolidNotClosedCheck extends Check {
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_NOT_CLOSED);
}
@Override
public CheckType getType() {
return CheckType.GEOMETRY;
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
......
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