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

fixes

parent 2d2487cc
Pipeline #12355 failed with stage
in 1 minute and 54 seconds
......@@ -112,13 +112,13 @@ public class BoundingVolumeHierarchyTree<E> {
}
// Works with overlaps()<--includes touching; not with intersects()
public List<E> getAllIntersectingElements(AABB query) {
public List<E> getAllOverlappingElements(AABB query) {
List<E> result = new ArrayList<>();
getAllIntersectingElementsRecursive(root, query, result);
getAllOverlappingElementsRecursive(root, query, result);
return result;
}
private void getAllIntersectingElementsRecursive(Node<E> node, AABB query, List<E> result) {
private void getAllOverlappingElementsRecursive(Node<E> node, AABB query, List<E> result) {
if (node == null) {
return;
}
......@@ -137,7 +137,7 @@ public class BoundingVolumeHierarchyTree<E> {
}
for (Node<E> child : node.getChildren()) {
getAllIntersectingElementsRecursive(child, query, result);
getAllOverlappingElementsRecursive(child, query, result);
}
}
......
......@@ -122,7 +122,7 @@ public class RingSelfIntCheckAABB extends Check {
return;
}
}
// --- Original pairwise edge test, now with AABB early-out ---
for (int i = 0; i < edges.size() - 1; i++) {
Edge e1 = edges.get(i);
......
......@@ -123,6 +123,66 @@ public class SelfIntersectionUtil {
return tesselatedPolygons;
}
/*
* @ Baris Numanoglu
*
* New Version with tree query
* */
public static List<PolygonIntersection> calculateSolidSelfIntersectionWithTree(
Geometry g, double delta) {
List<TesselatedPolygon> tesselatedPolygons = tesselateAndFilter(g, delta);
List<Integer> indices = new ArrayList<>(tesselatedPolygons.size());
for (int i = 0; i < tesselatedPolygons.size(); i++) {
indices.add(i);
}
// Build BVH on polygons, but compute AABBs from the *original* polygons
BoundingVolumeHierarchyTree<Integer> tree =
new BoundingVolumeHierarchyTree<>(indices, index -> AABB.of(tesselatedPolygons.get(index).getOriginal()));
// Map: original ConcretePolygon (identity) -> index in tesselatedPolygons
// IdentityHashMap<ConcretePolygon, Integer> indexByOriginal = new IdentityHashMap<>();
// for (int i = 0; i < tesselatedPolygons.size(); i++) {
// Polygon p = tesselatedPolygons.get(i).getOriginal(); // returns Polygon
// ConcretePolygon orig = p.getOriginal(); // returns ConcretePolygon
// indexByOriginal.put(orig, i);
// }
List<PolygonIntersection> intersections = new ArrayList<>();
for (int i = 0; i < tesselatedPolygons.size() - 1; i++) {
TesselatedPolygon p1 = tesselatedPolygons.get(i);
// Query AABB based on original polygon (consistent with tree construction)
AABB q = AABB.of(p1.getOriginal());
List<Integer> candidates = tree.getAllOverlappingElements(q);
if (candidates.isEmpty()) {
continue; // no candidate ergo no overlap
}
for (Integer j : candidates) {
if (j <= i) {
// avoids double pairwise checks and self-pair
continue;
}
TesselatedPolygon p2 = tesselatedPolygons.get(j);
// TODO may be later a further tree in here
GeometrySelfIntersection inter = doPolygonsIntersect(p1, p2, delta);
if (inter != null) {
intersections.add(PolygonIntersection.triangles(inter.t1(), inter.t2()));
}
}
}
return intersections;
}
/*
* @ Baris Numanoglu
*
......@@ -150,7 +210,7 @@ public class SelfIntersectionUtil {
ConcretePolygon p1Orig = p1.getOriginal().getOriginal(); // p1:teselatedPoly->Polygon->Concrete Polygon
AABB q = AABB.of(p1Orig);
List<Polygon> candidates = tree.getAllIntersectingElements(q);
List<Polygon> candidates = tree.getAllOverlappingElements(q);
if (candidates.isEmpty()) {
continue; // no candidate ergo no overlap
}
......
......@@ -4,7 +4,7 @@ import static org.junit.Assert.*;
import java.util.List;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
......@@ -27,42 +27,48 @@ import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
* */
public class SolidSelfIntersectionOldVsNewTest {
@Test
public void testOldVsNewSameResultCount() throws CityGmlParseException, InvalidGmlFileException {
compareOnFile("src/test/resources/SolidSelfIntTest1.gml", 0.001);
}
@Test
public void testOldVsNewSameResultCount() throws CityGmlParseException, InvalidGmlFileException {
compareOnFile("src/test/resources/SolidSelfIntTest-known_false_positive_Big_Mesh2.gml", 0.001);
}
@Test
public void testOldVsNewSameResultCountFalsePositiveExample1() throws CityGmlParseException, InvalidGmlFileException {
compareOnFile("src/test/resources/SolidSelfIntTest-known_false_positive1.gml", 0.001);
}
// @Test
// public void testOldVsNewSameResultCountFalsePositiveExample1() throws CityGmlParseException, InvalidGmlFileException {
// compareOnFile("src/test/resources/SolidSelfIntTest-known_false_positive1.gml", 0.001);
// }
//
// @Test
// public void testOldVsNewSameResultCountFalsePositiveExample2() throws CityGmlParseException, InvalidGmlFileException {
// compareOnFile("src/test/resources/SolidSelfIntTest-known_false_positive2.gml", 0.001);
// }
@Test
public void testOldVsNewSameResultCountFalsePositiveExample2() throws CityGmlParseException, InvalidGmlFileException {
compareOnFile("src/test/resources/SolidSelfIntTest-known_false_positive2.gml", 0.001);
}
private void compareOnFile(String gmlPath, double delta) throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
private void compareOnFile(String gmlPath, double delta) throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
CityDoctorModel m = CityGmlParser.parseCityGmlFile(gmlPath, config.getParserConfiguration());
CityDoctorModel m = CityGmlParser.parseCityGmlFile(gmlPath, config.getParserConfiguration());
Building building = m.getBuildings().findFirst().orElseThrow();
Geometry g = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
assertNotNull("Expected SOLID LOD2 geometry in test model: " + gmlPath, g);
Building building = m.getBuildings().findFirst().orElseThrow();
Geometry g = building.getGeometry(GeometryType.SOLID, Lod.LOD2);
assertNotNull("Expected SOLID LOD2 geometry in test model: " + gmlPath, g);
List<Polygon> polys = g.getPolygons();
assertNotNull(polys);
assertTrue("Expected at least 2 polygons in: " + gmlPath, polys.size() > 1);
List<Polygon> polys = g.getPolygons();
assertNotNull(polys);
assertTrue("Expected at least 2 polygons in: " + gmlPath, polys.size() > 1);
long start = System.nanoTime();
List<PolygonIntersection> oldRes = SelfIntersectionUtil.calculateSolidSelfIntersection(g, delta);
long dif = System.nanoTime() - start;
System.out.println("Alt: " + dif);
BoundingVolumeHierarchyTree<Polygon> tree =
new BoundingVolumeHierarchyTree<>(polys, p -> AABB.of(p.getOriginal()));
start = System.nanoTime();
List<PolygonIntersection> newRes = SelfIntersectionUtil.calculateSolidSelfIntersectionWithTree(g, delta);
dif = System.nanoTime() - start;
System.out.println("Neu: " + dif);
List<PolygonIntersection> oldRes = SelfIntersectionUtil.calculateSolidSelfIntersection(g, delta);
List<PolygonIntersection> newRes = SelfIntersectionUtil.calculateSolidSelfIntersection(g, delta, tree);
assertFalse(oldRes.isEmpty());
assertFalse(newRes.isEmpty());
assertEquals("Old vs new self-intersection result count differs for: " + gmlPath,
oldRes.size(), newRes.size());
}
assertEquals("Old vs new self-intersection result count differs for: " + gmlPath, oldRes.size(), newRes.size());
}
}
\ No newline at end of file
Supports Markdown
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