Commit dac80587 authored by BZoennchen's avatar BZoennchen

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
......@@ -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;
......
......@@ -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 {
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment