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
e53df320
Commit
e53df320
authored
Feb 11, 2026
by
Luna Riegel
Browse files
Feat: Implement feature collision check
parent
aeb56f2e
Changes
3
Show whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/LinearRing.java
View file @
e53df320
...
@@ -294,6 +294,15 @@ public class LinearRing extends GmlElement {
...
@@ -294,6 +294,15 @@ public class LinearRing extends GmlElement {
return
false
;
return
false
;
}
}
public
List
<
Ray
>
getEdgeRays
(){
List
<
Ray
>
rays
=
new
ArrayList
<>();
//First and last vertice are the same point
for
(
int
i
=
0
;
i
<
vertices
.
size
()
-
1
;
i
++){
rays
.
add
(
new
Ray
(
vertices
.
get
(
i
),
new
Vector3d
(
vertices
.
get
(
i
+
1
)).
minus
(
vertices
.
get
(
i
))));
}
return
rays
;
}
public
boolean
hasPointAsCorner
(
Vertex
v
)
{
public
boolean
hasPointAsCorner
(
Vertex
v
)
{
return
vertices
.
contains
(
v
);
return
vertices
.
contains
(
v
);
}
}
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/topology/FeatureCollisionCheck.java
View file @
e53df320
...
@@ -2,18 +2,36 @@ package de.hft.stuttgart.citydoctor2.checks.topology;
...
@@ -2,18 +2,36 @@ package de.hft.stuttgart.citydoctor2.checks.topology;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.Check
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckResult
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.check.Checkable
;
import
de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor
;
import
de.hft.stuttgart.citydoctor2.check.GlobalParameters
;
import
de.hft.stuttgart.citydoctor2.check.GlobalParameters
;
import
de.hft.stuttgart.citydoctor2.check.Requirement
;
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.error.FeatureCollisionError
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.Checks
;
import
de.hft.stuttgart.citydoctor2.checks.util.GeometryCollisionUtil
;
import
de.hft.stuttgart.citydoctor2.database.CityObjectCache
;
import
de.hft.stuttgart.citydoctor2.database.CityObjectCache
;
import
de.hft.stuttgart.citydoctor2.datastructure.BridgeObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Building
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityFurniture
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlId
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.OtherConstructionObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.TopLevelTransportFeature
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vegetation
;
import
de.hft.stuttgart.citydoctor2.edge.PolygonPolygonIntersection
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
...
@@ -40,7 +58,6 @@ public class FeatureCollisionCheck extends Check{
...
@@ -40,7 +58,6 @@ public class FeatureCollisionCheck extends Check{
}
}
@Override
@Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
Set
.
of
(
Requirement
.
R_TO_FEATURE_COLLISION
);
return
Set
.
of
(
Requirement
.
R_TO_FEATURE_COLLISION
);
...
@@ -71,11 +88,125 @@ public class FeatureCollisionCheck extends Check{
...
@@ -71,11 +88,125 @@ public class FeatureCollisionCheck extends Check{
}
}
@Override
@Override
public
void
check
(
CityObject
co
){
public
void
check
(
BridgeObject
bo
)
{
checkForFeatureCollisions
(
bo
);
}
@Override
public
void
check
(
Building
b
)
{
checkForFeatureCollisions
(
b
);
}
@Override
public
void
check
(
TopLevelTransportFeature
top
)
{
checkForFeatureCollisions
(
top
);
}
@Override
public
void
check
(
Vegetation
veg
)
{
checkForFeatureCollisions
(
veg
);
}
@Override
public
void
check
(
CityFurniture
cf
)
{
checkForFeatureCollisions
(
cf
);
}
@Override
public
void
check
(
GenericCityObject
gco
)
{
checkForFeatureCollisions
(
gco
);
}
@Override
public
void
check
(
OtherConstructionObject
oco
)
{
checkForFeatureCollisions
(
oco
);
}
private
void
checkForFeatureCollisions
(
CityObject
subject
){
Collection
<
CityObject
>
candidates
=
cache
.
getCandidates
(
subject
,
epsilon
);
List
<
Geometry
>
subjGeoms
=
new
ArrayList
<>();
subject
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
geom
)
{
subjGeoms
.
add
(
geom
);
}
});
List
<
CollisionRecord
>
collisions
=
new
ArrayList
<>();
subjGeoms
.
forEach
(
sGeo
->{
candidates
.
forEach
(
candidate
->{
candidate
.
accept
(
new
CheckableUtilsVisitor
()
{
@Override
public
void
check
(
Geometry
geom
)
{
List
<
PolygonPolygonIntersection
>
intersections
=
GeometryCollisionUtil
.
getGeometryIntersections
(
sGeo
,
geom
,
epsilon
);
if
(!
intersections
.
isEmpty
()){
CollisionRecord
collRec
=
new
CollisionRecord
(
sGeo
,
geom
,
candidate
);
intersections
.
forEach
(
ppi
->
collRec
.
addCollision
(
ppi
.
getPolygon1
().
getOriginal
(),
ppi
.
getPolygon2
().
getOriginal
()));
collisions
.
add
(
collRec
);
}
}
});
});
});
if
(
collisions
.
isEmpty
()){
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
}
else
{
for
(
CollisionRecord
collRec
:
collisions
){
subject
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
new
FeatureCollisionError
(
subject
,
collRec
.
getSubjectGeom
(),
collRec
.
getCollidingFeatureId
(),
collRec
.
getCollidingGeom
(),
collRec
.
getCollisionMap
())
));
}
}
}
private
static
class
CollisionRecord
{
private
final
Geometry
subjectGeom
;
private
final
Geometry
collidingGeom
;
private
final
GmlId
collidingFeatureId
;
private
final
Map
<
Polygon
,
List
<
Polygon
>>
collisionMap
;
public
CollisionRecord
(
Geometry
subjectGeom
,
Geometry
collidingGeom
,
CityObject
collidingFeature
){
this
.
subjectGeom
=
subjectGeom
;
this
.
collidingGeom
=
collidingGeom
;
this
.
collidingFeatureId
=
collidingFeature
.
getGmlId
();
this
.
collisionMap
=
new
HashMap
<>();
}
public
void
addCollision
(
Polygon
subjectPoly
,
Polygon
collidingPoly
){
List
<
Polygon
>
polyList
=
collisionMap
.
computeIfAbsent
(
subjectPoly
,
k
->
new
ArrayList
<>());
polyList
.
add
(
collidingPoly
);
}
}
public
Map
<
Polygon
,
List
<
Polygon
>>
getCollisionMap
()
{
return
collisionMap
;
}
public
Geometry
getSubjectGeom
()
{
return
subjectGeom
;
}
public
Geometry
getCollidingGeom
()
{
return
collidingGeom
;
}
public
GmlId
getCollidingFeatureId
()
{
return
collidingFeatureId
;
}
}
@Override
@Override
public
Check
createNewInstance
()
{
public
Check
createNewInstance
()
{
return
new
FeatureCollisionCheck
();
return
new
FeatureCollisionCheck
();
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/checks/util/GeometryCollisionUtil.java
0 → 100644
View file @
e53df320
package
de.hft.stuttgart.citydoctor2.checks.util
;
import
de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Geometry
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.edge.CDPolygonNs
;
import
de.hft.stuttgart.citydoctor2.edge.IntersectPlanarPolygons
;
import
de.hft.stuttgart.citydoctor2.edge.MeshSurface
;
import
de.hft.stuttgart.citydoctor2.edge.PolygonPolygonIntersection
;
import
de.hft.stuttgart.citydoctor2.math.Ray
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
GeometryCollisionUtil
{
public
static
boolean
doPolygonsCollide
(
Polygon
subjectPoly
,
Polygon
candidatePoly
,
double
samePointTolerance
){
ConcretePolygon
subject
=
subjectPoly
.
getOriginal
();
ConcretePolygon
candidate
=
candidatePoly
.
getOriginal
();
for
(
Ray
ray
:
subject
.
getExteriorRing
().
getEdgeRays
()){
Vector3d
intersection
=
ray
.
intersectsPolygon
(
candidate
);
if
(
intersection
!=
null
){
Vertex
nearestVertex
=
findClosestVertexToIntersection
(
intersection
,
candidate
);
if
(
nearestVertex
.
getDistance
(
intersection
)
<
samePointTolerance
){
continue
;
}
return
true
;
}
}
return
false
;
}
public
static
List
<
PolygonPolygonIntersection
>
getGeometryIntersections
(
Geometry
subject
,
Geometry
candidate
,
double
samePointTolerance
){
MeshSurface
subjectMesh
=
MeshSurface
.
of
(
subject
);
MeshSurface
candidateMesh
=
MeshSurface
.
of
(
candidate
);
List
<
PolygonPolygonIntersection
>
intersections
=
new
ArrayList
<>();
for
(
CDPolygonNs
subjPoly:
subjectMesh
.
polygons
()){
for
(
CDPolygonNs
candPoly:
candidateMesh
.
polygons
()){
intersections
=
IntersectPlanarPolygons
.
intersectPolygons
(
subjPoly
,
candPoly
,
samePointTolerance
,
0.001
);
intersections
=
intersections
.
stream
()
.
filter
(
ppi
->
!
ppi
.
getPolyLine
().
isNullLine
(
samePointTolerance
))
.
toList
();
}
}
return
intersections
;
}
public
static
Vertex
findClosestVertexToIntersection
(
Vector3d
intersection
,
ConcretePolygon
poly
){
List
<
Vertex
>
vertices
=
poly
.
getExteriorRing
().
getVertices
();
double
min
=
Double
.
MAX_VALUE
;
Vertex
closestVertex
=
null
;
for
(
Vertex
vertex
:
vertices
){
if
(
vertex
.
getDistance
(
intersection
)
<
min
){
closestVertex
=
vertex
;
min
=
vertex
.
getDistance
(
intersection
);
}
}
return
closestVertex
;
}
}
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