Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
1d8506eb
Commit
1d8506eb
authored
9 months ago
by
Riegel
Browse files
Options
Download
Email Patches
Plain Diff
Extracted methods to reduce cognitive complexity. Ref
#69
parent
e284489e
Pipeline
#10052
passed with stage
in 1 minute and 16 seconds
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java
+163
-131
...t/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java
with
163 additions
and
131 deletions
+163
-131
CityDoctorParent/CityDoctorEdge/src/main/java/de/hft/stuttgart/citydoctor2/edge/IntersectPlanarPolygons.java
+
163
-
131
View file @
1d8506eb
...
...
@@ -82,20 +82,7 @@ public class IntersectPlanarPolygons {
for
(
Interval
in2
:
intervals2
)
{
if
(
in1
.
isOverlapping
(
in2
))
{
Interval
overlap
=
in1
.
overlap
(
in2
);
Point3d
start
=
straight
.
evaluate
(
overlap
.
getStart
());
if
(
overlap
.
getLength
()
<
Global
.
getHighAccuracyTolerance
()
*
1
e6
)
{
checkAndAddRealIntersectionPoint
(
cpPolygon1
,
cpPolygon2
,
start
,
intersections
,
epsilon
);
}
else
{
Point3d
end
=
straight
.
evaluate
(
overlap
.
getEnd
());
PolyLine
pPL
=
new
PolyLine
(
new
Coordinate3d
(
start
),
new
Coordinate3d
(
end
));
if
(!
isPolyLineASharedEdge
(
cpPolygon1
,
pPL
))
{
PolygonPolygonIntersection
pPPI
=
new
PolygonPolygonIntersection
(
cpPolygon1
,
cpPolygon2
,
pPL
);
intersections
.
add
(
pPPI
);
}
}
handleIntersectionIntervalOverlap
(
cpPolygon1
,
cpPolygon2
,
straight
,
intersections
,
epsilon
,
overlap
);
}
else
if
(
Math
.
abs
(
in1
.
getStart
()
-
in2
.
getEnd
())
<
Global
.
getHighAccuracyTolerance
())
{
// check if the overlaps with a tolerance (numeric errors)
Point3d
point
=
straight
.
evaluate
(
in1
.
getStart
());
...
...
@@ -108,6 +95,25 @@ public class IntersectPlanarPolygons {
}
}
private
static
void
handleIntersectionIntervalOverlap
(
EdgePolygon
cpPolygon1
,
EdgePolygon
cpPolygon2
,
GmStraight
straight
,
List
<
PolygonPolygonIntersection
>
intersections
,
double
epsilon
,
Interval
overlap
)
{
Point3d
start
=
straight
.
evaluate
(
overlap
.
getStart
());
if
(
overlap
.
getLength
()
<
Global
.
getHighAccuracyTolerance
()
*
1
e6
)
{
checkAndAddRealIntersectionPoint
(
cpPolygon1
,
cpPolygon2
,
start
,
intersections
,
epsilon
);
}
else
{
Point3d
end
=
straight
.
evaluate
(
overlap
.
getEnd
());
PolyLine
pPL
=
new
PolyLine
(
new
Coordinate3d
(
start
),
new
Coordinate3d
(
end
));
if
(!
isPolyLineASharedEdge
(
cpPolygon1
,
pPL
))
{
PolygonPolygonIntersection
pPPI
=
new
PolygonPolygonIntersection
(
cpPolygon1
,
cpPolygon2
,
pPL
);
intersections
.
add
(
pPPI
);
}
}
}
private
static
boolean
isPolyLineASharedEdge
(
EdgePolygon
p1
,
PolyLine
polyLine
)
{
// get coordinates of the poly line
Point3d
polyLineStart
=
polyLine
.
getStart
().
getPoint
();
...
...
@@ -136,10 +142,12 @@ public class IntersectPlanarPolygons {
/**
*
* Checks if the given point is a "real" intersection point and add's it to the
* intersection segments member variable. Real means, that this point isn't
* shared by both polygons as corner point.
*
* Checks if the given point is a 'real' intersection point and adds it to the
* intersection segments member variable. 'Real' meaning, that this point isn't
* a shared corner point of both polygons.
*
* @param p1 First polygon
* @param p2 Second polygon
* @param point A possible intersection point
*/
private
static
void
checkAndAddRealIntersectionPoint
(
EdgePolygon
p1
,
EdgePolygon
p2
,
Point3d
point
,
...
...
@@ -200,7 +208,6 @@ public class IntersectPlanarPolygons {
* with the exception, that the straight and the half edges of the polygon will
* be projected on the plane of the polygon, so the calculation of the
* intersection will be reduced to a 2d problem.
*
* The intersection intervals contains pairs of parameters from the intersection
* straight. If an intersection between the straight and the polygon contains
* only a point, the according interval will contain the same parameter twice
...
...
@@ -271,39 +278,7 @@ public class IntersectPlanarPolygons {
GmBoundedStraight2d
heStraight2d
=
polyPlane
.
projectOn2dStraight
(
heStraight
);
GmStraight2dIntersectionResult
intersectionResult
=
heStraight2d
.
intersect
(
intersectingStraight2d
);
if
(
intersectionResult
.
areParallel
())
{
Vector2d
dir
=
intersectingStraight2d
.
getDirection
();
Vector2d
diffVec
=
heStraight2d
.
getOrigin
().
minus
(
intersectingStraight2d
.
getOrigin
());
double
diffVecDotPerpDir
=
diffVec
.
dot
(
dir
.
getPerpendicularVector
());
if
(
Math
.
abs
(
diffVecDotPerpDir
)
<
Global
.
getZeroAngleCosine
())
{
// Straights are identical
Point2d
p1
=
heStraight2d
.
getOrigin
();
Point2d
p2
=
heStraight2d
.
getTarget
();
Point2d
orig
=
intersectingStraight2d
.
getOrigin
();
double
[]
params
=
new
double
[
2
];
if
(
Math
.
abs
(
dir
.
getX
())
>
Global
.
getHighAccuracyTolerance
())
{
params
[
0
]
=
(
p1
.
getX
()
-
orig
.
getX
())
/
dir
.
getX
();
params
[
1
]
=
(
p2
.
getX
()
-
orig
.
getX
())
/
dir
.
getX
();
}
else
if
(
Math
.
abs
(
dir
.
getY
())
>
Global
.
getHighAccuracyTolerance
())
{
params
[
0
]
=
(
p1
.
getY
()
-
orig
.
getY
())
/
dir
.
getY
();
params
[
1
]
=
(
p2
.
getY
()
-
orig
.
getY
())
/
dir
.
getY
();
}
else
{
throw
new
IllegalStateException
(
"Directional vector of identical straights is equal to the zero vector "
+
dir
);
}
assignParameterToCorrectList
(
params
[
0
],
intersectionValues
,
intersectedPolygonPoints
);
assignParameterToCorrectList
(
params
[
1
],
intersectionValues
,
intersectedPolygonPoints
);
}
}
else
{
if
(
heStraight2d
.
isWithinBoundaries
(
intersectionResult
.
paramHE
(),
1
e
-
9
))
{
assignParameterToCorrectList
(
intersectionResult
.
paramInt
(),
intersectionValues
,
intersectedPolygonPoints
);
}
}
analyseProjectedIntersection
(
intersectionResult
,
intersectingStraight2d
,
heStraight2d
,
intersectionValues
,
intersectedPolygonPoints
);
}
processIntersectionIntervals
(
p
,
intersectingStraight
,
intersectionValues
,
intersectedPolygonPoints
,
...
...
@@ -312,6 +287,42 @@ public class IntersectPlanarPolygons {
}
private
static
void
analyseProjectedIntersection
(
GmStraight2dIntersectionResult
intersectionResult
,
GmStraight2d
intersectingStraight2d
,
GmBoundedStraight2d
heStraight2d
,
TreeSet
<
Double
>
intersectionValues
,
TreeSet
<
Double
>
intersectedPolygonPoints
)
{
if
(
intersectionResult
.
areParallel
())
{
Vector2d
dir
=
intersectingStraight2d
.
getDirection
();
Vector2d
diffVec
=
heStraight2d
.
getOrigin
().
minus
(
intersectingStraight2d
.
getOrigin
());
double
diffVecDotPerpDir
=
diffVec
.
dot
(
dir
.
getPerpendicularVector
());
if
(
Math
.
abs
(
diffVecDotPerpDir
)
<
Global
.
getZeroAngleCosine
())
{
// Straights are identical
Point2d
p1
=
heStraight2d
.
getOrigin
();
Point2d
p2
=
heStraight2d
.
getTarget
();
Point2d
orig
=
intersectingStraight2d
.
getOrigin
();
double
[]
params
=
new
double
[
2
];
if
(
Math
.
abs
(
dir
.
getX
())
>
Global
.
getHighAccuracyTolerance
())
{
params
[
0
]
=
(
p1
.
getX
()
-
orig
.
getX
())
/
dir
.
getX
();
params
[
1
]
=
(
p2
.
getX
()
-
orig
.
getX
())
/
dir
.
getX
();
}
else
if
(
Math
.
abs
(
dir
.
getY
())
>
Global
.
getHighAccuracyTolerance
())
{
params
[
0
]
=
(
p1
.
getY
()
-
orig
.
getY
())
/
dir
.
getY
();
params
[
1
]
=
(
p2
.
getY
()
-
orig
.
getY
())
/
dir
.
getY
();
}
else
{
throw
new
IllegalStateException
(
"Directional vector of identical straights is equal to the zero vector "
+
dir
);
}
assignParameterToCorrectList
(
params
[
0
],
intersectionValues
,
intersectedPolygonPoints
);
assignParameterToCorrectList
(
params
[
1
],
intersectionValues
,
intersectedPolygonPoints
);
}
}
else
{
if
(
heStraight2d
.
isWithinBoundaries
(
intersectionResult
.
paramHE
(),
1
e
-
9
))
{
assignParameterToCorrectList
(
intersectionResult
.
paramInt
(),
intersectionValues
,
intersectedPolygonPoints
);
}
}
}
/**
* This methods computes the intervals of the intersection between the given
* straight and polygon. It gets only parameters where the straight hits the
...
...
@@ -350,43 +361,18 @@ public class IntersectPlanarPolygons {
List
<
Double
>
valuesList
=
new
ArrayList
<>(
intersectionValues
);
for
(
int
i
=
0
;
i
<
valuesList
.
size
();
i
++)
{
double
i1
=
valuesList
.
get
(
i
);
i
=
i
+
1
;
if
(
i
<
valuesList
.
size
())
{
double
i2
=
valuesList
.
get
(
i
);
i
nt
j
=
i
+
1
;
if
(
j
<
valuesList
.
size
())
{
double
i2
=
valuesList
.
get
(
j
);
// check if the double values are corner points of the polygon
boolean
gotPolygonPoint
=
intersectedPolygonPoints
.
contains
(
i1
)
||
intersectedPolygonPoints
.
contains
(
i2
);
if
(
gotPolygonPoint
)
{
// maybe an interval
// check if the point between the two parameters is inside the
// polygon or outside ( i.e. i1 and i2 are both corner points of
// a concave polygon, so the connection line don't need to lie
// inside the polygon )
Point3d
pnt
=
intersectingStraight
.
evaluate
((
i1
+
i2
)
/
2
);
if
(
pcPolygon
.
isPointInsidePolygon
(
pnt
,
1
e
-
9
))
{
Interval
newLineInt
=
new
Interval
(
i1
,
i2
);
// there is already at least one point interval present. We need
// to remove this first, otherwise we would get a normal interval
// and one or two point intervals at the end of the normal int.
Iterator
<
Interval
>
intervalIterator
=
intersectionIntervals
.
iterator
();
while
(
intervalIterator
.
hasNext
()
&&
!
intersectionIntervals
.
isEmpty
())
{
for
(
Interval
inter
=
intervalIterator
.
next
();
intervalIterator
.
hasNext
();
inter
=
intervalIterator
.
next
())
{
if
(
Math
.
abs
(
inter
.
getLength
())
<
Global
.
getHighAccuracyTolerance
())
{
if
(
Math
.
abs
(
inter
.
getStart
()
-
i1
)
<
1
e
-
9
||
Math
.
abs
(
inter
.
getStart
()
-
i2
)
<
1
e
-
9
)
{
intervalIterator
.
remove
();
intervalIterator
=
intersectionIntervals
.
iterator
();
break
;
}
}
}
}
Interval
newLineInt
=
checkIntersectionInvervalPoints
(
pcPolygon
,
intersectingStraight
,
intersectionIntervals
,
i1
,
i2
);
if
(
newLineInt
!=
null
)
{
intersectionIntervals
.
add
(
newLineInt
);
}
else
{
i
--;
}
}
else
{
intersectionIntervals
.
add
(
new
Interval
(
i1
,
i2
));
...
...
@@ -403,6 +389,37 @@ public class IntersectPlanarPolygons {
}
}
private
static
Interval
checkIntersectionInvervalPoints
(
EdgePolygon
pcPolygon
,
GmStraight
intersectingStraight
,
List
<
Interval
>
intersectionIntervals
,
double
i1
,
double
i2
)
{
// maybe an interval
// check if the point between the two parameters is inside the
// polygon or outside ( i.e. i1 and i2 are both corner points of
// a concave polygon, so the connection line don't need to lie
// inside the polygon )
Point3d
pnt
=
intersectingStraight
.
evaluate
((
i1
+
i2
)
/
2
);
if
(
pcPolygon
.
isPointInsidePolygon
(
pnt
,
1
e
-
9
))
{
Interval
newLineInt
=
new
Interval
(
i1
,
i2
);
// there is already at least one point interval present. We need
// to remove this first, otherwise we would get a normal interval
// and one or two point intervals at the end of the normal int.
Iterator
<
Interval
>
intervalIterator
=
intersectionIntervals
.
iterator
();
while
(
intervalIterator
.
hasNext
()
&&
!
intersectionIntervals
.
isEmpty
())
{
for
(
Interval
inter
=
intervalIterator
.
next
();
intervalIterator
.
hasNext
();
inter
=
intervalIterator
.
next
())
{
if
(
Math
.
abs
(
inter
.
getLength
())
<
Global
.
getHighAccuracyTolerance
()
&&
(
Math
.
abs
(
inter
.
getStart
()
-
i1
)
<
1
e
-
9
||
Math
.
abs
(
inter
.
getStart
()
-
i2
)
<
1
e
-
9
))
{
intervalIterator
.
remove
();
intervalIterator
=
intersectionIntervals
.
iterator
();
break
;
}
}
}
return
newLineInt
;
}
return
null
;
}
/**
* Util method. Checks if the given parameter has already been inserted as
* intersection parameter. If this is true, the parameter will be added as
...
...
@@ -442,46 +459,9 @@ public class IntersectPlanarPolygons {
List
<
HalfEdge
>
heList
=
new
ArrayList
<>(
p1
.
getHalfEdges
());
heList
.
addAll
(
p2
.
getHalfEdges
());
List
<
HalfEdge
>
heListColinear
=
new
ArrayList
<>();
for
(
HalfEdge
he
:
heList
)
{
if
(
null
!=
he
.
getPartner
())
{
// this half edge is shared by both polygons ==> no intersection
// NOTE: The issue of more than 2 half edges per edge is solved by
// circular pointer, so we have to cycle threw all partners
HalfEdge
pStartHE
=
he
;
HalfEdge
pPartnerHE
=
pStartHE
.
getPartner
();
boolean
bothPolysShareThisEdge
=
false
;
while
(
pStartHE
!=
pPartnerHE
&&
!
bothPolysShareThisEdge
)
{
if
(
pPartnerHE
.
getPolygon
()
==
p1
||
pPartnerHE
.
getPolygon
()
==
p2
)
{
bothPolysShareThisEdge
=
true
;
}
pPartnerHE
=
pPartnerHE
.
getPartner
();
}
if
(
bothPolysShareThisEdge
)
{
continue
;
}
}
GmBoundedStraight
straightHe
=
he
.
getStraight
();
Point3d
origin
=
straightHe
.
getOrigin
();
Point3d
target
=
straightHe
.
getTarget
();
boolean
straightsAreColinear
=
IntersectPlanarPolygons
.
areStraightsColinear
(
straightHe
,
straight
,
epsilon
,
angleEpsilon
);
ProjectedPoint3d
projPoint1
=
straight
.
project
(
origin
);
ProjectedPoint3d
projPoint2
=
straight
.
project
(
target
);
List
<
HalfEdge
>
heListCollinear
=
getCollinearHalfEdgeList
(
p1
,
p2
,
straight
,
epsilon
,
angleEpsilon
,
heList
);
boolean
originLiesOnIntStraight
=
projPoint1
.
getPoint
().
isAlmostEqual
(
origin
,
PROJECTED_POINT_DISTANCE_EPSILON
);
boolean
targetLiesOnIntStraight
=
projPoint2
.
getPoint
().
isAlmostEqual
(
target
,
PROJECTED_POINT_DISTANCE_EPSILON
);
if
(
straightsAreColinear
&&
(
originLiesOnIntStraight
||
targetLiesOnIntStraight
))
{
heListColinear
.
add
(
he
);
}
}
for
(
HalfEdge
he
:
heListColinear
)
{
for
(
HalfEdge
he
:
heListCollinear
)
{
// 1.2) determine if fully or partially or not at all embedded
// create parameter interval of the first projected half edge
Point3d
startPoint1
=
he
.
getStraight
().
getOrigin
();
...
...
@@ -489,7 +469,7 @@ public class IntersectPlanarPolygons {
ProjectedPoint3d
projP1
=
straight
.
project
(
startPoint1
);
ProjectedPoint3d
projP2
=
straight
.
project
(
endPoint1
);
Interval
int1
=
new
Interval
(
projP1
.
getParameter
(),
projP2
.
getParameter
());
for
(
HalfEdge
he2
:
heListColinear
)
{
for
(
HalfEdge
he2
:
heListCol
l
inear
)
{
if
(
he
==
he2
)
{
continue
;
}
...
...
@@ -526,8 +506,63 @@ public class IntersectPlanarPolygons {
}
}
private
static
boolean
areStraightsColinear
(
GmBoundedStraight
straight1
,
GmStraight
straight2
,
double
epsilon
,
double
angleEpsilon
)
{
private
static
List
<
HalfEdge
>
getCollinearHalfEdgeList
(
EdgePolygon
p1
,
EdgePolygon
p2
,
GmStraight
straight
,
double
epsilon
,
double
angleEpsilon
,
List
<
HalfEdge
>
heList
)
{
List
<
HalfEdge
>
heListCollinear
=
new
ArrayList
<>();
for
(
HalfEdge
he
:
heList
)
{
if
(
isHalfEdgeSharedByPolygons
(
he
,
p1
,
p2
)){
// If the HalfEdge is shared, it is not collinear.
// Ignore it and continue with next HalfEdge.
continue
;
}
GmBoundedStraight
straightHe
=
he
.
getStraight
();
Point3d
origin
=
straightHe
.
getOrigin
();
Point3d
target
=
straightHe
.
getTarget
();
boolean
straightsAreCollinear
=
IntersectPlanarPolygons
.
areStraightsCollinear
(
straightHe
,
straight
,
epsilon
,
angleEpsilon
);
ProjectedPoint3d
projPoint1
=
straight
.
project
(
origin
);
ProjectedPoint3d
projPoint2
=
straight
.
project
(
target
);
boolean
originLiesOnIntStraight
=
projPoint1
.
getPoint
().
isAlmostEqual
(
origin
,
PROJECTED_POINT_DISTANCE_EPSILON
);
boolean
targetLiesOnIntStraight
=
projPoint2
.
getPoint
().
isAlmostEqual
(
target
,
PROJECTED_POINT_DISTANCE_EPSILON
);
if
(
straightsAreCollinear
&&
(
originLiesOnIntStraight
||
targetLiesOnIntStraight
))
{
heListCollinear
.
add
(
he
);
}
}
return
heListCollinear
;
}
/**
* Checks whether a specific HalfEdge is shared by two EdgePolygons.
*
*
* @param he The HalfEdge in question
* @param p1 First Polygon
* @param p2 Second Polygon
* @return true if the HalfEdge is shared
*/
private
static
boolean
isHalfEdgeSharedByPolygons
(
HalfEdge
he
,
EdgePolygon
p1
,
EdgePolygon
p2
)
{
boolean
bothPolysShareThisEdge
=
false
;
if
(
he
.
getPartner
()
!=
null
)
{
// NOTE: The issue of more than 2 half edges per edge is solved by
// circular pointer, so we have to cycle threw all partners
HalfEdge
pPartnerHE
=
he
.
getPartner
();
while
(
he
!=
pPartnerHE
&&
!
bothPolysShareThisEdge
)
{
if
(
pPartnerHE
.
getPolygon
()
==
p1
||
pPartnerHE
.
getPolygon
()
==
p2
)
{
bothPolysShareThisEdge
=
true
;
}
pPartnerHE
=
pPartnerHE
.
getPartner
();
}
}
return
bothPolysShareThisEdge
;
}
private
static
boolean
areStraightsCollinear
(
GmBoundedStraight
straight1
,
GmStraight
straight2
,
double
epsilon
,
double
angleEpsilon
)
{
UnitVector3d
rDir1
=
straight1
.
getDir
();
UnitVector3d
rDir2
=
straight2
.
getDir
();
...
...
@@ -541,12 +576,9 @@ public class IntersectPlanarPolygons {
ProjectedPoint3d
foot1
=
straight2
.
project
(
rOrigin
);
Point3d
rTarget
=
straight1
.
getTarget
();
ProjectedPoint3d
foot2
=
straight2
.
project
(
rTarget
);
if
((
foot1
.
getPoint
().
minus
(
rOrigin
)).
getLength
()
>
epsilon
||
(
foot2
.
getPoint
().
minus
(
rTarget
)).
getLength
()
>
epsilon
)
{
return
false
;
}
return
true
;
}
return
!(((
foot1
.
getPoint
().
minus
(
rOrigin
)).
getLength
()
>
epsilon
)
||
((
foot2
.
getPoint
().
minus
(
rTarget
)).
getLength
()
>
epsilon
));
}
private
static
List
<
PolygonPolygonIntersection
>
handlePolygonsInSamePlane
(
GmPlane
plane
,
EdgePolygon
p1
,
EdgePolygon
p2
,
double
epsilon
)
{
...
...
This diff is collapsed.
Click to expand it.
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
Menu
Explore
Projects
Groups
Snippets