main/src/georegression/geometry/algs/TangentLinesTwoEllipses_F64.java
public boolean process(EllipseRotated_F64 ellipseA , EllipseRotated_F64 ellipseB ,
						   Point2D_F64 tangentA0 , Point2D_F64 tangentA1 ,
						   Point2D_F64 tangentA2 , Point2D_F64 tangentA3 ,
						   Point2D_F64 tangentB0 , Point2D_F64 tangentB1 ,
						   Point2D_F64 tangentB2 , Point2D_F64 tangentB3 )
	{
		converged = false;

		// initialize by picking an arbitrary point on A and then finding the points on B in which
		// a line is tangent to B and passes through the point on A
		if (!initialize(ellipseA, ellipseB,
				tangentA0, tangentA1, tangentA2, tangentA3,
				tangentB0, tangentB1, tangentB2, tangentB3))
			return false;

		// update the location of each point until it converges or the maximum number of iterations has been exceeded
		int iteration = 0;
		for( ;iteration < maxIterations; iteration++ ) {
			boolean allGood = false;
			sumDifference = 0;

			if( !selectTangent(tangentA0,tangentB0,ellipseB,tangentB0, false) )
				return false;
			if( !selectTangent(tangentA1,tangentB1,ellipseB,tangentB1, true) )
				return false;
			if( !selectTangent(tangentA2,tangentB2,ellipseB,tangentB2, true) )
				return false;
			if( !selectTangent(tangentA3,tangentB3,ellipseB,tangentB3, false) )
				return false;

			if( Math.sqrt(sumDifference)/4.0 <= convergenceTol ) {
				allGood = true;
			}
			sumDifference = 0;

			if( !selectTangent(tangentB0,tangentA0,ellipseA,tangentA0, false) )
				return false;
			if( !selectTangent(tangentB1,tangentA1,ellipseA,tangentA1, true) )
				return false;
			if( !selectTangent(tangentB2,tangentA2,ellipseA,tangentA2, true) )
				return false;
			if( !selectTangent(tangentB3,tangentA3,ellipseA,tangentA3, false) )
				return false;

			if( allGood && Math.sqrt(sumDifference)/4.0 <= convergenceTol ) {
				break;
			}

		}

		converged = iteration < maxIterations;

		return true;
	}
public boolean process(EllipseRotated_F64 ellipseA , EllipseRotated_F64 ellipseB ,
						   Point2D_F64 tangentA0 , Point2D_F64 tangentA1 ,
						   Point2D_F64 tangentA2 , Point2D_F64 tangentA3 ,
						   Point2D_F64 tangentB0 , Point2D_F64 tangentB1 ,
						   Point2D_F64 tangentB2 , Point2D_F64 tangentB3 )
	{
		converged = false;

		// initialize by picking an arbitrary point on A and then finding the points on B in which
		// a line is tangent to B and passes through the point on A
		if (!initialize(ellipseA, ellipseB,
				tangentA0, tangentA1, tangentA2, tangentA3,
				tangentB0, tangentB1, tangentB2, tangentB3))
			return false;

		// update the location of each point until it converges or the maximum number of iterations has been exceeded
		int iteration = 0;
		for( ;iteration < maxIterations; iteration++ ) {
			boolean allGood = false;
			sumDifference = 0;

			if( !selectTangent(tangentA0,tangentB0,ellipseB,tangentB0, false) )
				return false;
			if( !selectTangent(tangentA1,tangentB1,ellipseB,tangentB1, true) )
				return false;
			if( !selectTangent(tangentA2,tangentB2,ellipseB,tangentB2, true) )
				return false;
			if( !selectTangent(tangentA3,tangentB3,ellipseB,tangentB3, false) )
				return false;

			if( Math.sqrt(sumDifference)/4.0 <= convergenceTol ) {
				allGood = true;
			}
			sumDifference = 0;

			if( !selectTangent(tangentB0,tangentA0,ellipseA,tangentA0, false) )
				return false;
			if( !selectTangent(tangentB1,tangentA1,ellipseA,tangentA1, true) )
				return false;
			if( !selectTangent(tangentB2,tangentA2,ellipseA,tangentA2, true) )
				return false;
			if( !selectTangent(tangentB3,tangentA3,ellipseA,tangentA3, false) )
				return false;

			if( allGood && Math.sqrt(sumDifference)/4.0 <= convergenceTol ) {
				break;
			}

		}

		converged = iteration < maxIterations;

		return true;
	}
