Commit 216ab18a authored by Riegel's avatar Riegel
Browse files

Revert "Added basis for implementation of InteriorFacesCheck"

This reverts commit 22fce970
parent 22fce970
Pipeline #9850 passed with stage
in 1 minute and 12 seconds
...@@ -37,7 +37,6 @@ public class CheckId implements Serializable { ...@@ -37,7 +37,6 @@ public class CheckId implements Serializable {
public static final CheckId C_GE_R_NULL_AREA = new CheckId("C_GE_R_NULL_AREA"); public static final CheckId C_GE_R_NULL_AREA = new CheckId("C_GE_R_NULL_AREA");
public static final CheckId C_GE_S_NON_MANIFOLD_EDGE = new CheckId("C_GE_S_NON_MANIFOLD_EDGE"); public static final CheckId C_GE_S_NON_MANIFOLD_EDGE = new CheckId("C_GE_S_NON_MANIFOLD_EDGE");
public static final CheckId C_GE_S_POLYGON_WRONG_ORIENTATION = new CheckId("C_GE_S_POLYGON_WRONG_ORIENTATION"); public static final CheckId C_GE_S_POLYGON_WRONG_ORIENTATION = new CheckId("C_GE_S_POLYGON_WRONG_ORIENTATION");
public static final CheckId C_GE_S_INTERIOR_FACE = new CheckId("C_GE_S_INTERIOR_FACE");
public static final CheckId C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION = new CheckId( public static final CheckId C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION = new CheckId(
"C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION"); "C_GE_S_ALL_POLYGONS_WRONG_ORIENTATION");
public static final CheckId C_GE_S_NON_MANIFOLD_VERTEX = new CheckId("C_GE_S_NON_MANIFOLD_VERTEX"); public static final CheckId C_GE_S_NON_MANIFOLD_VERTEX = new CheckId("C_GE_S_NON_MANIFOLD_VERTEX");
......
...@@ -47,7 +47,6 @@ public class ErrorId implements Serializable { ...@@ -47,7 +47,6 @@ public class ErrorId implements Serializable {
public static final ErrorId GE_R_NULL_AREA = new ErrorId("GE_R_NULL_AREA"); public static final ErrorId GE_R_NULL_AREA = new ErrorId("GE_R_NULL_AREA");
public static final ErrorId GE_R_TOO_FEW_POINTS = new ErrorId("GE_R_TOO_FEW_POINTS"); public static final ErrorId GE_R_TOO_FEW_POINTS = new ErrorId("GE_R_TOO_FEW_POINTS");
public static final ErrorId GE_S_NON_MANIFOLD_EDGE = new ErrorId("GE_S_NON_MANIFOLD_EDGE"); public static final ErrorId GE_S_NON_MANIFOLD_EDGE = new ErrorId("GE_S_NON_MANIFOLD_EDGE");
public static final ErrorId GE_S_INTERIOR_FACE = new ErrorId("GE_S_INTERIOR_FACE");
public static final ErrorId GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION = new ErrorId( public static final ErrorId GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION = new ErrorId(
"GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION"); "GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION");
public static final ErrorId GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE = new ErrorId( public static final ErrorId GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE = new ErrorId(
......
...@@ -47,7 +47,6 @@ public class Requirement implements Serializable { ...@@ -47,7 +47,6 @@ public class Requirement implements Serializable {
public static final Requirement R_GE_P_INNER_RINGS_NESTED = new Requirement("R_GE_P_INNER_RINGS_NESTED", RequirementType.GEOMETRY); public static final Requirement R_GE_P_INNER_RINGS_NESTED = new Requirement("R_GE_P_INNER_RINGS_NESTED", RequirementType.GEOMETRY);
public static final Requirement R_GE_S_TOO_FEW_POLYGONS = new Requirement("R_GE_S_TOO_FEW_POLYGONS", RequirementType.GEOMETRY); public static final Requirement R_GE_S_TOO_FEW_POLYGONS = new Requirement("R_GE_S_TOO_FEW_POLYGONS", RequirementType.GEOMETRY);
public static final Requirement R_GE_S_NOT_CLOSED = new Requirement("R_GE_S_NOT_CLOSED", RequirementType.GEOMETRY); public static final Requirement R_GE_S_NOT_CLOSED = new Requirement("R_GE_S_NOT_CLOSED", RequirementType.GEOMETRY);
public static final Requirement R_GE_S_INTERIOR_FACE = new Requirement("R_GE_S_INTERIOR_FACE", RequirementType.GEOMETRY);
public static final Requirement R_GE_S_NON_MANIFOLD_EDGE = new Requirement("R_GE_S_NON_MANIFOLD_EDGE", RequirementType.GEOMETRY); public static final Requirement R_GE_S_NON_MANIFOLD_EDGE = new Requirement("R_GE_S_NON_MANIFOLD_EDGE", RequirementType.GEOMETRY);
public static final Requirement R_GE_S_POLYGON_WRONG_ORIENTATION = new Requirement( public static final Requirement R_GE_S_POLYGON_WRONG_ORIENTATION = new Requirement(
"R_GE_S_POLYGON_WRONG_ORIENTATION", RequirementType.GEOMETRY); "R_GE_S_POLYGON_WRONG_ORIENTATION", RequirementType.GEOMETRY);
......
package de.hft.stuttgart.citydoctor2.check.error;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ErrorReport;
import de.hft.stuttgart.citydoctor2.check.ErrorType;
import de.hft.stuttgart.citydoctor2.check.ErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.HealingMethod;
import de.hft.stuttgart.citydoctor2.check.ModificationListener;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
/**
* If a polygon is fully inside a solid geometry this error is created.
*
* @author Alexander Riegel
*/
public class InteriorFaceError implements CheckError{
private static final long serialVersionUID = 6633158315015689806L;
private List<Polygon> polygons;
private Geometry geom;
public InteriorFaceError(Geometry geom, List<Polygon> polygons) {
super();
this.polygons = polygons;
this.geom = geom;
}
public Geometry getGeometry() {
return geom;
}
public List<Polygon> getPolygons(){
return polygons;
}
@Override
public ErrorType getType() {
return ErrorType.ERROR;
}
@Override
public ErrorId getErrorId() {
return ErrorId.GE_S_INTERIOR_FACE;
}
@Override
public GmlElement getFeature() {
return getGeometry();
}
@Override
public void accept(ErrorVisitor errorVisitor) {
errorVisitor.visit(this);
}
public String toString() {
return "InteriorFaceError [Polygons=" + polygons + ", geom=" + geom + "]";
}
@Override
public boolean accept(HealingMethod method, ModificationListener l) {
return method.visit(this, l);
}
@Override
public void report(ErrorReport report) {
report.add(geom);
polygons.forEach(x -> report.add(x));
}
}
...@@ -34,7 +34,6 @@ import de.hft.stuttgart.citydoctor2.checks.geometry.AllPolygonsWrongOrientationC ...@@ -34,7 +34,6 @@ import de.hft.stuttgart.citydoctor2.checks.geometry.AllPolygonsWrongOrientationC
import de.hft.stuttgart.citydoctor2.checks.geometry.DuplicatePointsCheck; import de.hft.stuttgart.citydoctor2.checks.geometry.DuplicatePointsCheck;
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.InteriorFacesCheck;
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;
...@@ -103,7 +102,6 @@ public class Checks { ...@@ -103,7 +102,6 @@ public class Checks {
publish(new PolygonWrongOrientationCheck()); publish(new PolygonWrongOrientationCheck());
publish(new AllPolygonsWrongOrientationCheck()); publish(new AllPolygonsWrongOrientationCheck());
publish(new TooFewPolygonsCheck()); publish(new TooFewPolygonsCheck());
publish(new InteriorFacesCheck());
publish(new ManifoldVertexCheck()); publish(new ManifoldVertexCheck());
publish(new SolidSelfIntCheck()); publish(new SolidSelfIntCheck());
......
package de.hft.stuttgart.citydoctor2.checks.geometry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
/**
* This class checks if a solid geometry has polygons that are fully enclosed inside the boundary surfaces.
*
* @author Alexander Riegel
*/
public class InteriorFacesCheck extends Check {
private static final List<CheckId> dependencies;
static {
ArrayList<CheckId> deps = new ArrayList<>();
deps.add(CheckId.C_GE_R_TOO_FEW_POINTS);
deps.add(CheckId.C_GE_R_NOT_CLOSED);
deps.add(CheckId.C_GE_R_DUPLICATE_POINT);
deps.add(CheckId.C_GE_R_SELF_INTERSECTION);
deps.add(CheckId.C_GE_P_INTERIOR_DISCONNECTED);
deps.add(CheckId.C_GE_P_INTERSECTING_RINGS);
deps.add(CheckId.C_GE_P_NON_PLANAR);
deps.add(CheckId.C_GE_S_TOO_FEW_POLYGONS);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Geometry g) {
// only check solids
if (g.getType() != GeometryType.SOLID) {
return;
}
// TODO: Implement check logic
// Assuming geometry is well defined (no holes or dangling polygons).
// Check should run just before the ManifoldEdgesCheck
// Step 1:
// Check pairs of polygons for their distance
// if they are too closely together (within EPSILON) add them to confirmed set
// Step 2:
// get centroid of each polygon and move it EPSILON * normalized polygon normal vector
// if that point is inside the solid's geometry, add polygon to confirmed set
// Step 3:
// Use intersections of the polygon normal vector(raycast from centroid)
// with other polygons to establish a list of suspects.
// Check all found suspects for number of intersections.
// Use intersection count to eliminate wrongly suspected polygons
// After sorting in ascending number of intersections:
// 0 intersections are safe to remove from suspects (safe)
// 1 intersection is guaranteed to be an interior face (confirmed)
// Move these polygons into their respective sets
// Intersection counts >= 2 require more analysis,
// using dot product of the normalized polygon normal vectors.
// Count the number of positive (same face direction) and negative (opposite face directions) dot products.
// If the intersected polygon is in the confirmed set, ignore them
// If positive count = negative count, move into preliminary safe set
//
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_S_INTERIOR_FACE);
}
@Override
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
public Check createNewInstance() {
return new InteriorFacesCheck();
}
@Override
public CheckId getCheckId() {
return CheckId.C_GE_S_INTERIOR_FACE;
}
}
package de.hft.stuttgart.citydoctor2.checks.geometry;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.InteriorFaceError;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static de.hft.stuttgart.citydoctor2.checks.util.GeometryTestUtils.createGoodGeometry;
import static de.hft.stuttgart.citydoctor2.checks.util.GeometryTestUtils.createVertex;
import static de.hft.stuttgart.citydoctor2.checks.util.GeometryTestUtils.addPolygon;
public class InteriorFacesCheckTest {
Geometry geom;
@Before
public void setup() {
geom = createGoodGeometry();
}
@Test
public void testGoodGeometry() {
InteriorFacesCheck check = new InteriorFacesCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull("Check result must not be null", cr);
assertEquals("Good geometry must return OK check result", ResultStatus.OK, cr.getResultStatus());
}
@Test
public void testSimpleGeometryWithInteriorFace() {
Vertex v0 = createVertex(5,0,0,geom);
Vertex v1 = createVertex(5,0,10,geom);
Vertex v2 = createVertex(5,10,10,geom);
Vertex v3 = createVertex(5,10,0,geom);
Polygon insertedInteriorFace = addPolygon(geom, v0, v1, v2, v3);
geom.updateEdgesAndVertices();
InteriorFacesCheck check = new InteriorFacesCheck();
check.check(geom);
CheckResult cr = geom.getCheckResult(check);
assertNotNull(cr);
assertEquals("Check should have detected an error", ResultStatus.ERROR, cr.getResultStatus());
assertEquals("ID of found Error should be GE_S_INTERIOR_FACE",ErrorId.GE_S_INTERIOR_FACE,cr.getError().getErrorId());
CheckError foundError = cr.getError();
assertTrue("Check should have returned a InteriorFaceError",foundError instanceof InteriorFaceError);
List<Polygon> interiorFaces = ((InteriorFaceError) foundError).getPolygons();
assertNotNull(interiorFaces);
assertTrue("InteriorFaces should have a single entry", interiorFaces.size() == 1);
Polygon foundInteriorFace = interiorFaces.getFirst();
assertEquals("Found interior face should be the inserted polygon", insertedInteriorFace, foundInteriorFace);
}
}
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