/* * Copyright (C) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of Geometric Regression Library (GeoRegression). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package georegression.geometry.algs; import georegression.geometry.UtilEllipse_F64; import georegression.geometry.UtilVector2D_F64; import georegression.misc.GrlConstants; import georegression.struct.point.Point2D_F64; import georegression.struct.point.Vector2D_F32; import georegression.struct.point.Vector2D_F64; import georegression.struct.shapes.EllipseRotated_F64; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; /** * @author Peter Abeles */ public class TestTangentLinesTwoEllipses_F64 { Point2D_F64 tangentA0 = new Point2D_F64(); Point2D_F64 tangentA1 = new Point2D_F64(); Point2D_F64 tangentA2 = new Point2D_F64(); Point2D_F64 tangentA3 = new Point2D_F64(); Point2D_F64 tangentB0 = new Point2D_F64(); Point2D_F64 tangentB1 = new Point2D_F64(); Point2D_F64 tangentB2 = new Point2D_F64(); Point2D_F64 tangentB3 = new Point2D_F64(); @Test public void process() { TangentLinesTwoEllipses_F64 alg = new TangentLinesTwoEllipses_F64(GrlConstants.DOUBLE_TEST_TOL, 20); for( int i = 0; i < 20; i++ ) { double theta = i*GrlConstants.PI/20 - GrlConstants.PI/2.0; // System.out.println(i+" Theta = "+theta); check( new EllipseRotated_F64(0,10,5,4,theta), new EllipseRotated_F64(0,0,4,3,0), alg); check( new EllipseRotated_F64(0,10,4,4,theta), new EllipseRotated_F64(0,0,4,4,0), alg); check( new EllipseRotated_F64(2.5,10,5,4,theta), new EllipseRotated_F64(0,0,4.9,3, GrlConstants.PId2), alg); } } public void check( EllipseRotated_F64 ellipseA , EllipseRotated_F64 ellipseB , TangentLinesTwoEllipses_F64 alg ) { assertTrue(alg.process(ellipseA,ellipseB, tangentA0, tangentA1, tangentA2, tangentA3, tangentB0, tangentB1, tangentB2, tangentB3)); assertTrue(alg.isConverged()); // make sure all the points are unique checkResults(ellipseA, ellipseB, true); } @Test public void initialize() { TangentLinesTwoEllipses_F64 alg = new TangentLinesTwoEllipses_F64(GrlConstants.DOUBLE_TEST_TOL, 20); EllipseRotated_F64 ellipseA = new EllipseRotated_F64(0,10,5,4,0); EllipseRotated_F64 ellipseB = new EllipseRotated_F64(0,0,4,3, Math.PI/2.0); assertTrue(alg.initialize(ellipseA,ellipseB, tangentA0, tangentA1, tangentA2, tangentA3, tangentB0, tangentB1, tangentB2, tangentB3)); checkResults(ellipseA, ellipseB, false); } private void checkResults(EllipseRotated_F64 ellipseA, EllipseRotated_F64 ellipseB , boolean completeTest ) { // make sure all the points are unique assertFalse(tangentA0.distance(tangentA1) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentA0.distance(tangentA2) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentA0.distance(tangentA3) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentA1.distance(tangentA2) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentA1.distance(tangentA3) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentA2.distance(tangentA3) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentB0.distance(tangentB1) <= GrlConstants.DOUBLE_TEST_TOL ); if( completeTest ) { assertFalse(tangentB0.distance(tangentB2) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentB0.distance(tangentB3) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentB1.distance(tangentB2) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentB1.distance(tangentB3) <= GrlConstants.DOUBLE_TEST_TOL ); assertFalse(tangentB2.distance(tangentB3) <= GrlConstants.DOUBLE_TEST_TOL ); // make sure each pair is tangent checkIsTangent(tangentA0, tangentB0, ellipseA, ellipseB); checkIsTangent(tangentA1, tangentB1, ellipseA, ellipseB); checkIsTangent(tangentA2, tangentB2, ellipseA, ellipseB); checkIsTangent(tangentA3, tangentB3, ellipseA, ellipseB); } } private void checkIsTangent( Point2D_F64 a , Point2D_F64 b , EllipseRotated_F64 ellipseA, EllipseRotated_F64 ellipseB) { double ta = UtilEllipse_F64.computeAngle(a,ellipseA); double tb = UtilEllipse_F64.computeAngle(b,ellipseB); double slopeX = b.x-a.x; double slopeY = b.y-a.y; double r = Math.sqrt( slopeX*slopeX + slopeY*slopeY); slopeX /= r; slopeY /= r; Vector2D_F64 slopeA = UtilEllipse_F64.computeTangent(ta,ellipseA,null); Vector2D_F64 slopeB = UtilEllipse_F64.computeTangent(tb,ellipseB,null); assertTrue(UtilVector2D_F64.identicalSign(slopeX,slopeY, slopeA.x, slopeA.y, GrlConstants.DOUBLE_TEST_TOL_SQRT )); assertTrue(UtilVector2D_F64.identicalSign(slopeX,slopeY, slopeB.x, slopeB.y, GrlConstants.DOUBLE_TEST_TOL_SQRT )); } @Test public void selectTangent() { TangentLinesTwoEllipses_F64 alg = new TangentLinesTwoEllipses_F64(GrlConstants.DOUBLE_TEST_TOL, 20); EllipseRotated_F64 ellipse = new EllipseRotated_F64(0,10,2,2,0); Point2D_F64 a = new Point2D_F64(2,5); Point2D_F64 srcA = new Point2D_F64(2,11.5); Point2D_F64 found = new Point2D_F64(); alg.centerLine.set(0,0,0,10); assertTrue(alg.selectTangent(a,srcA,ellipse,found, false)); assertEquals(2, found.x, GrlConstants.DOUBLE_TEST_TOL); assertEquals(10, found.y, GrlConstants.DOUBLE_TEST_TOL); assertEquals(1.5*1.5, alg.sumDifference, GrlConstants.DOUBLE_TEST_TOL ); assertTrue(alg.selectTangent(a,srcA,ellipse,found, true)); assertNotEquals(2, found.x, GrlConstants.DOUBLE_TEST_TOL); assertNotEquals(10, found.y, GrlConstants.DOUBLE_TEST_TOL); } }