Ror*_*ton 11
这是使用三角学的一种方法。如果您了解三角函数,这种方法很容易理解,尽管由于三角函数缺乏精确性,它可能无法给出准确的正确答案。
给出了点C = (Cx, Cy)和P = (Px, Py)以及半径a。半径在我的图中显示了两次,即a1和a2。b您可以轻松计算点P和之间的距离C,并且您可以看到该线段b形成了两个边长为 的直角三角形的斜边a。角度theta(在我的图中也显示了两次)位于斜边和相邻边之间a,因此可以使用反余弦来计算。C从一点到另一点的向量的方向角P也可以通过反正切轻松找到。切点的方向角是原始方向角与计算出的三角形角的和与差。最后,我们可以使用这些方向角和距离a来找到这些切点的坐标。
这是 Python 3 中的代码。
# Example values
(Px, Py) = (5, 2)
(Cx, Cy) = (1, 1)
a = 2
from math import sqrt, acos, atan2, sin, cos
b = sqrt((Px - Cx)**2 + (Py - Cy)**2) # hypot() also works here
th = acos(a / b) # angle theta
d = atan2(Py - Cy, Px - Cx) # direction angle of point P from C
d1 = d + th # direction angle of point T1 from C
d2 = d - th # direction angle of point T2 from C
T1x = Cx + a * cos(d1)
T1y = Cy + a * sin(d1)
T2x = Cx + a * cos(d2)
T2y = Cy + a * sin(d2)
Run Code Online (Sandbox Code Playgroud)
有明显的方法可以组合这些计算并使它们更加优化,但我将把它留给您。还可以使用三角学的角度加法和减法公式以及一些其他恒等式来从计算中完全删除三角函数。然而,结果更加复杂且难以理解。未经测试,我不知道哪种方法更“优化”,但这取决于您的目的。如果您需要这种其他方法,请告诉我,但这里的其他答案无论如何都会为您提供其他方法。
注意,if a > bthenacos(a / b)会抛出异常,但这意味着该点P在圆内并且没有切点。若该a == b点在圆上且只有一个切点,即点本身。我的代码适用于这种情况。我将让您对其他情况进行编码并确定确定和 是否相等所需的精度。PPa < bab
这是使用复数的另一种方法。如果 a 是从圆心 c 开始的圆上切点的方向(长度为 1 的复数),d 是沿切线到达 p 的(实数)长度,那么(因为切线的方向是我*一)
p = c + r*a + d*I*a
Run Code Online (Sandbox Code Playgroud)
重新排列
(r+I*d)*a = p-c
Run Code Online (Sandbox Code Playgroud)
但 a 的长度为 1,所以取我们得到的长度
|r+I*d| = |p-c|
Run Code Online (Sandbox Code Playgroud)
除了 d 之外我们什么都知道,所以我们可以求解 d:
d = +- sqrt( |p-c|*|p-c| - r*r)
Run Code Online (Sandbox Code Playgroud)
然后找到 a 和圆上的点,每个 d 值对应一个:
a = (p-c)/(r+I*d)
q = c + r*a
Run Code Online (Sandbox Code Playgroud)