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
fb72860f
Commit
fb72860f
authored
May 26, 2026
by
Numanoglu
Browse files
Add BVH auto usage policy
parent
e7bb119d
Changes
4
Show whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/NestedRingsCheck.java
View file @
fb72860f
...
@@ -34,6 +34,8 @@ import de.hft.stuttgart.citydoctor2.check.RequirementType;
...
@@ -34,6 +34,8 @@ import de.hft.stuttgart.citydoctor2.check.RequirementType;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.check.error.NestedRingError
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy.BvhCheckType
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
...
@@ -134,6 +136,10 @@ public class NestedRingsCheck extends Check {
...
@@ -134,6 +136,10 @@ public class NestedRingsCheck extends Check {
checkWithBoundingBoxFilter
(
p
);
checkWithBoundingBoxFilter
(
p
);
}
else
if
(
variant
.
isBvh
())
{
}
else
if
(
variant
.
isBvh
())
{
checkWithBvhFilter
(
p
,
variant
.
getSplitStrategy
());
checkWithBvhFilter
(
p
,
variant
.
getSplitStrategy
());
}
else
if
(
BvhUsagePolicy
.
shouldUseTree
(
BvhCheckType
.
NESTED_RINGS
,
p
.
getInnerRings
().
size
()))
{
SplitStrategy
splitStrategy
=
BvhUsagePolicy
.
chooseSplitStrategy
(
BvhCheckType
.
NESTED_RINGS
,
p
.
getInnerRings
().
size
());
checkWithBvhFilter
(
p
,
splitStrategy
);
}
else
if
(
p
.
getInnerRings
().
size
()
>
3
)
{
}
else
if
(
p
.
getInnerRings
().
size
()
>
3
)
{
checkWithBoundingBoxFilter
(
p
);
checkWithBoundingBoxFilter
(
p
);
}
else
{
}
else
{
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/RingSelfIntCheck.java
View file @
fb72860f
...
@@ -36,6 +36,8 @@ import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
...
@@ -36,6 +36,8 @@ import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import
de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError
;
import
de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError
;
import
de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy.BvhCheckType
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.Edge
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
...
@@ -89,6 +91,7 @@ public class RingSelfIntCheck extends Check {
...
@@ -89,6 +91,7 @@ public class RingSelfIntCheck extends Check {
}
}
public
enum
Variant
{
public
enum
Variant
{
AUTO
,
OLD
,
OLD
,
BVH_BINARY_OBJECT_MEDIAN
(
SplitStrategy
.
BINARY_OBJECT_MEDIAN
),
BVH_BINARY_OBJECT_MEDIAN
(
SplitStrategy
.
BINARY_OBJECT_MEDIAN
),
BVH_BINARY_OBJECT_MEAN
(
SplitStrategy
.
BINARY_OBJECT_MEAN
),
BVH_BINARY_OBJECT_MEAN
(
SplitStrategy
.
BINARY_OBJECT_MEAN
),
...
@@ -153,6 +156,17 @@ public class RingSelfIntCheck extends Check {
...
@@ -153,6 +156,17 @@ public class RingSelfIntCheck extends Check {
checkRingOld
(
lr
);
checkRingOld
(
lr
);
return
;
return
;
}
}
if
(
variant
==
Variant
.
AUTO
)
{
int
edgeCount
=
Math
.
max
(
0
,
lr
.
getVertices
().
size
()
-
1
);
if
(
BvhUsagePolicy
.
shouldUseTree
(
BvhCheckType
.
RING_SELF_INTERSECTION
,
edgeCount
))
{
SplitStrategy
splitStrategy
=
BvhUsagePolicy
.
chooseSplitStrategy
(
BvhCheckType
.
RING_SELF_INTERSECTION
,
edgeCount
);
checkRingBvh
(
lr
,
splitStrategy
);
}
else
{
checkRingOld
(
lr
);
}
return
;
}
checkRingBvh
(
lr
,
variant
.
getSplitStrategy
());
checkRingBvh
(
lr
,
variant
.
getSplitStrategy
());
}
}
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/geometry/SolidSelfIntCheck.java
View file @
fb72860f
...
@@ -32,10 +32,14 @@ import de.hft.stuttgart.citydoctor2.check.Requirement;
...
@@ -32,10 +32,14 @@ import de.hft.stuttgart.citydoctor2.check.Requirement;
import
de.hft.stuttgart.citydoctor2.check.RequirementType
;
import
de.hft.stuttgart.citydoctor2.check.RequirementType
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError
;
import
de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy
;
import
de.hft.stuttgart.citydoctor2.checks.util.BvhUsagePolicy.BvhCheckType
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.checks.util.CollectionUtils
;
import
de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil
;
import
de.hft.stuttgart.citydoctor2.checks.util.SelfIntersectionUtil
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GeometryType
;
import
de.hft.stuttgart.citydoctor2.datastructure.GeometryType
;
import
de.hft.stuttgart.citydoctor2.datastructure.bht.BoundingVolumeHierarchyTree
;
import
de.hft.stuttgart.citydoctor2.datastructure.bht.SplitStrategy
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.PolygonIntersection
;
import
de.hft.stuttgart.citydoctor2.utils.PolygonIntersection
;
...
@@ -50,6 +54,39 @@ public class SolidSelfIntCheck extends Check {
...
@@ -50,6 +54,39 @@ public class SolidSelfIntCheck extends Check {
private
static
final
List
<
CheckId
>
dependencies
;
private
static
final
List
<
CheckId
>
dependencies
;
private
double
delta
=
0.01
;
private
double
delta
=
0.01
;
private
Variant
variant
=
Variant
.
OLD
;
public
enum
Variant
{
AUTO
,
OLD
,
BVH_BINARY_OBJECT_MEDIAN
(
SplitStrategy
.
BINARY_OBJECT_MEDIAN
),
BVH_BINARY_OBJECT_MEAN
(
SplitStrategy
.
BINARY_OBJECT_MEAN
),
BVH_BINARY_SPATIAL_MEDIAN
(
SplitStrategy
.
BINARY_SPATIAL_MEDIAN
),
BVH_OCTONARY_OBJECT_MEDIAN
(
SplitStrategy
.
OCTONARY_OBJECT_MEDIAN
),
BVH_OCTONARY_OBJECT_MEAN
(
SplitStrategy
.
OCTONARY_OBJECT_MEAN
),
BVH_OCTONARY_SPATIAL_MEDIAN
(
SplitStrategy
.
OCTONARY_SPATIAL_MEDIAN
);
private
final
SplitStrategy
splitStrategy
;
Variant
()
{
this
.
splitStrategy
=
null
;
}
Variant
(
SplitStrategy
splitStrategy
)
{
this
.
splitStrategy
=
splitStrategy
;
}
public
boolean
isBvh
()
{
return
splitStrategy
!=
null
;
}
public
SplitStrategy
getSplitStrategy
()
{
if
(
splitStrategy
==
null
)
{
throw
new
IllegalStateException
(
"Variant "
+
this
+
" has no BVH split strategy."
);
}
return
splitStrategy
;
}
}
static
{
static
{
ArrayList
<
CheckId
>
deps
=
new
ArrayList
<>();
ArrayList
<
CheckId
>
deps
=
new
ArrayList
<>();
...
@@ -79,14 +116,28 @@ public class SolidSelfIntCheck extends Check {
...
@@ -79,14 +116,28 @@ public class SolidSelfIntCheck extends Check {
}
}
}
}
public
SolidSelfIntCheck
()
{
}
public
SolidSelfIntCheck
(
Variant
variant
)
{
this
.
variant
=
variant
;
}
public
void
setVariant
(
Variant
variant
)
{
this
.
variant
=
variant
;
}
public
Variant
getVariant
()
{
return
variant
;
}
@Override
@Override
public
void
check
(
Geometry
g
)
{
public
void
check
(
Geometry
g
)
{
if
(
g
.
getType
()
!=
GeometryType
.
SOLID
&&
g
.
getType
()
!=
GeometryType
.
COMPOSITE_SURFACE
)
{
if
(
g
.
getType
()
!=
GeometryType
.
SOLID
&&
g
.
getType
()
!=
GeometryType
.
COMPOSITE_SURFACE
)
{
return
;
return
;
}
}
CheckResult
cr
;
CheckResult
cr
;
// TODO: reproduce older version by Mathias of calculateSolidSefInt to compare
List
<
PolygonIntersection
>
intersections
=
calculateIntersections
(
g
);
List
<
PolygonIntersection
>
intersections
=
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
,
delta
);
if
(
intersections
.
isEmpty
())
{
if
(
intersections
.
isEmpty
())
{
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
}
else
{
}
else
{
...
@@ -96,6 +147,36 @@ public class SolidSelfIntCheck extends Check {
...
@@ -96,6 +147,36 @@ public class SolidSelfIntCheck extends Check {
g
.
addCheckResult
(
cr
);
g
.
addCheckResult
(
cr
);
}
}
private
List
<
PolygonIntersection
>
calculateIntersections
(
Geometry
g
)
{
if
(
variant
==
Variant
.
OLD
)
{
return
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
,
delta
);
}
if
(
variant
.
isBvh
())
{
return
calculateIntersectionsWithTree
(
g
,
variant
.
getSplitStrategy
());
}
int
polygonCount
=
g
.
getPolygons
().
size
();
if
(!
BvhUsagePolicy
.
shouldUseTree
(
BvhCheckType
.
SOLID_SELF_INTERSECTION
,
polygonCount
))
{
return
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
,
delta
);
}
SplitStrategy
splitStrategy
=
BvhUsagePolicy
.
chooseSplitStrategy
(
BvhCheckType
.
SOLID_SELF_INTERSECTION
,
polygonCount
);
return
calculateIntersectionsWithTree
(
g
,
splitStrategy
);
}
private
List
<
PolygonIntersection
>
calculateIntersectionsWithTree
(
Geometry
g
,
SplitStrategy
splitStrategy
)
{
BoundingVolumeHierarchyTree
.
Builder
<
Integer
>
treeConfig
=
BoundingVolumeHierarchyTree
.<
Integer
>
builder
()
.
degree
(
isBinary
(
splitStrategy
)
?
2
:
8
)
.
splitStrategy
(
splitStrategy
);
return
SelfIntersectionUtil
.
calculateSolidSelfIntersectionWithTree
(
g
,
delta
,
treeConfig
);
}
private
static
boolean
isBinary
(
SplitStrategy
splitStrategy
)
{
return
splitStrategy
==
SplitStrategy
.
BINARY_OBJECT_MEDIAN
||
splitStrategy
==
SplitStrategy
.
BINARY_OBJECT_MEAN
||
splitStrategy
==
SplitStrategy
.
BINARY_SPATIAL_MEDIAN
;
}
@Override
@Override
public
List
<
CheckId
>
getDependencies
()
{
public
List
<
CheckId
>
getDependencies
()
{
return
dependencies
;
return
dependencies
;
...
@@ -113,7 +194,7 @@ public class SolidSelfIntCheck extends Check {
...
@@ -113,7 +194,7 @@ public class SolidSelfIntCheck extends Check {
@Override
@Override
public
Check
createNewInstance
()
{
public
Check
createNewInstance
()
{
return
new
SolidSelfIntCheck
();
return
new
SolidSelfIntCheck
(
variant
);
}
}
@Override
@Override
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/BvhUsagePolicy.java
0 → 100644
View file @
fb72860f
package
de.hft.stuttgart.citydoctor2.checks.util
;
import
de.hft.stuttgart.citydoctor2.datastructure.bht.SplitStrategy
;
/**
* Central policy for cheap BVH decisions in geometry checks.
*/
public
final
class
BvhUsagePolicy
{
private
static
final
int
SOLID_SELF_INTERSECTION_TREE_THRESHOLD
=
16
;
private
static
final
int
NESTED_RINGS_TREE_THRESHOLD
=
8
;
private
static
final
int
RING_SELF_INTERSECTION_TREE_THRESHOLD
=
32
;
private
BvhUsagePolicy
()
{
}
public
enum
BvhCheckType
{
SOLID_SELF_INTERSECTION
,
NESTED_RINGS
,
RING_SELF_INTERSECTION
}
public
static
boolean
shouldUseTree
(
BvhCheckType
checkType
,
int
elementCount
)
{
if
(
elementCount
<
2
)
{
return
false
;
}
return
elementCount
>=
thresholdFor
(
checkType
);
}
public
static
SplitStrategy
chooseSplitStrategy
(
BvhCheckType
checkType
,
int
elementCount
)
{
if
(
checkType
==
BvhCheckType
.
RING_SELF_INTERSECTION
)
{
return
SplitStrategy
.
BINARY_SPATIAL_MEDIAN
;
}
if
(
elementCount
>=
128
)
{
return
SplitStrategy
.
OCTONARY_OBJECT_MEAN
;
}
return
SplitStrategy
.
BINARY_SPATIAL_MEDIAN
;
}
private
static
int
thresholdFor
(
BvhCheckType
checkType
)
{
switch
(
checkType
)
{
case
SOLID_SELF_INTERSECTION:
return
SOLID_SELF_INTERSECTION_TREE_THRESHOLD
;
case
NESTED_RINGS:
return
NESTED_RINGS_TREE_THRESHOLD
;
case
RING_SELF_INTERSECTION:
return
RING_SELF_INTERSECTION_TREE_THRESHOLD
;
default
:
throw
new
IllegalArgumentException
(
"Unsupported BVH check type: "
+
checkType
);
}
}
}
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