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

如何用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()
http://www.xdnf.cn/news/3545.html

相关文章:

  • 从原理到实战讲解回归算法!!!
  • FastAPI 与数据库交互示例
  • 集成Langfuse和Langchain:简化开发,增强自然语言理解能力
  • 解决“‘mvn‘ 不是内部或外部命令,也不是可运行的程序”错误
  • 5.2算法学习笔记(动态规划)
  • 书生实战营之沐曦专场
  • FHQ Treap
  • 蒙特卡罗方法(Monte Carlo Method)​​:基于随机采样的数值计算与模拟技术
  • WMO 介绍
  • 【Redis】List类型
  • AntSK:基于大模型的一体化AI知识库解决方案深度解析
  • 【JS压缩图片】js压缩图片至指定大小
  • MCP智能体意图识别与工具路由:让AI自主决策调用链路
  • 支持向量机(SVM)详解
  • Arduino逻辑控制详细解答,一点自己的想法记录
  • 2025A卷华为OD机试真题-数组二叉树(C++/Java/Python)-100分
  • 当神经网络突破摩尔定律:探索大模型时代的算力新纪元
  • ValueError: expected sequence of length 8 at dim 2 (got 0)
  • 解构区块链身份认证:从ID到零知识证明的实战指南
  • JAVA:使用 XStream 实现对象与XML转换的技术指南
  • GPT-4o 图像生成与八个示例指南
  • 免费视频文件压缩工具使用教程与技巧详解
  • [面试]SoC验证工程师面试常见问题(四)
  • 中小企业MES系统概要设计
  • shell_plus
  • Day.js和Moment.js对比,日期时间库怎么选?
  • C++调试(贰):Dump文件的生成(附Qt示例)
  • 2.maven 手动安装 jar包
  • 【优选算法 | 位运算】位运算基础:深入理解二进制操作
  • lib和dll介绍和VS2019生成实例