I have two concentric circles and two tangent lines originating from a (single) point on the outer circle. I want to determine where the extension of the tangent lines intersect the outer circle. If it matters, this is in JS, drawing on a canvas.
I know the coordinates and/or values for A, R, r, Tb, Tc, [and the center of the circles, of course, which we can assume is at (0, 0)]. I need to find the coordinates of "B" and "C".
Any help/suggestions welcome.
B.x = 2*Tb.x - A.x
B.y = 2*Tb.y - A.y
C.x = 2*Tc.x - A.x
C.y = 2*Tc.y - A.y
Solution when Tb, Tc
are not known (as I thought at first...):
At first we need to find tangent points T
(TB
and TC
).
Small circle radius vector to tangent point is perpendicular to tangent, so scalar product of these vectors is zero - eq.[1]. And this vector's length is r
- eq.[2], so we have equation system:
Tx*(Tx-Ax)+Ty*(Ty-Ay)=0 [1]
Tx^2+Ty^2 = r^2 [2]
Transforming it we get quadratic equation for unknown Tx
coordinate
Tx^2-Tx*Ax+Ty^2-TyAy=0
r*r = Tx*Ax+TyAy
Ty = (r^2 - Tx*Ax) / Ay [3]
Tx^2*Ay^2+(r^2 - Tx*Ax)^2 = r^2*Ay^2
Tx^2*(Ay^2+Ax^2) + Tx*(-2*r^2*Ax) + (r^4-r^2*Ay^2) = 0 [4]
Solving the last quadratic equation we get two (in general case) solutions for coordinates TBx, TCx
, then calculate Y-coordinates from [3] if Ay!=0
or from [2] otherwise.
A-B
vector is just doubled A-TB
vector, so
Bx = Ax + 2*(TBx-Ax) = 2*TBx - Ax
By = Ay + 2*(TCy-Ay) = 2*TBy - Ay
and similar for C
point coordinates
Python code for reference:
def square_eq(a, b, c):
Dis = b*b-4*a*c
if Dis < 0:
return []
elif Dis ==0:
return [-0.5*b/a]
else:
Dis = Dis**0.5
return [0.5*(-b-Dis)/a, 0.5*(-b+Dis)/a]
def twocirctan(ax, ay, r):
a = ay*ay+ax*ax
if a <= r*r:
return None
b = -2*r*r*ax
c = r**4-r*r*ay*ay
sol = square_eq(a, b, c)
if len(sol)==0:
return None
elif len(sol)==1:
tbx = sol[0]
tcx = sol[0]
tby = (r*r - tbx*tbx)**0.5
tcy = -tby
else:
tbx = sol[0]
tcx = sol[1]
tby = (r*r - tbx*ax) / ay
tcy = (r*r - tcx*ax) / ay
return [[2*tbx-ax, 2*tby-ay], [2*tcx-ax, 2*tcy-ay]]
print(twocirctan(1,0,2))
print(twocirctan(5,0,2))
print(twocirctan(3,4,2))
Results:
None
[[-3.4, 3.666060555964672], [-3.4, -3.666060555964672]]
[[-4.972848444771738, -0.520363666421197], [0.8928484447717375, -4.919636333578803]]
And as a JavaScript snippet:
const square_eq = (a, b, c) => {
let dis = b*b-4*a*c;
if (dis < 0) {
return [];
}
else if (dis === 0) {
return [-0.5*b/a];
}
else {
dis = dis ** 0.5;
return [0.5*(-b-dis)/a, 0.5*(-b+dis)/a];
}
}
const twocirctan = (ax, ay, r) => {
const a = ay*ay+ax*ax;
if (a <= r*r) {
return NaN;
}
const b = -2*r*r*ax;
const c = r**4-r*r*ay*ay;
const sol = square_eq(a, b, c);
let tbx, tcx, tby, tcy;
if (sol.length === 0) {
return NaN;
}
else if (sol.length === 1) {
tbx = sol[0];
tcx = sol[0];
tby = (r*r - tbx*tbx)**0.5;
tcy = -tby;
}
else {
tbx = sol[0];
tcx = sol[1];
tby = (r*r - tbx*ax) / ay;
tcy = (r*r - tcx*ax) / ay;
}
return [[2*tbx-ax, 2*tby-ay], [2*tcx-ax, 2*tcy-ay]];
}
console.log(twocirctan(1,0,2))
console.log(twocirctan(5,0,2))
console.log(twocirctan(3,4,2))
Proof picture (B,C,E,F coordinates):