public boolean process ( EllipseRotated_F64 ellipseA , EllipseRotated_F64 ellipseB , Point2D_F64 tangentA0 , Point2D_F64 tangentA1 , Point2D_F64 tangentA2 , Point2D_F64 tangentA3 , Point2D_F64 tangentB0 , Point2D_F64 tangentB1 , Point2D_F64 tangentB2 , Point2D_F64 tangentB3 ) { converged = false ; // initialize by picking an arbitrary point on A and then finding the points on B in which // a line is tangent to B and passes through the point on A if ( ! initialize ( ellipseA , ellipseB , tangentA0 , tangentA1 , tangentA2 , tangentA3 , tangentB0 , tangentB1 , tangentB2 , tangentB3 ) ) return false ; // update the location of each point until it converges or the maximum number of iterations has been exceeded int iteration = 0 ; for ( ; iteration < maxIterations ; iteration ++ ) { boolean allGood = false ; sumDifference = 0 ; if ( ! selectTangent ( tangentA0 , tangentB0 , ellipseB , tangentB0 , false ) ) return false ; if ( ! selectTangent ( tangentA1 , tangentB1 , ellipseB , tangentB1 , true ) ) return false ; if ( ! selectTangent ( tangentA2 , tangentB2 , ellipseB , tangentB2 , true ) ) return false ; if ( ! selectTangent ( tangentA3 , tangentB3 , ellipseB , tangentB3 , false ) ) return false ; if ( Math . sqrt ( sumDifference ) / 4.0 <= convergenceTol ) { allGood = true ; } sumDifference = 0 ; if ( ! selectTangent ( tangentB0 , tangentA0 , ellipseA , tangentA0 , false ) ) return false ; if ( ! selectTangent ( tangentB1 , tangentA1 , ellipseA , tangentA1 , true ) ) return false ; if ( ! selectTangent ( tangentB2 , tangentA2 , ellipseA , tangentA2 , true ) ) return false ; if ( ! selectTangent ( tangentB3 , tangentA3 , ellipseA , tangentA3 , false ) ) return false ; if ( allGood && Math . sqrt ( sumDifference ) / 4.0 <= convergenceTol ) { break ; } } converged = iteration < maxIterations ; return true ; }
<p>Selects 4 pairs of points.  Each point in the pair represents an end point in a line segment which is tangent
to both ellipseA and ellipseB.  Both ellipses are assumed to not intersect each other.  If a fatal error
occurs the function will return false.  However it can return true and did not converge.  To check for
convergence call {@link #isConverged()}.</p>

<p>Line 0 and line 3 will not intersect the line joining the center of the two ellipses while line 1 and 2 will.</p>

@param ellipseA (Input) An ellipse
@param ellipseB (Input) An ellipse
@param tangentA0 (Output) Tangent point on A for line segment 0
@param tangentA1 (Output) Tangent point on A for line segment 1
@param tangentA2 (Output) Tangent point on A for line segment 2
@param tangentA3 (Output) Tangent point on A for line segment 3
@param tangentB0 (Output) Tangent point on B for line segment 0
@param tangentB1 (Output) Tangent point on B for line segment 1
@param tangentB2 (Output) Tangent point on B for line segment 2
@param tangentB3 (Output) Tangent point on B for line segment 3
@return true if no fatal error, false if one happened.
<p > Selects 4 pairs of points . Each point in the pair represents an end point in a line segment which is tangent to both ellipseA and ellipseB . Both ellipses are assumed to not intersect each other . If a fatal error occurs the function will return false . However it can return true and did not converge . To check for convergence call { @link #isConverged () } . < / p >