Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
vadere
vadere
Commits
dac80587
Commit
dac80587
authored
May 15, 2019
by
Benedikt Zoennchen
Browse files
Merge branch 'fixGetOrthocenterBug' into 'master'
getOrthocenter without slope determination See merge request
!49
parents
c6997cb8
f1d5730d
Pipeline
#113405
passed with stages
in 168 minutes and 54 seconds
Changes
2
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
VadereUtils/src/org/vadere/util/geometry/shapes/VTriangle.java
View file @
dac80587
...
...
@@ -5,6 +5,10 @@ import java.util.stream.Stream;
import
org.jetbrains.annotations.NotNull
;
import
org.vadere.util.geometry.GeometryUtils
;
import
org.vadere.util.geometry.Vector3D
;
import
static
java
.
lang
.
Double
.
isInfinite
;
import
static
java
.
lang
.
Double
.
isNaN
;
/**
* A triangle. Points must be given in counter clockwise manner to get correct
...
...
@@ -112,25 +116,58 @@ public class VTriangle extends VPolygon {
}
public
VPoint
getOrthocenter
()
{
if
(
orthocenter
==
null
)
{
double
slope
=
-
1
/
((
p2
.
getY
()
-
p1
.
getY
())
/
(
p2
.
getX
()
-
p1
.
getX
()));
// y = slope * (x - p3.x) + p3.y
double
slope2
=
-
1
/
((
p1
.
getY
()
-
p3
.
getY
())
/
(
p1
.
getX
()
-
p3
.
getX
()));
// y = slope2 * (x - p2.x) + p2.y
// slope2 * (x - p2.x) + p2.y = slope * (x - p3.x) + p3.y
// slope2 * (x - p2.x) - slope * (x - p3.x) = + p3.y - p2.y
// slope2 * x - slope2 * p2.x - slope * x + slope * p3.x = + p3.y - p2.y
// slope2 * x - slope * x = + p3.y - p2.y + slope2 * p2.x - slope * p3.x
// x * (slope2 - slope) = + p3.y - p2.y + slope2 * p2.x - slope * p3.x
double
x
=
(
p3
.
getY
()
-
p2
.
getY
()
+
slope2
*
p2
.
getX
()
-
slope
*
p3
.
getX
())
/
(
slope2
-
slope
);
double
y
=
slope
*
(
x
-
p3
.
getX
())
+
p3
.
getY
();
orthocenter
=
new
VPoint
(
x
,
y
);
VPoint
p12
,
p13
,
p23
,
L1
,
L2
;
// create edge vectors
p12
=
p2
.
subtract
(
p1
);
// Vector2D better??
p13
=
p3
.
subtract
(
p1
);
p23
=
p3
.
subtract
(
p2
);
// create system of equations
double
cross
=
p13
.
crossProduct
(
p12
);
L1
=
new
VPoint
(-
cross
*
p23
.
getY
()
,
cross
*
p23
.
getX
()
);
L2
=
new
VPoint
(-
cross
*
p13
.
getY
()
,
cross
*
p13
.
getX
()
);
// solve system of equation (determine first element of resulting vector lamda with cramers rule; second element not necessary)
double
lamda1
=
(
p12
.
getX
()
*
L2
.
getY
()
-
p12
.
getY
()
*
L2
.
getX
()
)
/
(
L1
.
getX
()*
L2
.
getY
()
-
L2
.
getX
()*
L1
.
getY
()
)
;
orthocenter
=
new
VPoint
(
p1
.
add
(
L1
.
scalarMultiply
(
lamda1
)
)
);
}
//VPoint orthocenter2 = getOrthocenterSlowImplementation() ;
//assert Math.abs( orthocenter.distance(orthocenter2)) < GeometryUtils.DOUBLE_EPS ;
return
orthocenter
;
}
public
VPoint
getOrthocenterSlowImplementation
()
{
// create edge vectors
VPoint
p12
=
p2
.
subtract
(
p1
);
// Vector2D better??
VPoint
p13
=
p3
.
subtract
(
p1
);
VPoint
p23
=
p3
.
subtract
(
p2
);
// edge vectors reverse
VPoint
p21
=
new
VPoint
(
p12
.
scalarMultiply
(-
1.0
));
VPoint
p31
=
new
VPoint
(
p13
.
scalarMultiply
(-
1.0
));
VPoint
p32
=
new
VPoint
(
p23
.
scalarMultiply
(-
1.0
));
// calculate angles a1, a2, a3
double
a1
=
Math
.
atan2
(
Math
.
abs
(
p13
.
crossProduct
(
p12
)),
p13
.
scalarProduct
(
p12
))
;
double
a2
=
Math
.
atan2
(
Math
.
abs
(
p23
.
crossProduct
(
p21
)),
p23
.
scalarProduct
(
p21
))
;
double
a3
=
Math
.
atan2
(
Math
.
abs
(
p31
.
crossProduct
(
p32
)),
p31
.
scalarProduct
(
p32
))
;
double
div
=
Math
.
tan
(
a1
)+
Math
.
tan
(
a2
)+
Math
.
tan
(
a3
)
;
double
x
=
(
Math
.
tan
(
a1
)*
p1
.
getX
()
+
Math
.
tan
(
a2
)*
p2
.
getX
()
+
Math
.
tan
(
a3
)*
p3
.
getX
()
)
/
div
;
double
y
=
(
Math
.
tan
(
a1
)*
p1
.
getY
()
+
Math
.
tan
(
a2
)*
p2
.
getY
()
+
Math
.
tan
(
a3
)*
p3
.
getY
()
)
/
div
;
return
new
VPoint
(
x
,
y
);
}
public
VPoint
closestPoint
(
final
IPoint
point
)
{
VPoint
currentClosest
=
null
;
...
...
VadereUtils/tests/org/vadere/util/geometry/shapes/TestVTriangle.java
View file @
dac80587
...
...
@@ -2,14 +2,9 @@ package org.vadere.util.geometry.shapes;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
org.vadere.util.geometry.GeometryUtils
;
import
org.vadere.util.logging.Logger
;
import
java.time.ZonedDateTime
;
import
java.time.temporal.ChronoUnit
;
import
static
org
.
junit
.
Assert
.*;
public
class
TestVTriangle
{
...
...
@@ -23,11 +18,10 @@ public class TestVTriangle {
private
double
coorTop
=
Math
.
sqrt
(
Math
.
pow
(
radiusShould
,
2
)
+
Math
.
pow
(
coor
,
2
)
);
private
VTriangle
vTriangle_symY_60degree
=
new
VTriangle
(
new
VPoint
(-
coor
,-
radiusShould
),
new
VPoint
(
coor
,-
radiusShould
),
new
VPoint
(
0
.,
coorTop
)
);
// create y-symmetric 45°-45°-90°-triangle (90°-angle is split by y-axis)
private
VPoint
vPoint1
=
new
VPoint
(-
1
.,
0
.);
private
VPoint
vPoint2
=
new
VPoint
(
1
.,
0
.);
private
VPoint
vPoint3
=
new
VPoint
(
0
.,
1
.
);
private
VPoint
vPoint3
=
new
VPoint
(
0
.,
1
);
private
VTriangle
vTriangle_sym
=
new
VTriangle
(
vPoint1
,
vPoint2
,
vPoint3
);
private
VPoint
vPoint4
=
new
VPoint
(
vPoint2
.
getX
()
+
0.1
,
vPoint2
.
getY
());
// getter not necessary because attributes are public
...
...
@@ -40,23 +34,13 @@ public class TestVTriangle {
@Before
public
void
setUp
()
throws
Exception
{
// ?
}
@Test
public
void
testClosestPoint0
(){
// also write time stemp because it is not included into ASCI output file VadereUtils/log.out
logger
.
info
(
"Start Test testClosestPoint"
+
ZonedDateTime
.
now
().
toLocalTime
().
truncatedTo
(
ChronoUnit
.
SECONDS
));
System
.
out
.
println
(
"Point 1 == Point 2"
);
System
.
out
.
println
(
vTriangle_sym
.
closestPoint
(
vPoint1
).
equals
(
vPoint2
,
0.1
)
);
System
.
out
.
println
(
"Point 2 == Point 2"
);
System
.
out
.
println
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint2
,
0.1
)
);
System
.
out
.
println
(
"Point 2 == Point 4; accurate"
);
System
.
out
.
println
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint4
,
0.1
)
);
System
.
out
.
println
(
"Point 2 == Point 4; not accurate"
);
System
.
out
.
println
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint4
,
0.2
)
);
//double d1 = GeometryUtils.ccw(vPoint1, vPoint2, vPoint3);
assertFalse
(
vTriangle_sym
.
closestPoint
(
vPoint1
).
equals
(
vPoint2
,
0.1
)
);
assertTrue
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint2
,
0.1
)
);
assertFalse
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint4
,
0.1
)
);
assertTrue
(
vTriangle_sym
.
closestPoint
(
vPoint2
).
equals
(
vPoint4
,
0.2
)
);
}
/**
...
...
@@ -65,13 +49,6 @@ public class TestVTriangle {
*/
@Test
public
void
testContains
()
{
/*
System.out.println( "Point 1 - 3 belong to the triangle; should be true" );
System.out.println( vTriangle_sym.contains(vPoint1) && vTriangle_sym.contains(vPoint2) && vTriangle_sym.contains(vPoint3) );
System.out.println( "Point 2 - 4 belong to the triangle; should be false" );
System.out.println( vTriangle_sym.contains(vPoint2) && vTriangle_sym.contains(vPoint3) && vTriangle_sym.contains(vPoint4) );
*/
// vTriangle_sym.contains returns true if point is a vertex or point is inside triangle
assertTrue
(
"Point 1 is vertex of Triangle 1."
,
vTriangle_sym
.
contains
(
vPoint1
));
assertTrue
(
"Point 2 is vertex of Triangle 1."
,
vTriangle_sym
.
contains
(
vPoint2
));
...
...
@@ -88,15 +65,6 @@ public class TestVTriangle {
*/
@Test
public
void
testIsPartOf
()
{
/*
System.out.println( "Point 1 is in triangle; should be true" );
System.out.println( vTriangle_sym.isPartOf(vPoint1,0.0));
System.out.println( "Point 4 is in triangle; should be true" );
System.out.println( vTriangle_sym.isPartOf(vPoint4,0.2));
System.out.println( "Point 4 is in triangle; should be false" );
System.out.println( vTriangle_sym.isPartOf(vPoint4,0.1));
System.out.println( vTriangle_sym.isPartOf(vPoint5,0.01));*/
// vTriangle_sym.isPartOf returns true if point is a vertex or point is inside triangle + tolerance
double
tolerance
=
0.0
;
assertTrue
(
"Point 1 is vertex of Triangle 1."
,
vTriangle_sym
.
isPartOf
(
vPoint1
,
tolerance
));
...
...
@@ -106,7 +74,6 @@ public class TestVTriangle {
// vTriangle_sym.isPartOf returns false if point is outside triangle + tolerance
assertFalse
(
"Point 4 lays outside Triangle 1."
,
vTriangle_sym
.
isPartOf
(
vPoint4
,
tolerance
));
}
@Test
...
...
@@ -115,19 +82,9 @@ public class TestVTriangle {
double
x
=
vPoint
.
getX
();
double
y
=
vPoint
.
getY
();
double
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
1
./
3
));
System
.
out
.
print
(
vPoint
.
toString
()
);
if
(
eps
>
GeometryUtils
.
DOUBLE_EPS
)
System
.
out
.
print
(
" is not Midpoint. Error \n"
);
else
System
.
out
.
print
(
" is Midpoint. \n"
);
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
}
@Test
public
void
testMidPointA
()
{
VPoint
vPoint
=
vTriangle_sym
.
midPoint
();
VPoint
checkPoint
=
new
VPoint
(
0.0
,
1
./
3
);
assertEquals
(
checkPoint
,
vPoint
);
}
@Test
public
void
testIsLine
()
{
...
...
@@ -143,8 +100,7 @@ public class TestVTriangle {
@Test
public
void
testGetCentroid
()
{
VPoint
vPoint
=
vTriangle_sym
.
getCentroid
();
// special structure of triangle: midpoint = centroid
VPoint
checkPoint
=
new
VPoint
(
0.0
,
1
./
3
);
VPoint
checkPoint
=
new
VPoint
(
0.0
,
1
./
3
);
// special structure of triangle: midpoint = centroid
assertEquals
(
checkPoint
,
vPoint
);
}
...
...
@@ -158,33 +114,66 @@ public class TestVTriangle {
//assertEquals(vPoint, new VPoint(0.0,0.0), GeometryUtils.DOUBLE_EPS);
double
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
0.0
));
// Point (0,0) is incenter
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
// assertEquals(0.0, vPoint.distance(new VPoint(x, y)), GeometryUtils.DOUBLE_EPS);
}
/**
* test fails because slope is infinite
* */
@Ignore
@Test
public
void
testGetOrthocenter
()
{
// use 60°-triangle (2 vertices on y-axis) for test
VPoint
vPoint
=
vTriangle_60degree
.
getOrthocenter
();
// time measure
long
startTime
,
runTimeInNs
,
runTimeInNsSlow
;
VPoint
vPointY
,
vPoint
;
/** Triangle 1: use 60°-triangle (2 vertices on y-axis) for test */
// fast implementation
startTime
=
System
.
nanoTime
();
vPoint
=
vTriangle_60degree
.
getOrthocenter
();
runTimeInNs
=
System
.
nanoTime
()
-
startTime
;
double
x
=
vPoint
.
getX
();
double
y
=
vPoint
.
getY
();
double
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.5
),
Math
.
abs
(
y
-
0.0
));
// Point (0.5,0) is orthocenter
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
// triangle with y-symmetry (45°-90°-45°); does not work because of infinite slope
// exception handling ?
VPoint
vPointY
=
this
.
vTriangle_sym
.
getOrthocenter
();
// slow implementation
startTime
=
System
.
nanoTime
();
vPoint
=
vTriangle_60degree
.
getOrthocenterSlowImplementation
();
runTimeInNsSlow
=
System
.
nanoTime
()
-
startTime
;
x
=
vPoint
.
getX
();
y
=
vPoint
.
getY
();
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.5
),
Math
.
abs
(
y
-
0.0
));
// Point (0.5,0) is orthocenter
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
// compare fast and slow implementation
logger
.
info
(
"Triangle 1: Fast implementation required "
+
runTimeInNs
+
"[nano sec]"
);
logger
.
info
(
"Triangle 1: Slow implementation required "
+
runTimeInNsSlow
+
"[nano sec]"
);
logger
.
info
(
"Triangle 1: time factor -> slow to fast: "
+
1.0
*
runTimeInNsSlow
/
runTimeInNs
);
/** Triangle 2: triangle with y-symmetry (45°-90°-45°); does not work because of infinite slope */
// fast implementation
startTime
=
System
.
nanoTime
();
vPointY
=
this
.
vTriangle_sym
.
getOrthocenter
();
runTimeInNs
=
System
.
nanoTime
()
-
startTime
;
x
=
vPointY
.
getX
();
y
=
vPointY
.
getY
();
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
1.0
));
// Point (0.5,0) is orthocenter
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
// slow implementation
startTime
=
System
.
nanoTime
();
vPointY
=
this
.
vTriangle_sym
.
getOrthocenterSlowImplementation
();
runTimeInNsSlow
=
System
.
nanoTime
()
-
startTime
;
x
=
vPointY
.
getX
();
y
=
vPointY
.
getY
();
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
1.0
));
// Point (0.5,0) is orthocenter
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
// compare fast and slow implementation
logger
.
info
(
"Triangle 2: Fast implementation required "
+
runTimeInNs
+
"[nano sec]"
);
logger
.
info
(
"Triangle 2: Slow implementation required "
+
runTimeInNsSlow
+
"[nano sec]"
);
logger
.
info
(
"Triangle 2: time factor -> slow to fast: "
+
1.0
*
runTimeInNsSlow
/
runTimeInNs
);
}
@Test
public
void
testClosestPoint
()
{
// y-symmetric triangle contains vPoint1
assertEquals
(
vTriangle_sym
.
closestPoint
(
vPoint1
),
vPoint1
);
...
...
@@ -205,20 +194,17 @@ public class TestVTriangle {
y
=
newPoint3
.
getY
();
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
0.3
));
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
}
@Test
public
void
testGetCircumcenter
(){
// y-symmetric 60°-triangle: Circumcenter = Incenter = (0.0,0.0)
// y-symmetric 60°-triangle: Circumcenter = (0.0,0.0)
VPoint
vPoint
=
vTriangle_symY_60degree
.
getIncenter
();
double
x
=
vPoint
.
getX
();
double
y
=
vPoint
.
getY
();
double
eps
=
Math
.
max
(
Math
.
abs
(
x
-
0.0
),
Math
.
abs
(
y
-
0.0
));
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
}
@Test
...
...
@@ -229,17 +215,6 @@ public class TestVTriangle {
assertTrue
(
eps
<
GeometryUtils
.
DOUBLE_EPS
);
}
/*
@Test
public void testIsInCircumscribedCycle() {
}
@Test
public void testMaxCoordinate() {
}
@Test
public void testGetLines() {
} */
@After
public
void
tearDown
()
throws
Exception
{
}
...
...
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