Commit a27795de authored by Riegel's avatar Riegel
Browse files

Bugfix for found false positives of C_GE_S_SELF_INTERSECTION

parent 216ab18a
Pipeline #9981 passed with stage
in 1 minute and 14 seconds
......@@ -78,6 +78,43 @@ public class PolyLine extends BaseEntity {
return mpLast;
}
public Boolean isNullLine() {
return isNullLine(0.00);
}
public Boolean isNullLine(Double tolerance) {
// If either start or end Segment is null, return immediately
if (mpFirst == null || mpLast == null) {
return true;
}
PolyLineSegment currentSegment = mpFirst;
Double length = 0.00;
// Add length of all segments, starting from mpFirst
do {
Double segmentLength = currentSegment.getLengthVector().getLength();
if (segmentLength > tolerance) {
length += segmentLength;
}
if (currentSegment.getNext() != null) {
currentSegment = currentSegment.getNext();
}
} while (currentSegment.getNext() != null);
// Since mpLast will be missed due to loop condition add its length afterwards
Double segmentLength = mpLast.getLengthVector().getLength();
if (segmentLength > tolerance) {
length += segmentLength;
}
// Check if total length is less than the set tolerance
if (length <= tolerance) {
return true;
}
return false;
}
@Override
public String toString() {
return "PolyLine [mpFirst=" + mpFirst + ", mpLast=" + mpLast + "]";
......
......@@ -58,6 +58,11 @@ public class PolyLineSegment extends BaseEntity {
return mpNext;
}
public Vector3d getLengthVector() {
Vector3d representation = mpEnd.getPoint().minus(mpStart.getPoint());
return representation;
}
@Override
public String toString() {
return "PolyLineSegment [mpStart=" + mpStart + ", mpEnd=" + mpEnd + "]";
......
......@@ -34,9 +34,12 @@ import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.math.Segment3d;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
/**
* Check for self intersecting solids
......
......@@ -118,13 +118,20 @@ public class SelfIntersectionUtil {
Polygon p1, Polygon p2) {
EdgePolygon edgeP1 = edgePolyMap.get(p1);
EdgePolygon edgeP2 = edgePolyMap.get(p2);
List<PolygonPolygonIntersection> result = IntersectPlanarPolygons.intersectPolygons(edgeP1, edgeP2, 0.000001, 0.001);
if (!result.isEmpty()) {
List<PolygonPolygonIntersection> results = IntersectPlanarPolygons.intersectPolygons(edgeP1, edgeP2, 0.000001, 0.001);
if (!results.isEmpty()) {
// at least one intersection happened
for (PolygonPolygonIntersection result: results) {
// Ensure that Intersection-Edge is not a Null-Line.
// If it is a Null-Line, detected Intersection is a False-Positive.
if (!result.getPolyLine().isNullLine()) {
intersections.add(PolygonIntersection.lines(Collections.emptyList(), p1, p2));
}
}
}
}
/**
* Checks if two polygons are intersecting. Result may be nothing, a line or a
* polygon if they are planar and intersecting.
......
......@@ -18,8 +18,15 @@
*/
package de.hft.stuttgart.citydoctor2.checks.geometry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.core.util.internal.Status;
import org.junit.Assert;
import org.junit.Test;
......@@ -28,8 +35,11 @@ import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.checks.util.GeometryTestUtils;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
......@@ -73,4 +83,96 @@ public class SolidSelfIntCheckTest {
assertFalse(m.getBuildings().get(0).containsAnyError());
}
@Test
public void testKnownFalsePositiveExample1() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/SolidSelfIntTest-known_false_positive1.gml", config.getParserConfiguration());
Checker c = new Checker(config, m);
c.runChecks();
Building building = m.getBuildings().get(0);
System.out.println(building.containsAnyError());
// Example1 Building has some BuildingInstallations, which throw semantic errors
if (building.containsAnyError()) {
Geometry buildingGeom = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
buildingGeom.clearCheckResults();
SolidSelfIntCheck check = new SolidSelfIntCheck();
check.check(buildingGeom);
CheckResult cr = buildingGeom.getCheckResult(check);
assertNotNull(cr);
//Ensure that checker did not find a self intersection
assertEquals("Known False-Positive self-intersection was detected as error", ResultStatus.OK, cr.getResultStatus());
}
}
@Test
public void testKnownFalsePositiveExample2() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/SolidSelfIntTest-known_false_positive2.gml", config.getParserConfiguration());
Checker c = new Checker(config, m);
c.runChecks();
Building building = m.getBuildings().get(0);
// If an error was found, check if error is SolidSelfInt
if (building.containsAnyError()) {
Geometry buildingGeom = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
buildingGeom.clearCheckResults();
SolidSelfIntCheck check = new SolidSelfIntCheck();
check.check(buildingGeom);
CheckResult cr = buildingGeom.getCheckResult(check);
assertNotNull(cr);
assertEquals("Known False-Positive self-intersection was detected as error", ResultStatus.OK, cr.getResultStatus());
}
}
@Test
public void testKnownFalsePositiveExample3() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/SolidSelfIntTest-known_false_positive3.gml", config.getParserConfiguration());
Checker c = new Checker(config, m);
c.runChecks();
Building building = m.getBuildings().get(0);
// If an error was found, check if error is SolidSelfInt
if (building.containsAnyError()) {
Geometry buildingGeom = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
buildingGeom.clearCheckResults();
SolidSelfIntCheck check = new SolidSelfIntCheck();
check.check(buildingGeom);
CheckResult cr = buildingGeom.getCheckResult(check);
assertNotNull(cr);
//Ensure that checker did not find the false-positive self intersection
assertEquals("Known False-Positive self-intersection was detected as error", ResultStatus.OK, cr.getResultStatus());
}
}
@Test
public void testKnownFalsePositiveExample4() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel m = CityGmlParser.parseCityGmlFile("src/test/resources/SolidSelfIntTest-known_false_positive4.gml", config.getParserConfiguration());
Checker c = new Checker(config, m);
c.runChecks();
Building building = m.getBuildings().get(0);
// If an error was found, check if error is SolidSelfInt
if (building.containsAnyError()) {
Geometry buildingGeom = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
buildingGeom.clearCheckResults();
SolidSelfIntCheck check = new SolidSelfIntCheck();
check.check(buildingGeom);
CheckResult cr = buildingGeom.getCheckResult(check);
assertNotNull(cr);
//Ensure that checker did not find the false-positive self intersection
assertEquals("Known False-Positive self-intersection was detected as error", ResultStatus.OK, cr.getResultStatus());
}
}
}
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