Пусть (xP, yP)
будет пересечением касательных, (xC,yY)
будет центром круга, где вы ищите координаты (xT,yT)
точек касания.Далее, пусть T
будет вектором касательной, а R
будет вектором радиуса.Поскольку они перпендикулярны, у вас есть R . T = 0
.
Это дает нам
(xT-xC,yT-yC) . (xT-xP, yT-yP) = 0
Пусть r
- радиус круга, и пусть x:=xT-xC, y:=yT-yC, xp:=xP-xC, yp:=yP-yC
(в основном, мы перемещаем круг в (0,0)
).Точка касания находится на круге, поэтому у вас есть x²+y²=r²
и, следовательно, также y=sqrt(r²-x²)
.
Подстановка переменной, примененная к приведенному выше уравнению, дает нам:
(x,y) . (x-xp, y-yp) = 0
x²-xp*x + y²-yp*y = 0
Использование кругаинформация, которую мы имеем:
r² -xp*x - yp*sqrt(r²-x²) = 0
r² -xp*x = yp*sqrt(r²-x²)
r^4 - 2*r²*xp*x + xp²*x² = yp²*(r²-x²)
(yp²+xp²)*x² - 2*r²*xp*x + r^4-yp²*r² = 0
now let a:=yp²+xp², b:=2*r²*xp, c:= (r²-yp²)*r²
=> ax² + bx + c = 0
Это квадратное уравнение с 0, 1 или 2 решениями.0, если P равно в круге, 1, если P равно на круге и 2, если P равно вне круга.
Я не буду помещать здесь явное решение, так как это адская формула, и ее гораздо проще написать, если вы сопоставите введенные здесь переменные с переменными в вашем коде как:
var sq:Function = function (f:Number) { return f*f; }, sqrt:Function = Math.sqrt;
var xp:Number = xP-xC, yp:Number = yP-yC,
a:Number = sq(xp)+sq(yp), b:Number = 2*sq(r)*xp, c:Number = sq(r)*(sq(r)-sq(yp));
var x1:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a),
x2:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a);
if (isNan(x1)) return [];
var p1:Point = new Point(x1+cX, sqrt(sq(r)-sq(x1))+cY),//calculate y and undo shift
p2:Point = new Point(x2+cX, sqrt(sq(r)-sq(x2))+cY);
return p1.equals(p2) ? [p1] : [p1, p2];
Bestудачи в этом, потому что я очень плохо разбираюсь, плюс здесь 04:00, так что вы можете поспорить, где-то есть ошибка, но это должно привести вас в правильном направлении;)