当前位置: 首页 > news >正文

如何用Python绘制两个圆之间的8条公切线

引言

在几何学中,两圆之间存在多种类型的公共切线。本文将通过Python代码演示如何绘制两个同心圆(半径分别为1.0和3.0)之间的8条公切线,并解释相关数学原理与代码实现细节。

环境准备

import matplotlib.pyplot as plt
import numpy as np

这两个库是绘制图形的基础:

  • matplotlib 用于可视化
  • numpy 提供数值计算支持

参数设置

radius = 1.0         # 小圆半径
radius_large = 3.0   # 大圆半径
num_lines = 8        # 切线数量
theta_step = 2 * np.pi / num_lines

参数说明:

  • radiusradius_large 定义两个圆的半径
  • num_lines 控制切线的数量(这里选择8条)
  • theta_step 计算每个角度间隔

角度生成

thetas = np.linspace(0, 2 * np.pi, num_lines, endpoint=False)
thetas = thetas.tolist() + [0]

这个步骤的目的是生成均匀分布的角度点:

  1. 使用 linspace 生成不包括终点的8个点
  2. 添加0作为闭合循环的最后一个点

绘制基本图形

plt.figure(figsize=(6, 6))
plt.axis('equal')  # 确保坐标轴比例一致# 绘制两个圆
plt.plot(radius * np.cos(thetas), radius * np.sin(thetas), label='Original Circle')
plt.plot(radius_large * np.cos(thetas), radius_large * np.sin(thetas), label='Large Circle')

plt.axis('equal') 确保图形保持正圆形状,避免变形。

切线绘制分析

问题所在

原始代码中的切线绘制存在逻辑错误:

for theta, theta1 in zip(thetas[1:], thetas[:-1]):# 原始圆上的点x1 = radius * np.cos(theta)y1 = radius * np.sin(theta)x2 = radius_large * np.cos(theta1)y2 = radius_large * np.sin(theta1)plt.plot([x1, x2], [y1, y2], 'r-', label='Tangent Line (Small Circle)')

这段代码的问题在于:

  • thetas 的处理导致循环配对错误
  • 直接连接两个圆上的点无法保证是公切线

正确做法

要正确绘制两圆之间的公切线,需要计算切线方程:

  1. 两圆心距离:d = radius_large - radius = 2.0
  2. 切线长度:L = sqrt(d² + r²)(r为半径差)

正确的切线方向向量应为:

dx = (radius_large * np.cos(theta) - radius * np.cos(theta))
dy = (radius_large * np.sin(theta) - radius * np.sin(theta))

但更准确的计算需要使用几何公式:

改进代码

# 计算公切线方向向量
dx_tangent_small = np.sin(thetas)
dy_tangent_small = -np.cos(thetas)dx_tangent_large = np.sin(thetas)
dy_tangent_large = -np.cos(thetas)line_length = 2.0for theta in thetas:# 小圆切线点x1 = radius * np.cos(theta)y1 = radius * np.sin(theta)x2 = x1 + dx_tangent_small[theta] * line_lengthy2 = y1 + dy_tangent_small[theta] * line_length# 大圆切线点x3 = radius_large * np.cos(theta)y3 = radius_large * np.sin(theta)x4 = x3 + dx_tangent_large[theta] * line_lengthy4 = y3 + dy_tangent_large[theta] * line_lengthplt.plot([x1, x2], [y1, y2], 'r-', label='Tangent Line (Small Circle)')plt.plot([x3, x4], [y3, y4], 'b-', label='Tangent Line (Large Circle)')

注意事项

  1. 切线方向计算:正确的切线方向是圆周的法向量(-sinθ, cosθ)
  2. 长度控制:确保线段在圆外延伸
  3. 闭合循环:thetas数组需要正确闭合以形成完整图形
  4. 图例显示:建议使用plt.legend()展示所有元素

最终效果

运行代码后,会得到一个包含:

  • 两个同心圆
  • 8条公切线(红色和蓝色分别代表小圆和大圆的切线)
  • 均匀分布的切线方向

总结

