Commit a4715310 authored by Matthias Betz's avatar Matthias Betz
Browse files

Moving degeneration test to ring instead of polygon

parent 43660f7f
Pipeline #4349 passed with stage
in 2 minutes and 14 seconds
...@@ -62,7 +62,7 @@ public class ErrorId implements Serializable { ...@@ -62,7 +62,7 @@ public class ErrorId implements Serializable {
public static final ErrorId SE_BS_NOT_GROUND = new ErrorId("SE_BS_NOT_GROUND"); public static final ErrorId SE_BS_NOT_GROUND = new ErrorId("SE_BS_NOT_GROUND");
public static final ErrorId SE_SCHEMATRON_ERROR = new ErrorId("SE_SCHEMATRON_ERROR"); public static final ErrorId SE_SCHEMATRON_ERROR = new ErrorId("SE_SCHEMATRON_ERROR");
public static final ErrorId SE_BS_UNFRAGMENTED = new ErrorId("SE_BS_UNFRAGMENTED"); public static final ErrorId SE_BS_UNFRAGMENTED = new ErrorId("SE_BS_UNFRAGMENTED");
public static final ErrorId GE_P_DEGENERATED_POLYGON = new ErrorId("GE_P_DEGENERATED_POLYGON"); public static final ErrorId GE_P_DEGENERATED_RING = new ErrorId("GE_P_DEGENERATED_POLYGON");
private String name; private String name;
......
...@@ -48,7 +48,7 @@ import de.hft.stuttgart.citydoctor2.check.error.SchematronError; ...@@ -48,7 +48,7 @@ import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError; import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError; import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError; import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedPolygonError; import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError; import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
...@@ -123,7 +123,7 @@ public interface ErrorVisitor { ...@@ -123,7 +123,7 @@ public interface ErrorVisitor {
public void visit(SurfaceUnfragmentedError err); public void visit(SurfaceUnfragmentedError err);
public void visit(DegeneratedPolygonError err); public void visit(DegeneratedRingError err);
public void visit(AttributeMissingError err); public void visit(AttributeMissingError err);
......
...@@ -47,7 +47,7 @@ import de.hft.stuttgart.citydoctor2.check.error.SchematronError; ...@@ -47,7 +47,7 @@ import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError; import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError; import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError; import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedPolygonError; import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError; import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError; import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
...@@ -65,7 +65,7 @@ public interface HealingMethod { ...@@ -65,7 +65,7 @@ public interface HealingMethod {
return false; return false;
} }
default boolean visit(DegeneratedPolygonError e, ModificationListener l) { default boolean visit(DegeneratedRingError e, ModificationListener l) {
return false; return false;
} }
......
...@@ -30,7 +30,7 @@ public class Requirement implements Serializable { ...@@ -30,7 +30,7 @@ public class Requirement implements Serializable {
private static final String DISTANCE_TOLERANCE = "distanceTolerance"; private static final String DISTANCE_TOLERANCE = "distanceTolerance";
private static final String ANGLE_TOLERANCE = "angleTolerance"; private static final String ANGLE_TOLERANCE = "angleTolerance";
private static final String TYPE_STRING = "type"; private static final String TYPE_STRING = "type";
private static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance"; public static final String DEGENERATED_RING_TOLERANCE = "degeneratedRingTolerance";
private static final String LOWER_ANGLE_NAME = "lowerAngle"; private static final String LOWER_ANGLE_NAME = "lowerAngle";
private static final String UPPER_ANGLE_NAME = "upperAngle"; private static final String UPPER_ANGLE_NAME = "upperAngle";
private static final String MAX_ANGLE_DEVIATION = "maxAngleDeviation"; private static final String MAX_ANGLE_DEVIATION = "maxAngleDeviation";
...@@ -73,7 +73,6 @@ public class Requirement implements Serializable { ...@@ -73,7 +73,6 @@ public class Requirement implements Serializable {
defaultParameters.add(new DefaultParameter(TYPE_STRING, "distance", Unit.NONE)); defaultParameters.add(new DefaultParameter(TYPE_STRING, "distance", Unit.NONE));
defaultParameters.add(new DefaultParameter(DISTANCE_TOLERANCE, "0.01", Unit.METER)); defaultParameters.add(new DefaultParameter(DISTANCE_TOLERANCE, "0.01", Unit.METER));
defaultParameters.add(new DefaultParameter(ANGLE_TOLERANCE, "1", Unit.DEGREE)); defaultParameters.add(new DefaultParameter(ANGLE_TOLERANCE, "1", Unit.DEGREE));
defaultParameters.add(new DefaultParameter(DEGENERATED_POLYGON_TOLERANCE, "0.00000", Unit.METER));
R_GE_P_NON_PLANAR.parameters = Collections.unmodifiableList(defaultParameters); R_GE_P_NON_PLANAR.parameters = Collections.unmodifiableList(defaultParameters);
defaultParameters = new ArrayList<>(); defaultParameters = new ArrayList<>();
...@@ -83,6 +82,10 @@ public class Requirement implements Serializable { ...@@ -83,6 +82,10 @@ public class Requirement implements Serializable {
defaultParameters.add(new DefaultParameter(MAX_ANGLE_DEVIATION, "1", Unit.DEGREE)); defaultParameters.add(new DefaultParameter(MAX_ANGLE_DEVIATION, "1", Unit.DEGREE));
R_SE_BS_ROOF_UNFRAGMENTED.parameters = Collections.unmodifiableList(defaultParameters); R_SE_BS_ROOF_UNFRAGMENTED.parameters = Collections.unmodifiableList(defaultParameters);
defaultParameters = new ArrayList<>();
defaultParameters.add(new DefaultParameter(DEGENERATED_RING_TOLERANCE, "0.00000", Unit.METER));
R_GE_R_SELF_INTERSECTION.parameters = Collections.unmodifiableList(defaultParameters);
} }
......
...@@ -26,20 +26,20 @@ import de.hft.stuttgart.citydoctor2.check.ErrorVisitor; ...@@ -26,20 +26,20 @@ import de.hft.stuttgart.citydoctor2.check.ErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.HealingMethod; import de.hft.stuttgart.citydoctor2.check.HealingMethod;
import de.hft.stuttgart.citydoctor2.check.ModificationListener; import de.hft.stuttgart.citydoctor2.check.ModificationListener;
import de.hft.stuttgart.citydoctor2.datastructure.GmlElement; import de.hft.stuttgart.citydoctor2.datastructure.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon; import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
public class DegeneratedPolygonError implements CheckError { public class DegeneratedRingError implements CheckError {
private static final long serialVersionUID = 865493182529055651L; private static final long serialVersionUID = 865493182529055651L;
private Polygon p; private LinearRing lr;
public DegeneratedPolygonError(Polygon p) { public DegeneratedRingError(LinearRing lr) {
this.p = p; this.lr = lr;
} }
public Polygon getPolygon() { public LinearRing getRing() {
return p; return lr;
} }
@Override @Override
...@@ -54,7 +54,8 @@ public class DegeneratedPolygonError implements CheckError { ...@@ -54,7 +54,8 @@ public class DegeneratedPolygonError implements CheckError {
@Override @Override
public void report(ErrorReport report) { public void report(ErrorReport report) {
report.add(getPolygon()); report.add("type", "degenerated ring");
report.add(getRing());
} }
@Override @Override
...@@ -64,12 +65,12 @@ public class DegeneratedPolygonError implements CheckError { ...@@ -64,12 +65,12 @@ public class DegeneratedPolygonError implements CheckError {
@Override @Override
public ErrorId getErrorId() { public ErrorId getErrorId() {
return ErrorId.GE_P_DEGENERATED_POLYGON; return ErrorId.GE_R_SELF_INTERSECTION;
} }
@Override @Override
public GmlElement getFeature() { public GmlElement getFeature() {
return getPolygon(); return getRing();
} }
} }
...@@ -32,16 +32,13 @@ import de.hft.stuttgart.citydoctor2.check.CheckResult; ...@@ -32,16 +32,13 @@ import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.Requirement; import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementType; 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.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.checks.util.CollectionUtils; 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;
...@@ -63,7 +60,6 @@ public class PlanarCheck extends Check { ...@@ -63,7 +60,6 @@ public class PlanarCheck extends Check {
private static final String DISTANCE_TOLERANCE = "distanceTolerance"; private static final String DISTANCE_TOLERANCE = "distanceTolerance";
private static final String ANGLE_TOLERANCE = "angleTolerance"; private static final String ANGLE_TOLERANCE = "angleTolerance";
private static final String TYPE = "type"; private static final String TYPE = "type";
private static final String DEGENERATED_POLYGON_TOLERANCE = "degeneratedPolygonTolerance";
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
...@@ -80,7 +76,6 @@ public class PlanarCheck extends Check { ...@@ -80,7 +76,6 @@ public class PlanarCheck extends Check {
private double rad = Math.toRadians(1); private double rad = Math.toRadians(1);
private double delta = 0.01; private double delta = 0.01;
private double degeneratedPolygonTolerance = 0.00000;
@Override @Override
public void init(Map<String, String> parameters, ParserConfiguration config) { public void init(Map<String, String> parameters, ParserConfiguration config) {
...@@ -95,9 +90,6 @@ public class PlanarCheck extends Check { ...@@ -95,9 +90,6 @@ public class PlanarCheck extends Check {
if (parameters.containsKey(DISTANCE_TOLERANCE)) { if (parameters.containsKey(DISTANCE_TOLERANCE)) {
delta = Double.parseDouble(parameters.get(DISTANCE_TOLERANCE)); delta = Double.parseDouble(parameters.get(DISTANCE_TOLERANCE));
} }
if (parameters.containsKey(DEGENERATED_POLYGON_TOLERANCE)) {
degeneratedPolygonTolerance = Double.parseDouble(parameters.get(DEGENERATED_POLYGON_TOLERANCE));
}
} }
@Override @Override
...@@ -105,15 +97,6 @@ public class PlanarCheck extends Check { ...@@ -105,15 +97,6 @@ public class PlanarCheck extends Check {
if (DISTANCE.equals(planarCheckType)) { if (DISTANCE.equals(planarCheckType)) {
planarDistance(p); planarDistance(p);
} else if ("angle".equals(planarCheckType)) { } else if ("angle".equals(planarCheckType)) {
// check for tiny edge as well
// store all used points in temporary list
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;
}
planarNormalDeviation(p); planarNormalDeviation(p);
} else if ("both".equals(planarCheckType)) { } else if ("both".equals(planarCheckType)) {
planarDistance(p); planarDistance(p);
...@@ -172,12 +155,6 @@ public class PlanarCheck extends Check { ...@@ -172,12 +155,6 @@ 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);
if (checkEigenvalues(p, vertices, ed)) {
// found tiny edge error, abort further checking
return;
}
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed); 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) {
...@@ -211,33 +188,6 @@ public class PlanarCheck extends Check { ...@@ -211,33 +188,6 @@ public class PlanarCheck extends Check {
return vertices; return vertices;
} }
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;
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));
return true;
}
return false;
}
@Override @Override
public List<CheckId> getDependencies() { public List<CheckId> getDependencies() {
return dependencies; return dependencies;
......
...@@ -24,23 +24,30 @@ import java.util.List; ...@@ -24,23 +24,30 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
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.RequirementType;
import de.hft.stuttgart.citydoctor2.check.Requirement; 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.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError; import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError; import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.checks.Checks; import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils; import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
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.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.CovarianceMatrix;
import de.hft.stuttgart.citydoctor2.math.DistanceResult; import de.hft.stuttgart.citydoctor2.math.DistanceResult;
import de.hft.stuttgart.citydoctor2.math.Matrix3x3d;
import de.hft.stuttgart.citydoctor2.math.OrthogonalRegressionPlane;
import de.hft.stuttgart.citydoctor2.math.Segment3d; import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration; import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
/** /**
...@@ -54,6 +61,9 @@ public class RingSelfIntCheck extends Check { ...@@ -54,6 +61,9 @@ public class RingSelfIntCheck extends Check {
private static final String EPSILON_NAME = "minVertexDistance"; private static final String EPSILON_NAME = "minVertexDistance";
private double degeneratedRingTolerance = 0.00000;
private static final List<CheckId> dependencies; private static final List<CheckId> dependencies;
static { static {
...@@ -72,6 +82,9 @@ public class RingSelfIntCheck extends Check { ...@@ -72,6 +82,9 @@ public class RingSelfIntCheck extends Check {
if (epsilonString != null) { if (epsilonString != null) {
epsilon = Double.parseDouble(epsilonString); epsilon = Double.parseDouble(epsilonString);
} }
if (parameters.containsKey(Requirement.DEGENERATED_RING_TOLERANCE)) {
degeneratedRingTolerance = Double.parseDouble(parameters.get(Requirement.DEGENERATED_RING_TOLERANCE));
}
} }
@Override @Override
...@@ -80,6 +93,17 @@ public class RingSelfIntCheck extends Check { ...@@ -80,6 +93,17 @@ public class RingSelfIntCheck extends Check {
} }
private void checkRingJava(LinearRing lr) { private void checkRingJava(LinearRing lr) {
// check for tiny edge as well
// store all used points in temporary list
List<Vertex> vertices = lr.getVertices();
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
if (checkEigenvalues(lr, vertices, ed)) {
// found tiny edge error, abort further checking
return;
}
List<Edge> edges = getEdgesForRing(lr); List<Edge> edges = getEdgesForRing(lr);
for (Edge e : edges) { for (Edge e : edges) {
...@@ -113,6 +137,33 @@ public class RingSelfIntCheck extends Check { ...@@ -113,6 +137,33 @@ public class RingSelfIntCheck extends Check {
CheckResult cr = new CheckResult(this, ResultStatus.OK, null); CheckResult cr = new CheckResult(this, ResultStatus.OK, null);
lr.addCheckResult(cr); lr.addCheckResult(cr);
} }
private boolean checkEigenvalues(LinearRing lr, 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;
if (bbox.getWidth() < degeneratedRingTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getHeight() < degeneratedRingTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (bbox.getDepth() < degeneratedRingTolerance) {
nrOfEigenvaluesBelowTolerance++;
}
if (nrOfEigenvaluesBelowTolerance >= 2) {
CheckError err = new DegeneratedRingError(lr);
lr.addCheckResult(new CheckResult(this, ResultStatus.ERROR, err));
return true;
}
return false;
}
private boolean checkForPointsTouchingEdge(LinearRing lr, Edge e1) { private boolean checkForPointsTouchingEdge(LinearRing lr, Edge e1) {
Segment3d seg = new Segment3d(e1.getFrom(), e1.getTo()); Segment3d seg = new Segment3d(e1.getFrom(), e1.getTo());
......
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