求圆外一点做圆切线的切点坐标(python)

import math
def get_tangent_line(tx, ty, ox, oy, r):

  # 求点T到圆心O的距离
  distance = math.sqrt((tx-ox) ** 2 + (ty-oy) ** 2)
  # print('distance', distance)
  # 点T到切点P的距离
  length = math.sqrt(distance ** 2 - r ** 2)
  # print('length', length)
  if distance <= r:
      print("输入的数值不在范围内")
  return
  # 点到圆心的单位向量
  cx = abs(ox - tx) / distance
  cy = abs(oy - ty) / distance
  # print('cx', cx)
  # print('cy', cy)
  # 计算切线与圆心连线的夹角
  angle = math.asin(r / distance)
  print('angle', angle)
  # 向正反两个方向旋转单位向量
  q1x = cx * math.cos(angle)  -  cy * math.sin(angle)
  q1y = cx * math.sin(angle)  +  cy * math.cos(angle)
  q2x = cx * math.cos(-angle) -  cy * math.sin(-angle)
  q2y = cx * math.sin(-angle) +  cy * math.cos(-angle)
  # 得到新座标y
  q1x = q1x * length + tx
  q1y = q1y * length + ty
  q2x = q2x * length + tx
  q2y = q2y * length + ty
  return [q1x, q1y, q2x, q2y]

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
首先,我们需要确定两个的位置和半径。假设1的坐标为 (x1, y1),半径为 r1;2的坐标为 (x2, y2),半径为 r2。可以使用勾股定理计算出两个心之间的距离 d: ```python import math x1, y1, r1 = 1, 2, 3 x2, y2, r2 = -1, -2, 4 d = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) ``` 接下来,我们需要判断两个是否相交或包含。如果两个相离,则它们之间不存在公共切线。如果一个包含另一个,则公共切线无限多。 ```python if d > r1 + r2: print("两个相离,不存在公共切线") elif d < abs(r1 - r2): print("一个包含另一个,公共切线无限多") ``` 对于两个相交的,我们可以通过计算它们的切点坐标来得到公共切线。假设切点分别为 P1 和 P2,我们可以将两个心连线的中垂线作为公共切线的法线,然后计算法线与心连线的夹角 α。根据三角函数的定义,切线心连线的夹角为 90° - α。因此,我们可以计算切线的斜率 k,然后使用两点式得到切线的方程。 ```python else: a = (r1**2 - r2**2 + d**2) / (2 * d) h = math.sqrt(r1**2 - a**2) x3 = x1 + a * (x2 - x1) / d y3 = y1 + a * (y2 - y1) / d x4_1 = x3 + h * (y2 - y1) / d y4_1 = y3 - h * (x2 - x1) / d x4_2 = x3 - h * (y2 - y1) / d y4_2 = y3 + h * (x2 - x1) / d print("切点坐标为 ({:.2f}, {:.2f}) 和 ({:.2f}, {:.2f})".format(x4_1, y4_1, x4_2, y4_2)) ``` 完整代码如下: ```python import math x1, y1, r1 = 1, 2, 3 x2, y2, r2 = -1, -2, 4 d = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) if d > r1 + r2: print("两个相离,不存在公共切线") elif d < abs(r1 - r2): print("一个包含另一个,公共切线无限多") else: a = (r1**2 - r2**2 + d**2) / (2 * d) h = math.sqrt(r1**2 - a**2) x3 = x1 + a * (x2 - x1) / d y3 = y1 + a * (y2 - y1) / d x4_1 = x3 + h * (y2 - y1) / d y4_1 = y3 - h * (x2 - x1) / d x4_2 = x3 - h * (y2 - y1) / d y4_2 = y3 + h * (x2 - x1) / d print("切点坐标为 ({:.2f}, {:.2f}) 和 ({:.2f}, {:.2f})".format(x4_1, y4_1, x4_2, y4_2)) ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值