public class Circle { public double[] center; public double radius; public Circle(double[] center, double radius) { this.center = center; this.radius = radius; } public String toString() { return String.format("Circle[x=%.2f,y=%.2f,r=%.2f]",center[0],center[1], radius); } } public class ApolloniusSolver { /** Solves the Problem of Apollonius (finding a circle tangent to three other * circles in the plane). The method uses approximately 68 heavy operations * (multiplication, division, square-roots). * @param c1 One of the circles in the problem * @param c2 One of the circles in the problem * @param c3 One of the circles in the problem * @param s1 An indication if the solution should be externally or internally * tangent (+1/-1) to c1 * @param s2 An indication if the solution should be externally or internally * tangent (+1/-1) to c2 * @param s3 An indication if the solution should be externally or internally * tangent (+1/-1) to c3 * @return The circle that is tangent to c1, c2 and c3. */ public static Circle solveApollonius(Circle c1, Circle c2, Circle c3, int s1, int s2, int s3) { float x1 = c1.center[0]; float y1 = c1.center[1]; float r1 = c1.radius; float x2 = c2.center[0]; float y2 = c2.center[1]; float r2 = c2.radius; float x3 = c3.center[0]; float y3 = c3.center[1]; float r3 = c3.radius; //Currently optimized for fewest multiplications. Should be optimized for //readability float v11 = 2*x2 - 2*x1; float v12 = 2*y2 - 2*y1; float v13 = x1*x1 - x2*x2 + y1*y1 - y2*y2 - r1*r1 + r2*r2; float v14 = 2*s2*r2 - 2*s1*r1; float v21 = 2*x3 - 2*x2; float v22 = 2*y3 - 2*y2; float v23 = x2*x2 - x3*x3 + y2*y2 - y3*y3 - r2*r2 + r3*r3; float v24 = 2*s3*r3 - 2*s2*r2; float w12 = v12/v11; float w13 = v13/v11; float w14 = v14/v11; float w22 = v22/v21-w12; float w23 = v23/v21-w13; float w24 = v24/v21-w14; float P = -w23/w22; float Q = w24/w22; float M = -w12*P-w13; float N = w14 - w12*Q; float a = N*N + Q*Q - 1; float b = 2*M*N - 2*N*x1 + 2*P*Q - 2*Q*y1 + 2*s1*r1; float c = x1*x1 + M*M - 2*M*x1 + P*P + y1*y1 - 2*P*y1 - r1*r1; // Find a root of a quadratic equation. This requires the circle centers not // to be e.g. colinear float D = b*b-4*a*c; float rs = (-b-Math.sqrt(D))/(2*a); float xs = M + N * rs; float ys = P + Q * rs; return new Circle(new double[]{xs,ys}, rs); } public static void main(final String[] args) { Circle c1 = new Circle(new double[]{0,0}, 1); Circle c2 = new Circle(new double[]{4,0}, 1); Circle c3 = new Circle(new double[]{2,4}, 2); // Expects "Circle[x=2.00,y=2.10,r=3.90]" (green circle in image) System.out.println(solveApollonius(c1,c2,c3,1,1,1)); // Expects "Circle[x=2.00,y=0.83,r=1.17]" (red circle in image) System.out.println(solveApollonius(c1,c2,c3,-1,-1,-1)); } }