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
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.check;
public class GlobalParameters {
private GlobalParameters() {
}
public static final String SCHEMATRON_PATH = "schematronPath";
public static final String MIN_VERTEX_DISTANCE = "minVertexDistance";
public static final String NUMBER_OF_ROUNDING_PLACES = "numberOfRoundingPlaces";
}
...@@ -29,7 +29,7 @@ import java.util.Map; ...@@ -29,7 +29,7 @@ import java.util.Map;
* @author Matthias Betz * @author Matthias Betz
* *
*/ */
public class CheckConfiguration implements Serializable { public class RequirementConfiguration implements Serializable {
private static final long serialVersionUID = -1258195428669813888L; private static final long serialVersionUID = -1258195428669813888L;
...@@ -60,9 +60,6 @@ public class CheckConfiguration implements Serializable { ...@@ -60,9 +60,6 @@ public class CheckConfiguration implements Serializable {
return parameters; return parameters;
} }
/**
* @param parameters Sets the parameters of this check.
*/
public void setParameters(Map<String, String> parameters) { public void setParameters(Map<String, String> parameters) {
this.parameters = parameters; this.parameters = parameters;
} }
......
/*-
* 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.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import org.citygml4j.factory.GMLGeometryFactory;
import org.citygml4j.model.citygml.core.CityModel;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.checks.SvrlContentHandler;
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.CityObject;
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.reporting.XmlStreamReporter;
import de.hft.stuttgart.citydoctor2.reporting.pdf.PdfStreamReporter;
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.ErrorStatistics;
import de.hft.stuttgart.quality.model.jaxb.FeatureStatistics;
import de.hft.stuttgart.quality.model.jaxb.Statistics;
public class StreamCityGmlConsumer implements CityGmlConsumer {
private Checker c;
private XmlStreamReporter xmlReporter;
private PdfStreamReporter pdfReporter;
private SvrlContentHandler handler;
private Map<ErrorId, AtomicInteger> errorCount;
private GMLGeometryFactory gmlFactory;
private ValidationConfiguration config;
private Statistics statistics;
private FeatureStatistics buildingStatistics;
private FeatureStatistics bridgeStatistics;
private FeatureStatistics transportationStatistics;
private FeatureStatistics vegetationStatistics;
private FeatureStatistics landStatistics;
private FeatureStatistics waterStatistics;
private Validation val;
private FeatureCheckedListener l;
public StreamCityGmlConsumer(Checker c, XmlStreamReporter xmlReporter, PdfStreamReporter pdfReporter,
SvrlContentHandler handler, ValidationConfiguration config, FeatureCheckedListener l) {
this.c = c;
this.xmlReporter = xmlReporter;
this.pdfReporter = pdfReporter;
this.handler = handler;
this.config = config;
this.l = l;
errorCount = new HashMap<>();
gmlFactory = new GMLGeometryFactory();
val = new Validation();
val.setValidationDate(ZonedDateTime.now());
val.setValidationSoftware("CityDoctor " + Localization.getText(Localization.VERSION));
statistics = new Statistics();
buildingStatistics = new FeatureStatistics();
statistics.setNumErrorBuildings(buildingStatistics);
bridgeStatistics = new FeatureStatistics();
statistics.setNumErrorBridgeObjects(bridgeStatistics);
transportationStatistics = new FeatureStatistics();
statistics.setNumErrorTransportation(transportationStatistics);
vegetationStatistics = new FeatureStatistics();
statistics.setNumErrorVegetation(vegetationStatistics);
landStatistics = new FeatureStatistics();
statistics.setNumErrorLandObjects(landStatistics);
waterStatistics = new FeatureStatistics();
statistics.setNumErrorWaterObjects(waterStatistics);
}
@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) {
Checker.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);
}
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);
}
}
}
...@@ -28,6 +28,7 @@ import java.io.InputStream; ...@@ -28,6 +28,7 @@ import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -40,7 +41,6 @@ import org.yaml.snakeyaml.representer.Representer; ...@@ -40,7 +41,6 @@ import org.yaml.snakeyaml.representer.Representer;
import de.hft.stuttgart.citydoctor2.checks.CheckPrototype; 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.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.Localization;
/** /**
* The validation configuration class represented in the yaml configuration * The validation configuration class represented in the yaml configuration
...@@ -52,19 +52,17 @@ import de.hft.stuttgart.citydoctor2.utils.Localization; ...@@ -52,19 +52,17 @@ import de.hft.stuttgart.citydoctor2.utils.Localization;
*/ */
public class ValidationConfiguration implements Serializable { 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 long serialVersionUID = -8020055032177740646L;
private static final Logger logger = LogManager.getLogger(ValidationConfiguration.class); 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 xmlValidation = false;
private boolean useStreaming = false; private boolean useStreaming = false;
private FilterConfiguration filter; private FilterConfiguration filter;
private Map<CheckId, CheckConfiguration> checks; private Map<String, RequirementConfiguration> requirements;
private ParserConfiguration parserConfig; private ParserConfiguration parserConfig;
...@@ -81,19 +79,20 @@ public class ValidationConfiguration implements Serializable { ...@@ -81,19 +79,20 @@ public class ValidationConfiguration implements Serializable {
public static ValidationConfiguration loadStandardValidationConfig() { public static ValidationConfiguration loadStandardValidationConfig() {
ValidationConfiguration config = new ValidationConfiguration(); ValidationConfiguration config = new ValidationConfiguration();
config.checks = new HashMap<>(); config.requirements = new HashMap<>();
for (CheckPrototype c : Checks.getCheckPrototypes()) { for (CheckPrototype c : Checks.getCheckPrototypes()) {
CheckConfiguration cConfig = new CheckConfiguration(); for (Requirement req : c.checksRequirements()) {
cConfig.setEnabled(true); RequirementConfiguration reqConfig = new RequirementConfiguration();
if (!c.getDefaultParameter().isEmpty()) { reqConfig.setEnabled(true);
Map<String, String> paramMap = new HashMap<>(); for (DefaultParameter param : req.getDefaultParameter()) {
for (DefaultParameter param : c.getDefaultParameter()) { reqConfig.getParameters().put(param.getName(), param.getValue());
paramMap.put(param.getName(), param.getDefaultValue());
} }
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; return config;
} }
...@@ -117,14 +116,6 @@ public class ValidationConfiguration implements Serializable { ...@@ -117,14 +116,6 @@ public class ValidationConfiguration implements Serializable {
this.xmlValidation = xmlValidation; this.xmlValidation = xmlValidation;
} }
public String getSchematronFilePath() {
return schematronFilePath;
}
public void setSchematronFilePath(String schematronFilePath) {
this.schematronFilePath = schematronFilePath;
}
public boolean isUseStreaming() { public boolean isUseStreaming() {
return useStreaming; return useStreaming;
} }
...@@ -141,88 +132,67 @@ public class ValidationConfiguration implements Serializable { ...@@ -141,88 +132,67 @@ public class ValidationConfiguration implements Serializable {
this.filter = filter; this.filter = filter;
} }
public Map<CheckId, CheckConfiguration> getChecks() { public Map<String, RequirementConfiguration> getRequirements() {
if (checks == null) { if (requirements == null) {
checks = new HashMap<>(); requirements = new HashMap<>();
} }
return checks; return requirements;
} }
public void setChecks(Map<CheckId, CheckConfiguration> checks) { public Map<String, String> getGlobalParameters() {
this.checks = checks; 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 * Validates the configuration, adds all missing requirements as enabled.
* checks that are necessary to perform other checks
* *
* @return true if it reenabled disabled checks, false otherwise
*/ */
public boolean validateConfiguration() { public void validateConfiguration() {
for (CheckPrototype c : Checks.getCheckPrototypes()) { logger.trace("Validating configuration");
// enable all checks that are missing in the validation config Map<String, Requirement> availableRequirements = Checks.getAvailableRequirements();
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());
}
}
}
return reenabledChecks;
}
private boolean reenableNecessaryChecks() { for (Entry<String, RequirementConfiguration> entry : requirements.entrySet()) {
boolean reenabledChecks = false; Requirement req = availableRequirements.get(entry.getKey());
for (java.util.Map.Entry<CheckId, CheckConfiguration> e : checks.entrySet()) { if (req != null) {
if (!e.getValue().isEnabled()) { for (DefaultParameter param : req.getDefaultParameter()) {
continue; RequirementConfiguration config = entry.getValue();
} config.getParameters().computeIfAbsent(param.getName(), k -> param.getValue());
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());
}
} }
} }
insertMissingParametersWithDefaultParameters(e, c);
} }
return reenabledChecks; for (Requirement req : availableRequirements.values()) {
} requirements.computeIfAbsent(req.getId(), id -> {
RequirementConfiguration cConfig = new RequirementConfiguration();
private void insertMissingParametersWithDefaultParameters(java.util.Map.Entry<CheckId, CheckConfiguration> e, cConfig.setEnabled(true);
CheckPrototype c) { for (DefaultParameter param : req.getDefaultParameter()) {
for (DefaultParameter param : c.getDefaultParameter()) { cConfig.getParameters().put(param.getName(), param.getValue());
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() { public int getNumberOfRoundingPlaces() {
return numberOfRoundingPlaces; return Integer.parseInt(globalParameters.get(GlobalParameters.NUMBER_OF_ROUNDING_PLACES));
} }
public void setNumberOfRoundingPlaces(int numberOfRoundingPlaces) { public void setNumberOfRoundingPlacesInGlobalParameters(int numberOfRoundingPlaces) {
this.numberOfRoundingPlaces = numberOfRoundingPlaces; globalParameters.put(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, Integer.toString(numberOfRoundingPlaces));
} }
public ParserConfiguration getParserConfiguration() { public ParserConfiguration getParserConfiguration() {
if (parserConfig == null) { if (parserConfig == null) {
parserConfig = new ParserConfiguration(numberOfRoundingPlaces, xmlValidation); parserConfig = new ParserConfiguration(getNumberOfRoundingPlaces(), xmlValidation);
} }
return parserConfig; return parserConfig;
} }
...@@ -231,11 +201,31 @@ public class ValidationConfiguration implements Serializable { ...@@ -231,11 +201,31 @@ public class ValidationConfiguration implements Serializable {
this.parserConfig = parserConfig; this.parserConfig = parserConfig;
} }
public void setMinVertexDistance(double minVertexDistance) { public void setMinVertexDistanceInGlobalParameters(double minVertexDistance) {
this.minVertexDistance = minVertexDistance; globalParameters.put(GlobalParameters.MIN_VERTEX_DISTANCE, Double.toString(minVertexDistance));
} }
public double getMinVertexDistance() { 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; ...@@ -20,6 +20,7 @@ package de.hft.stuttgart.citydoctor2.checks;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -28,9 +29,9 @@ import de.hft.stuttgart.citydoctor2.check.Check; ...@@ -28,9 +29,9 @@ import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType;
import de.hft.stuttgart.citydoctor2.check.Checkable; 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.RequirementType;
import de.hft.stuttgart.citydoctor2.check.ResultStatus; import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding; import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
...@@ -69,6 +70,11 @@ public class CheckContainer extends Check { ...@@ -69,6 +70,11 @@ public class CheckContainer extends Check {
this.check = check; this.check = check;
} }
@Override
public Set<Requirement> appliesToRequirements() {
return check.appliesToRequirements();
}
@Override @Override
public void init(Map<String, String> parameters, ParserConfiguration config) { public void init(Map<String, String> parameters, ParserConfiguration config) {
check.init(parameters, config); check.init(parameters, config);
...@@ -98,11 +104,6 @@ public class CheckContainer extends Check { ...@@ -98,11 +104,6 @@ public class CheckContainer extends Check {
c.addCheckResult(cr); c.addCheckResult(cr);
} }
@Override
public List<DefaultParameter> getDefaultParameter() {
return check.getDefaultParameter();
}
@Override @Override
public List<CheckId> getDependencies() { public List<CheckId> getDependencies() {
return check.getDependencies(); return check.getDependencies();
...@@ -244,7 +245,7 @@ public class CheckContainer extends Check { ...@@ -244,7 +245,7 @@ public class CheckContainer extends Check {
} }
@Override @Override
public CheckType getType() { public RequirementType getType() {
return check.getType(); return check.getType();
} }
......
...@@ -19,11 +19,12 @@ ...@@ -19,11 +19,12 @@
package de.hft.stuttgart.citydoctor2.checks; package de.hft.stuttgart.citydoctor2.checks;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckType; import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter; import de.hft.stuttgart.citydoctor2.check.RequirementType;
/** /**
* This class is for having a read only access to a check for accessing meta * This class is for having a read only access to a check for accessing meta
...@@ -58,12 +59,12 @@ public class CheckPrototype { ...@@ -58,12 +59,12 @@ public class CheckPrototype {
return c.getDependencies(); return c.getDependencies();
} }
public List<DefaultParameter> getDefaultParameter() { public RequirementType getType() {
return c.getDefaultParameter(); return c.getType();
} }
public CheckType getType() { public Set<Requirement> checksRequirements() {
return c.getType(); return c.appliesToRequirements();
} }
} }
...@@ -29,15 +29,15 @@ import org.apache.logging.log4j.Logger; ...@@ -29,15 +29,15 @@ import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId; 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.DuplicatePointsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.FaceOutCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.HoleOutsideCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.HoleOutsideCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.InteriorDisconnectedCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.InteriorDisconnectedCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.ManifoldVertexCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.ManifoldVertexCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.MultipleConnectedComponentCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.MultipleConnectedComponentCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.NestedRingsCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.NestedRingsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.NonManifoldEdgeCheck; 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.PlanarCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonIntersectingRingsCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonIntersectingRingsCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonSameOrientationCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.PolygonSameOrientationCheck;
...@@ -46,6 +46,7 @@ import de.hft.stuttgart.citydoctor2.checks.geometry.RingNotClosedCheck; ...@@ -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.RingSelfIntCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidNotClosedCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.SolidNotClosedCheck;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidSelfIntCheck; 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.geometry.TooFewPolygonsCheck;
import de.hft.stuttgart.citydoctor2.checks.semantics.IsCeilingCheck; import de.hft.stuttgart.citydoctor2.checks.semantics.IsCeilingCheck;
import de.hft.stuttgart.citydoctor2.checks.semantics.IsFloorCheck; import de.hft.stuttgart.citydoctor2.checks.semantics.IsFloorCheck;
...@@ -63,10 +64,14 @@ import de.hft.stuttgart.citydoctor2.utils.Localization; ...@@ -63,10 +64,14 @@ import de.hft.stuttgart.citydoctor2.utils.Localization;
*/ */
public class Checks { public class Checks {
public static final double MIN_VERTEX_DISTANCE_DEFAULT = 0.0001;
private static final Logger logger = LogManager.getLogger(Checks.class); private static final Logger logger = LogManager.getLogger(Checks.class);
private static List<CheckPrototype> checkPrototypes; private static List<CheckPrototype> checkPrototypes;
private static Map<CheckId, CheckPrototype> prototypeMap; private static Map<CheckId, CheckPrototype> prototypeMap;
private static Map<String, Requirement> availableRequirements;
private Map<CheckId, Check> checkMap; private Map<CheckId, Check> checkMap;
...@@ -75,21 +80,26 @@ public class Checks { ...@@ -75,21 +80,26 @@ public class Checks {
prototypeMap = new HashMap<>(); prototypeMap = new HashMap<>();
// add new checks here // add new checks here
publish(new NumPointsCheck()); // ring checks
publish(new TooFewPointsCheck());
publish(new RingNotClosedCheck()); publish(new RingNotClosedCheck());
publish(new DuplicatePointsCheck()); publish(new DuplicatePointsCheck());
publish(new RingSelfIntCheck()); publish(new RingSelfIntCheck());
// polygon checks
publish(new PlanarCheck()); publish(new PlanarCheck());
publish(new PolygonSameOrientationCheck()); publish(new PolygonSameOrientationCheck());
publish(new HoleOutsideCheck()); publish(new HoleOutsideCheck());
publish(new NestedRingsCheck()); publish(new NestedRingsCheck());
publish(new PolygonIntersectingRingsCheck()); publish(new PolygonIntersectingRingsCheck());
publish(new InteriorDisconnectedCheck()); publish(new InteriorDisconnectedCheck());
// solid checks
publish(new MultipleConnectedComponentCheck()); publish(new MultipleConnectedComponentCheck());
publish(new SolidNotClosedCheck()); publish(new SolidNotClosedCheck());
publish(new NonManifoldEdgeCheck()); publish(new NonManifoldEdgeCheck());
publish(new PolygonWrongOrientationCheck()); publish(new PolygonWrongOrientationCheck());
publish(new FaceOutCheck()); publish(new AllPolygonsWrongOrientationCheck());
publish(new TooFewPolygonsCheck()); publish(new TooFewPolygonsCheck());
publish(new ManifoldVertexCheck()); publish(new ManifoldVertexCheck());
publish(new SolidSelfIntCheck()); publish(new SolidSelfIntCheck());
...@@ -121,6 +131,30 @@ public class Checks { ...@@ -121,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) { private static void publish(Check check) {
CheckPrototype prototype = new CheckPrototype(check); CheckPrototype prototype = new CheckPrototype(check);
checkPrototypes.add(prototype); checkPrototypes.add(prototype);
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError; 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.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
...@@ -38,11 +41,12 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d; ...@@ -38,11 +41,12 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; 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; private static final List<CheckId> dependencies;
...@@ -173,13 +177,18 @@ public class FaceOutCheck extends Check { ...@@ -173,13 +177,18 @@ public class FaceOutCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
public Check createNewInstance() { public Check createNewInstance() {
return new FaceOutCheck(); return new AllPolygonsWrongOrientationCheck();
} }
@Override @Override
......
...@@ -22,16 +22,19 @@ import java.util.ArrayList; ...@@ -22,16 +22,19 @@ 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.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.Checkable;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.ResultStatus; import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError; import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
...@@ -44,7 +47,7 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; ...@@ -44,7 +47,7 @@ import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
* <dd> * <dd>
* <dd>CP_CLOSE</dd></dd> * <dd>CP_CLOSE</dd></dd>
* *
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de * @author Matthias Betz
* *
*/ */
public class DuplicatePointsCheck extends Check { public class DuplicatePointsCheck extends Check {
...@@ -68,9 +71,7 @@ public class DuplicatePointsCheck extends Check { ...@@ -68,9 +71,7 @@ public class DuplicatePointsCheck extends Check {
@Override @Override
public void init(Map<String, String> params, ParserConfiguration config) { public void init(Map<String, String> params, ParserConfiguration config) {
String epsilonString = params.get(EPSILON_NAME); String epsilonString = params.get(EPSILON_NAME);
if (epsilonString == null) { if (epsilonString != null) {
epsilon = 0.0001;
} else {
epsilon = Double.parseDouble(epsilonString); epsilon = Double.parseDouble(epsilonString);
} }
} }
...@@ -80,6 +81,11 @@ public class DuplicatePointsCheck extends Check { ...@@ -80,6 +81,11 @@ public class DuplicatePointsCheck extends Check {
return dependencies; return dependencies;
} }
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.asSet(Requirement.R_GE_R_CONSECUTIVE_POINTS_SAME, Requirement.R_GE_R_SELF_INTERSECTION);
}
@Override @Override
public void check(LinearRing lr) { public void check(LinearRing lr) {
List<Vertex> pointList = lr.getVertices(); List<Vertex> pointList = lr.getVertices();
...@@ -99,8 +105,8 @@ public class DuplicatePointsCheck extends Check { ...@@ -99,8 +105,8 @@ public class DuplicatePointsCheck extends Check {
// ignore last point, because last point = first, but this is allowed // ignore last point, because last point = first, but this is allowed
for (int i = 0; i < pointList.size() - 2; i++) { for (int i = 0; i < pointList.size() - 2; i++) {
for (int j = i + 2; j < pointList.size() - 1; j++) {
Vertex point1 = pointList.get(i); Vertex point1 = pointList.get(i);
for (int j = i + 2; j < pointList.size() - 1; j++) {
Vertex point2 = pointList.get(j); Vertex point2 = pointList.get(j);
if (point1.equalsWithEpsilon(point2, epsilon)) { if (point1.equalsWithEpsilon(point2, epsilon)) {
// non consecutive points same // non consecutive points same
...@@ -116,8 +122,8 @@ public class DuplicatePointsCheck extends Check { ...@@ -116,8 +122,8 @@ public class DuplicatePointsCheck extends Check {
} }
@Override @Override
public CheckType getType() { public RequirementType getType() {
return CheckType.GEOMETRY; return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
...@@ -81,8 +84,13 @@ public class HoleOutsideCheck extends Check { ...@@ -81,8 +84,13 @@ public class HoleOutsideCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_HOLE_OUTSIDE);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -23,14 +23,17 @@ import java.util.Collections; ...@@ -23,14 +23,17 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
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.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
...@@ -38,6 +41,12 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d; ...@@ -38,6 +41,12 @@ import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.graph.CycleNode; import de.hft.stuttgart.citydoctor2.math.graph.CycleNode;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; 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 { public class InteriorDisconnectedCheck extends Check {
private static final String EPSILON_NAME = "minVertexDistance"; private static final String EPSILON_NAME = "minVertexDistance";
...@@ -59,9 +68,7 @@ public class InteriorDisconnectedCheck extends Check { ...@@ -59,9 +68,7 @@ public class InteriorDisconnectedCheck extends Check {
@Override @Override
public void init(Map<String, String> params, ParserConfiguration config) { public void init(Map<String, String> params, ParserConfiguration config) {
String epsilonString = params.get(EPSILON_NAME); String epsilonString = params.get(EPSILON_NAME);
if (epsilonString == null) { if (epsilonString != null) {
epsilon = 0.0001;
} else {
epsilon = Double.parseDouble(epsilonString); epsilon = Double.parseDouble(epsilonString);
} }
} }
...@@ -159,8 +166,13 @@ public class InteriorDisconnectedCheck extends Check { ...@@ -159,8 +166,13 @@ public class InteriorDisconnectedCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_INTERIOR_DISCONNECTED);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError; 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.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
...@@ -40,7 +43,7 @@ import de.hft.stuttgart.citydoctor2.math.graph.PolygonGraph; ...@@ -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 * Checks if the polygons adjacent to a vertex are attached via edges or are
* they discontinuous. * they discontinuous.
* *
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de * @author Matthias Betz
* *
*/ */
public class ManifoldVertexCheck extends Check { public class ManifoldVertexCheck extends Check {
...@@ -94,8 +97,13 @@ public class ManifoldVertexCheck extends Check { ...@@ -94,8 +97,13 @@ public class ManifoldVertexCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_S_NON_MANIFOLD_VERTEX);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError; 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.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
...@@ -38,7 +41,7 @@ import de.hft.stuttgart.citydoctor2.math.graph.PolygonGraph; ...@@ -38,7 +41,7 @@ import de.hft.stuttgart.citydoctor2.math.graph.PolygonGraph;
/** /**
* Checks if all parts of a solid are connected or not. * 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 { public class MultipleConnectedComponentCheck extends Check {
...@@ -88,8 +91,13 @@ public class MultipleConnectedComponentCheck extends Check { ...@@ -88,8 +91,13 @@ public class MultipleConnectedComponentCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_S_MULTIPLE_CONNECTED_COMPONENTS);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,18 +21,28 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,18 +21,28 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; 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 { public class NestedRingsCheck extends Check {
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
...@@ -87,8 +97,13 @@ public class NestedRingsCheck extends Check { ...@@ -87,8 +97,13 @@ public class NestedRingsCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_INNER_RINGS_NESTED);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError; 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.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
...@@ -37,7 +40,9 @@ 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. * This class detects half edges with more than two neighbors, i.e.
* non-2-manifold geometries * non-2-manifold geometries
* *
* @author dwagner, alam * @author dwagner
* @author alam
* @author Matthias Betz
*/ */
public class NonManifoldEdgeCheck extends Check { public class NonManifoldEdgeCheck extends Check {
...@@ -81,14 +86,19 @@ public class NonManifoldEdgeCheck extends Check { ...@@ -81,14 +86,19 @@ public class NonManifoldEdgeCheck extends Check {
g.addCheckResult(cr); g.addCheckResult(cr);
} }
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_NON_MANIFOLD_EDGE);
}
@Override @Override
public List<CheckId> getDependencies() { public List<CheckId> getDependencies() {
return dependencies; return dependencies;
} }
@Override @Override
public CheckType getType() { public RequirementType getType() {
return CheckType.GEOMETRY; return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -22,15 +22,16 @@ import java.util.ArrayList; ...@@ -22,15 +22,16 @@ 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.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType; import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter; import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.ResultStatus; 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.check.error.NullAreaError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.Line3d; import de.hft.stuttgart.citydoctor2.math.Line3d;
...@@ -45,7 +46,6 @@ public class NullAreaCheck extends Check { ...@@ -45,7 +46,6 @@ public class NullAreaCheck extends Check {
private static final String DELTA_NAME = "delta"; private static final String DELTA_NAME = "delta";
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
private static final List<DefaultParameter> defaultParameters;
static { static {
ArrayList<CheckId> deps = new ArrayList<>(); ArrayList<CheckId> deps = new ArrayList<>();
...@@ -53,10 +53,6 @@ public class NullAreaCheck extends Check { ...@@ -53,10 +53,6 @@ public class NullAreaCheck extends Check {
deps.add(CheckId.C_GE_R_NOT_CLOSED); deps.add(CheckId.C_GE_R_NOT_CLOSED);
deps.add(CheckId.C_GE_R_DUPLICATE_POINT); deps.add(CheckId.C_GE_R_DUPLICATE_POINT);
dependencies = Collections.unmodifiableList(deps); dependencies = Collections.unmodifiableList(deps);
ArrayList<DefaultParameter> defParameters = new ArrayList<>();
defParameters.add(new DefaultParameter(DELTA_NAME, "0.0001", Unit.SQUARE_METER));
defaultParameters = Collections.unmodifiableList(defParameters);
} }
private double delta = 0.0001; private double delta = 0.0001;
...@@ -68,11 +64,6 @@ public class NullAreaCheck extends Check { ...@@ -68,11 +64,6 @@ public class NullAreaCheck extends Check {
} }
} }
@Override
public List<DefaultParameter> getDefaultParameter() {
return defaultParameters;
}
@Override @Override
public void check(LinearRing lr) { public void check(LinearRing lr) {
boolean areaIsNull = checkWithDistanceToRegressionLine(lr, delta); boolean areaIsNull = checkWithDistanceToRegressionLine(lr, delta);
...@@ -107,14 +98,19 @@ public class NullAreaCheck extends Check { ...@@ -107,14 +98,19 @@ public class NullAreaCheck extends Check {
return area < 0.0001; return area < 0.0001;
} }
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_R_NULL_AREA);
}
@Override @Override
public List<CheckId> getDependencies() { public List<CheckId> getDependencies() {
return dependencies; return dependencies;
} }
@Override @Override
public CheckType getType() { public RequirementType getType() {
return CheckType.GEOMETRY; return RequirementType.GEOMETRY;
} }
......
...@@ -22,23 +22,26 @@ import java.util.ArrayList; ...@@ -22,23 +22,26 @@ 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 Jama.EigenvalueDecomposition; import Jama.EigenvalueDecomposition;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.CheckType; import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter; import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.check.ResultStatus; 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.NonPlanarPolygonDistancePlaneError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex; import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.CovarianceMatrix; 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.OrthogonalRegressionPlane;
import de.hft.stuttgart.citydoctor2.math.Plane; import de.hft.stuttgart.citydoctor2.math.Plane;
import de.hft.stuttgart.citydoctor2.math.Triangle3d; import de.hft.stuttgart.citydoctor2.math.Triangle3d;
...@@ -48,7 +51,8 @@ import de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator; ...@@ -48,7 +51,8 @@ import de.hft.stuttgart.citydoctor2.tesselation.JoglTesselator;
import de.hft.stuttgart.citydoctor2.tesselation.TesselatedPolygon; 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 * @author Matthias Betz
* *
...@@ -62,7 +66,6 @@ public class PlanarCheck extends Check { ...@@ -62,7 +66,6 @@ public class PlanarCheck extends Check {
private static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance"; private static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance";
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
private static final List<DefaultParameter> defaultParameters;
static { static {
ArrayList<CheckId> deps = new ArrayList<>(4); ArrayList<CheckId> deps = new ArrayList<>(4);
...@@ -71,14 +74,6 @@ public class PlanarCheck extends Check { ...@@ -71,14 +74,6 @@ public class PlanarCheck extends Check {
deps.add(CheckId.C_GE_R_DUPLICATE_POINT); deps.add(CheckId.C_GE_R_DUPLICATE_POINT);
deps.add(CheckId.C_GE_R_SELF_INTERSECTION); deps.add(CheckId.C_GE_R_SELF_INTERSECTION);
dependencies = Collections.unmodifiableList(deps); dependencies = Collections.unmodifiableList(deps);
ArrayList<DefaultParameter> defParameters = new ArrayList<>(3);
defParameters.add(new DefaultParameter(TYPE, DISTANCE, Unit.NONE));
defParameters.add(new DefaultParameter(DISTANCE_TOLERANCE, "0.01", Unit.METER));
defParameters.add(new DefaultParameter(ANGLE_TOLERANCE, "1", Unit.DEGREE));
defParameters.add(new DefaultParameter(DEGENERATED_POLYGON_TOLERANCE, "0.00000", Unit.METER));
defaultParameters = Collections.unmodifiableList(defParameters);
} }
private String planarCheckType = DISTANCE; private String planarCheckType = DISTANCE;
...@@ -91,6 +86,8 @@ public class PlanarCheck extends Check { ...@@ -91,6 +86,8 @@ public class PlanarCheck extends Check {
public void init(Map<String, String> parameters, ParserConfiguration config) { public void init(Map<String, String> parameters, ParserConfiguration config) {
if (parameters.containsKey(TYPE)) { if (parameters.containsKey(TYPE)) {
planarCheckType = parameters.get(TYPE).toLowerCase(); planarCheckType = parameters.get(TYPE).toLowerCase();
} else {
throw new IllegalStateException("Parameter " + TYPE + " is missing from parameters");
} }
if (parameters.containsKey(ANGLE_TOLERANCE)) { if (parameters.containsKey(ANGLE_TOLERANCE)) {
rad = Math.toRadians(Double.parseDouble(parameters.get(ANGLE_TOLERANCE))); rad = Math.toRadians(Double.parseDouble(parameters.get(ANGLE_TOLERANCE)));
...@@ -103,11 +100,6 @@ public class PlanarCheck extends Check { ...@@ -103,11 +100,6 @@ public class PlanarCheck extends Check {
} }
} }
@Override
public List<DefaultParameter> getDefaultParameter() {
return defaultParameters;
}
@Override @Override
public void check(Polygon p) { public void check(Polygon p) {
if (DISTANCE.equals(planarCheckType)) { if (DISTANCE.equals(planarCheckType)) {
...@@ -118,8 +110,7 @@ public class PlanarCheck extends Check { ...@@ -118,8 +110,7 @@ public class PlanarCheck extends Check {
ArrayList<Vertex> vertices = collectVertices(p); ArrayList<Vertex> vertices = collectVertices(p);
Vector3d centroid = CovarianceMatrix.getCentroid(vertices); Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid); EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed); if (checkEigenvalues(p, vertices, ed)) {
if (checkEigenvalues(p, eigenvalues)) {
// found tiny edge error, abort further checking // found tiny edge error, abort further checking
return; return;
} }
...@@ -181,13 +172,13 @@ public class PlanarCheck extends Check { ...@@ -181,13 +172,13 @@ public class PlanarCheck extends Check {
ArrayList<Vertex> vertices = collectVertices(p); ArrayList<Vertex> vertices = collectVertices(p);
Vector3d centroid = CovarianceMatrix.getCentroid(vertices); Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid); 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 // found tiny edge error, abort further checking
return; return;
} }
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed);
Plane plane = OrthogonalRegressionPlane.calculatePlane(centroid, ed, eigenvalues); Plane plane = OrthogonalRegressionPlane.calculatePlane(centroid, ed, eigenvalues);
for (Vertex v : vertices) { for (Vertex v : vertices) {
double distance = plane.getDistance(v); double distance = plane.getDistance(v);
...@@ -220,13 +211,25 @@ public class PlanarCheck extends Check { ...@@ -220,13 +211,25 @@ public class PlanarCheck extends Check {
return vertices; 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; int nrOfEigenvaluesBelowTolerance = 0;
for (double d : eigenvalues.getCoordinates()) { if (bbox.getWidth() < degeneratedPolygonTolerance) {
if (d <= degeneratedPolygonTolerance) { nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getHeight() < degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++; nrOfEigenvaluesBelowTolerance++;
} }
if (bbox.getDepth() < degeneratedPolygonTolerance) {
nrOfEigenvaluesBelowTolerance++;
} }
if (nrOfEigenvaluesBelowTolerance >= 2) { if (nrOfEigenvaluesBelowTolerance >= 2) {
CheckError err = new DegeneratedPolygonError(p); CheckError err = new DegeneratedPolygonError(p);
p.addCheckResult(new CheckResult(this, ResultStatus.ERROR, err)); p.addCheckResult(new CheckResult(this, ResultStatus.ERROR, err));
...@@ -241,8 +244,13 @@ public class PlanarCheck extends Check { ...@@ -241,8 +244,13 @@ public class PlanarCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_NON_PLANAR);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,14 +21,17 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError; 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.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Polygon2d; import de.hft.stuttgart.citydoctor2.math.Polygon2d;
...@@ -38,9 +41,14 @@ import de.hft.stuttgart.citydoctor2.math.Vector2d; ...@@ -38,9 +41,14 @@ import de.hft.stuttgart.citydoctor2.math.Vector2d;
import de.hft.stuttgart.citydoctor2.utils.Pair; import de.hft.stuttgart.citydoctor2.utils.Pair;
import de.hft.stuttgart.citydoctor2.utils.SerializablePair; 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 { public class PolygonIntersectingRingsCheck extends Check {
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
static { static {
...@@ -124,8 +132,13 @@ public class PolygonIntersectingRingsCheck extends Check { ...@@ -124,8 +132,13 @@ public class PolygonIntersectingRingsCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_INTERSECTING_RINGS);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,20 +21,31 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,20 +21,31 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError; 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.Orientation;
import de.hft.stuttgart.citydoctor2.checks.util.RingOrientationUtil; import de.hft.stuttgart.citydoctor2.checks.util.RingOrientationUtil;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.Polygon2d; import de.hft.stuttgart.citydoctor2.math.Polygon2d;
import de.hft.stuttgart.citydoctor2.math.Ring2d; 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 { public class PolygonSameOrientationCheck extends Check {
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
...@@ -80,8 +91,13 @@ public class PolygonSameOrientationCheck extends Check { ...@@ -80,8 +91,13 @@ public class PolygonSameOrientationCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_P_ORIENTATION_RINGS_SAME);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @Override
......
...@@ -21,26 +21,30 @@ package de.hft.stuttgart.citydoctor2.checks.geometry; ...@@ -21,26 +21,30 @@ package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check; import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError; import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId; import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult; 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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError; 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.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry; import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType; import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
/** /**
* This class checks the orientation of each face of a solid * Checks whether polygons share a edge that is walked more than one time in the
* @author Matthias Betz - 12bema1bif@hft-stuttgart.de * same direction by two or more polygons indicating that a polygon is oriented wrong.
*
* @author Matthias Betz
* *
*/ */
public class PolygonWrongOrientationCheck extends Check { public class PolygonWrongOrientationCheck extends Check {
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
static { static {
...@@ -87,8 +91,13 @@ public class PolygonWrongOrientationCheck extends Check { ...@@ -87,8 +91,13 @@ public class PolygonWrongOrientationCheck extends Check {
} }
@Override @Override
public CheckType getType() { public Set<Requirement> appliesToRequirements() {
return CheckType.GEOMETRY; return CollectionUtils.singletonSet(Requirement.R_GE_S_POLYGON_WRONG_ORIENTATION);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
} }
@Override @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