通过分析原始代码并理解几何原理,我们修正了切线绘制方法。正确的做法是:

  1. 计算切线方向向量
  2. 确保线段长度在圆外
  3. 正确闭合循环形成完整图形

这种可视化可以帮助深入理解圆的公切线性质,在工程制图、计算机视觉等领域有广泛应用价值。

import matplotlib.pyplot as plt
import numpy as np# 圆的参数设置
radius = 1.0  # 原始圆半径
radius_large = 3.0  # 较大的圆半径
num_lines = 8  # 线段数量
theta_step = 2 * np.pi / num_lines  # 每条线段对应的角度步长# 计算角度(均匀分布)
thetas = np.linspace(0, 2 * np.pi, num_lines, endpoint=False)
thetas = thetas.tolist()+[0]
# 初始化绘图区域
plt.figure(figsize=(6, 6))
plt.axis('equal')  # 确保坐标轴比例一致,绘制圆形# 绘制两个圆
plt.plot(radius * np.cos(thetas), radius * np.sin(thetas),  label='Original Circle')
plt.plot(radius_large * np.cos(thetas), radius_large * np.sin(thetas), label='Large Circle')# 定义线段长度(确保在圆外)
line_length = 2.0# 绘制切线方向的8条线
for theta,theta1 in zip(thetas[1:],thetas[:-1]):# 原始圆上的点x1 = radius * np.cos(theta)y1 = radius * np.sin(theta)x2 = radius_large * np.cos(theta1)y2 = radius_large * np.sin(theta1)plt.plot([x1, x2], [y1, y2], 'r-', label='Tangent Line (Small Circle)')# 较大圆上的点# x1_large = radius_large * np.cos(theta)# y1_large = radius_large * np.sin(theta)## dx_tangent_large = -np.sin(theta)# dy_tangent_large = np.cos(theta)## x2_large = x1_large + dx_tangent_large * line_length# y2_large = y1_large + dy_tangent_large * line_length## plt.plot([x1_large, x2_large], [y1_large, y2_large], 'b-', label='Tangent Line (Large Circle)')# 去除刻度线和网格线
plt.tick_params(axis='both', which='both', length=0)
plt.grid(False)# 添加图例(可选)
# plt.legend()# 显示图形
plt.title("8 Tangent Lines on Two Circles")
plt.show()

相关文章:

  • 第J6周:ResNeXt-50实战
  • C++ 动态内存管理详讲
  • 数字智慧方案5877丨智慧交通项目方案(122页PPT)(文末有下载方式)
  • SX24C01.UG-PXI程控电阻桥板卡
  • 英一真题阅读单词笔记 20-21年
  • 藏文词云生成器学习实践
  • 2000-2020年全国各地级市资本存量测算数据(以2000年为基期)(含原始数据+计算过程+结果)
  • 数字智慧方案5875丨智慧交通枢纽综合解决方案(43页PPT)(文末有下载方式)
  • ValueError: expected sequence of length 8 at dim 2 (got 0)
  • 历史数据分析——运输服务
  • B站Michale_ee——ESP32_IDF SDK——FreeRTOS_6 任务通知同步、任务通知值
  • Qt QGraphicsScene 的用法
  • 分享国产AI工作流集成数据库完成业务处理
  • 常见工业汽车行业通讯接口一览表
  • 珠江桥牌闪耀第137届广交会,展现中国味道与创新活力
  • 【Redis】Hash哈希
  • YOLO旋转目标检测之ONNX模型推理
  • 基于SpringBoot+Vue实现的电影推荐平台功能一
  • 通过组策略使能长路径
  • re题(52)BUUCTF-[FlareOn5]Minesweeper Championship Registration
  • 2025年五一档电影票房破4亿,《水饺皇后》领跑
  • 跳水世界杯总决赛:程子龙/朱子锋夺男子双人10米台冠军
  • 乘客被困停滞车厢超4小时,哈尔滨铁路局客服:列车晚点,表示歉意
  • 多地景区发公告称售票达接待峰值,有景区暂停网络和线下售票
  • 全球最大汽车板供应商宝钢股份:汽车工业加速转型中材料商如何共舞?
  • 据报特斯拉寻找新CEO,马斯克财报会议上表态:把更多时间投入特斯拉