Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
7f3fa92f
Commit
7f3fa92f
authored
Jan 20, 2026
by
Matthias Betz
Browse files
changes for better integration
parent
c67a5961
Pipeline
#12320
failed with stage
in 1 minute and 32 seconds
Changes
15
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/AABB.java
View file @
7f3fa92f
...
@@ -2,106 +2,307 @@ package de.hft.stuttgart.citydoctor2.datastructure.bht;
...
@@ -2,106 +2,307 @@ package de.hft.stuttgart.citydoctor2.datastructure.bht;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
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.
* Represents an Axis-Aligned Bounding Box (AABB) using six double values.
*/
*/
public
class
AABB
{
public
class
AABB
{
private
double
minX
,
minY
,
minZ
;
private
double
minX
,
minY
,
minZ
;
private
double
maxX
,
maxY
,
maxZ
;
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
);
}
public
double
getMinX
()
{
return
minX
;
}
// public static AABB of(Geometry geom) {
public
double
getMinY
()
{
return
minY
;
}
// return of(geom.getPolygons());
public
double
getMinZ
()
{
return
minZ
;
}
// }
public
double
getMaxX
()
{
return
maxX
;
}
//
public
double
getMaxY
()
{
return
maxY
;
}
//
public
double
getMaxZ
()
{
return
maxZ
;
}
public
static
AABB
ofPolygons
(
List
<?
extends
Polygon
>
polygons
)
{
List
<
Vector3d
>
points
=
new
ArrayList
<>();
public
double
getCenterX
()
{
return
(
minX
+
maxX
)
/
2.0
;
}
for
(
Polygon
p
:
polygons
)
{
public
double
getCenterY
()
{
return
(
minY
+
maxY
)
/
2.0
;
}
points
.
addAll
(
p
.
getExteriorRing
().
getVertices
());
public
double
getCenterZ
()
{
return
(
minZ
+
maxZ
)
/
2.0
;
}
}
return
ofPoints
(
points
);
/**
* 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
(
Polygon
poly
)
{
* Checks whether a point lies inside or on the surface of the AABB.
LinearRing
ring
=
poly
.
getExteriorRing
();
*/
if
(
ring
==
null
)
public
boolean
encloses
(
double
x
,
double
y
,
double
z
)
{
return
null
;
return
minX
<=
x
&&
x
<=
maxX
&&
return
of
(
ring
);
minY
<=
y
&&
y
<=
maxY
&&
}
minZ
<=
z
&&
z
<=
maxZ
;
}
/**
// NOTE: May replaced later: double[] extractBoundsFromPoints(List<? extends
* Checks if this and other boxes intersect
// Point> points)
*/
public
static
AABB
ofPoints
(
List
<?
extends
Vector3d
>
points
)
{
public
boolean
intersects
(
AABB
other
)
{
double
minX
=
Double
.
POSITIVE_INFINITY
,
minY
=
Double
.
POSITIVE_INFINITY
,
minZ
=
Double
.
POSITIVE_INFINITY
;
return
!(
other
.
maxX
<
this
.
minX
||
other
.
minX
>
this
.
maxX
||
double
maxX
=
Double
.
NEGATIVE_INFINITY
,
maxY
=
Double
.
NEGATIVE_INFINITY
,
maxZ
=
Double
.
NEGATIVE_INFINITY
;
other
.
maxY
<
this
.
minY
||
other
.
minY
>
this
.
maxY
||
other
.
maxZ
<
this
.
minZ
||
other
.
minZ
>
this
.
maxZ
);
for
(
Vector3d
p
:
points
)
{
}
minX
=
Math
.
min
(
minX
,
p
.
getX
());
minY
=
Math
.
min
(
minY
,
p
.
getY
());
@Override
minZ
=
Math
.
min
(
minZ
,
p
.
getZ
());
public
boolean
equals
(
Object
obj
)
{
maxX
=
Math
.
max
(
maxX
,
p
.
getX
());
if
(
this
==
obj
)
return
true
;
maxY
=
Math
.
max
(
maxY
,
p
.
getY
());
if
(!(
obj
instanceof
AABB
other
))
return
false
;
maxZ
=
Math
.
max
(
maxZ
,
p
.
getZ
());
return
minX
==
other
.
minX
&&
minY
==
other
.
minY
&&
minZ
==
other
.
minZ
&&
}
maxX
==
other
.
maxX
&&
maxY
==
other
.
maxY
&&
maxZ
==
other
.
maxZ
;
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
);
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/AABBUtils.java
View file @
7f3fa92f
package
de.hft.stuttgart.citydoctor2.datastructure.bht
;
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.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
java.util.*
;
/**
/**
...
@@ -19,183 +20,60 @@ import java.util.*;
...
@@ -19,183 +20,60 @@ import java.util.*;
*/
*/
public
class
AABBUtils
{
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.
* Counts distinct vertices of a ring using a tolerance.
* Implementation: uniform quantization (grid hashing) for speed and determinism.
* Implementation: uniform quantization (grid hashing) for speed and determinism.
*/
*/
public
static
int
countDistinctVertices
(
LinearRing
ring
,
double
tol
)
{
public
static
int
countDistinctVertices
(
LinearRing
ring
,
double
tol
)
{
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
)
return
0
;
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
)
{
// Use a quantization resolution based on tol (avoid div by zero).
return
0
;
final
double
q
=
(
tol
>
0
)
?
tol
:
1
e
-
9
;
}
// Use a quantization resolution based on tol (avoid div by zero).
// Hash set of quantized integer triplets "ix|iy|iz"
final
double
q
=
(
tol
>
0
)
?
tol
:
1
e
-
9
;
Set
<
Long
>
buckets
=
new
HashSet
<>(
ring
.
getVertices
().
size
()
*
2
);
List
<
Vertex
>
vertices
=
ring
.
getVertices
();
for
(
Vertex
v
:
ring
.
getVertices
())
{
Set
<
long
[]>
set
=
new
HashSet
<>();
long
ix
=
Math
.
round
(
v
.
getX
()
/
q
);
for
(
Vertex
v
:
vertices
)
{
long
iy
=
Math
.
round
(
v
.
getY
()
/
q
);
long
xLong
=
Math
.
round
(
v
.
getX
()
/
q
);
long
iz
=
Math
.
round
(
v
.
getZ
()
/
q
);
long
yLong
=
Math
.
round
(
v
.
getY
()
/
q
);
// pack into a 64-bit key (simple mixing; safe if ranges are reasonable)
long
zLong
=
Math
.
round
(
v
.
getZ
()
/
q
);
long
key
=
mix3
(
ix
,
iy
,
iz
);
long
[]
compareArray
=
new
long
[]
{
xLong
,
yLong
,
zLong
};
buckets
.
add
(
key
);
set
.
add
(
compareArray
);
}
}
return
buckets
.
size
();
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
// Simple 3D integer mix to a 64-bit key (Xorshift-ish) from JavaDoc
private
static
long
mix3
(
long
x
,
long
y
,
long
z
)
{
//
private static long mix3(long x, long y, long z) {
long
h
=
x
*
73856093L
^
y
*
19349663L
^
z
*
83492791L
;
//
long h = x * 73856093L ^ y * 19349663L ^ z * 83492791L;
// final avalanche
//
// final avalanche
h
^=
(
h
>>>
33
);
//
h ^= (h >>> 33);
h
*=
0xff51afd7ed558ccd
L
;
//
h *= 0xff51afd7ed558ccdL;
h
^=
(
h
>>>
33
);
//
h ^= (h >>> 33);
h
*=
0xc4ceb9fe1a85ec53
L
;
//
h *= 0xc4ceb9fe1a85ec53L;
h
^=
(
h
>>>
33
);
//
h ^= (h >>> 33);
return
h
;
//
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
;
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/AABB_BVH.java
deleted
100644 → 0
View file @
c67a5961
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
;
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/BVHStructures.java
deleted
100644 → 0
View file @
c67a5961
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
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/
AABB
Tree.java
→
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/
BoundingVolumeHierarchy
Tree.java
View file @
7f3fa92f
...
@@ -5,14 +5,16 @@ import java.util.List;
...
@@ -5,14 +5,16 @@ import java.util.List;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.function.Function
;
import
java.util.function.Function
;
import
de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon
;
/**
/**
* Generic AABB Tree implementation using a binary tree structure.
* 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.
* @param <E> The type of elements stored in the tree, which must be able to provide an AABB.
*/
*/
public
class
AABB
Tree
<
E
>
{
public
class
BoundingVolumeHierarchy
Tree
<
E
>
{
private
BVHStructures
.
Node
<
E
>
root
;
private
Node
<
E
>
root
;
private
final
Function
<
E
,
AABB
>
aabbFunction
;
private
final
Function
<
E
,
AABB
>
aabbFunction
;
/**
/**
...
@@ -20,7 +22,7 @@ public class AABBTree<E> {
...
@@ -20,7 +22,7 @@ public class AABBTree<E> {
*
*
* @param aabbFunction Function to extract an AABB from an element of type E
* @param aabbFunction Function to extract an AABB from an element of type E
*/
*/
public
AABB
Tree
(
Function
<
E
,
AABB
>
aabbFunction
)
{
public
BoundingVolumeHierarchy
Tree
(
Function
<
E
,
AABB
>
aabbFunction
)
{
this
.
root
=
null
;
this
.
root
=
null
;
this
.
aabbFunction
=
aabbFunction
;
this
.
aabbFunction
=
aabbFunction
;
}
}
...
@@ -31,7 +33,7 @@ public class AABBTree<E> {
...
@@ -31,7 +33,7 @@ public class AABBTree<E> {
* @param elements The list of elements to insert into the tree
* @param elements The list of elements to insert into the tree
* @param aabbFunction Function to extract an AABB from an element of type E
* @param aabbFunction Function to extract an AABB from an element of type E
*/
*/
public
AABB
Tree
(
List
<
E
>
elements
,
Function
<
E
,
AABB
>
aabbFunction
)
{
public
BoundingVolumeHierarchy
Tree
(
List
<
E
>
elements
,
Function
<
E
,
AABB
>
aabbFunction
)
{
this
.
aabbFunction
=
aabbFunction
;
this
.
aabbFunction
=
aabbFunction
;
if
(
elements
==
null
||
elements
.
isEmpty
())
{
if
(
elements
==
null
||
elements
.
isEmpty
())
{
this
.
root
=
null
;
this
.
root
=
null
;
...
@@ -39,36 +41,66 @@ public class AABBTree<E> {
...
@@ -39,36 +41,66 @@ public class AABBTree<E> {
this
.
root
=
buildRecursive
(
elements
);
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.
* Returns the root node of the AABB tree.
*/
*/
public
BVHStructures
.
Node
<
E
>
getRoot
()
{
public
Node
<
E
>
getRoot
()
{
return
root
;
return
root
;
}
}
/**
/**
* Sets the root node manually.
* Sets the root node manually.
*/
*/
public
void
setRoot
(
BVHStructures
.
Node
<
E
>
root
)
{
public
void
setRoot
(
Node
<
E
>
root
)
{
this
.
root
=
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.
* 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
)
{
if
(
elements
.
size
()
==
1
)
{
E
elem
=
elements
.
get
(
0
);
E
elem
=
elements
.
get
(
0
);
BVHStructures
.
Node
<
E
>
leaf
=
new
BVHStructures
.
Node
<>();
return
new
Node
<>(
elem
,
aabbFunction
.
apply
(
elem
));
leaf
.
element
=
elem
;
leaf
.
aabb
=
aabbFunction
.
apply
(
elem
);
return
leaf
;
}
}
// Compute total AABB
// Compute total AABB
AABB
totalAabb
=
BVHStructures
.
getAggregateAABB
(
elements
,
aabbFunction
);
AABB
totalAabb
=
getAggregateAABB
(
elements
,
aabbFunction
);
int
axis
=
BVHStructures
.
findLongestAxis
(
totalAabb
);
int
axis
=
totalAabb
.
findLongestAxis
();
// Sort elements along axis
// Sort elements along axis
elements
.
sort
(
Comparator
.
comparingDouble
(
e
->
elements
.
sort
(
Comparator
.
comparingDouble
(
e
->
...
@@ -77,10 +109,9 @@ public class AABBTree<E> {
...
@@ -77,10 +109,9 @@ public class AABBTree<E> {
List
<
E
>
leftList
=
elements
.
subList
(
0
,
mid
);
List
<
E
>
leftList
=
elements
.
subList
(
0
,
mid
);
List
<
E
>
rightList
=
elements
.
subList
(
mid
,
elements
.
size
());
List
<
E
>
rightList
=
elements
.
subList
(
mid
,
elements
.
size
());
BVHStructures
.
Node
<
E
>
node
=
new
BVHStructures
.
Node
<>();
Node
<
E
>
node
=
new
Node
<>(
null
,
totalAabb
);
node
.
aabb
=
totalAabb
;
node
.
getChildren
().
add
(
buildRecursive
(
leftList
));
node
.
children
.
add
(
buildRecursive
(
leftList
));
node
.
getChildren
().
add
(
buildRecursive
(
rightList
));
node
.
children
.
add
(
buildRecursive
(
rightList
));
return
node
;
return
node
;
}
}
...
@@ -101,17 +132,17 @@ public class AABBTree<E> {
...
@@ -101,17 +132,17 @@ public class AABBTree<E> {
*
*
*
*
*/
*/
private
void
findCandidatesRecursive
(
BVHStructures
.
Node
<
E
>
node
,
AABB
query
,
List
<
E
>
result
)
{
private
void
findCandidatesRecursive
(
Node
<
E
>
node
,
AABB
query
,
List
<
E
>
result
)
{
if
(
node
==
null
||
!
node
.
a
abb
.
intersects
(
query
))
{
if
(
node
==
null
||
!
node
.
getA
abb
()
.
intersects
(
query
))
{
return
;
return
;
}
}
if
(
node
.
isLeaf
())
{
if
(
node
.
isLeaf
())
{
if
(
aabbFunction
.
apply
(
node
.
e
lement
).
intersects
(
query
))
{
if
(
aabbFunction
.
apply
(
node
.
getE
lement
()
).
intersects
(
query
))
{
result
.
add
(
node
.
e
lement
);
result
.
add
(
node
.
getE
lement
()
);
}
}
}
else
{
}
else
{
for
(
BVHStructures
.
Node
<
E
>
child
:
node
.
c
hildren
)
{
for
(
Node
<
E
>
child
:
node
.
getC
hildren
()
)
{
findCandidatesRecursive
(
child
,
query
,
result
);
findCandidatesRecursive
(
child
,
query
,
result
);
}
}
}
}
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/Line.java
deleted
100644 → 0
View file @
c67a5961
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
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/Node.java
0 → 100644
View file @
7f3fa92f
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
;
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/Point.java
deleted
100644 → 0
View file @
c67a5961
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
=
1
e
-
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
+
")"
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/bht/Point3d.java
0 → 100644
View file @
7f3fa92f
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
);
}
}
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/bht/
Test
AABB.java
→
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/bht/AABB
Test
.java
View file @
7f3fa92f
package
de.hft.stuttgart.citydoctor2.datastructure.bht
;
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.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
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.LinearRing.LinearRingType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
public
class
Test
AABB
{
public
class
AABB
Test
{
/**
/**
* Entry point for AABB testing
* 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
();
ConcretePolygon
polygon
=
new
ConcretePolygon
();
LinearRing
exterior
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
LinearRing
exterior
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
...
@@ -26,10 +34,10 @@ public class TestAABB {
...
@@ -26,10 +34,10 @@ public class TestAABB {
polygon
.
setExteriorRing
(
exterior
);
polygon
.
setExteriorRing
(
exterior
);
// Define points of a tetrahedron
// Define points of a tetrahedron
Point
p1
=
new
Point
(
0
,
0
,
0
);
Point
3d
p1
=
new
Point
3d
(
0
,
0
,
0
);
Point
p2
=
new
Point
(
1
,
0
,
0
);
Point
3d
p2
=
new
Point
3d
(
1
,
0
,
0
);
Point
p3
=
new
Point
(
0.5
,
1
,
0
);
Point
3d
p3
=
new
Point
3d
(
0.5
,
1
,
0
);
Point
p4
=
new
Point
(
0.5
,
0.5
,
1
);
Point
3d
p4
=
new
Point
3d
(
0.5
,
0.5
,
1
);
// Define triangle faces of the tetrahedron
// Define triangle faces of the tetrahedron
ConcretePolygon
base
=
new
ConcretePolygon
();
ConcretePolygon
base
=
new
ConcretePolygon
();
...
@@ -64,11 +72,10 @@ public class TestAABB {
...
@@ -64,11 +72,10 @@ public class TestAABB {
ring3
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
ring3
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
side3
.
setExteriorRing
(
ring3
);
side3
.
setExteriorRing
(
ring3
);
List
<
Concrete
Polygon
>
poly
=
Arrays
.
asList
(
base
,
side1
,
side2
,
side3
);
List
<
Polygon
>
poly
s
=
Arrays
.
asList
(
base
,
side1
,
side2
,
side3
);
AABB
aabb
=
BVHStructures
.
getAggregateAABB
(
poly
);
AABB
aabb
=
AABB
.
ofPolygons
(
polys
);
System
.
out
.
println
(
"\nComputed AABB:"
);
// System.out.println("\nComputed " + aabb);
aabb
.
print
();
/*** 3D-Point-coords with Test Properties ***/
/*** 3D-Point-coords with Test Properties ***/
// Inside laying Point
// Inside laying Point
...
@@ -84,13 +91,21 @@ public class TestAABB {
...
@@ -84,13 +91,21 @@ public class TestAABB {
double
testOnEdgeY
=
1.0
;
double
testOnEdgeY
=
1.0
;
double
testOnEdgeZ
=
0.0
;
double
testOnEdgeZ
=
0.0
;
System
.
out
.
println
(
"\nTest point (inside): "
+
testInsideX
+
" "
+
testInsideY
+
" "
+
testInsideZ
);
// inside point
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testInsideX
,
testInsideY
,
testInsideZ
));
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
);
// outside point
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testOutsideX
,
testOutsideY
,
testOutsideZ
));
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
);
// edge point
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testOnEdgeX
,
testOnEdgeY
,
testOnEdgeZ
));
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));
}
}
}
}
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/bht/TestHouseAABB.java
View file @
7f3fa92f
...
@@ -26,20 +26,20 @@ public class TestHouseAABB {
...
@@ -26,20 +26,20 @@ public class TestHouseAABB {
double
roofHeight
=
1.0
;
double
roofHeight
=
1.0
;
// points for Ground floor
// points for Ground floor
Point
b1
=
new
Point
(
0
,
0
,
0
);
Point
3d
b1
=
new
Point
3d
(
0
,
0
,
0
);
Point
b2
=
new
Point
(
baseSize
,
0
,
0
);
Point
3d
b2
=
new
Point
3d
(
baseSize
,
0
,
0
);
Point
b3
=
new
Point
(
baseSize
,
baseSize
,
0
);
Point
3d
b3
=
new
Point
3d
(
baseSize
,
baseSize
,
0
);
Point
b4
=
new
Point
(
0
,
baseSize
,
0
);
Point
3d
b4
=
new
Point
3d
(
0
,
baseSize
,
0
);
// points for Roof
// points for Roof
Point
t1
=
new
Point
(
0
,
0
,
height
);
Point
3d
t1
=
new
Point
3d
(
0
,
0
,
height
);
Point
t2
=
new
Point
(
baseSize
,
0
,
height
);
Point
3d
t2
=
new
Point
3d
(
baseSize
,
0
,
height
);
Point
t3
=
new
Point
(
baseSize
,
baseSize
,
height
);
Point
3d
t3
=
new
Point
3d
(
baseSize
,
baseSize
,
height
);
Point
t4
=
new
Point
(
0
,
baseSize
,
height
);
Point
3d
t4
=
new
Point
3d
(
0
,
baseSize
,
height
);
// Roofpeaks
// Roofpeaks
Point
roofPeak1
=
new
Point
(
baseSize
/
2
,
-
0.2
,
height
+
roofHeight
);
Point
3d
roofPeak1
=
new
Point
3d
(
baseSize
/
2
,
-
0.2
,
height
+
roofHeight
);
Point
roofPeak2
=
new
Point
(
baseSize
/
2
,
baseSize
+
0.2
,
height
+
roofHeight
);
Point
3d
roofPeak2
=
new
Point
3d
(
baseSize
/
2
,
baseSize
+
0.2
,
height
+
roofHeight
);
List
<
ConcretePolygon
>
house
=
new
ArrayList
<>();
List
<
ConcretePolygon
>
house
=
new
ArrayList
<>();
...
@@ -63,8 +63,8 @@ public class TestHouseAABB {
...
@@ -63,8 +63,8 @@ public class TestHouseAABB {
house
.
add
(
createQuadPolygon
(
t1
,
t4
,
roofPeak2
,
roofPeak1
));
house
.
add
(
createQuadPolygon
(
t1
,
t4
,
roofPeak2
,
roofPeak1
));
AABB
houseAABB
=
BVHStructures
.
getAggregateAABB
(
house
);
AABB
houseAABB
=
AABB
.
ofPolygons
(
house
);
houseAABB
.
print
();
//
houseAABB.print();
// Define test points
// Define test points
double
[]
insidePoint
=
{
1.0
,
1.0
,
1.0
};
// clearly inside (center of the base cube)
double
[]
insidePoint
=
{
1.0
,
1.0
,
1.0
};
// clearly inside (center of the base cube)
...
@@ -74,21 +74,21 @@ public class TestHouseAABB {
...
@@ -74,21 +74,21 @@ public class TestHouseAABB {
// Test containment
// Test containment
System
.
out
.
println
(
"\nTest point (inside): "
+
Arrays
.
toString
(
insidePoint
));
System
.
out
.
println
(
"\nTest point (inside): "
+
Arrays
.
toString
(
insidePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
enclose
s
(
insidePoint
[
0
],
insidePoint
[
1
],
insidePoint
[
2
]));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
contain
s
(
insidePoint
[
0
],
insidePoint
[
1
],
insidePoint
[
2
]));
System
.
out
.
println
(
"\nTest point (on roof): "
+
Arrays
.
toString
(
roofPoint
));
System
.
out
.
println
(
"\nTest point (on roof): "
+
Arrays
.
toString
(
roofPoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
enclose
s
(
roofPoint
[
0
],
roofPoint
[
1
],
roofPoint
[
2
]));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
contain
s
(
roofPoint
[
0
],
roofPoint
[
1
],
roofPoint
[
2
]));
System
.
out
.
println
(
"\nTest point (outside): "
+
Arrays
.
toString
(
outsidePoint
));
System
.
out
.
println
(
"\nTest point (outside): "
+
Arrays
.
toString
(
outsidePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
enclose
s
(
outsidePoint
[
0
],
outsidePoint
[
1
],
outsidePoint
[
2
]));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
contain
s
(
outsidePoint
[
0
],
outsidePoint
[
1
],
outsidePoint
[
2
]));
System
.
out
.
println
(
"\nTest point (on edge): "
+
Arrays
.
toString
(
edgePoint
));
System
.
out
.
println
(
"\nTest point (on edge): "
+
Arrays
.
toString
(
edgePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
enclose
s
(
edgePoint
[
0
],
edgePoint
[
1
],
edgePoint
[
2
]));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
contain
s
(
edgePoint
[
0
],
edgePoint
[
1
],
edgePoint
[
2
]));
}
}
/** Creates a triangular polygon from three points */
/** Creates a triangular polygon from three points */
private
static
ConcretePolygon
createTrianglePolygon
(
Point
p1
,
Point
p2
,
Point
p3
)
{
private
static
ConcretePolygon
createTrianglePolygon
(
Point
3d
p1
,
Point
3d
p2
,
Point
3d
p3
)
{
// alocate poly
// alocate poly
ConcretePolygon
poly
=
new
ConcretePolygon
();
ConcretePolygon
poly
=
new
ConcretePolygon
();
// alocate ring
// alocate ring
...
@@ -104,7 +104,7 @@ public class TestHouseAABB {
...
@@ -104,7 +104,7 @@ public class TestHouseAABB {
}
}
/** Creates a quadrilateral polygon from four points */
/** Creates a quadrilateral polygon from four points */
private
static
ConcretePolygon
createQuadPolygon
(
Point
p1
,
Point
p2
,
Point
p3
,
Point
p4
)
{
private
static
ConcretePolygon
createQuadPolygon
(
Point
3d
p1
,
Point
3d
p2
,
Point
3d
p3
,
Point
3d
p4
)
{
ConcretePolygon
poly
=
new
ConcretePolygon
();
ConcretePolygon
poly
=
new
ConcretePolygon
();
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/bht/RingSelfIntCheckAABB.java
View file @
7f3fa92f
...
@@ -167,7 +167,7 @@ public class RingSelfIntCheckAABB extends Check {
...
@@ -167,7 +167,7 @@ public class RingSelfIntCheckAABB extends Check {
// --- AABB replacement for BoundingBox.ofPoints(rotatedVertices) ---
// --- AABB replacement for BoundingBox.ofPoints(rotatedVertices) ---
// Computes the axis-aligned extents of the rotated point cloud.
// Computes the axis-aligned extents of the rotated point cloud.
AABB
aabb
=
AABB
Utils
.
aabbFromVector3d
(
rotatedVertices
);
AABB
aabb
=
AABB
.
ofPoints
(
rotatedVertices
);
double
dx
=
aabb
.
getMaxX
()
-
aabb
.
getMinX
();
double
dx
=
aabb
.
getMaxX
()
-
aabb
.
getMinX
();
double
dy
=
aabb
.
getMaxY
()
-
aabb
.
getMinY
();
double
dy
=
aabb
.
getMaxY
()
-
aabb
.
getMinY
();
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/bht/SolidSelfIntCheckAABB.java
View file @
7f3fa92f
...
@@ -86,21 +86,24 @@ public class SolidSelfIntCheckAABB extends Check {
...
@@ -86,21 +86,24 @@ public class SolidSelfIntCheckAABB extends Check {
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
return
;
return
;
}
}
// Building BVH Tree
// Build AABBs once
// Build AABBs once
AABB
[]
boxes
=
new
AABB
[
polys
.
size
()];
AABB
[]
boxes
=
new
AABB
[
polys
.
size
()];
for
(
int
i
=
0
;
i
<
polys
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
polys
.
size
();
i
++)
{
ConcretePolygon
cp
=
polys
.
get
(
i
).
getOriginal
();
ConcretePolygon
cp
=
polys
.
get
(
i
).
getOriginal
();
boxes
[
i
]
=
AABB
Utils
.
getAABB
(
cp
);
boxes
[
i
]
=
AABB
.
of
(
cp
);
}
}
// If no AABB pair overlaps, self-intersection is impossible
// If no AABB pair overlaps, self-intersection is impossible
if
(!
AABB
Utils
.
any
Overlap
(
boxes
))
{
if
(!
AABB
.
doAnyBoxes
Overlap
(
boxes
))
{
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
return
;
return
;
}
}
// --- ---
// --- ---
CheckResult
cr
;
CheckResult
cr
;
List
<
PolygonIntersection
>
intersections
=
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
);
List
<
PolygonIntersection
>
intersections
=
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
,
0.001
,
tree
);
if
(
intersections
.
isEmpty
())
{
if
(
intersections
.
isEmpty
())
{
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
}
else
{
}
else
{
...
@@ -110,18 +113,6 @@ public class SolidSelfIntCheckAABB extends Check {
...
@@ -110,18 +113,6 @@ public class SolidSelfIntCheckAABB extends Check {
g
.
addCheckResult
(
cr
);
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
@Override
public
List
<
CheckId
>
getDependencies
()
{
public
List
<
CheckId
>
getDependencies
()
{
return
dependencies
;
return
dependencies
;
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/SelfIntersectionUtil.java
View file @
7f3fa92f
...
@@ -49,6 +49,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
...
@@ -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.LinearRing.LinearRingType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
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.EdgePolygon
;
import
de.hft.stuttgart.citydoctor2.edge.IntersectPlanarPolygons
;
import
de.hft.stuttgart.citydoctor2.edge.IntersectPlanarPolygons
;
import
de.hft.stuttgart.citydoctor2.edge.MeshSurface
;
import
de.hft.stuttgart.citydoctor2.edge.MeshSurface
;
...
@@ -89,7 +91,7 @@ public class SelfIntersectionUtil {
...
@@ -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
<>();
List
<
TesselatedPolygon
>
tesselatedPolygons
=
new
ArrayList
<>();
for
(
Polygon
p
:
g
.
getPolygons
())
{
for
(
Polygon
p
:
g
.
getPolygons
())
{
TesselatedPolygon
tessPolygon
=
EarcutTesselator
.
tesselatePolygon
(
p
);
TesselatedPolygon
tessPolygon
=
EarcutTesselator
.
tesselatePolygon
(
p
);
...
@@ -116,6 +118,11 @@ public class SelfIntersectionUtil {
...
@@ -116,6 +118,11 @@ public class SelfIntersectionUtil {
List
<
PolygonIntersection
>
intersections
=
new
ArrayList
<>();
List
<
PolygonIntersection
>
intersections
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
tesselatedPolygons
.
size
()
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
tesselatedPolygons
.
size
()
-
1
;
i
++)
{
TesselatedPolygon
p1
=
tesselatedPolygons
.
get
(
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
++)
{
for
(
int
j
=
i
+
1
;
j
<
tesselatedPolygons
.
size
();
j
++)
{
TesselatedPolygon
p2
=
tesselatedPolygons
.
get
(
j
);
TesselatedPolygon
p2
=
tesselatedPolygons
.
get
(
j
);
GeometrySelfIntersection
intersection
=
doPolygonsIntersect
(
p1
,
p2
,
delta
);
GeometrySelfIntersection
intersection
=
doPolygonsIntersect
(
p1
,
p2
,
delta
);
...
...
CityDoctorParent/Extensions/CityDoctorHealer/src/test/java/de/hft/stuttgart/citydoctor2/healing/bht/TestCityGmlAABB.java
View file @
7f3fa92f
...
@@ -82,7 +82,7 @@ public class TestCityGmlAABB {
...
@@ -82,7 +82,7 @@ public class TestCityGmlAABB {
System
.
out
.
println
(
"\n> Polygon-level AABB (broad-phase)"
);
System
.
out
.
println
(
"\n> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABB
Tree
<
ConcretePolygon
>
bvh
=
new
AABB
Tree
<>(
BoundingVolumeHierarchy
Tree
<
ConcretePolygon
>
bvh
=
new
BoundingVolumeHierarchy
Tree
<>(
new
ArrayList
<>(
polys
),
new
ArrayList
<>(
polys
),
AABBUtils:
:
getAABB
AABBUtils:
:
getAABB
);
);
...
@@ -102,7 +102,7 @@ public class TestCityGmlAABB {
...
@@ -102,7 +102,7 @@ public class TestCityGmlAABB {
?
collectExteriorRings
(
buildings
)
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
:
collectInteriorRings
(
buildings
);
AABB
Tree
<
LinearRing
>
bvh
=
new
AABB
Tree
<>(
BoundingVolumeHierarchy
Tree
<
LinearRing
>
bvh
=
new
BoundingVolumeHierarchy
Tree
<>(
new
ArrayList
<>(
rings
),
new
ArrayList
<>(
rings
),
AABBUtils:
:
computeAABBFromRing
AABBUtils:
:
computeAABBFromRing
);
);
...
@@ -118,7 +118,7 @@ public class TestCityGmlAABB {
...
@@ -118,7 +118,7 @@ public class TestCityGmlAABB {
System
.
out
.
println
(
"\n> Vertex-level AABB (fine-phase)"
);
System
.
out
.
println
(
"\n> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABB
Tree
<>(
BoundingVolumeHierarchyTree
<
Vertex
>
bvh
=
new
BoundingVolumeHierarchy
Tree
<>(
new
ArrayList
<>(
verts
),
new
ArrayList
<>(
verts
),
AABBUtils:
:
computeAABBFromVertex
AABBUtils:
:
computeAABBFromVertex
);
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment