从投篮弧线到卫星天线抛物线方程变换让二次函数平移伸缩旋转不再难
那个夏天的篮球,教会我的数学
你还记得第一次认真观察篮球划出的那道弧线吗?
那年夏天,球场上的风有点大,你起跳、出手,球在空中画出一条完美的曲线,”唰”的一声空心入网。你站在原地,突然有点好奇:这条线到底是什么形状?为什么它总是这样弯?
如果你当时问了一个数学老师,老师可能会翻开课本,写下 \(y = ax^2 + bx + c\)。然后你盯着这一串符号,感觉它和你刚才看到的弧线之间隔着一整个宇宙。
别急。今天我们不背公式,我们用一种更像”人话”的方式,重新认识这条曲线——抛物线,以及它身上发生的各种变换。
第一步:把篮球”装”进坐标系
想象一下,如果你把球场铺上一层巨大的坐标纸:
- 原点 \((0,0)\) 就在篮筐的正下方
- \(x\) 轴沿着地面,\(y\) 轴垂直向上
- 你站在 \(x = -5\) 的位置起跳投篮
那么篮球的轨迹就会是一条开口向下的抛物线,最高点大约在 \(x = -2.5\) 处(出手点和落地点的中点)。
我们来用一个最简单的模型:
\[y = -\frac{1}{5}x^2 + 5\]
这个方程告诉你:当你站在 \(x = -5\) 的位置,球的高度是 \(y = 0\)(出手点);走到 \(x = 0\)(篮筐正下方),高度是 \(y = 5\) 米——这就是抛物线的顶点。
用 Python 把它画出来,你就明白为什么这个方程看起来”长得像”一条弧线了:
import numpy as np
import matplotlib.pyplot as plt
# 定义抛物线函数
def basketball_trajectory(x):
return -1/5 * x**2 + 5
# 生成数据
x = np.linspace(-5, 5, 200)
y = basketball_trajectory(x)
# 画图
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-', linewidth=2.5, label='投篮轨迹')
plt.scatter([-5, 0, 5], [0, 5, 0], color='red', s=80, zorder=5)
plt.text(-5.3, 0.5, '出手点', fontsize=10)
plt.text(0.3, 5.3, '最高点', fontsize=10)
plt.text(4.8, 0.5, '入网点', fontsize=10)
plt.axhline(y=3.05, color='orange', linestyle='--', linewidth=1.5, label='篮筐高度 3.05m')
plt.axvline(x=0, color='gray', linestyle=':', alpha=0.5)
plt.xlabel('水平距离 x (米)', fontsize=12)
plt.ylabel('高度 y (米)', fontsize=12)
plt.title('篮球投篮轨迹:y = -1/5·x² + 5', fontsize=14, fontweight='bold')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('basketball.png', dpi=150)
plt.show()
看,数学不是冷冰冰的符号,它是在描述一个真实的动作。
第二步:平移——把抛物线”搬”到你想去的地方
现在问题来了:如果篮筐不在正中间,或者你站的位置不一样,这条抛物线该怎么变?
这就是平移变换在起作用。
左右平移
假设原来的抛物线是 \(y = x^2\),它的顶点在原点。现在你想把顶点移到 \((3, 0)\) 的位置——也就是说,整个图像向右平移了 3 个单位。
新方程变成:
\[y = (x - 3)^2\]
为什么是 \((x - 3)\) 而不是 \((x + 3)\)?你可以这样理解:
为了让 \(y\) 的值保持不变,当 \(x\) 变成了 \(x - 3\) 之后,你需要更大的 \(x\) 才能得到原来的 \(y\)。比如原来 \(x = 0\) 时 \(y = 0\),现在要让 \((x-3)^2 = 0\),就得 \(x = 3\)。所以图像确实向右移动了。
向左平移 2 个单位呢?就是:
\[y = (x + 2)^2\]
上下平移
同样的逻辑,把顶点从 \((0, 0)\) 移到 \((0, 4)\):
\[y = x^2 + 4\]
平移的通用公式
把顶点从 \((h, k)\) 平移后,标准形式就是:
\[y = a(x - h)^2 + k\]
其中 \((h, k)\) 就是新顶点的坐标。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-4, 8, 300)
# 原始抛物线 y = x²
y1 = x**2
# 向右平移3,向上平移2:y = (x-3)² + 2
y2 = (x - 3)**2 + 2
plt.figure(figsize=(10, 6))
plt.plot(x, y1, 'b--', linewidth=2, label=r'$y = x^2$ (原始)')
plt.plot(x, y2, 'r-', linewidth=2.5, label=r'$y = (x-3)^2 + 2$ (平移后)')
plt.scatter([0, 3], [0, 2], color='green', s=100, zorder=5)
plt.text(-0.5, -0.5, '顶点(0,0)', fontsize=10)
plt.text(3.2, 1.5, '顶点(3,2)', fontsize=10)
plt.xlabel('x', fontsize=12)
plt.ylabel('y', fontsize=12)
plt.title('平移变换:抛物线从原点移动到(3, 2)', fontsize=14, fontweight='bold')
plt.legend()
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linewidth=0.5)
plt.axvline(x=0, color='k', linewidth=0.5)
plt.tight_layout()
plt.savefig('translation.png', dpi=150)
plt.show()
核心记忆口诀:”左加右减在括号里,上加下减在外面。”
第三步:伸缩——让抛物线”变胖”或”变瘦”
回到投篮的场景。如果你轻轻抛出一个高弧线(抛物线很”胖”),或者用力投出一个平直的弧线(抛物线很”瘦”),这就涉及到了伸缩变换。
纵向伸缩
把 \(y = x^2\) 的每个 \(y\) 值都乘以 2,得到 \(y = 2x^2\)。图像变”瘦”了,开口更窄。
把每个 \(y\) 值都乘以 \(\frac{1}{2}\),得到 \(y = \frac{1}{2}x^2\)。图像变”胖”了,开口更宽。
横向伸缩
把 \(x\) 替换成 \(2x\),得到 \(y = (2x)^2 = 4x^2\)。这看起来和纵向伸缩 4 倍一样?没错,但它们本质不同——横向压缩会让图像在 \(x\) 方向上”捏紧”。
伸缩的通用公式
\[y = a \cdot (kx - h)^2 + m\]
- \(|a| > 1\):纵向拉伸,开口变窄
- \(0 < |a| < 1\):纵向压缩,开口变宽
- \(a < 0\):开口向下(比如投篮)
- \(|k| > 1\):横向压缩
- \(0 < |k| < 1\):横向拉伸
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 300)
# 不同a值的伸缩效果
y1 = 0.5 * x**2 # 开口变宽
y2 = x**2 # 原始
y3 = 2 * x**2 # 开口变窄
y4 = -x**2 # 开口向下(像投篮)
plt.figure(figsize=(12, 6))
plt.plot(x, y1, 'b-', linewidth=2, label=r'$y = 0.5x^2$ (宽)')
plt.plot(x, y2, 'g--', linewidth=2, label=r'$y = x^2$ (原始)')
plt.plot(x, y3, 'orange', linewidth=2, label=r'$y = 2x^2$ (窄)')
plt.plot(x, y4, 'r-', linewidth=2.5, label=r'$y = -x^2$ (向下)')
plt.xlabel('x', fontsize=12)
plt.ylabel('y', fontsize=12)
plt.title('伸缩变换:系数a如何改变抛物线的形状', fontsize=14, fontweight='bold')
plt.legend()
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linewidth=0.5)
plt.axvline(x=0, color='k', linewidth=0.5)
plt.tight_layout()
plt.savefig('stretch.png', dpi=150)
plt.show()
第四步:旋转——最容易被忽略,但最强大的变换
到这里,平移和伸缩你可能已经滚瓜烂熟了。但旋转——这是大多数人(包括很多大学生)第一次认真面对的东西。
为什么旋转很重要?
你有没有想过:卫星天线为什么是那种碗状的?它接收信号的抛物面,如果安装时歪了一点角度,还能正常工作吗?
这就涉及到抛物线的旋转。
旋转的基本公式
在二维平面上,把一个点 \((x, y)\) 绕原点逆时针旋转 \(\theta\) 角度,新坐标 \((x', y')\) 是:
\[x' = x\cos\theta - y\sin\theta\]
\[y' = x\sin\theta + y\cos\theta\]
反过来,如果你知道旋转后的坐标,想求原来的坐标,就用:
\[x = x'\cos\theta + y'\sin\theta\]
\[y = -x'\sin\theta + y'\cos\theta\]
举个具体的例子
假设我们有一条抛物线 \(y = x^2\),我们把它绕原点逆时针旋转 \(45°\)(\(\theta = \frac{\pi}{4}\))。
用上面的公式,把 \(x\) 和 \(y\) 替换进去:
\[x = \frac{x' + y'}{\sqrt{2}}, \quad y = \frac{-x' + y'}{\sqrt{2}}\]
代入 \(y = x^2\):
\[\frac{-x' + y'}{\sqrt{2}} = \left(\frac{x' + y'}{\sqrt{2}}\right)^2\]
整理后得到旋转后的方程。虽然看起来复杂,但用代码来验证就一目了然了:
import numpy as np
import matplotlib.pyplot as plt
# 原始抛物线
theta = np.pi / 4 # 45度旋转
x_orig = np.linspace(-2, 2, 300)
y_orig = x_orig**2
# 旋转公式
x_rot = x_orig * np.cos(theta) - y_orig * np.sin(theta)
y_rot = x_orig * np.sin(theta) + y_orig * np.cos(theta)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(x_orig, y_orig, 'b-', linewidth=2)
plt.scatter([0], [0], color='red', s=60)
plt.xlabel('x'); plt.ylabel('y')
plt.title('原始抛物线: y = x²', fontsize=12)
plt.grid(True, alpha=0.3)
plt.gca().set_aspect('equal')
plt.subplot(1, 2, 2)
plt.plot(x_rot, y_rot, 'r-', linewidth=2)
plt.scatter([0], [0], color='red', s=60)
plt.xlabel("x'"); plt.ylabel("y'")
plt.title('旋转45°后的抛物线', fontsize=12)
plt.grid(True, alpha=0.3)
plt.gca().set_aspect('equal')
plt.tight_layout()
plt.savefig('rotation.png', dpi=150)
plt.show()
旋转后,原来的抛物线不再是一个”函数”了(一个 \(x\) 可能对应两个 \(y\)),但它仍然是一条抛物线,只是方向变了。
3D视角:卫星天线就是旋转抛物面
这才是旋转最精彩的应用。
想象一条抛物线 \(y = x^2\)(开口向上),我们让它绕 \(y\) 轴旋转一整圈——得到的曲面叫做旋转抛物面。
它的方程是:
\[z = x^2 + y^2\]
这就是卫星天线的形状!无论信号从哪个方向来,只要沿着抛物线的轴线方向入射,都会被反射到同一个焦点上。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 创建旋转抛物面
u = np.linspace(-2, 2, 100)
v = np.linspace(0, 2*np.pi, 100)
U, V = np.meshgrid(u, v)
X = U * np.cos(V)
Y = U * np.sin(V)
Z = U**2 + Y**0 * 0 # z = x² + y²
fig = plt.figure(figsize=(12, 5))
# 左图:原始抛物线
ax1 = fig.add_subplot(1, 2, 1)
x = np.linspace(-2, 2, 200)
y = x**2
ax1.plot(x, y, 'b-', linewidth=2.5)
ax1.scatter([0], [0], color='red', s=80, zorder=5, label='焦点')
ax1.axhline(y=0.25, color='orange', linestyle='--', alpha=0.7, label='准线')
ax1.set_xlabel('x'); ax1.set_ylabel('y')
ax1.set_title('抛物线 y = x² (绕y轴旋转得到卫星天线)', fontsize=12)
ax1.legend()
ax1.grid(True, alpha=0.3)
ax1.set_aspect('equal')
# 右图:旋转抛物面(3D)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
ax2.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8, edgecolor='none')
ax2.scatter([0], [0], [0.25], color='red', s=100, label='焦点 (0,0,0.25)')
ax2.set_xlabel('x'); ax2.set_ylabel('y'); ax2.set_zlabel('z')
ax2.set_title('旋转抛物面 z = x² + y² (卫星天线形状)', fontsize=12)
ax2.legend()
plt.tight_layout()
plt.savefig('satellite_dish.png', dpi=150)
plt.show()
为什么卫星天线要长成这样?
这就是抛物线的光学性质:
从焦点发出的光线,经抛物面反射后,会变成平行于轴线的光束。 反过来,平行于轴线入射的光线,经抛物面反射后,会汇聚到焦点。
卫星通信就是利用这个原理:地面站的天线把电信号转换成电磁波,从焦点发出,经抛物面反射后变成平行波束射向卫星;卫星接收到的平行波束又经抛物面反射汇聚到焦点,转换成电信号传回地面。
综合变换:一次搞定所有操作
现在我们把平移、伸缩、旋转全部结合起来。
一个通用的二次曲线方程是:
\[Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0\]
当 \(B^2 - 4AC < 0\) 时,这是一个椭圆(包括圆);当 \(B^2 - 4AC = 0\) 时,是抛物线;当 \(B^2 - 4AC > 0\) 时,是双曲线。
我们用代码来演示一次完整的变换流程:
import numpy as np
import matplotlib.pyplot as plt
def transform_parabola(a, h, k, scale_x=1, scale_y=1, angle_deg=0):
"""
对抛物线 y = a(x-h)² + k 进行变换
参数:
a: 开口大小和方向
h, k: 顶点坐标(平移)
scale_x: 横向伸缩系数
scale_y: 纵向伸缩系数
angle_deg: 旋转角度(度)
返回:
变换后的 (x, y) 坐标
"""
# 原始抛物线上的点
x_orig = np.linspace(h - 3, h + 3, 300)
y_orig = a * (x_orig - h)**2 + k
# 平移回原点(方便后续变换)
x1 = x_orig - h
y1 = y_orig - k
# 伸缩
x2 = x1 / scale_x
y2 = y1 / scale_y
# 旋转
theta = np.radians(angle_deg)
x3 = x2 * np.cos(theta) - y2 * np.sin(theta)
y3 = x2 * np.sin(theta) + y2 * np.cos(theta)
# 平移回顶点
x_final = x3 + h
y_final = y3 + k
return x_final, y_final
# 绘制不同变换效果
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
# 原始抛物线
axes[0, 0].plot(*transform_parabola(a=-1, h=0, k=0), 'b-', linewidth=2)
axes[0, 0].set_title('原始: y = -x²', fontsize=11)
axes[0, 0].grid(True, alpha=0.3)
axes[0, 0].set_aspect('equal')
# 平移
axes[0, 1].plot(*transform_parabola(a=-1, h=2, k=3), 'r-', linewidth=2)
axes[0, 1].set_title('平移: 顶点移到(2,3)', fontsize=11)
axes[0, 1].grid(True, alpha=0.3)
axes[0, 1].set_aspect('equal')
# 伸缩
axes[0, 2].plot(*transform_parabola(a=-1, h=0, k=0, scale_y=0.5), 'g-', linewidth=2)
axes[0, 2].set_title('纵向压缩: a变为-0.5', fontsize=11)
axes[0, 2].grid(True, alpha=0.3)
axes[0, 2].set_aspect('equal')
# 旋转
axes[1, 0].plot(*transform_parabola(a=-1, h=0, k=0, angle_deg=30), 'orange', linewidth=2)
axes[1, 0].set_title('旋转30°', fontsize=11)
axes[1, 0].grid(True, alpha=0.3)
axes[1, 0].set_aspect('equal')
# 综合变换
axes[1, 1].plot(*transform_parabola(a=-1, h=2, k=3, scale_y=0.5, angle_deg=30), 'purple', linewidth=2)
axes[1, 1].set_title('综合变换: 平移+伸缩+旋转', fontsize=11)
axes[1, 1].grid(True, alpha=0.3)
axes[1, 1].set_aspect('equal')
# 交互式说明
axes[1, 2].text(0.5, 0.8, '变换步骤总结', fontsize=13, fontweight='bold',
transform=axes[1, 2].transAxes, ha='center')
axes[1, 2].text(0.5, 0.6, '1. 平移: (x-h)² → 顶点移到(h,k)', fontsize=10,
transform=axes[1, 2].transAxes, ha='center')
axes[1, 2].text(0.5, 0.45, '2. 伸缩: y = a·(缩放后的x)² + 缩放后的y', fontsize=10,
transform=axes[1, 2].transAxes, ha='center')
axes[1, 2].text(0.5, 0.3, '3. 旋转: 用旋转矩阵处理坐标', fontsize=10,
transform=axes[1, 2].transAxes, ha='center')
axes[1, 2].text(0.5, 0.1, '口诀: 先平移归原点 → 再伸缩 → 再旋转 → 最后平移回顶点',
fontsize=10, fontweight='bold', transform=axes[1, 2].transAxes, ha='center',
bbox=dict(boxstyle='round', facecolor='lightyellow', edgecolor='orange'))
axes[1, 2].axis('off')
plt.tight_layout()
plt.savefig('comprehensive.png', dpi=150)
plt.show()
从篮球场到太空:抛物线的威力
你看,从你投篮时划出的那道弧线,到千里之外接收卫星信号的巨大天线,它们用的都是同一条曲线——抛物线。
平移让你能把抛物线放到任何位置;伸缩让你能调整它的宽窄和方向;旋转让你能把二维的曲线变成三维的卫星天线。
这三种变换,本质上都是在回答同一个问题:“这条曲线在哪里?长什么样?朝向哪里?”
掌握了它们,你就掌握了一把钥匙——一把能打开物理、工程、甚至计算机图形学大门的钥匙。
下次再看到抛物线,别只想到数学课本。想想那个篮球,想想那座卫星天线,想想光从焦点出发后变成平行光束的奇妙过程。
数学从来不是冷冰冰的符号,它是描述这个世界的语言。而抛物线,是其中最优雅的一句诗。
