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;
	}
<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.