Commit d3605f6a authored by Numanoglu's avatar Numanoglu
Browse files

remove metadata

parent e087346b
package de.hft.stuttgart.citydoctor2.healing.bht;
import de.hft.stuttgart.citydoctor2.datastructure.bht.*;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.parser.*;
import de.hft.stuttgart.citydoctor2.check.*;
import java.io.IOException;
import java.util.*;
import java.net.URL;
import java.nio.file.Paths;
public class TestCityGmlAABB {
public static void main(String[] args) throws CityGmlParseException, IOException, InvalidGmlFileException {
System.out.println("=== CityGML AABB Test ===");
// --- 1) Ask user which test case to run ---
Scanner sc = new Scanner(System.in);
System.out.print("Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+ "or press Enter for default: ");
String id = sc.nextLine().trim();
// Default wählen
String resourcePath = TestPaths.PO_TWO_INNERS;
if (!id.isEmpty()) {
try {
resourcePath = (String) TestPaths.class.getField(id).get(null);
} catch (ReflectiveOperationException ex) {
System.out.println("Unknown testcase: " + id + " (using default)");
}
}
String filePathForParser = resolveResourceOnClasspath(resourcePath);
System.out.println("Using file: " + filePathForParser);
// --- 2) Load CityGML model ---
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
// TODO: Study class model
CityDoctorModel model = de.hft.stuttgart.citydoctor2.healing.TestUtil.loadCityModel(filePathForParser, config);
System.out.println("Model loaded successfully.\n");
List<Building> buildings = model.getBuildings();
// --- 3) Menu: choose granularity ---
System.out.println("\nChoose granularity:");
System.out.println(" 1) Polygon-level (broad-phase)");
System.out.println(" 2) Ring-level (EXTERIOR)");
System.out.println(" 3) Ring-level (INTERIOR)");
System.out.println(" 4) Vertex-level (fine-phase)");
System.out.println(" 5) All of the above");
System.out.print("Your choice [1-5]: ");
int choice = readChoice(sc, 1, 5);
boolean doPolygon = (choice == 1 || choice == 5);
boolean doExtRing = (choice == 2 || choice == 5);
boolean doIntRing = (choice == 3 || choice == 5);
boolean doVertex = (choice == 4 || choice == 5);
// --- 4) Run the selected modes ---
if (doPolygon) runPolygonMode(buildings);
if (doExtRing) runRingMode(buildings, true);
if (doIntRing) runRingMode(buildings, false);
if (doVertex) runVertexMode(buildings);
System.out.println("\n=== Done ===");
}
// ---------- Modes ----------
private static void runPolygonMode(List<Building> buildings) {
System.out.println("\n> Polygon-level AABB (broad-phase)");
Set<ConcretePolygon> polys = collectAllPolygons(buildings);
AABBTree<ConcretePolygon> bvh = new AABBTree<>(
new ArrayList<>(polys),
AABBUtils::getAABB
);
System.out.println("Polygons: " + polys.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
private static void runRingMode(List<Building> buildings, boolean exterior) {
String label = exterior ? "EXTERIOR" : "INTERIOR";
System.out.println("\n> Ring-level AABB (" + label + ")");
Set<LinearRing> rings = exterior
? collectExteriorRings(buildings)
: collectInteriorRings(buildings);
AABBTree<LinearRing> bvh = new AABBTree<>(
new ArrayList<>(rings),
AABBUtils::computeAABBFromRing
);
System.out.println(label + " rings: " + rings.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
private static void runVertexMode(List<Building> buildings) {
System.out.println("\n> Vertex-level AABB (fine-phase)");
Set<Vertex> verts = collectAllVertices(buildings);
AABBTree<Vertex> bvh = new AABBTree<>(
new ArrayList<>(verts),
AABBUtils::computeAABBFromVertex
);
System.out.println("Vertices: " + verts.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
// ---------- Collectors ----------
/** Collects all ConcretePolygons (unique) via visitor. */
private static Set<ConcretePolygon> collectAllPolygons(List<Building> buildings) {
Set<ConcretePolygon> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
set.add(poly.getOriginal());
}
});
}
return set;
}
/** Collects all EXTERIOR rings (unique). */
private static Set<LinearRing> collectExteriorRings(List<Building> buildings) {
Set<LinearRing> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
LinearRing ext = poly.getOriginal().getExteriorRing();
if (ext != null) set.add(ext);
}
});
}
return set;
}
/** Collects all INTERIOR rings (unique). */
private static Set<LinearRing> collectInteriorRings(List<Building> buildings) {
Set<LinearRing> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
List<LinearRing> inner = poly.getOriginal().getInnerRings();
if (inner != null && !inner.isEmpty()) {
set.addAll(inner);
}
}
});
}
return set;
}
/** Collects all vertices (unique) from both exterior and interior rings. */
private static Set<Vertex> collectAllVertices(List<Building> buildings) {
Set<Vertex> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
ConcretePolygon cp = poly.getOriginal();
LinearRing ext = cp.getExteriorRing();
if (ext != null) set.addAll(ext.getVertices());
List<LinearRing> inner = cp.getInnerRings();
if (inner != null) {
for (LinearRing lr : inner) set.addAll(lr.getVertices());
}
}
});
}
return set;
}
// ---------- Utils ----------
/* Helper method reads choice of the user */
private static int readChoice(Scanner sc, int min, int max) {
while (true) {
String s = sc.nextLine().trim();
try {
int v = Integer.parseInt(s);
if (v >= min && v <= max) return v;
} catch (NumberFormatException ignored) {}
System.out.print("Please enter a number between " + min + " and " + max + ": ");
}
}
/* Helper method Pathfinder */
private static String resolveResourceOnClasspath(String resourcePath) {
String rp = normalizeResourcePath(resourcePath);
// 1) Klassenpfad via Class.getResource
URL url = TestCityGmlAABB.class.getResource(rp);
// 2) Klassenpfad via Context-ClassLoader:
if (url == null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String noSlash = rp.startsWith("/") ? rp.substring(1) : rp;
url = cl.getResource(noSlash);
}
// 3) Wenn gefunden: in Pfad umwandeln
if (url != null) {
try {
return Paths.get(url.toURI()).toString();
} catch (Exception e) {
throw new RuntimeException("Konnte Resource-URI nicht auflösen: " + url, e);
}
}
// 4) Fallbacks: Projekt-relative Kandidaten prüfen
String noSlash = rp.startsWith("/") ? rp.substring(1) : rp;
String[] candidates = {
"src/test/resources/" + noSlash,
"src/main/resources/" + noSlash,
resourcePath // falls bereits ein echter Dateipfad übergeben wurde
};
for (String cand : candidates) {
java.nio.file.Path p = java.nio.file.Paths.get(cand);
if (java.nio.file.Files.exists(p)) {
return p.toAbsolutePath().toString();
}
}
throw new IllegalArgumentException(
"Resource nicht im Klassenpfad gefunden: " + resourcePath + " (versucht als: " + rp + ")"
);
}
// FÜR ALLE FÄLLE zur Zeit REDUNDAD
private static String normalizeResourcePath(String path) {
String p = path.replace('\\', '/');
// Quellordner-Präfixe entfernen, falls mit übergeben
if (p.startsWith("src/test/resources/")) {
p = p.substring("src/test/resources/".length());
} else if (p.startsWith("src/main/resources/")) {
p = p.substring("src/main/resources/".length());
}
// Für Class.getResource: führenden Slash setzen
if (!p.startsWith("/")) p = "/" + p;
return p;
}
}
package de.hft.stuttgart.citydoctor2.checks.aabb;
import java.util.*;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
public class TestDummyAABB {
/**
* Entry point for AABB testing
*/
public static void main(String[] args) {
System.out.println("=== AABB TEST ===");
ConcretePolygon polygon = new ConcretePolygon();
LinearRing exterior = new LinearRing(LinearRingType.EXTERIOR);
exterior.addVertex(new Vertex(0, 0, 0));
exterior.addVertex(new Vertex(1, 0, 0));
exterior.addVertex(new Vertex(0, 1, 0));
exterior.addVertex(new Vertex(0, 0, 0));
polygon.setExteriorRing(exterior);
// Define points of a tetrahedron
Point p1 = new Point(0, 0, 0);
Point p2 = new Point(1, 0, 0);
Point p3 = new Point(0.5, 1, 0);
Point p4 = new Point(0.5, 0.5, 1);
// Define triangle faces of the tetrahedron
ConcretePolygon base = new ConcretePolygon();
LinearRing baseRing = new LinearRing(LinearRingType.EXTERIOR);
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
baseRing.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
baseRing.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
base.setExteriorRing(baseRing);
ConcretePolygon side1 = new ConcretePolygon();
LinearRing ring1 = new LinearRing(LinearRingType.EXTERIOR);
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring1.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring1.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
side1.setExteriorRing(ring1);
ConcretePolygon side2 = new ConcretePolygon();
LinearRing ring2 = new LinearRing(LinearRingType.EXTERIOR);
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring2.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring2.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
side2.setExteriorRing(ring2);
ConcretePolygon side3 = new ConcretePolygon();
LinearRing ring3 = new LinearRing(LinearRingType.EXTERIOR);
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring3.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring3.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
side3.setExteriorRing(ring3);
List<ConcretePolygon> poly = Arrays.asList(base, side1, side2, side3);
AABB aabb = BVHStructures.getAggregateAABB(poly);
System.out.println("\nComputed AABB:");
aabb.print();
/*** 3D-Point-coords with Test Properties ***/
// Inside laying Point
double testInsideX = 0.5;
double testInsideY = 0.5;
double testInsideZ = 0.3;
// Outside laying Point
double testOutsideX = 2.0;
double testOutsideY = 2.0;
double testOutsideZ = 2.0;
// On edge laying Point
double testOnEdgeX = 1.0;
double testOnEdgeY = 1.0;
double testOnEdgeZ = 0.0;
System.out.println("\nTest point (inside): " + testInsideX + " " + testInsideY + " " + testInsideZ);
System.out.println("-> contained?: " + aabb.encloses(testInsideX, testInsideY, testInsideZ));
System.out.println("\nTest point (outside): " + testOutsideX + " " + testOutsideY + " " + testOutsideZ);
System.out.println("-> contained?: " + aabb.encloses(testOutsideX, testOutsideY, testOutsideZ));
System.out.println("\nTest point (on edge): " + testOnEdgeX + " " + testOnEdgeY + " " + testOnEdgeZ);
System.out.println("-> contained?: " + aabb.encloses(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
}
}
package de.hft.stuttgart.citydoctor2.checks.bht;
//import de.hft.stuttgart.citydoctor2.checks.*;
import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.parser.*;
import de.hft.stuttgart.citydoctor2.check.*;
import java.io.IOException;
import java.util.*;
//src/test/java/.../TestCityGmlAABB.java
import java.net.URL;
import java.nio.file.Paths;
public class TestCityGmlAABB {
public static void main(String[] args) throws CityGmlParseException, IOException, InvalidGmlFileException {
System.out.println("=== CityGML AABB Test ===");
// --- 1) Ask user which test case to run ---
Scanner sc = new Scanner(System.in);
System.out.print("Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+ "or press Enter for default: ");
String id = sc.nextLine().trim();
// Default wählen
String resourcePath = TestPaths.PO_TWO_INNERS;
if (!id.isEmpty()) {
try {
// Holt TestPaths per Reflection
resourcePath = (String) TestPaths.class.getField(id).get(null);
} catch (ReflectiveOperationException ex) {
System.out.println("Unknown testcase: " + id + " (using default)");
}
}
String filePathForParser = resolveResourceOnClasspath(resourcePath);
System.out.println("Using file: " + filePathForParser);
// --- 2) Load CityGML model ---
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
// TODO: Study class model
CityDoctorModel model = de.hft.stuttgart.citydoctor2.healing.TestUtil.loadCityModel(filePathForParser, config);
System.out.println("Model loaded successfully.\n");
List<Building> buildings = model.getBuildings();
// --- 3) Menu: choose granularity ---
System.out.println("\nChoose granularity:");
System.out.println(" 1) Polygon-level (broad-phase)");
System.out.println(" 2) Ring-level (EXTERIOR)");
System.out.println(" 3) Ring-level (INTERIOR)");
System.out.println(" 4) Vertex-level (fine-phase)");
System.out.println(" 5) All of the above");
System.out.print("Your choice [1-5]: ");
int choice = readChoice(sc, 1, 5);
boolean doPolygon = (choice == 1 || choice == 5);
boolean doExtRing = (choice == 2 || choice == 5);
boolean doIntRing = (choice == 3 || choice == 5);
boolean doVertex = (choice == 4 || choice == 5);
// --- 4) Run the selected modes ---
if (doPolygon) runPolygonMode(buildings);
if (doExtRing) runRingMode(buildings, true);
if (doIntRing) runRingMode(buildings, false);
if (doVertex) runVertexMode(buildings);
System.out.println("\n=== Done ===");
}
// ---------- Modes ----------
private static void runPolygonMode(List<Building> buildings) {
System.out.println("\n> Polygon-level AABB (broad-phase)");
Set<ConcretePolygon> polys = collectAllPolygons(buildings);
AABBTree<ConcretePolygon> bvh = new AABBTree<>(
new ArrayList<>(polys),
AABBUtils::getAABB
);
System.out.println("Polygons: " + polys.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
private static void runRingMode(List<Building> buildings, boolean exterior) {
String label = exterior ? "EXTERIOR" : "INTERIOR";
System.out.println("\n> Ring-level AABB (" + label + ")");
Set<LinearRing> rings = exterior
? collectExteriorRings(buildings)
: collectInteriorRings(buildings);
AABBTree<LinearRing> bvh = new AABBTree<>(
new ArrayList<>(rings),
AABBUtils::computeAABBFromRing
);
System.out.println(label + " rings: " + rings.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
private static void runVertexMode(List<Building> buildings) {
System.out.println("\n> Vertex-level AABB (fine-phase)");
Set<Vertex> verts = collectAllVertices(buildings);
AABBTree<Vertex> bvh = new AABBTree<>(
new ArrayList<>(verts),
AABBUtils::computeAABBFromVertex
);
System.out.println("Vertices: " + verts.size());
if (bvh.getRoot() != null) {
System.out.print("Root AABB: ");
bvh.getRoot().aabb.print();
}
}
// ---------- Collectors ----------
/** Collects all ConcretePolygons (unique) via visitor. */
private static Set<ConcretePolygon> collectAllPolygons(List<Building> buildings) {
Set<ConcretePolygon> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
set.add(poly.getOriginal());
}
});
}
return set;
}
/** Collects all EXTERIOR rings (unique). */
private static Set<LinearRing> collectExteriorRings(List<Building> buildings) {
Set<LinearRing> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
LinearRing ext = poly.getOriginal().getExteriorRing();
if (ext != null) set.add(ext);
}
});
}
return set;
}
/** Collects all INTERIOR rings (unique). */
private static Set<LinearRing> collectInteriorRings(List<Building> buildings) {
Set<LinearRing> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
List<LinearRing> inner = poly.getOriginal().getInnerRings();
if (inner != null && !inner.isEmpty()) {
set.addAll(inner);
}
}
});
}
return set;
}
/** Collects all vertices (unique) from both exterior and interior rings. */
private static Set<Vertex> collectAllVertices(List<Building> buildings) {
Set<Vertex> set = new HashSet<>();
for (Building b : buildings) {
b.accept(new CheckableUtilsVisitor() {
@Override
public void check(Polygon poly) {
ConcretePolygon cp = poly.getOriginal();
LinearRing ext = cp.getExteriorRing();
if (ext != null) set.addAll(ext.getVertices());
List<LinearRing> inner = cp.getInnerRings();
if (inner != null) {
for (LinearRing lr : inner) set.addAll(lr.getVertices());
}
}
});
}
return set;
}
// ---------- Utils ----------
/* Helper method reads choice of the user */
private static int readChoice(Scanner sc, int min, int max) {
while (true) {
String s = sc.nextLine().trim();
try {
int v = Integer.parseInt(s);
if (v >= min && v <= max) return v;
} catch (NumberFormatException ignored) {}
System.out.print("Please enter a number between " + min + " and " + max + ": ");
}
}
/* Helper method Pathfinder */
private static String resolveResourceOnClasspath(String resourcePath) {
String rp = normalizeResourcePath(resourcePath);
// 1) Klassenpfad via Class.getResource
URL url = TestCityGmlAABB.class.getResource(rp);
// 2) Klassenpfad via Context-ClassLoader:
if (url == null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String noSlash = rp.startsWith("/") ? rp.substring(1) : rp;
url = cl.getResource(noSlash);
}
// 3) Wenn gefunden: in Pfad umwandeln
if (url != null) {
try {
return Paths.get(url.toURI()).toString();
} catch (Exception e) {
throw new RuntimeException("Konnte Resource-URI nicht auflösen: " + url, e);
}
}
// 4) Fallbacks: Projekt-relative Kandidaten prüfen
String noSlash = rp.startsWith("/") ? rp.substring(1) : rp;
String[] candidates = {
"src/test/resources/" + noSlash,
"src/main/resources/" + noSlash,
resourcePath // falls bereits ein echter Dateipfad übergeben wurde
};
for (String cand : candidates) {
java.nio.file.Path p = java.nio.file.Paths.get(cand);
if (java.nio.file.Files.exists(p)) {
return p.toAbsolutePath().toString();
}
}
throw new IllegalArgumentException(
"Resource nicht im Klassenpfad gefunden: " + resourcePath + " (versucht als: " + rp + ")"
);
}
// FÜR ALLE FÄLLE zur Zeit REDUNDAD
private static String normalizeResourcePath(String path) {
String p = path.replace('\\', '/');
// Quellordner-Präfixe entfernen, falls mit übergeben
if (p.startsWith("src/test/resources/")) {
p = p.substring("src/test/resources/".length());
} else if (p.startsWith("src/main/resources/")) {
p = p.substring("src/main/resources/".length());
}
// Für Class.getResource: führenden Slash setzen
if (!p.startsWith("/")) p = "/" + p;
return p;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.checks.bht;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
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.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError;
import de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
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.AABBUtils;
/**
* Checks whether a inner ring is completely contained in another inner ring
* within the same polygon
*
* @author Baris Numanoglu
*
*/
public class NestedRingsCheckAABB 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_NON_PLANAR);
deps.add(CheckId.C_GE_P_ORIENTATION_RINGS_SAME);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void check(Polygon p) {
List<LinearRing> inner = p.getInnerRings();
if (inner == null || inner.isEmpty()) {
p.addCheckResult(new CheckResult(this, ResultStatus.OK, null));
return;
}
// --- NEW: cache AABBs of inner rings for broad-phase ---
Map<LinearRing, AABB> ringBoxes = new HashMap<>(inner.size());
for (LinearRing r : inner) {
ringBoxes.put(r, AABBUtils.computeAABBFromRing(r));
}
for (LinearRing interiorRing : inner) {
AABB interiorBox = ringBoxes.get(interiorRing);
for (LinearRing checkRing : inner) {
if (checkRing == interiorRing) {
// do not compare with itself
continue;
}
// --- NEW: Broad-phase rejection ---
AABB checkBox = ringBoxes.get(checkRing);
// If the inner AABB is not fully inside the other ring's AABB,
// "nested" is impossible -> skip narrow phase.
if (!containsAabb(interiorBox, checkBox)) {
continue;
}
// are all points from checkRing inside interiorRing?
if (areAllPointsInside(interiorRing, checkRing)) {
// found all vertices inside another interior ring
CheckError err = new NestedRingError(p, interiorRing, checkRing);
CheckResult cr = new CheckResult(this, ResultStatus.ERROR, err);
p.addCheckResult(cr);
return;
}
}
}
CheckResult cr = new CheckResult(this, ResultStatus.OK, null);
p.addCheckResult(cr);
}
private boolean areAllPointsInside(LinearRing ring, LinearRing checkRing) {
boolean isInside = true;
for (Vertex v : checkRing.getVertices()) {
if (!ring.isPointInside(v)) {
isInside = false;
break;
}
}
return isInside;
}
@Override
public List<CheckId> getDependencies() {
return dependencies;
}
@Override
public Set<Requirement> appliesToRequirements() {
return CollectionUtils.singletonSet(Requirement.R_GE_P_INNER_RINGS_NESTED);
}
@Override
public RequirementType getType() {
return RequirementType.GEOMETRY;
}
@Override
public Check createNewInstance() {
return new NestedRingsCheckAABB();
}
@Override
public CheckId getCheckId() {
return CheckId.C_GE_P_INNER_RINGS_NESTED;
}
// TODO
/* ---------------- AABB helpers (broad-phase) ---------------- */
/** Returns true if 'outer' fully contains 'inner' (inclusive) in axis-aligned sense. */
private static boolean containsAabb(AABB outer, AABB inner) {
return outer.getMinX() <= inner.getMinX()
&& outer.getMinY() <= inner.getMinY()
&& outer.getMinZ() <= inner.getMinZ()
&& outer.getMaxX() >= inner.getMaxX()
&& outer.getMaxY() >= inner.getMaxY()
&& outer.getMaxZ() >= inner.getMaxZ();
}
}
package de.hft.stuttgart.citydoctor2.checks.bht;
import java.io.IOException;
//import java.io.InputStream; //new
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Scanner; //new
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.check.CheckableVisitor;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
import de.hft.stuttgart.citydoctor2.healing.TestUtil;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
public class TestExample {
// InputStream inStream = getClass().getClassLoader().getResourceAsStream("SimpleSolid_SrefBS.gml"); //new
// //if you want to load a src/test/resources file out of a different package
public static void main(String[] args) throws CityGmlParseException, IOException, InvalidGmlFileException {
System.out.println("Start TestExample... \n"); //new
// String path = args[0];
// String path = "src/test/resources/SimpleSolid_SrefBS.gml"; //new valid LoD2 model
// String path = "src/test/resources/TestBuilding1.gml"; //new block model
//new valid model with inner rings
String path = "src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml";
// too big, main gets terminated
// String path = "src/test/resources/bht/KreishausFeuerwache.gml";
// String path = "src/test/resources/bht/TestBuilding_SelfInt.gml";
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
CityDoctorModel model = TestUtil.loadCityModel(path, config);
System.out.println("\nModel has been loaded..."); //new
// visitor
// filter duplicate polygons out
Set<ConcretePolygon> allBuildingPolygons = new HashSet<>();
for (Building b : model.getBuildings()) {
b.accept(new CheckableUtilsVisitor() {
public void check(Polygon poly) {
allBuildingPolygons.add(poly.getOriginal());
}
});
}
System.out.println("\nPolygons via visitor:" + allBuildingPolygons); //new
// // for loop
List<Polygon> allBuildingPolygons2 = new ArrayList<>();
for (Building b : model.getBuildings()) {
for (Geometry geom : b.getGeometries()) {
for (Polygon p : geom.getPolygons()) {
allBuildingPolygons2.add(p);
allBuildingPolygons2.add(p.getOriginal()); //new
}
}
}
System.out.println("\nPolygon List:" + allBuildingPolygons2); //new
// new: LinearRings
// visitor
// filter duplicate linear rings out
Set<LinearRing> allBuildingLinearRings = new HashSet<>();
for (Building b : model.getBuildings()) {
b.accept(new CheckableUtilsVisitor() {
public void check(LinearRing ring) {
allBuildingLinearRings.add(ring);
}
});
}
System.out.println("\nLinearRings via visitor:" + allBuildingLinearRings); //new
// new: ExteriorRings
// visitor
// filter duplicate exterior rings out
Set<LinearRing> allBuildingExteriorRings = new HashSet<>();
for (Building b : model.getBuildings()) {
b.accept(new CheckableUtilsVisitor() {
public void check(LinearRing ring) {
allBuildingExteriorRings.add(ring.getParent().getExteriorRing()); // ACHTUNG getParent
}
});
}
System.out.println("\nExteriorRings via visitor:" + allBuildingExteriorRings); //new
// // new: ExteriorRings (List)
// // for loop
// List<LinearRing> allBuildingExteriorRings2 = new ArrayList<>();
// for (Building b : model.getBuildings()) {
// for (Geometry geom : b.getGeometries()) {
// for (Polygon p : geom.getPolygons()) {
// allBuildingExteriorRings2.add(p.getOriginal().getExteriorRing());
// }
// }
// }
// System.out.println("\nExteriorRing List:" + allBuildingExteriorRings2); //new
// new: InnerRings
// visitor
// filter duplicate inner rings out
Set<LinearRing> allBuildingInnerRings = new HashSet<>();
for (Building b : model.getBuildings()) {
b.accept(new CheckableUtilsVisitor() {
public void check(Polygon poly) {
allBuildingInnerRings.addAll(poly.getOriginal().getInnerRings());// ACHTUNG getOriginal
}
});
}
System.out.println("\nInnerRings via visitor:" + allBuildingInnerRings); //new
// // new: InnerRings (List)
// // for loop
// List<LinearRing> allBuildingInnerRings2 = new ArrayList<>();
// for (Building b : model.getBuildings()) {
// for (Geometry geom : b.getGeometries()) {
// for (Polygon p : geom.getPolygons()) {
// for (LinearRing lr : p.getInnerRings()) {
// allBuildingInnerRings2.add(lr);
// }
//
// }
// }
// }
// System.out.println("\nInnerRing List:" + allBuildingInnerRings2); //new
// // get Vertices for LinearRing, ExteriorRing and InteriorRing
// // new: LinearRingVertices
// // visitor
// // filter duplicate linear rings out
// Set<Vertex> allBuildingLinearRingVertices = new HashSet<>();
// for (Building b : model.getBuildings()) {
// b.accept(new CheckableUtilsVisitor() {
// public void check(LinearRing ring) {
// allBuildingLinearRingVertices.addAll(ring.getVertices());
// }
//
// });
// }
// System.out.println("\nLinearRingVertices via visitor:" + allBuildingLinearRingVertices); //new
// // new: ExteriorRingVertices
// // visitor
// // filter duplicate exterior rings out
// Set<Vertex> allBuildingExteriorRingVertices = new HashSet<>();
// for (Building b : model.getBuildings()) {
// b.accept(new CheckableUtilsVisitor() {
// public void check(LinearRing ring) {
// allBuildingExteriorRingVertices.addAll(ring.getParent().getOriginal().getExteriorRing().getVertices());
// }
//
// });
// }
// System.out.println("\nExteriorRingVertices via visitor:" + allBuildingExteriorRingVertices); //new
// // new: ExteriorRingVertices (List)
// // for loop
// List<Vertex> allBuildingExteriorRingVertices2 = new ArrayList<>();
// for (Building b : model.getBuildings()) {
// for (Geometry geom : b.getGeometries()) {
// for (Polygon p : geom.getPolygons()) {
// for (Vertex v : p.getOriginal().getExteriorRing().getVertices()) {
// allBuildingExteriorRingVertices2.add(v);
// }
// }
// }
// }
// System.out.println("\nExteriorRingVertices List:" + allBuildingExteriorRingVertices2); //new
// // new: InnerRingVertices
// // visitor
// // filter duplicate linear vertices out
// Set<Vertex> allBuildingInnerRingVertices = new HashSet<>();
// for (Building b : model.getBuildings()) {
// b.accept(new CheckableUtilsVisitor() {
// public void check(Polygon poly) {
// poly.getOriginal().getInnerRings().forEach(ring->allBuildingInnerRingVertices.addAll(ring.getVertices()));
// }
// });
// }
// System.out.println("\nInnerRingVertices via visitor:" + allBuildingInnerRingVertices); //new
// // new: InnerRingVertices (List)
// // for loop
// List<Vertex> allInnerRingVertices2 = new ArrayList<>();
// for (Building b : model.getBuildings()) {
// for (Geometry geom : b.getGeometries()) {
// for (Polygon p : geom.getPolygons()) {
// for (LinearRing lr : p.getInnerRings()) {
// for (Vertex v : lr.getVertices()) {
// allInnerRingVertices2.add(v);
// }
// }
//
// }
// }
// }
// System.out.println("\nInnerRingVertices List:" + allInnerRingVertices2); //new
// // TODO: HashMap to show Ring and gmlId
// Map<LinearRing, Set<Vertex>> test = new HashMap<>();
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
/**
* Represents a CityGML test model with metadata for easier handling in tests.
*/
public class TestModel {
/** A short unique ID (e.g. "PO_TWO_INNERS", "SO_NOT_WATERTIGHT"). */
private final String id;
/** Path to the GML file (classpath or relative path under src/test/resources). */
private final String resourcePath;
/** Human-readable description of the test case. */
private final String description;
/** Category of test (e.g. "PO" = polygon, "SO" = solid, "LR" = linear ring). */
private final String category;
/** Optional: Author or source of the model (if useful for tracing). */
private final String source;
/** Optional: Known type of geometry error (e.g. "ring not closed", "not watertight"). */
private final String errorType;
// --- Constructor ---
public TestModel(String id, String resourcePath, String description,
String category, String source, String errorType) {
this.id = id;
this.resourcePath = resourcePath;
this.description = description;
this.category = category;
this.source = source;
this.errorType = errorType;
}
// --- Getters ---
public String getId() { return id; }
public String getResourcePath() { return resourcePath; }
public String getDescription() { return description; }
public String getCategory() { return category; }
public String getSource() { return source; }
public String getErrorType() { return errorType; }
@Override
public String toString() {
return "[" + id + "] " + description + " (" + resourcePath + ")";
}
}
package de.hft.stuttgart.citydoctor2.healing.bht;
/**
* Central collection of CityGML test file paths used for AABB / healing experiments.
* Files are located under {@code src/test/resources} or {@code src/test/resources/bht/}
* ACHTUNG: mit '!!!' markierte Objekte haben einen falschen Pfad
*/
public final class TestPaths {
private TestPaths() {
// utility class
}
// ==================================================
// Schematron / Validation tests
// ==================================================
/** Not XSD valid, namespaces removed, for schematron experiments. */
public static final String SCHEMATRON =
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml";
// ==================================================
// LinearRing (LR) test cases
// ==================================================
/**1 LinearRing has only 2 points. */
public static final String LR_2POINTS =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml";
/**2 LinearRing has 3 points but is not closed. */
public static final String LR_NOTCLOSED =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml";
/**3 LinearRing has consecutive duplicate vertices. */
public static final String LR_DUPLICATE_CONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml";
/**4 LinearRing has non-consecutive duplicate vertices. */
public static final String LR_DUPLICATE_NONCONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml";
/**added 5 LinearRing points form a straight line. */
public static final String LR_LINE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml";
/**added 6 LinearRing has consecutive points closer than 0.1. */
public static final String LR_TOO_CLOSE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml";
/**added 7 LinearRing has too few points and duplicate points. */
public static final String LR_TOO_FEW_DUP =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml";
/**8 LinearRing is not closed. */
public static final String LR_NOTCLOSED_2 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml";
/**added 9 LinearRing is closed but with point distance < 0.1. */
public static final String LR_CLOSED_SMALLDIST =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml";
/**10 LinearRing has a loop. */
public static final String LR_LOOP =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml";
/** 11 LinearRing point touches edge with distance < 0.1. */
public static final String LR_TOUCH_EDGE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml";
// ==================================================
// Polygon (PO) test cases
// ==================================================
/**12 Inner ring intersects outer ring. */
public static final String PO_INTERSECT_OUTER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml";
/**13 Polygon has 2 inner rings. */
public static final String PO_TWO_INNERS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml";
/**14 Polygon has 2 intersecting inner rings. */
public static final String PO_INNER_INTERSECT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml";
/**15 Polygon has 2 inner rings; one vertex too far from the plane. */
public static final String PO_INNER_OFF_PLANE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml";
/**added 16 Polygon has normal deviation error. */
public static final String PO_NORMAL_ERROR =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml";
/**17 Polygon has disconnected interior surface. */
public static final String PO_DISCONNECTED_INTERIOR_1 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml";
/**added 18 Polygon has disconnected interior surface due to two inner rings. */
public static final String PO_DISCONNECTED_INTERIOR_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml";
/** added 19 Inner ring completely outside the outer ring. */
public static final String PO_INNER_OUTSIDE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml";
/**added 20 Inner ring completely inside another inner ring. */
public static final String PO_INNER_INSIDE_ANOTHER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml";
/**21 Two inner rings with wrong orientation. */
public static final String PO_TWO_INNERS_WRONG_ORIENT =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml";
// ==================================================
// Solid (SO) test cases
// ==================================================
/**added 22 Solid consists of only 3 polygons. */
public static final String SO_TOO_FEW_POLYGONS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml";
/**added 23 Shell is not watertight. */
public static final String SO_NOT_WATERTIGHT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml";
/** 24 Two buildings connected only by a single point. */
public static final String SO_CONNECTED_BY_POINT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml";
/**25 Roof point slightly deviates (e.g., 10.0 14.95 2.95 vs 10.0 15.0 3.0). */
public static final String SO_ROOF_COORD_DEVIATION_1 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml";
/**25 Missing polygon. */
public static final String SO_MISSING_POLYGON =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml";
/*
*
* komplex Data from NRW; whole Quartier
* */
/** 26added EXTRA Whole Church forum. */
public static final String CHURCH_FORUM =
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml";
/* LOST DATA
/** Slight coordinate deviations on multiple roof polygons (CityGML 2.0 only).
public static final String SO_ROOF_COORD_DEVIATION_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0003.gml";
*/
/**added 27 Solid geometry actually contains two buildings. */
public static final String SO_TWO_BUILDINGS_IN_ONE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml";
/** LOST! 33 All polygons have wrong orientation. */
public static final String SO_WRONG_POLY_ORIENTATION_ALL =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml";
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
public class Point {
private double x, y, z;
public Point() {
this(0.0, 0.0, 0.0);
}
public Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point other) {
this.x = other.getX();
this.y = other.getY();
this.z = other.getZ();
}
/* Operators */
public Point add(Point p) {
return new Point(this.x + p.x, this.y + p.y, this.z + p.z);
}
public Point subtract(Point p) {
return new Point(this.x - p.x, this.y - p.y, this.z - p.z);
}
public Point multiply(double a) {
return new Point(this.x * a, this.y * a, this.z * a);
}
public Point divide(double a) {
if (a == 0) throw new ArithmeticException("Zero Division while scaling the pos. vector of point !");
return new Point(this.x / a, this.y / a, this.z / a);
}
public boolean equals(Point p) {
return this.x == p.x && this.y == p.y && this.z == p.z;
}
public boolean notEquals(Point p) {
return !this.equals(p);
}
public boolean isSmallerThan(Point p) {
return this.x < p.x && this.y < p.y && this.z < p.z;
}
// Bounding Box of a Point
public AABB getAABB() {
// extractBoundsFromPoints(Point p1, Point p2)
//return new AABB(this, this);
return new AABB(this.x, this.y, this.z , this.x, this.y, this.z);
}
/*
* calculates the square of length of the line
* to avoid squarerooth-operation
* */
public double getLengthSquared() {
double tol = 1e-3;
double val = x * x + y * y + z * z;
return val < tol ? 0.0 : val;
}
/* Getter and Setter */
public double getComponent(int axis) {
return switch (axis) {
case 0 -> getX();
case 1 -> getY();
case 2 -> getZ();
default -> throw new IllegalArgumentException("Axis must be 0, 1, or 2.");
};
}
public double getX() { return x; }
public double getY() { return y; }
public double getZ() { return z; }
public void setX(double x) { this.x = x; }
public void setY(double y) { this.y = y; }
public void setZ(double z) { this.z = z; }
// Debug-Aid-Print
public void print() {
System.out.println("Point(" + x + ", " + y + ", " + z + ")");
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.*;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
public class Main {
/**
* Entry point for AABB testing
*/
public static void main(String[] args) {
System.out.println("=== AABB TEST ===");
ConcretePolygon polygon = new ConcretePolygon();
LinearRing exterior = new LinearRing(LinearRingType.EXTERIOR);
exterior.addVertex(new Vertex(0, 0, 0));
exterior.addVertex(new Vertex(1, 0, 0));
exterior.addVertex(new Vertex(0, 1, 0));
exterior.addVertex(new Vertex(0, 0, 0));
polygon.setExteriorRing(exterior);
// Define points of a tetrahedron
Point p1 = new Point(0, 0, 0);
Point p2 = new Point(1, 0, 0);
Point p3 = new Point(0.5, 1, 0);
Point p4 = new Point(0.5, 0.5, 1);
// Define triangle faces of the tetrahedron
ConcretePolygon base = new ConcretePolygon();
LinearRing baseRing = new LinearRing(LinearRingType.EXTERIOR);
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
baseRing.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
baseRing.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
base.setExteriorRing(baseRing);
ConcretePolygon side1 = new ConcretePolygon();
LinearRing ring1 = new LinearRing(LinearRingType.EXTERIOR);
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring1.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring1.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
side1.setExteriorRing(ring1);
ConcretePolygon side2 = new ConcretePolygon();
LinearRing ring2 = new LinearRing(LinearRingType.EXTERIOR);
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring2.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring2.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
side2.setExteriorRing(ring2);
ConcretePolygon side3 = new ConcretePolygon();
LinearRing ring3 = new LinearRing(LinearRingType.EXTERIOR);
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring3.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring3.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
side3.setExteriorRing(ring3);
List<ConcretePolygon> poly = Arrays.asList(base, side1, side2, side3);
AABB aabb = BVHStructures.getAggregateAABB(poly);
System.out.println("\nComputed AABB:");
aabb.print();
/*** 3D-Point-coords with Test Properties ***/
// Inside laying Point
double testInsideX = 0.5;
double testInsideY = 0.5;
double testInsideZ = 0.3;
// Outside laying Point
double testOutsideX = 2.0;
double testOutsideY = 2.0;
double testOutsideZ = 2.0;
// On edge laying Point
double testOnEdgeX = 1.0;
double testOnEdgeY = 1.0;
double testOnEdgeZ = 0.0;
System.out.println("\nTest point (inside): " + testInsideX + " " + testInsideY + " " + testInsideZ);
System.out.println("-> contained?: " + aabb.encloses(testInsideX, testInsideY, testInsideZ));
System.out.println("\nTest point (outside): " + testOutsideX + " " + testOutsideY + " " + testOutsideZ);
System.out.println("-> contained?: " + aabb.encloses(testOutsideX, testOutsideY, testOutsideZ));
System.out.println("\nTest point (on edge): " + testOnEdgeX + " " + testOnEdgeY + " " + testOnEdgeZ);
System.out.println("-> contained?: " + aabb.encloses(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
}
}
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.17.2</version>
</parent>
<properties>
<versionString>${project.version}-${git.commit.id.abbrev}</versionString>
</properties>
<artifactId>CityDoctorModel</artifactId>
<name>CityDoctorModel</name>
<dependencies>
<dependency>
<groupId>org.citygml4j</groupId>
<artifactId>citygml4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.citygml4j</groupId>
<artifactId>citygml4j-xml</artifactId>
</dependency>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>citygml4j-quality-ade</artifactId>
</dependency>
<dependency>
<groupId>gov.nist.math</groupId>
<artifactId>jama</artifactId>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-main</artifactId>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-main</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>org.locationtech.proj4j</groupId>
<artifactId>proj4j</artifactId>
</dependency>
<dependency>
<groupId>org.locationtech.proj4j</groupId>
<artifactId>proj4j-epsg</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.earcut4j</groupId>
<artifactId>earcut4j</artifactId>
</dependency>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorValidation</artifactId>
<version>3.17.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.9.10</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/../../.git</dotGitDirectory>
<prefix>git</prefix>
<verbose>false</verbose>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>
${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<gitDescribe>
<skip>false</skip>
<always>false</always>
</gitDescribe>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.*;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
public class TestAABB {
/**
* Entry point for AABB testing
*/
public static void main(String[] args) {
System.out.println("=== AABB TEST ===");
ConcretePolygon polygon = new ConcretePolygon();
LinearRing exterior = new LinearRing(LinearRingType.EXTERIOR);
exterior.addVertex(new Vertex(0, 0, 0));
exterior.addVertex(new Vertex(1, 0, 0));
exterior.addVertex(new Vertex(0, 1, 0));
exterior.addVertex(new Vertex(0, 0, 0));
polygon.setExteriorRing(exterior);
// Define points of a tetrahedron
Point p1 = new Point(0, 0, 0);
Point p2 = new Point(1, 0, 0);
Point p3 = new Point(0.5, 1, 0);
Point p4 = new Point(0.5, 0.5, 1);
// Define triangle faces of the tetrahedron
ConcretePolygon base = new ConcretePolygon();
LinearRing baseRing = new LinearRing(LinearRingType.EXTERIOR);
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
baseRing.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
baseRing.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
baseRing.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
base.setExteriorRing(baseRing);
ConcretePolygon side1 = new ConcretePolygon();
LinearRing ring1 = new LinearRing(LinearRingType.EXTERIOR);
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring1.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring1.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring1.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
side1.setExteriorRing(ring1);
ConcretePolygon side2 = new ConcretePolygon();
LinearRing ring2 = new LinearRing(LinearRingType.EXTERIOR);
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring2.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring2.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring2.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
side2.setExteriorRing(ring2);
ConcretePolygon side3 = new ConcretePolygon();
LinearRing ring3 = new LinearRing(LinearRingType.EXTERIOR);
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring3.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring3.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
side3.setExteriorRing(ring3);
List<ConcretePolygon> poly = Arrays.asList(base, side1, side2, side3);
AABB aabb = BVHStructures.getAggregateAABB(poly);
System.out.println("\nComputed AABB:");
aabb.print();
/*** 3D-Point-coords with Test Properties ***/
// Inside laying Point
double testInsideX = 0.5;
double testInsideY = 0.5;
double testInsideZ = 0.3;
// Outside laying Point
double testOutsideX = 2.0;
double testOutsideY = 2.0;
double testOutsideZ = 2.0;
// On edge laying Point
double testOnEdgeX = 1.0;
double testOnEdgeY = 1.0;
double testOnEdgeZ = 0.0;
System.out.println("\nTest point (inside): " + testInsideX + " " + testInsideY + " " + testInsideZ);
System.out.println("-> contained?: " + aabb.encloses(testInsideX, testInsideY, testInsideZ));
System.out.println("\nTest point (outside): " + testOutsideX + " " + testOutsideY + " " + testOutsideZ);
System.out.println("-> contained?: " + aabb.encloses(testOutsideX, testOutsideY, testOutsideZ));
System.out.println("\nTest point (on edge): " + testOnEdgeX + " " + testOnEdgeY + " " + testOnEdgeZ);
System.out.println("-> contained?: " + aabb.encloses(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
}
}
package de.hft.stuttgart.citydoctor2.healing.bht;
/**
* Central collection of CityGML test file paths used for AABB / healing experiments.
* Files are located under {@code src/test/resources} or {@code src/test/resources/bht/}
* ACHTUNG: mit '!!!' markierte Objekte haben einen falschen Pfad
*/
public final class TestPaths {
private TestPaths() {
// utility class
}
// ==================================================
// Schematron / Validation tests
// ==================================================
/**!!! Not XSD valid, namespaces removed, for schematron experiments. */
public static final String SCHEMATRON =
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml";
//CityDoctorParent
//"src/test/resources/bht/SimpleSolid_SrefBS-Schematron-Test.gml";
// ==================================================
// LinearRing (LR) test cases
// ==================================================
/**1 LinearRing has only 2 points. */
public static final String LR_2POINTS =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml";
/**2 LinearRing has 3 points but is not closed. */
public static final String LR_NOTCLOSED =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml";
/**3 LinearRing has consecutive duplicate vertices. */
public static final String LR_DUPLICATE_CONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml";
/**4 LinearRing has non-consecutive duplicate vertices. */
public static final String LR_DUPLICATE_NONCONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml";
/**added 5 LinearRing points form a straight line. */
public static final String LR_LINE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml";
/**added 6 LinearRing has consecutive points closer than 0.1. */
public static final String LR_TOO_CLOSE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml";
/**added 7 LinearRing has too few points and duplicate points. */
public static final String LR_TOO_FEW_DUP =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml";
/**8 LinearRing is not closed. */
public static final String LR_NOTCLOSED_2 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml";
/**added 9 LinearRing is closed but with point distance < 0.1. */
public static final String LR_CLOSED_SMALLDIST =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml";
/**10 LinearRing has a loop. */
public static final String LR_LOOP =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml";
/** 11 LinearRing point touches edge with distance < 0.1. */
public static final String LR_TOUCH_EDGE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml";
// ==================================================
// Polygon (PO) test cases
// ==================================================
/**12 Inner ring intersects outer ring. */
public static final String PO_INTERSECT_OUTER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml";
/**13 Polygon has 2 inner rings. */
public static final String PO_TWO_INNERS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml";
/**14 Polygon has 2 intersecting inner rings. */
public static final String PO_INNER_INTERSECT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml";
/**15 Polygon has 2 inner rings; one vertex too far from the plane. */
public static final String PO_INNER_OFF_PLANE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml";
/**added 16 Polygon has normal deviation error. */
public static final String PO_NORMAL_ERROR =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml";
/**17 Polygon has disconnected interior surface. */
public static final String PO_DISCONNECTED_INTERIOR_1 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml";
/**added 18 Polygon has disconnected interior surface due to two inner rings. */
public static final String PO_DISCONNECTED_INTERIOR_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml";
/** added 19 Inner ring completely outside the outer ring. */
public static final String PO_INNER_OUTSIDE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml";
/**added 20 Inner ring completely inside another inner ring. */
public static final String PO_INNER_INSIDE_ANOTHER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml";
/**21 Two inner rings with wrong orientation. */
public static final String PO_TWO_INNERS_WRONG_ORIENT =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml";
// ==================================================
// Solid (SO) test cases
// ==================================================
/**added 22 Solid consists of only 3 polygons. */
public static final String SO_TOO_FEW_POLYGONS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml";
/**added 23 Shell is not watertight. */
public static final String SO_NOT_WATERTIGHT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml";
/** 24 Two buildings connected only by a single point. */
public static final String SO_CONNECTED_BY_POINT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml";
/**25 Roof point slightly deviates (e.g., 10.0 14.95 2.95 vs 10.0 15.0 3.0). */
public static final String SO_ROOF_COORD_DEVIATION_1 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml";
/**25 Missing polygon. */
public static final String SO_MISSING_POLYGON =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml";
/*
*
* komplex Data from NRW; whole Quartier
* */
/** 26added EXTRA Whole Church forum. */
public static final String CHURCH_FORUM =
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml";
/* LOST DATA
/** Slight coordinate deviations on multiple roof polygons (CityGML 2.0 only).
public static final String SO_ROOF_COORD_DEVIATION_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0003.gml";
*/
/**added 27 Solid geometry actually contains two buildings. */
public static final String SO_TWO_BUILDINGS_IN_ONE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml";
//
// Falsches Datei !!!!
/**!!! 28 Self-intersecting geometry. */
public static final String SO_SELF_INTERSECTING =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml";
// ACHTUNG FALSCHES LABEL
/**29 Polygon with wrong orientation. */
public static final String ENTER_LABEL1 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0001.gml";
/**30 Polygon with wrong orientation. ACHTUNG FALSCHES LABEL */
public static final String ENTER_LABEL2 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0002.gml";
/**31 Polygon with wrong orientation. ACHTUNG FALSCHES LABEL */
public static final String ENTER_LABEL3 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0003.gml";
//
/** LOST! 33 All polygons have wrong orientation. */
public static final String SO_WRONG_POLY_ORIENTATION_ALL =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml";
}
package de.hft.stuttgart.citydoctor2.healing.bht;
/**
* Central collection of CityGML test file paths used for AABB / healing experiments.
* Files are located under {@code src/test/resources} or {@code src/test/resources/bht/}
*
* Some Test Cases are missing
* To be completed with more complex models from NRW
*
* */
public final class TestPaths {
private TestPaths() {
// utility class
}
// ==================================================
// Schematron / Validation tests
// ==================================================
/** Not XSD valid, namespaces removed, for schematron experiments. */
public static final String SCHEMATRON =
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml";
// ==================================================
// LinearRing (LR) test cases
// ==================================================
/**1 LinearRing has only 2 points. */
public static final String LR_2POINTS =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml";
/**2 LinearRing has 3 points but is not closed. */
public static final String LR_NOTCLOSED =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml";
/**3 LinearRing has consecutive duplicate vertices. */
public static final String LR_DUPLICATE_CONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml";
/**4 LinearRing has non-consecutive duplicate vertices. */
public static final String LR_DUPLICATE_NONCONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml";
/** 5 LinearRing points form a straight line. */
public static final String LR_LINE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml";
/** 6 LinearRing has consecutive points closer than 0.1. */
public static final String LR_TOO_CLOSE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml";
/** 7 LinearRing has too few points and duplicate points. */
public static final String LR_TOO_FEW_DUP =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml";
/**8 LinearRing is not closed. */
public static final String LR_NOTCLOSED_2 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml";
/** 9 LinearRing is closed but with point distance < 0.1. */
public static final String LR_CLOSED_SMALLDIST =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml";
/**10 LinearRing has a loop. */
public static final String LR_LOOP =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml";
/** 11 LinearRing point touches edge with distance < 0.1. */
public static final String LR_TOUCH_EDGE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml";
// ==================================================
// Polygon (PO) test cases
// ==================================================
/**12 Inner ring intersects outer ring. */
public static final String PO_INTERSECT_OUTER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml";
/**13 Polygon has 2 inner rings. */
public static final String PO_TWO_INNERS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml";
/**14 Polygon has 2 intersecting inner rings. */
public static final String PO_INNER_INTERSECT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml";
/**15 Polygon has 2 inner rings; one vertex too far from the plane. */
public static final String PO_INNER_OFF_PLANE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml";
/**added 16 Polygon has normal deviation error. */
public static final String PO_NORMAL_ERROR =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml";
/**17 Polygon has disconnected interior surface. */
public static final String PO_DISCONNECTED_INTERIOR_1 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml";
/**added 18 Polygon has disconnected interior surface due to two inner rings. */
public static final String PO_DISCONNECTED_INTERIOR_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml";
/** added 19 Inner ring completely outside the outer ring. */
public static final String PO_INNER_OUTSIDE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml";
/**added 20 Inner ring completely inside another inner ring. */
public static final String PO_INNER_INSIDE_ANOTHER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml";
/**21 Two inner rings with wrong orientation. */
public static final String PO_TWO_INNERS_WRONG_ORIENT =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml";
// ==================================================
// Solid (SO) test cases
// ==================================================
/**added 22 Solid consists of only 3 polygons. */
public static final String SO_TOO_FEW_POLYGONS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml";
/**added 23 Shell is not watertight. */
public static final String SO_NOT_WATERTIGHT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml";
/** 24 Two buildings connected only by a single point. */
public static final String SO_CONNECTED_BY_POINT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml";
/**25 Roof point slightly deviates (e.g., 10.0 14.95 2.95 vs 10.0 15.0 3.0). */
public static final String SO_ROOF_COORD_DEVIATION_1 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml";
/**25 Missing polygon. */
public static final String SO_MISSING_POLYGON =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml";
/*
* komplex Data from NRW; whole Quartier
*/
/** 26 added EXTRA Whole Church forum. */
public static final String CHURCH_FORUM =
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml";
/**added 27 Solid geometry actually contains two buildings. */
public static final String SO_TWO_BUILDINGS_IN_ONE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml";
// TODO Aprove the label
/** All polygons have wrong orientation. */
public static final String SO_WRONG_POLY_ORIENTATION_ALL =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml";
}
package de.hft.stuttgart.citydoctor2.checks.bht;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyBoolean;
import java.io.IOException;
//import java.io.InputStream; //new
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Scanner; //new
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.check.CheckableVisitor;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidSelfIntCheck;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
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.datastructure.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
//import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat;
//import de.hft.stuttgart.citydoctor2.gui.tree.ErrorItemVisitor;
//import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
//import de.hft.stuttgart.citydoctor2.gui.tree.node.ErrorNode;
import de.hft.stuttgart.citydoctor2.healing.TestUtil;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator;
import de.hft.stuttgart.citydoctor2.utils.visitors.CheckableErrorCollector;
import javafx.scene.control.TreeItem;
public class TestExampleAABB {
public static void main(String[] args) throws CityGmlParseException, IOException, InvalidGmlFileException {
System.out.println("Start TestExampleAABB..."); //new
// String path = args[0];
// String path = "src/test/resources/TestBuilding1.gml"; //new block model
String path = "src/test/resources/bht/TestBuilding_SelfInt.gml"; //not just SelfInt errors
// String path = "src/test/resources/bht/SolidSelfIntTest1.gml"; //valid model
// String path = "src/test/resources/bht/DorstenGartenstrasse_SelfInt.gml"; //SelfInt and NotClosed errors
////Info: if test model doesn't include the desired error, use:
//// addCheckResult(new CheckResult(CheckId.C_GE_S_SELF_INTERSECTION), ResultStatus.ERROR, Mockito.mock(CheckError.class)) hinzufügen
System.out.println("\nModel has been loaded...\n"); //new
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
// CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/bht/SolidSelfIntTest1.gml", config.getParserConfiguration());
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building building = model.getBuildings().get(0);
// assertFalse(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertEquals(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertNotNull(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// System.out.println("\n" + building + " contains " + CheckId.C_GE_S_SELF_INTERSECTION); //new
List<CheckError> errors = new ArrayList<>();
building.collectContainedErrors(errors);
//features of errors containing CheckId.C_GE_R_SELF_INTERSECTION
// errors.get(0).getFeature().containsError(CheckId.C_GE_R_SELF_INTERSECTION);
// System.out.println("\n" + building + " contains the Errors " + errors ); //shows list of unknown check errors
//Check for Unknown Errors
// List<CheckError> AllErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.UNKNOWN_ERROR)).collect(Collectors.toList()); // returns UnknownCheckError
// System.out.println("\n" + building + " contains the Errors " + AllErrors ); //shows list of unknown check errors
//Check for Solid SelfIntersection
// List<CheckError> selfIntSolidErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_S_SELF_INTERSECTION)).collect(Collectors.toList());
// System.out.println("\n" + building + " contains the Solid Errors " + selfIntSolidErrors ); //shows list of solid selfInt
//Check for Ring SelfIntersection
List<CheckError> selfIntRingErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_R_SELF_INTERSECTION)).collect(Collectors.toList());
System.out.println("\n" + building + " contains the Ring Errors " + selfIntRingErrors ); //shows list of ring selfInt
//Get Vertices and BoundingBox of LinearRing(s) with SelfIntErrors
for (CheckError error : errors) {
if (error instanceof PointTouchesEdgeError err1) {
System.out.println("\nVertices of PointTouchesEdgeError: " + err1.getRing().getVertices());
BoundingBox bbox1 = BoundingBox.ofPoints(err1.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox1.getBox()));
}
if (error instanceof RingEdgeIntersectionError err2) {
System.out.println("\nVertices of RingEdgeIntersectionError: " + err2.getRing().getVertices());
BoundingBox bbox2 = BoundingBox.ofPoints(err2.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox2.getBox()));
}
if (error instanceof RingDuplicatePointError err3) {
System.out.println("\nVertices of RingDuplicatePointError: " + err3.getRing().getVertices());
BoundingBox bbox3 = BoundingBox.ofPoints(err3.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox3.getBox()));
}
if (error instanceof DegeneratedRingError err4) {
System.out.println("\nVertices of DegeneratedRingError: " + err4.getRing().getVertices());
BoundingBox bbox4 = BoundingBox.ofPoints(err4.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox4.getBox()));
}
}
// //Get BoundingBoxes out of Vertices
// // Test: edge from vertex v1 to vertex v2
// List<Vector3d> v3d = new ArrayList<>();
// Vector3d v1 = new Vector3d(375755.655, 5718919.166, 72.052);
// Vector3d v2 = new Vector3d(375755.655, 5718919.166, 67.772);
// v3d.add(v1);
// v3d.add(v2);
// System.out.println("\nVector Array: " + v3d);
// BoundingBox vbox = BoundingBox.ofPoints(v3d);
// System.out.println("\nBounding Box: " + Arrays.toString(vbox.getBox()));
//
// BoundingBox box = BoundingBox.of(new Vector3d[]{new Vector3d(375755.655, 5718919.166, 72.052), new Vector3d(375755.655, 5718919.166, 67.772)});
// System.out.println("\nBounding Box: " + Arrays.toString(box.getBox()));
//Other available informations for BoundingBox
// System.out.println("\nCenter of Bounding Box: " + box.getCenter());
// System.out.println("\nDiagonal of Bounding Box: " + box.getDiagonal());
// System.out.println("\nVolume of Bounding Box: " + box.getVolume());
// System.out.println("\nHeight of Bounding Box: " + box.getHeight());
// System.out.println("\nWidth of Bounding Box: " + box.getWidth());
}
}
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.checks.bht;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyBoolean;
import java.io.IOException;
//import java.io.InputStream; //new
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Scanner; //new
import org.junit.Test;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.check.CheckableVisitor;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.check.Check;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.checks.geometry.SolidSelfIntCheck;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
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.datastructure.GmlElement;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Lod;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.exceptions.CityDoctorWriteException;
//import de.hft.stuttgart.citydoctor2.gui.table.ErrorStat;
//import de.hft.stuttgart.citydoctor2.gui.tree.ErrorItemVisitor;
//import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
//import de.hft.stuttgart.citydoctor2.gui.tree.node.ErrorNode;
import de.hft.stuttgart.citydoctor2.healing.TestUtil;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.utils.BoundingBoxCalculator;
import de.hft.stuttgart.citydoctor2.utils.visitors.CheckableErrorCollector;
import javafx.scene.control.TreeItem;
public class TestExampleAABB {
public static void main(String[] args) throws CityGmlParseException, IOException, InvalidGmlFileException {
System.out.println("Start TestExampleAABB..."); //new
// String path = args[0];
// String path = "src/test/resources/TestBuilding1.gml"; //new block model
String path = "src/test/resources/bht/TestBuilding_SelfInt.gml"; //not just SelfInt errors
// String path = "src/test/resources/bht/SolidSelfIntTest1.gml"; //valid model
// String path = "src/test/resources/bht/DorstenGartenstrasse_SelfInt.gml"; //SelfInt and NotClosed errors
////Info: if test model doesn't include the desired error, use:
//// addCheckResult(new CheckResult(CheckId.C_GE_S_SELF_INTERSECTION), ResultStatus.ERROR, Mockito.mock(CheckError.class)) hinzufügen
System.out.println("\nModel has been loaded...\n"); //new
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
// CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/bht/SolidSelfIntTest1.gml", config.getParserConfiguration());
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building building = model.getBuildings().get(0);
// assertFalse(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertEquals(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertNotNull(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// System.out.println("\n" + building + " contains " + CheckId.C_GE_S_SELF_INTERSECTION); //new
List<CheckError> errors = new ArrayList<>();
building.collectContainedErrors(errors);
//features of errors containing CheckId.C_GE_R_SELF_INTERSECTION
// errors.get(0).getFeature().containsError(CheckId.C_GE_R_SELF_INTERSECTION);
// System.out.println("\n" + building + " contains the Errors " + errors ); //shows list of unknown check errors
//Check for Unknown Errors
// List<CheckError> AllErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.UNKNOWN_ERROR)).collect(Collectors.toList()); // returns UnknownCheckError
// System.out.println("\n" + building + " contains the Errors " + AllErrors ); //shows list of unknown check errors
//Check for Solid SelfIntersection
// List<CheckError> selfIntSolidErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_S_SELF_INTERSECTION)).collect(Collectors.toList());
// System.out.println("\n" + building + " contains the Solid Errors " + selfIntSolidErrors ); //shows list of solid selfInt
//Check for Ring SelfIntersection
List<CheckError> selfIntRingErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_R_SELF_INTERSECTION)).collect(Collectors.toList());
System.out.println("\n" + building + " contains the Ring Errors " + selfIntRingErrors ); //shows list of ring selfInt
//Get Vertices and BoundingBox of LinearRing(s) with SelfIntErrors
for (CheckError error : errors) {
if (error instanceof PointTouchesEdgeError err1) {
System.out.println("\nVertices of PointTouchesEdgeError: " + err1.getRing().getVertices());
BoundingBox bbox1 = BoundingBox.ofPoints(err1.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox1.getBox()));
}
if (error instanceof RingEdgeIntersectionError err2) {
System.out.println("\nVertices of RingEdgeIntersectionError: " + err2.getRing().getVertices());
BoundingBox bbox2 = BoundingBox.ofPoints(err2.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox2.getBox()));
}
if (error instanceof RingDuplicatePointError err3) {
System.out.println("\nVertices of RingDuplicatePointError: " + err3.getRing().getVertices());
BoundingBox bbox3 = BoundingBox.ofPoints(err3.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox3.getBox()));
}
if (error instanceof DegeneratedRingError err4) {
System.out.println("\nVertices of DegeneratedRingError: " + err4.getRing().getVertices());
BoundingBox bbox4 = BoundingBox.ofPoints(err4.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox4.getBox()));
}
}
// //Get BoundingBoxes out of Vertices
// // Test: edge from vertex v1 to vertex v2
// List<Vector3d> v3d = new ArrayList<>();
// Vector3d v1 = new Vector3d(375755.655, 5718919.166, 72.052);
// Vector3d v2 = new Vector3d(375755.655, 5718919.166, 67.772);
// v3d.add(v1);
// v3d.add(v2);
// System.out.println("\nVector Array: " + v3d);
// BoundingBox vbox = BoundingBox.ofPoints(v3d);
// System.out.println("\nBounding Box: " + Arrays.toString(vbox.getBox()));
//
// BoundingBox box = BoundingBox.of(new Vector3d[]{new Vector3d(375755.655, 5718919.166, 72.052), new Vector3d(375755.655, 5718919.166, 67.772)});
// System.out.println("\nBounding Box: " + Arrays.toString(box.getBox()));
//Other available informations for BoundingBox
// System.out.println("\nCenter of Bounding Box: " + box.getCenter());
// System.out.println("\nDiagonal of Bounding Box: " + box.getDiagonal());
// System.out.println("\nVolume of Bounding Box: " + box.getVolume());
// System.out.println("\nHeight of Bounding Box: " + box.getHeight());
// System.out.println("\nWidth of Bounding Box: " + box.getWidth());
}
}
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.io.PrintStream;
// TODO: Change Point-Init semantics to Double-Init
/**
* Represents a 3D line segment defined by a start and end point.
* Useful for geometric computations like intersection tests,
* ray casting, or clipping against bounding volumes such as AABBs.
*/
public class Line {
private Point start;
private Point end;
public Line() {
this.start = new Point();
this.end = new Point();
}
public Line(Point start, Point end) {
this.start = start;
this.end = end;
}
public Point getStart() {
return start;
}
public Point getEnd() {
return end;
}
// Calculates Bounding Box for this Line
public AABB getAABB() {
// return new AABB(start, end)
return new AABB(start.getX(),start.getY(),start.getZ(), end.getX(), end.getY(), end.getZ());
}
/*
* calculates the square of length of the line
* to avoid squarerooth-operation
* */
public double getLengthSquared() {
double dx = end.getX() - start.getX();
double dy = end.getY() - start.getY();
double dz = end.getZ() - start.getZ();
return dx * dx + dy * dy + dz * dz;
}
// Direction vector
public Point getDir() {
return new Point(
end.getX() - start.getX(),
end.getY() - start.getY(),
end.getZ() - start.getZ()
);
}
// Normal vector
public Point getNormDir() {
double length = Math.sqrt(getLengthSquared());
if (length == 0) {
return new Point(0, 0, 0);
}
return new Point(
(end.getX() - start.getX()) / length,
(end.getY() - start.getY()) / length,
(end.getZ() - start.getZ()) / length
);
}
public void print() {
System.out.println("Line from " + start + " to " + end);
}
// writes Line as Inventor-Data
public boolean writeToInventor(PrintStream s) {
s.println("Separator {");
s.println("Material { diffuseColor 1 0 0 }"); // RGB:1 0 0 ->red
s.println("Coordinate3 {");
s.println("point [");
s.printf("%.3f %.3f %.3f,%n", start.getX(), start.getY(), start.getZ());
s.printf("%.3f %.3f %.3f%n", end.getX(), end.getY(), end.getZ());
s.println("]");
s.println("}");
s.println("IndexedLineSet { coordIndex [ 0, 1, -1 ] }");
s.println("}");
return true;
}
}
package de.hft.stuttgart.citydoctor2.healing.bht;
/**
* Central collection of CityGML test file paths used for AABB / healing experiments.
* Files are located under {@code src/test/resources} or {@code src/test/resources/bht/}
*
* Some Test Cases are missing
* To be completed with more complex models from NRW
*
* */
public final class TestPaths {
private TestPaths() {
// utility class
}
// ==================================================
// Schematron / Validation tests
// ==================================================
/** Not XSD valid, namespaces removed, for schematron experiments. */
public static final String SCHEMATRON =
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml";
// ==================================================
// LinearRing (LR) test cases
// ==================================================
/**1 LinearRing has only 2 points. */
public static final String LR_2POINTS =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml";
/**2 LinearRing has 3 points but is not closed. */
public static final String LR_NOTCLOSED =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml";
/**3 LinearRing has consecutive duplicate vertices. */
public static final String LR_DUPLICATE_CONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml";
/**4 LinearRing has non-consecutive duplicate vertices. */
public static final String LR_DUPLICATE_NONCONSEC =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml";
/** 5 LinearRing points form a straight line. */
public static final String LR_LINE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml";
/** 6 LinearRing has consecutive points closer than 0.1. */
public static final String LR_TOO_CLOSE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml";
/** 7 LinearRing has too few points and duplicate points. */
public static final String LR_TOO_FEW_DUP =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml";
/**8 LinearRing is not closed. */
public static final String LR_NOTCLOSED_2 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml";
/** 9 LinearRing is closed but with point distance < 0.1. */
public static final String LR_CLOSED_SMALLDIST =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml";
/**10 LinearRing has a loop. */
public static final String LR_LOOP =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml";
/** 11 LinearRing point touches edge with distance < 0.1. */
public static final String LR_TOUCH_EDGE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml";
// ==================================================
// Polygon (PO) test cases
// ==================================================
/**12 Inner ring intersects outer ring. */
public static final String PO_INTERSECT_OUTER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml";
/**13 Polygon has 2 inner rings. */
public static final String PO_TWO_INNERS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml";
/**14 Polygon has 2 intersecting inner rings. */
public static final String PO_INNER_INTERSECT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml";
/**15 Polygon has 2 inner rings; one vertex too far from the plane. */
public static final String PO_INNER_OFF_PLANE =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml";
/**added 16 Polygon has normal deviation error. */
public static final String PO_NORMAL_ERROR =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml";
/**17 Polygon has disconnected interior surface. */
public static final String PO_DISCONNECTED_INTERIOR_1 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml";
/**added 18 Polygon has disconnected interior surface due to two inner rings. */
public static final String PO_DISCONNECTED_INTERIOR_2 =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml";
/** added 19 Inner ring completely outside the outer ring. */
public static final String PO_INNER_OUTSIDE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml";
/**added 20 Inner ring completely inside another inner ring. */
public static final String PO_INNER_INSIDE_ANOTHER =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml";
/**21 Two inner rings with wrong orientation. */
public static final String PO_TWO_INNERS_WRONG_ORIENT =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml";
// ==================================================
// Solid (SO) test cases
// ==================================================
/**added 22 Solid consists of only 3 polygons. */
public static final String SO_TOO_FEW_POLYGONS =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml";
/**added 23 Shell is not watertight. */
public static final String SO_NOT_WATERTIGHT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml";
/** 24 Two buildings connected only by a single point. */
public static final String SO_CONNECTED_BY_POINT =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml";
/**25 Roof point slightly deviates (e.g., 10.0 14.95 2.95 vs 10.0 15.0 3.0). */
public static final String SO_ROOF_COORD_DEVIATION_1 =
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml";
/**25 Missing polygon. */
public static final String SO_MISSING_POLYGON =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml";
/*
*
* komplex Data from NRW; whole Quartier
* */
/** 26added EXTRA Whole Church forum. */
public static final String CHURCH_FORUM =
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml";
/**added 27 Solid geometry actually contains two buildings. */
public static final String SO_TWO_BUILDINGS_IN_ONE =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml";
// TODO Aprove the label
/** All polygons have wrong orientation. */
public static final String SO_WRONG_POLY_ORIENTATION_ALL =
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml";
}
package de.hft.stuttgart.citydoctor2.healer.aabb.bht;
import java.util.*;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
public class test_house {
private static ConcretePolygon createTrianglePolygon(Point p1, Point p2, Point p3) {
ConcretePolygon poly = new ConcretePolygon();
LinearRing ring = new LinearRing(LinearRingType.EXTERIOR);
ring.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ())); // Ring schließen
poly.setExteriorRing(ring);
return poly;
}
private static ConcretePolygon createQuadPolygon(Point p1, Point p2, Point p3, Point p4) {
ConcretePolygon poly = new ConcretePolygon();
LinearRing ring = new LinearRing(LinearRingType.EXTERIOR);
ring.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ()));
ring.addVertex(new Vertex(p2.getX(), p2.getY(), p2.getZ()));
ring.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
ring.addVertex(new Vertex(p4.getX(), p4.getY(), p4.getZ()));
ring.addVertex(new Vertex(p1.getX(), p1.getY(), p1.getZ())); // Ring schließen
poly.setExteriorRing(ring);
return poly;
}
}
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