Commit 54c56f2d authored by Numanoglu's avatar Numanoglu
Browse files

Test with a synthetic Building added

parent 7eb83cde
Pipeline #12392 failed with stage
in 1 minute and 28 seconds
package de.hft.stuttgart.citydoctor2.checks.util;
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.List;
import org.junit.jupiter.api.Test;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry.Orientation;
import de.hft.stuttgart.citydoctor2.datastructure.GeometryType;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.bht.AABB;
import de.hft.stuttgart.citydoctor2.datastructure.bht.BoundingVolumeHierarchyTree;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
public class SolidSelfIntersectionBuildingTest {
private static final double DELTA = 0.001;
private static final int MIN_EXPECTED_POLYGONS = 60;
@Test
public void testBvhBuildAndQueryOnLod2AndLod3() {
Building building = createDenseBuildingWithoutIntersections();
assertBvhBuildAndQuery(building.getGeometry(GeometryType.SOLID, Lod.LOD2), "LOD2");
assertBvhBuildAndQuery(building.getGeometry(GeometryType.SOLID, Lod.LOD3), "LOD3");
}
@Test
public void testOldVsNewSameResultCountOnIntersectingLod2AndLod3() {
Building building = createDenseBuildingWithIntersections();
assertOldVsNewComparison(building.getGeometry(GeometryType.SOLID, Lod.LOD2), "LOD2");
assertOldVsNewComparison(building.getGeometry(GeometryType.SOLID, Lod.LOD3), "LOD3");
}
private void assertBvhBuildAndQuery(Geometry geometry, String lodLabel) {
List<Polygon> polygons = requireValidGeometry(geometry, lodLabel);
BoundingVolumeHierarchyTree<Polygon> tree = new BoundingVolumeHierarchyTree<>(
polygons,
p -> AABB.of(p.getOriginal()),
BoundingVolumeHierarchyTree.BuildConfig.binaryDefault());
Polygon probe = polygons.get(0);
AABB probeAabb = AABB.of(probe.getOriginal());
assertNotNull("Probe AABB must not be null for " + lodLabel, probeAabb);
List<Polygon> candidates = tree.getAllIntersectingElements(probeAabb);
int nonEmptyQueries = 0;
int totalCandidates = 0;
int maxCandidates = 0;
for (Polygon polygon : polygons) {
AABB query = AABB.of(polygon.getOriginal());
assertNotNull("Query AABB must not be null for " + lodLabel, query);
List<Polygon> perPolygonCandidates = tree.getAllIntersectingElements(query);
if (!perPolygonCandidates.isEmpty()) {
nonEmptyQueries++;
}
int currentSize = perPolygonCandidates.size();
totalCandidates += currentSize;
if (currentSize > maxCandidates) {
maxCandidates = currentSize;
}
}
printBvhStats(
lodLabel,
polygons.size(),
candidates.size(),
nonEmptyQueries,
totalCandidates,
maxCandidates);
assertTrue(
"Expected at least one non-empty BVH query on " + lodLabel,
nonEmptyQueries > 0);
}
private void assertOldVsNewComparison(Geometry geometry, String lodLabel) {
List<Polygon> polygons = requireValidGeometry(geometry, lodLabel);
List<PolygonIntersection> oldRes = SelfIntersectionUtil.calculateSolidSelfIntersection0(geometry, DELTA);
assertNotNull("Old result list must not be null for " + lodLabel, oldRes);
BoundingVolumeHierarchyTree<Polygon> externalTree = new BoundingVolumeHierarchyTree<>(
polygons,
p -> AABB.of(p.getOriginal()),
BoundingVolumeHierarchyTree.BuildConfig.binaryDefault());
List<PolygonIntersection> oldTreeRes = SelfIntersectionUtil.calculateSolidSelfIntersection(
geometry,
DELTA,
externalTree);
assertNotNull("Old+tree result list must not be null for " + lodLabel, oldTreeRes);
List<PolygonIntersection> newRes = SelfIntersectionUtil.calculateSolidSelfIntersectionWithTree(geometry, DELTA);
assertNotNull("New result list must not be null for " + lodLabel, newRes);
printComparisonStats(lodLabel, polygons.size(), oldRes.size(), oldTreeRes.size(), newRes.size());
assertEquals("Old vs external-tree differs for " + lodLabel, oldRes.size(), oldTreeRes.size());
assertEquals("Old vs new-tree differs for " + lodLabel, oldRes.size(), newRes.size());
}
private List<Polygon> requireValidGeometry(Geometry geometry, String lodLabel) {
assertNotNull("Expected geometry for " + lodLabel, geometry);
List<Polygon> polygons = geometry.getPolygons();
assertNotNull("Polygon list must not be null for " + lodLabel, polygons);
assertFalse("Polygon list must not be empty for " + lodLabel, polygons.isEmpty());
assertTrue(
"Expected many polygons for " + lodLabel + " (got " + polygons.size() + ")",
polygons.size() >= MIN_EXPECTED_POLYGONS);
return polygons;
}
private void printBvhStats(
String lodLabel,
int polygonCount,
int probeCandidateCount,
int nonEmptyQueries,
int totalCandidates,
int maxCandidates) {
System.out.printf(
"[BVH][%s] polygons=%d, probeCandidates=%d, nonEmptyQueries=%d/%d, totalCandidates=%d, maxPerQuery=%d%n",
lodLabel,
polygonCount,
probeCandidateCount,
nonEmptyQueries,
polygonCount,
totalCandidates,
maxCandidates);
}
private void printComparisonStats(
String lodLabel,
int polygonCount,
int oldCount,
int oldTreeCount,
int newCount) {
System.out.printf(
"[SelfInt][%s] polygons=%d, old=%d, old+tree=%d, new=%d%n",
lodLabel,
polygonCount,
oldCount,
oldTreeCount,
newCount);
}
private Building createDenseBuildingWithoutIntersections() {
Building b = new Building();
b.addGeometry(createGridGeometry(Lod.LOD2, 4, 4, false));
b.addGeometry(createGridGeometry(Lod.LOD3, 6, 6, false));
return b;
}
private Building createDenseBuildingWithIntersections() {
Building b = new Building();
b.addGeometry(createGridGeometry(Lod.LOD2, 4, 4, true));
b.addGeometry(createGridGeometry(Lod.LOD3, 6, 6, true));
return b;
}
private Geometry createGridGeometry(Lod lod, int xCount, int yCount, boolean addIntersections) {
Geometry g = new Geometry(GeometryType.SOLID, lod, Orientation.OUTWARD);
double spacing = 6.0;
double width = 4.0;
double depth = 4.0;
double height = 4.0;
for (int ix = 0; ix < xCount; ix++) {
for (int iy = 0; iy < yCount; iy++) {
double x = ix * spacing;
double y = iy * spacing;
addBox(g, x, y, 0.0, width, depth, height);
}
}
// TODO Re-validate the Intersction-Idee
if (addIntersections) {
// Two additional boxes overlap each other and the grid neighborhood.
addBox(g, spacing * 1.2, spacing * 1.2, 0.5, 6.0, 2.8, 3.5);
addBox(g, spacing * 1.4, spacing * 1.0, 0.0, 2.8, 6.0, 4.2);
}
g.updateEdgesAndVertices();
return g;
}
///----------------------------------- add geometric sub-entities ---------------------------///
private void addBox(Geometry geometry, double x, double y, double z, double width, double depth, double height) {
Vertex v000 = new Vertex(x, y, z);
Vertex v100 = new Vertex(x + width, y, z);
Vertex v110 = new Vertex(x + width, y + depth, z);
Vertex v010 = new Vertex(x, y + depth, z);
Vertex v001 = new Vertex(x, y, z + height);
Vertex v101 = new Vertex(x + width, y, z + height);
Vertex v111 = new Vertex(x + width, y + depth, z + height);
Vertex v011 = new Vertex(x, y + depth, z + height);
addQuad(geometry, v000, v100, v110, v010); // bottom
addQuad(geometry, v001, v011, v111, v101); // top
addQuad(geometry, v000, v001, v101, v100); // front
addQuad(geometry, v100, v101, v111, v110); // right
addQuad(geometry, v110, v111, v011, v010); // back
addQuad(geometry, v010, v011, v001, v000); // left
}
private void addQuad(Geometry geometry, Vertex a, Vertex b, Vertex c, Vertex d) {
ConcretePolygon polygon = new ConcretePolygon();
LinearRing ring = new LinearRing(LinearRingType.EXTERIOR);
polygon.setExteriorRing(ring);
// ACHTUNG :Ensure polygon->geometry parent relation exists before adding vertices.
// LinearRing.addVertex() updates vertex adjacency via parent geometry.
geometry.addPolygon(polygon);
ring.addVertex(a);
ring.addVertex(b);
ring.addVertex(c);
ring.addVertex(d);
ring.addVertex(a);
}
}
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