Commit 7f3fa92f authored by Matthias Betz's avatar Matthias Betz
Browse files

changes for better integration

parent c67a5961
Pipeline #12320 failed with stage
in 1 minute and 32 seconds
......@@ -2,106 +2,307 @@ package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
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.math.Vector3d;
/**
* Represents an Axis-Aligned Bounding Box (AABB) using six double values.
*/
public class AABB {
private double minX, minY, minZ;
private double maxX, maxY, maxZ;
/**
* Default constructor initializing to a zero-sized box at origin.
*/
/**
* Constructs an AABB from explicit min and max coordinates.
*/
public AABB(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
this.minX = Math.min(minX, maxX);
this.minY = Math.min(minY, maxY);
this.minZ = Math.min(minZ, maxZ);
this.maxX = Math.max(minX, maxX);
this.maxY = Math.max(minY, maxY);
this.maxZ = Math.max(minZ, maxZ);
}
private double minX, minY, minZ;
private double maxX, maxY, maxZ;
public double getMinX() { return minX; }
public double getMinY() { return minY; }
public double getMinZ() { return minZ; }
public double getMaxX() { return maxX; }
public double getMaxY() { return maxY; }
public double getMaxZ() { return maxZ; }
public double getCenterX() { return (minX + maxX) / 2.0; }
public double getCenterY() { return (minY + maxY) / 2.0; }
public double getCenterZ() { return (minZ + maxZ) / 2.0; }
/**
* Returns the center point of the AABB as a double array [x, y, z].
*
* @return the center coordinates
*/
public double[] getCenter() {
double centerX = (minX + maxX) / 2.0;
double centerY = (minY + maxY) / 2.0;
double centerZ = (minZ + maxZ) / 2.0;
return new double[] { centerX, centerY, centerZ };
}
/**
* Returns the 8 corner points of the AABB as list of double[3] arrays.
*/
public List<double[]> getCornerPoints() {
List<double[]> points = new ArrayList<>(8);
points.add(new double[]{minX, minY, minZ});
points.add(new double[]{minX, minY, maxZ});
points.add(new double[]{minX, maxY, minZ});
points.add(new double[]{minX, maxY, maxZ});
points.add(new double[]{maxX, minY, minZ});
points.add(new double[]{maxX, minY, maxZ});
points.add(new double[]{maxX, maxY, minZ});
points.add(new double[]{maxX, maxY, maxZ});
return points;
// public static AABB of(Geometry geom) {
// return of(geom.getPolygons());
// }
//
//
public static AABB ofPolygons(List<? extends Polygon> polygons) {
List<Vector3d> points = new ArrayList<>();
for (Polygon p : polygons) {
points.addAll(p.getExteriorRing().getVertices());
}
return ofPoints(points);
}
/**
* Checks whether a point lies inside or on the surface of the AABB.
*/
public boolean encloses(double x, double y, double z) {
return minX <= x && x <= maxX &&
minY <= y && y <= maxY &&
minZ <= z && z <= maxZ;
}
public static AABB of(Polygon poly) {
LinearRing ring = poly.getExteriorRing();
if (ring == null)
return null;
return of(ring);
}
/**
* Checks if this and other boxes intersect
*/
public boolean intersects(AABB other) {
return !(other.maxX < this.minX || other.minX > this.maxX ||
other.maxY < this.minY || other.minY > this.maxY ||
other.maxZ < this.minZ || other.minZ > this.maxZ);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof AABB other)) return false;
return minX == other.minX && minY == other.minY && minZ == other.minZ &&
maxX == other.maxX && maxY == other.maxY && maxZ == other.maxZ;
}
// NOTE: May replaced later: double[] extractBoundsFromPoints(List<? extends
// Point> points)
public static AABB ofPoints(List<? extends Vector3d> points) {
double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY, maxZ = Double.NEGATIVE_INFINITY;
for (Vector3d p : points) {
minX = Math.min(minX, p.getX());
minY = Math.min(minY, p.getY());
minZ = Math.min(minZ, p.getZ());
maxX = Math.max(maxX, p.getX());
maxY = Math.max(maxY, p.getY());
maxZ = Math.max(maxZ, p.getZ());
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Computes an AABB for a single vertex degenerate AABB with min=max=vertex
* coordinates
*
* @param vertex the vertex to wrap in an AABB
* @return AABB centered at the vertex position
*/
public static AABB of(Vector3d vertex) {
if (vertex == null) {
// Return a degenerate AABB with infinite bounds if vertex is null
return new AABB(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
}
double x = vertex.getX();
double y = vertex.getY();
double z = vertex.getZ();
return new AABB(x, y, z, x, y, z);
}
/**
* Computes an AABB from a LinearRing by iterating over its vertices.
*
* @param ring the LinearRing whose vertices define the AABB
* @return AABB enclosing the ring; returns an empty AABB if the ring has no
* vertices
*/
public static AABB of(LinearRing ring) {
if (ring == null || ring.getVertices() == null || ring.getVertices().isEmpty()) {
return new AABB(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
}
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
double maxZ = Double.NEGATIVE_INFINITY;
for (Vertex v : ring.getVertices()) {
double x = v.getX();
double y = v.getY();
double z = v.getZ();
minX = Math.min(minX, x);
minY = Math.min(minY, y);
minZ = Math.min(minZ, z);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
maxZ = Math.max(maxZ, z);
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/** Builds a padded AABB around a segment (two vertices). */
public static AABB of(Vertex a, Vertex b, double pad) {
double minX = Math.min(a.getX(), b.getX()) - pad;
double minY = Math.min(a.getY(), b.getY()) - pad;
double minZ = Math.min(a.getZ(), b.getZ()) - pad;
double maxX = Math.max(a.getX(), b.getX()) + pad;
double maxY = Math.max(a.getY(), b.getY()) + pad;
double maxZ = Math.max(a.getZ(), b.getZ()) + pad;
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Constructs an AABB from explicit min and max coordinates.
*/
public AABB(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
this.minX = Math.min(minX, maxX);
this.minY = Math.min(minY, maxY);
this.minZ = Math.min(minZ, maxZ);
this.maxX = Math.max(minX, maxX);
this.maxY = Math.max(minY, maxY);
this.maxZ = Math.max(minZ, maxZ);
}
public double getMinX() {
return minX;
}
public double getMinY() {
return minY;
}
public double getMinZ() {
return minZ;
}
public double getMaxX() {
return maxX;
}
public double getMaxY() {
return maxY;
}
public double getMaxZ() {
return maxZ;
}
public double getCenterX() {
return (minX + maxX) / 2.0;
}
public double getCenterY() {
return (minY + maxY) / 2.0;
}
public double getCenterZ() {
return (minZ + maxZ) / 2.0;
}
/**
* Returns the center point of the AABB as a double array [x, y, z].
*
* @return the center coordinates
*/
public double[] getCenter() {
double centerX = (minX + maxX) / 2.0;
double centerY = (minY + maxY) / 2.0;
double centerZ = (minZ + maxZ) / 2.0;
return new double[] { centerX, centerY, centerZ };
}
/**
* Returns the 8 corner points of the AABB as list of double[3] arrays.
*/
public List<double[]> getCornerPoints() {
List<double[]> points = new ArrayList<>(8);
points.add(new double[] { minX, minY, minZ });
points.add(new double[] { minX, minY, maxZ });
points.add(new double[] { minX, maxY, minZ });
points.add(new double[] { minX, maxY, maxZ });
points.add(new double[] { maxX, minY, minZ });
points.add(new double[] { maxX, minY, maxZ });
points.add(new double[] { maxX, maxY, minZ });
points.add(new double[] { maxX, maxY, maxZ });
return points;
}
/**
* Returns the index of the longest axis in the AABB
*/
public int findLongestAxis() {
double x = getMaxX() - getMinX();
double y = getMaxY() - getMinY();
double z = getMaxZ() - getMinZ();
if (x > y && x > z)
return 0;
if (y > x && y > z)
return 1;
return 2;
}
/** Returns true if the AABB is (nearly) flat in at least two axes. */
public boolean isDegenerate(double tol) {
double dx = getMaxX() - getMinX();
double dy = getMaxY() - getMinY();
double dz = getMaxZ() - getMinZ();
int flatAxes = 0;
if (dx <= tol)
flatAxes++;
if (dy <= tol)
flatAxes++;
if (dz <= tol)
flatAxes++;
return flatAxes >= 2; // cannot host 3 distinct points in 3D
}
/**
* Returns true if 'this' fully contains 'other' (inclusive) in axis-aligned
* sense.
*/
public boolean contains(AABB other) {
return contains(other.getMinX(), other.getMinY(), other.getMinZ()) &&
contains(other.getMaxX(), other.getMaxY(), other.getMaxZ());
}
/**
* Checks whether a point lies inside or on the surface of the AABB.
*/
public boolean contains(double x, double y, double z) {
return minX <= x && x <= maxX && minY <= y && y <= maxY && minZ <= z && z <= maxZ;
}
/**
* Returns true if two AABBs overlap (exclusive).
*/
public boolean overlaps(AABB other) {
return !(getMaxX() < other.getMinX() ||
getMinX() > other.getMaxX() ||
getMaxY() < other.getMinY() ||
getMinY() > other.getMaxY() ||
getMaxZ() < other.getMinZ() ||
getMinZ() > other.getMaxZ());
}
/** Returns true if there exists any overlapping AABB pair. */
public static boolean doAnyBoxesOverlap(AABB[] boxes) {
for (int i = 0; i < boxes.length - 1; i++) {
AABB a = boxes[i];
for (int j = i + 1; j < boxes.length; j++) {
AABB b = boxes[j];
if (a.overlaps(b)) return true;
}
}
return false;
}
/**
* Checks if this and other boxes intersect (inclusive)
*/
public boolean intersects(AABB other) {
return !(other.maxX <= this.minX || other.minX >= this.maxX || other.maxY <= this.minY || other.minY >= this.maxY
|| other.maxZ <= this.minZ || other.minZ >= this.maxZ);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AABB other = (AABB) obj;
return Double.doubleToLongBits(maxX) == Double.doubleToLongBits(other.maxX)
&& Double.doubleToLongBits(maxY) == Double.doubleToLongBits(other.maxY)
&& Double.doubleToLongBits(maxZ) == Double.doubleToLongBits(other.maxZ)
&& Double.doubleToLongBits(minX) == Double.doubleToLongBits(other.minX)
&& Double.doubleToLongBits(minY) == Double.doubleToLongBits(other.minY)
&& Double.doubleToLongBits(minZ) == Double.doubleToLongBits(other.minZ);
}
@Override
public int hashCode() {
return Objects.hash(maxX, maxY, maxZ, minX, minY, minZ);
}
@Override
public String toString() {
return "AABB [" + String.format("min: %.2f, %.2f, %.2f max: %.2f, %.2f, %.2f", minX, minY, minZ, maxX, maxY, maxZ) + "]";
}
@Override
public int hashCode() {
return Double.hashCode(minX) ^ Double.hashCode(maxX) ^
Double.hashCode(minY) ^ Double.hashCode(maxY) ^
Double.hashCode(minZ) ^ Double.hashCode(maxZ);
}
public void print() {
System.out.printf("min: %.2f, %.2f, %.2f%n", minX, minY, minZ);
System.out.printf("max: %.2f, %.2f, %.2f%n", maxX, maxY, maxZ);
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.math.Vector3d;
import java.util.*;
/**
......@@ -19,183 +20,60 @@ import java.util.*;
*/
public class AABBUtils {
public static AABB getAABB(ConcretePolygon poly) {
LinearRing ring = poly.getExteriorRing();
if (ring == null) return null;
return computeAABBFromRing(ring);
}
/**
* Computes an AABB from a LinearRing by iterating over its vertices.
*
* @param ring the LinearRing whose vertices define the AABB
* @return AABB enclosing the ring; returns an empty AABB if the ring has no vertices
*/
public static AABB computeAABBFromRing(LinearRing ring) {
if (ring == null || ring.getVertices() == null || ring.getVertices().isEmpty()) {
return new AABB(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
}
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
double maxZ = Double.NEGATIVE_INFINITY;
for (Vertex v : ring.getVertices()) {
double x = v.getX();
double y = v.getY();
double z = v.getZ();
minX = Math.min(minX, x);
minY = Math.min(minY, y);
minZ = Math.min(minZ, z);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
maxZ = Math.max(maxZ, z);
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
public static double[] extractBoundsFromPoints(Point p1, Point p2) {
double minX = Math.min(p1.getX(), p2.getX());
double minY = Math.min(p1.getY(), p2.getY());
double minZ = Math.min(p1.getZ(), p2.getZ());
double maxX = Math.max(p1.getX(), p2.getX());
double maxY = Math.max(p1.getY(), p2.getY());
double maxZ = Math.max(p1.getZ(), p2.getZ());
return new double[] { minX, minY, minZ, maxX, maxY, maxZ };
}
// NOTE: May replaced later: double[] extractBoundsFromPoints(List<? extends Point> points)
public static AABB aabbFromVector3d(List<? extends Vector3d> points) {
double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY, maxZ = Double.NEGATIVE_INFINITY;
for (Vector3d p : points) {
minX = Math.min(minX, p.getX());
minY = Math.min(minY, p.getY());
minZ = Math.min(minZ, p.getZ());
maxX = Math.max(maxX, p.getX());
maxY = Math.max(maxY, p.getY());
maxZ = Math.max(maxZ, p.getZ());
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Computes an AABB for a single vertex degenerate AABB with min=max=vertex coordinates
*
* @param vertex the vertex to wrap in an AABB
* @return AABB centered at the vertex position
*/
public static AABB computeAABBFromVertex(Vertex vertex) {
if (vertex == null) {
// Return a degenerate AABB with infinite bounds if vertex is null
return new AABB(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
}
double x = vertex.getX();
double y = vertex.getY();
double z = vertex.getZ();
return new AABB(x, y, z, x, y, z);
}
/** Returns true if the AABB is (nearly) flat in at least two axes. */
public static boolean isDegenerate(AABB aabb, double tol) {
double dx = aabb.getMaxX() - aabb.getMinX();
double dy = aabb.getMaxY() - aabb.getMinY();
double dz = aabb.getMaxZ() - aabb.getMinZ();
int flatAxes = 0;
if (dx <= tol) flatAxes++;
if (dy <= tol) flatAxes++;
if (dz <= tol) flatAxes++;
return flatAxes >= 2; // cannot host 3 distinct points in 3D
}
/**
* Counts distinct vertices of a ring using a tolerance.
* Implementation: uniform quantization (grid hashing) for speed and determinism.
*/
public static int countDistinctVertices(LinearRing ring, double tol) {
if (ring == null || ring.getVertices() == null) return 0;
// Use a quantization resolution based on tol (avoid div by zero).
final double q = (tol > 0) ? tol : 1e-9;
// Hash set of quantized integer triplets "ix|iy|iz"
Set<Long> buckets = new HashSet<>(ring.getVertices().size() * 2);
for (Vertex v : ring.getVertices()) {
long ix = Math.round(v.getX() / q);
long iy = Math.round(v.getY() / q);
long iz = Math.round(v.getZ() / q);
// pack into a 64-bit key (simple mixing; safe if ranges are reasonable)
long key = mix3(ix, iy, iz);
buckets.add(key);
}
return buckets.size();
if (ring == null || ring.getVertices() == null) {
return 0;
}
// Use a quantization resolution based on tol (avoid div by zero).
final double q = (tol > 0) ? tol : 1e-9;
List<Vertex> vertices = ring.getVertices();
Set<long[]> set = new HashSet<>();
for (Vertex v : vertices) {
long xLong = Math.round(v.getX() / q);
long yLong = Math.round(v.getY() / q);
long zLong = Math.round(v.getZ() / q);
long[] compareArray = new long[] {xLong, yLong, zLong};
set.add(compareArray);
}
return set.size();
// if (ring == null || ring.getVertices() == null) return 0;
// // Use a quantization resolution based on tol (avoid div by zero).
// final double q = (tol > 0) ? tol : 1e-9;
//
// // Hash set of quantized integer triplets "ix|iy|iz"
// Set<Long> buckets = new HashSet<>(ring.getVertices().size() * 2);
// for (Vertex v : ring.getVertices()) {
// long ix = Math.round(v.getX() / q);
// long iy = Math.round(v.getY() / q);
// long iz = Math.round(v.getZ() / q);
// // pack into a 64-bit key (simple mixing; safe if ranges are reasonable)
// long key = mix3(ix, iy, iz);
// buckets.add(key);
// }
// return buckets.size();
}
// Simple 3D integer mix to a 64-bit key (Xorshift-ish) from JavaDoc
private static long mix3(long x, long y, long z) {
long h = x * 73856093L ^ y * 19349663L ^ z * 83492791L;
// final avalanche
h ^= (h >>> 33);
h *= 0xff51afd7ed558ccdL;
h ^= (h >>> 33);
h *= 0xc4ceb9fe1a85ec53L;
h ^= (h >>> 33);
return h;
}
// private static long mix3(long x, long y, long z) {
// long h = x * 73856093L ^ y * 19349663L ^ z * 83492791L;
// // final avalanche
// h ^= (h >>> 33);
// h *= 0xff51afd7ed558ccdL;
// h ^= (h >>> 33);
// h *= 0xc4ceb9fe1a85ec53L;
// h ^= (h >>> 33);
// return h;
// }
/** Returns true if 'outer' fully contains 'inner' (inclusive) in axis-aligned sense. */
public 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();
}
/** Builds a padded AABB around a segment (two vertices). */
public static AABB edgeAabb(Vertex a, Vertex b, double pad) {
double minX = Math.min(a.getX(), b.getX()) - pad;
double minY = Math.min(a.getY(), b.getY()) - pad;
double minZ = Math.min(a.getZ(), b.getZ()) - pad;
double maxX = Math.max(a.getX(), b.getX()) + pad;
double maxY = Math.max(a.getY(), b.getY()) + pad;
double maxZ = Math.max(a.getZ(), b.getZ()) + pad;
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/** Returns true if two AABBs overlap (inclusive). */
public static boolean overlaps(AABB a, AABB b) {
return !(a.getMaxX() < b.getMinX() ||
a.getMinX() > b.getMaxX() ||
a.getMaxY() < b.getMinY() ||
a.getMinY() > b.getMaxY() ||
a.getMaxZ() < b.getMinZ() ||
a.getMinZ() > b.getMaxZ());
}
/** Returns true if there exists any overlapping AABB pair. */
public static boolean anyOverlap(AABB[] boxes) {
for (int i = 0; i < boxes.length - 1; i++) {
AABB a = boxes[i];
for (int j = i + 1; j < boxes.length; j++) {
AABB b = boxes[j];
if (AABBUtils.overlaps(a, b)) return true;
}
}
return false;
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
/*
*
*
*/
public class AABB_BVH<E> {
private BVHStructures.Node<E> root;
public AABB_BVH() {
this.root = null;
}
private void deleteTree(BVHStructures.Node<E> node) {
for (BVHStructures.Node<E> child : node.children) {
deleteTree(child);
}
node.children.clear();
}
public void deleteTree() {
if (root != null) {
deleteTree(root);
}
}
public BVHStructures.Node<E> getRoot() {
return root;
}
public void setRoot(BVHStructures.Node<E> root) {
this.root = root;
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
public class BVHStructures {
/**
* Generic node used in BVH tree
*/
public static class Node<E> {
public List<Node<E>> children = new ArrayList<>();
public AABB aabb;
public E element;
public Node() {
// Anchor-3DPoint given by means of its coords
double zeroX = 0;
double zeroY = 0;
double zeroZ = 0;
this.aabb = new AABB(zeroX, zeroY, zeroZ, zeroX, zeroY, zeroZ);
this.element = null;
}
public boolean isLeaf() {
return children.isEmpty() && element != null;
}
}
/**
* Represents a pair of geometry lists resulting from a split
*/
public static class SplitStruct<E> {
public List<E> list1 = new ArrayList<>();
public List<E> list2 = new ArrayList<>();
}
/**
* Stack element used during recursive BVH tree construction
*/
public static class StackElement<E> {
public int level;
public Node<E> node;
public List<E> elements = new ArrayList<>();
public StackElement(int level, Node<E> node, List<E> elements) {
this.level = level;
this.node = node;
this.elements = elements;
}
}
/**
* Pair of AABBs and polygon lists used during splitting
*/
public static class SplitStructB<E> {
public AABB box1, box2;
public List<E> list1 = new ArrayList<>();
public List<E> list2 = new ArrayList<>();
}
/**
* Generic array-based BVH node.
* Stores an AABB and an associated element (typically a leaf object).
*/
public static class NodeB_Ar<E> {
public AABB aabb;
public E element;
public NodeB_Ar(AABB aabb, E element) {
this.aabb = aabb;
this.element = element;
}
}
/**
* Stack element used for array-based BVH construction
*/
public static class StackElementAr {
public int arrayIndex;
public int level;
public AABB aabb;
public List<ConcretePolygon> polygons = new ArrayList<>();
public StackElementAr(int arrayIndex, int level, AABB aabb, List<ConcretePolygon> polygons) {
this.arrayIndex = arrayIndex;
this.level = level;
this.aabb = aabb;
this.polygons = polygons;
}
}
/**
* Creates a comparator to sort elements by their AABB center X coordinate.
*/
public static <E> Comparator<E> compareCenterX(Function<E, AABB> aabbGetter) {
return Comparator.comparingDouble(e -> {
AABB box = aabbGetter.apply(e);
return (box.getMinX() + box.getMaxX()) / 2.0;
});
}
/**
* Creates a comparator to sort elements by their AABB center Y coordinate.
*/
public static <E> Comparator<E> compareCenterY(Function<E, AABB> aabbGetter) {
return Comparator.comparingDouble(e -> {
AABB box = aabbGetter.apply(e);
return (box.getMinY() + box.getMaxY()) / 2.0;
});
}
/**
* Creates a comparator to sort elements by their AABB center Z coordinate.
*/
public static <E> Comparator<E> compareCenterZ(Function<E, AABB> aabbGetter) {
return Comparator.comparingDouble(e -> {
AABB box = aabbGetter.apply(e);
return (box.getMinZ() + box.getMaxZ()) / 2.0;
});
}
/**
* Sorts elements by AABB center along specified axis.
*
* @param elements the list to sort
* @param axis 0 = X, 1 = Y, 2 = Z
* @param aabbGetter a function to extract the AABB from an element
*/
public static <E> void sortElementsByCenterAxis(List<E> elements, int axis, Function<E, AABB> aabbGetter) {
switch (axis) {
case 0 -> elements.sort(compareCenterX(aabbGetter));
case 1 -> elements.sort(compareCenterY(aabbGetter));
case 2 -> elements.sort(compareCenterZ(aabbGetter));
default -> throw new IllegalArgumentException("Invalid axis index: " + axis);
}
}
/**
* Returns the index of the longest axis in the AABB
*/
public static int findLongestAxis(AABB aabb) {
double x = aabb.getMaxX() - aabb.getMinX();
double y = aabb.getMaxY() - aabb.getMinY();
double z = aabb.getMaxZ() - aabb.getMinZ();
if (x > y && x > z) return 0;
if (y > x && y > z) return 1;
return 2;
}
/**
* NOTE: Generic Version all ready exists
* Calculates the smallest AABB that encloses all given polygons
*/
public static AABB getAggregateAABB(List<ConcretePolygon> polygons) {
if (polygons.size() == 1) {
return AABBUtils.getAABB(polygons.get(0));
}
double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE, minZ = Double.MAX_VALUE;
double maxX = -Double.MAX_VALUE, maxY = -Double.MAX_VALUE, maxZ = -Double.MAX_VALUE;
for (ConcretePolygon p : polygons) {
AABB aabb = AABBUtils.getAABB(p);
minX = Math.min(minX, aabb.getMinX());
minY = Math.min(minY, aabb.getMinY());
minZ = Math.min(minZ, aabb.getMinZ());
maxX = Math.max(maxX, aabb.getMaxX());
maxY = Math.max(maxY, aabb.getMaxY());
maxZ = Math.max(maxZ, aabb.getMaxZ());
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
public static <E> AABB getAggregateAABB(List<E> elements, Function<E, AABB> aabbFunc) {
double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY, maxZ = Double.NEGATIVE_INFINITY;
for (E e : elements) {
AABB aabb = aabbFunc.apply(e);
minX = Math.min(minX, aabb.getMinX());
minY = Math.min(minY, aabb.getMinY());
minZ = Math.min(minZ, aabb.getMinZ());
maxX = Math.max(maxX, aabb.getMaxX());
maxY = Math.max(maxY, aabb.getMaxY());
maxZ = Math.max(maxZ, aabb.getMaxZ());
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
}
\ No newline at end of file
......@@ -5,14 +5,16 @@ import java.util.List;
import java.util.ArrayList;
import java.util.function.Function;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
/**
* Generic AABB Tree implementation using a binary tree structure.
*
* @param <E> The type of elements stored in the tree, which must be able to provide an AABB.
*/
public class AABBTree<E> {
public class BoundingVolumeHierarchyTree<E> {
private BVHStructures.Node<E> root;
private Node<E> root;
private final Function<E, AABB> aabbFunction;
/**
......@@ -20,7 +22,7 @@ public class AABBTree<E> {
*
* @param aabbFunction Function to extract an AABB from an element of type E
*/
public AABBTree(Function<E, AABB> aabbFunction) {
public BoundingVolumeHierarchyTree(Function<E, AABB> aabbFunction) {
this.root = null;
this.aabbFunction = aabbFunction;
}
......@@ -31,7 +33,7 @@ public class AABBTree<E> {
* @param elements The list of elements to insert into the tree
* @param aabbFunction Function to extract an AABB from an element of type E
*/
public AABBTree(List<E> elements, Function<E, AABB> aabbFunction) {
public BoundingVolumeHierarchyTree(List<E> elements, Function<E, AABB> aabbFunction) {
this.aabbFunction = aabbFunction;
if (elements == null || elements.isEmpty()) {
this.root = null;
......@@ -39,36 +41,66 @@ public class AABBTree<E> {
this.root = buildRecursive(elements);
}
}
/**
* NOTE: Generic Version all ready exists Calculates the smallest AABB that
* encloses all given polygons
*/
public static AABB getAggregateAABB(List<ConcretePolygon> polygons) {
if (polygons.size() == 1) {
return AABB.of(polygons.get(0));
}
return getAggregateAABB(polygons, AABB::of);
}
public static <E> AABB getAggregateAABB(List<E> elements, Function<E, AABB> aabbFunc) {
double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, minZ = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY, maxZ = Double.NEGATIVE_INFINITY;
for (E e : elements) {
AABB aabb = aabbFunc.apply(e);
minX = Math.min(minX, aabb.getMinX());
minY = Math.min(minY, aabb.getMinY());
minZ = Math.min(minZ, aabb.getMinZ());
maxX = Math.max(maxX, aabb.getMaxX());
maxY = Math.max(maxY, aabb.getMaxY());
maxZ = Math.max(maxZ, aabb.getMaxZ());
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Returns the root node of the AABB tree.
*/
public BVHStructures.Node<E> getRoot() {
public Node<E> getRoot() {
return root;
}
/**
* Sets the root node manually.
*/
public void setRoot(BVHStructures.Node<E> root) {
public void setRoot(Node<E> root) {
this.root = root;
}
public List<E> getAllIntersectingElements(AABB box) {
// TODO: implement
throw new UnsupportedOperationException();
}
/**
* Recursively builds a balanced AABB tree from the list of elements.
*/
private BVHStructures.Node<E> buildRecursive(List<E> elements) {
private Node<E> buildRecursive(List<E> elements) {
if (elements.size() == 1) {
E elem = elements.get(0);
BVHStructures.Node<E> leaf = new BVHStructures.Node<>();
leaf.element = elem;
leaf.aabb = aabbFunction.apply(elem);
return leaf;
return new Node<>(elem, aabbFunction.apply(elem));
}
// Compute total AABB
AABB totalAabb = BVHStructures.getAggregateAABB(elements, aabbFunction);
int axis = BVHStructures.findLongestAxis(totalAabb);
AABB totalAabb = getAggregateAABB(elements, aabbFunction);
int axis = totalAabb.findLongestAxis();
// Sort elements along axis
elements.sort(Comparator.comparingDouble(e ->
......@@ -77,10 +109,9 @@ public class AABBTree<E> {
List<E> leftList = elements.subList(0, mid);
List<E> rightList = elements.subList(mid, elements.size());
BVHStructures.Node<E> node = new BVHStructures.Node<>();
node.aabb = totalAabb;
node.children.add(buildRecursive(leftList));
node.children.add(buildRecursive(rightList));
Node<E> node = new Node<>(null, totalAabb);
node.getChildren().add(buildRecursive(leftList));
node.getChildren().add(buildRecursive(rightList));
return node;
}
......@@ -101,17 +132,17 @@ public class AABBTree<E> {
*
*
*/
private void findCandidatesRecursive(BVHStructures.Node<E> node, AABB query, List<E> result) {
if (node == null || !node.aabb.intersects(query)) {
private void findCandidatesRecursive(Node<E> node, AABB query, List<E> result) {
if (node == null || !node.getAabb().intersects(query)) {
return;
}
if (node.isLeaf()) {
if (aabbFunction.apply(node.element).intersects(query)) {
result.add(node.element);
if (aabbFunction.apply(node.getElement()).intersects(query)) {
result.add(node.getElement());
}
} else {
for (BVHStructures.Node<E> child : node.children) {
for (Node<E> child : node.getChildren()) {
findCandidatesRecursive(child, query, result);
}
}
......
package de.hft.stuttgart.citydoctor2.datastructure.bht;
/**
* 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);
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.ArrayList;
import java.util.List;
public class Node<E> {
private List<Node<E>> children = new ArrayList<>();
private AABB aabb;
private E element;
public Node(E element, AABB aabb) {
// // Anchor-3DPoint given by means of its coords
// double zeroX = 0;
// double zeroY = 0;
// double zeroZ = 0;
// this.aabb = new AABB(zeroX, zeroY, zeroZ, zeroX, zeroY, zeroZ);
this.aabb = aabb;
this.element = element;
}
public boolean isLeaf() {
return children.isEmpty() && element != null;
}
public AABB getAabb() {
return aabb;
}
public E getElement() {
return element;
}
public List<Node<E>> getChildren() {
return children;
}
}
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() {
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 org.locationtech.jts.geom.Coordinate;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
public class Point3d extends Vector3d {
private static final long serialVersionUID = -7748875994164271259L;
public Point3d() {
super();
}
public Point3d(Coordinate coord) {
super(coord);
}
public Point3d(double x, double y, double z) {
super(x, y, z);
}
public Point3d(double[] coords) {
super(coords);
}
public Point3d(Vector3d vec) {
super(vec);
}
}
package de.hft.stuttgart.citydoctor2.datastructure.bht;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
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;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
public class TestAABB {
public class AABBTest {
/**
* Entry point for AABB testing
*/
public static void main(String[] args) {
System.out.println("=== AABB TEST ===");
@Test
public void testContainsAABB() {
// System.out.println("=== AABB TEST ===");
ConcretePolygon polygon = new ConcretePolygon();
LinearRing exterior = new LinearRing(LinearRingType.EXTERIOR);
......@@ -26,10 +34,10 @@ public class TestAABB {
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);
Point3d p1 = new Point3d(0, 0, 0);
Point3d p2 = new Point3d(1, 0, 0);
Point3d p3 = new Point3d(0.5, 1, 0);
Point3d p4 = new Point3d(0.5, 0.5, 1);
// Define triangle faces of the tetrahedron
ConcretePolygon base = new ConcretePolygon();
......@@ -64,11 +72,10 @@ public class TestAABB {
ring3.addVertex(new Vertex(p3.getX(), p3.getY(), p3.getZ()));
side3.setExteriorRing(ring3);
List<ConcretePolygon> poly = Arrays.asList(base, side1, side2, side3);
List<Polygon> polys = Arrays.asList(base, side1, side2, side3);
AABB aabb = BVHStructures.getAggregateAABB(poly);
System.out.println("\nComputed AABB:");
aabb.print();
AABB aabb = AABB.ofPolygons(polys);
// System.out.println("\nComputed " + aabb);
/*** 3D-Point-coords with Test Properties ***/
// Inside laying Point
......@@ -84,13 +91,21 @@ public class TestAABB {
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));
// inside point
Assert.assertTrue(aabb.contains(testInsideX, testInsideY, testInsideZ));
// System.out.println("\nTest point (inside): " + testInsideX + " " + testInsideY + " " + testInsideZ);
// System.out.println("-> contained?: " + aabb.contains(testInsideX, testInsideY, testInsideZ));
System.out.println("\nTest point (outside): " + testOutsideX + " " + testOutsideY + " " + testOutsideZ);
System.out.println("-> contained?: " + aabb.encloses(testOutsideX, testOutsideY, testOutsideZ));
// outside point
Assert.assertFalse(aabb.contains(testOutsideX, testOutsideY, testOutsideZ));
// System.out.println("\nTest point (outside): " + testOutsideX + " " + testOutsideY + " " + testOutsideZ);
// System.out.println("-> contained?: " + aabb.contains(testOutsideX, testOutsideY, testOutsideZ));
System.out.println("\nTest point (on edge): " + testOnEdgeX + " " + testOnEdgeY + " " + testOnEdgeZ);
System.out.println("-> contained?: " + aabb.encloses(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
// edge point
Assert.assertTrue(aabb.contains(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
// System.out.println("\nTest point (on edge): " + testOnEdgeX + " " + testOnEdgeY + " " + testOnEdgeZ);
// System.out.println("-> contained?: " + aabb.contains(testOnEdgeX, testOnEdgeY, testOnEdgeZ));
}
}
......@@ -26,20 +26,20 @@ public class TestHouseAABB {
double roofHeight = 1.0;
// points for Ground floor
Point b1 = new Point(0, 0, 0);
Point b2 = new Point(baseSize, 0, 0);
Point b3 = new Point(baseSize, baseSize, 0);
Point b4 = new Point(0, baseSize, 0);
Point3d b1 = new Point3d(0, 0, 0);
Point3d b2 = new Point3d(baseSize, 0, 0);
Point3d b3 = new Point3d(baseSize, baseSize, 0);
Point3d b4 = new Point3d(0, baseSize, 0);
// points for Roof
Point t1 = new Point(0, 0, height);
Point t2 = new Point(baseSize, 0, height);
Point t3 = new Point(baseSize, baseSize, height);
Point t4 = new Point(0, baseSize, height);
Point3d t1 = new Point3d(0, 0, height);
Point3d t2 = new Point3d(baseSize, 0, height);
Point3d t3 = new Point3d(baseSize, baseSize, height);
Point3d t4 = new Point3d(0, baseSize, height);
// Roofpeaks
Point roofPeak1 = new Point(baseSize/2, -0.2, height + roofHeight);
Point roofPeak2 = new Point(baseSize/2, baseSize + 0.2, height + roofHeight);
Point3d roofPeak1 = new Point3d(baseSize/2, -0.2, height + roofHeight);
Point3d roofPeak2 = new Point3d(baseSize/2, baseSize + 0.2, height + roofHeight);
List<ConcretePolygon> house = new ArrayList<>();
......@@ -63,8 +63,8 @@ public class TestHouseAABB {
house.add(createQuadPolygon(t1, t4, roofPeak2, roofPeak1));
AABB houseAABB = BVHStructures.getAggregateAABB(house);
houseAABB.print();
AABB houseAABB = AABB.ofPolygons(house);
// houseAABB.print();
// Define test points
double[] insidePoint = {1.0, 1.0, 1.0}; // clearly inside (center of the base cube)
......@@ -74,21 +74,21 @@ public class TestHouseAABB {
// Test containment
System.out.println("\nTest point (inside): " + Arrays.toString(insidePoint));
System.out.println("-> contained? " + houseAABB.encloses(insidePoint[0], insidePoint[1], insidePoint[2]));
System.out.println("-> contained? " + houseAABB.contains(insidePoint[0], insidePoint[1], insidePoint[2]));
System.out.println("\nTest point (on roof): " + Arrays.toString(roofPoint));
System.out.println("-> contained? " + houseAABB.encloses(roofPoint[0], roofPoint[1], roofPoint[2]));
System.out.println("-> contained? " + houseAABB.contains(roofPoint[0], roofPoint[1], roofPoint[2]));
System.out.println("\nTest point (outside): " + Arrays.toString(outsidePoint));
System.out.println("-> contained? " + houseAABB.encloses(outsidePoint[0], outsidePoint[1], outsidePoint[2]));
System.out.println("-> contained? " + houseAABB.contains(outsidePoint[0], outsidePoint[1], outsidePoint[2]));
System.out.println("\nTest point (on edge): " + Arrays.toString(edgePoint));
System.out.println("-> contained? " + houseAABB.encloses(edgePoint[0], edgePoint[1], edgePoint[2]));
System.out.println("-> contained? " + houseAABB.contains(edgePoint[0], edgePoint[1], edgePoint[2]));
}
/** Creates a triangular polygon from three points */
private static ConcretePolygon createTrianglePolygon(Point p1, Point p2, Point p3) {
private static ConcretePolygon createTrianglePolygon(Point3d p1, Point3d p2, Point3d p3) {
// alocate poly
ConcretePolygon poly = new ConcretePolygon();
// alocate ring
......@@ -104,7 +104,7 @@ public class TestHouseAABB {
}
/** Creates a quadrilateral polygon from four points */
private static ConcretePolygon createQuadPolygon(Point p1, Point p2, Point p3, Point p4) {
private static ConcretePolygon createQuadPolygon(Point3d p1, Point3d p2, Point3d p3, Point3d p4) {
ConcretePolygon poly = new ConcretePolygon();
......
......@@ -167,7 +167,7 @@ public class RingSelfIntCheckAABB extends Check {
// --- AABB replacement for BoundingBox.ofPoints(rotatedVertices) ---
// Computes the axis-aligned extents of the rotated point cloud.
AABB aabb = AABBUtils.aabbFromVector3d(rotatedVertices);
AABB aabb = AABB.ofPoints(rotatedVertices);
double dx = aabb.getMaxX() - aabb.getMinX();
double dy = aabb.getMaxY() - aabb.getMinY();
......
......@@ -86,21 +86,24 @@ public class SolidSelfIntCheckAABB extends Check {
g.addCheckResult(new CheckResult(this, ResultStatus.OK, null));
return;
}
// Building BVH Tree
// Build AABBs once
AABB[] boxes = new AABB[polys.size()];
for (int i = 0; i < polys.size(); i++) {
ConcretePolygon cp = polys.get(i).getOriginal();
boxes[i] = AABBUtils.getAABB(cp);
boxes[i] = AABB.of(cp);
}
// If no AABB pair overlaps, self-intersection is impossible
if (!AABBUtils.anyOverlap(boxes)) {
if (!AABB.doAnyBoxesOverlap(boxes)) {
g.addCheckResult(new CheckResult(this, ResultStatus.OK, null));
return;
}
// --- ---
CheckResult cr;
List<PolygonIntersection> intersections = SelfIntersectionUtil.calculateSolidSelfIntersection(g);
List<PolygonIntersection> intersections = SelfIntersectionUtil.calculateSolidSelfIntersection(g, 0.001, tree);
if (intersections.isEmpty()) {
cr = new CheckResult(this, ResultStatus.OK, null);
} else {
......@@ -110,18 +113,6 @@ public class SolidSelfIntCheckAABB extends Check {
g.addCheckResult(cr);
}
@SuppressWarnings("unused")
private CheckResult oldIntersectionAlgorithm(Geometry g) {
CheckResult cr;
GeometrySelfIntersection intersect = SelfIntersectionUtil.doesSolidSelfIntersect(g);
if (intersect != null) {
cr = new CheckResult(this, ResultStatus.ERROR, null);
} else {
cr = new CheckResult(this, ResultStatus.OK, null);
}
return cr;
}
@Override
public List<CheckId> getDependencies() {
return dependencies;
......
......@@ -49,6 +49,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
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.edge.EdgePolygon;
import de.hft.stuttgart.citydoctor2.edge.IntersectPlanarPolygons;
import de.hft.stuttgart.citydoctor2.edge.MeshSurface;
......@@ -89,7 +91,7 @@ public class SelfIntersectionUtil {
}
public static List<PolygonIntersection> calculateSolidSelfIntersection(Geometry g, double delta) {
public static List<PolygonIntersection> calculateSolidSelfIntersection(Geometry g, double delta, BoundingVolumeHierarchyTree<Polygon> tree) {
List<TesselatedPolygon> tesselatedPolygons = new ArrayList<>();
for (Polygon p : g.getPolygons()) {
TesselatedPolygon tessPolygon = EarcutTesselator.tesselatePolygon(p);
......@@ -116,6 +118,11 @@ public class SelfIntersectionUtil {
List<PolygonIntersection> intersections = new ArrayList<>();
for (int i = 0; i < tesselatedPolygons.size() - 1; i++) {
TesselatedPolygon p1 = tesselatedPolygons.get(i);
List<Polygon> candidates = tree.findCandidates(AABB.of(p1.getOriginal()));
if (candidates.isEmpty()) {
// TODO:
}
for (int j = i + 1; j < tesselatedPolygons.size(); j++) {
TesselatedPolygon p2 = tesselatedPolygons.get(j);
GeometrySelfIntersection intersection = doPolygonsIntersect(p1, p2, delta);
......
......@@ -82,7 +82,7 @@ public class TestCityGmlAABB {
System.out.println("\n> Polygon-level AABB (broad-phase)");
Set<ConcretePolygon> polys = collectAllPolygons(buildings);
AABBTree<ConcretePolygon> bvh = new AABBTree<>(
BoundingVolumeHierarchyTree<ConcretePolygon> bvh = new BoundingVolumeHierarchyTree<>(
new ArrayList<>(polys),
AABBUtils::getAABB
);
......@@ -102,7 +102,7 @@ public class TestCityGmlAABB {
? collectExteriorRings(buildings)
: collectInteriorRings(buildings);
AABBTree<LinearRing> bvh = new AABBTree<>(
BoundingVolumeHierarchyTree<LinearRing> bvh = new BoundingVolumeHierarchyTree<>(
new ArrayList<>(rings),
AABBUtils::computeAABBFromRing
);
......@@ -118,7 +118,7 @@ public class TestCityGmlAABB {
System.out.println("\n> Vertex-level AABB (fine-phase)");
Set<Vertex> verts = collectAllVertices(buildings);
AABBTree<Vertex> bvh = new AABBTree<>(
BoundingVolumeHierarchyTree<Vertex> bvh = new BoundingVolumeHierarchyTree<>(
new ArrayList<>(verts),
AABBUtils::computeAABBFromVertex
);
......
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