一、二维坐标变换:平移、旋转、缩放
各位同学,咱们今天聊聊二维坐标变换。说实话,这玩意儿是仿真里最基础、也最绕不开的内容。我做了这么多年仿真,几乎每个项目都要跟它打交道。你想想看,不管是机械臂的运动模拟,还是图像处理里的像素操作,本质上都是在做坐标变换。
二维坐标变换,说白了就是三种操作:平移、旋转、缩放。别小看这三个词,它们组合起来能玩出花来。今天我就带大家把这三种变换彻底吃透。
1.1 平移变换
平移,顾名思义,就是把一个点从A位置挪到B位置。比如点P(x, y)想往右走3个单位,再往上走2个单位,那新坐标就是(x+3, y+2)。
用矩阵表示就是:
[x'] [1 0 tx] [x]
[y'] = [0 1 ty] [y]
[1 ] [0 0 1 ] [1]
这里tx和ty就是x方向和y方向的平移量。为什么用3x3矩阵?嗯,这里要注意——这是为了把平移和后面的旋转、缩放统一成一种表示方式。我们管这叫齐次坐标。
1.2 旋转变换
旋转稍微复杂一点。绕原点逆时针旋转θ角度,公式是:
x' = x*cosθ - y*sinθ
y' = x*sinθ + y*cosθ
矩阵形式:
[x'] [cosθ -sinθ 0] [x]
[y'] = [sinθ cosθ 0] [y]
[1 ] [0 0 1] [1]
旋转有个重要性质:它是正交变换。什么意思?就是旋转前后,图形的形状和大小都不变,只是朝向变了。这个性质在仿真里特别有用,比如做刚体运动模拟时,我们经常用旋转矩阵来保证物体不变形。
1.3 缩放变换
缩放就是放大或缩小。沿x轴缩放sx倍,沿y轴缩放sy倍:
[x'] [sx 0 0] [x]
[y'] = [0 sy 0] [y]
[1 ] [0 0 1] [1]
如果sx = sy,就是均匀缩放,图形形状不变。如果sx ≠ sy,就是非均匀缩放,图形会被拉伸或压缩。
1.4 三种变换的统一表示
现在我们把三种变换放在一起看。用齐次坐标,它们都是3x3矩阵:
| 变换类型 | 矩阵形式 | 参数说明 |
|---|---|---|
| 平移 | [1 0 tx; 0 1 ty; 0 0 1] | tx, ty为平移量 |
| 旋转 | [cosθ -sinθ 0; sinθ cosθ 0; 0 0 1] | θ为旋转角度(逆时针) |
| 缩放 | [sx 0 0; 0 sy 0; 0 0 1] | sx, sy为缩放因子 |
组合变换时,矩阵乘法的顺序很重要。我个人习惯用右乘的方式理解:先应用的变换放在右边,后应用的放在左边。比如先旋转再平移,变换矩阵就是 T * R。
1.5 实战:用Python实现二维变换
光说不练假把式。咱们写个简单的Python代码,把三种变换串起来:
import numpy as np
def translation(tx, ty):
return np.array([
[1, 0, tx],
[0, 1, ty],
[0, 0, 1]
])
def rotation(theta):
c, s = np.cos(theta), np.sin(theta)
return np.array([
[c, -s, 0],
[s, c, 0],
[0, 0, 1]
])
def scaling(sx, sy):
return np.array([
[sx, 0, 0],
[0, sy, 0],
[0, 0, 1]
])
# 组合变换:先旋转45度,再平移(2,3)
theta = np.pi / 4
T = translation(2, 3)
R = rotation(theta)
M = T @ R # 注意顺序:先R后T
# 对点(1,0)应用变换
p = np.array([1, 0, 1])
p_new = M @ p
print(f"变换后坐标: ({p_new[0]:.2f}, {p_new[1]:.2f})")
1.6 知识体系总览
为了让大家对本章内容有个整体认识,我画了张图:
从这张图可以看得很清楚:平移、旋转、缩放是三种基本操作,通过齐次坐标统一成矩阵形式,然后通过矩阵乘法组合出任意复杂的变换。这就是整个二维坐标变换的核心逻辑。
1.7 避坑指南
最后,我把自己这些年踩过的坑总结一下:
- 矩阵乘法顺序:先旋转再平移 和 先平移再旋转,结果完全不同。我建议用右乘顺序理解,代码里也按这个顺序写。
- 角度单位:Python的math库用弧度,但很多工程图纸用角度。我习惯在函数入口统一转成弧度,避免混淆。
- 浮点误差:多次变换累积后,坐标可能会有微小误差。做仿真时,我一般会定期对坐标做归一化处理。
- 坐标系方向:屏幕坐标系y轴向下,数学坐标系y轴向上。做图像相关的仿真时,这个坑我至少踩过三次。
好了,二维坐标变换就讲到这里。内容不多,但都是干货。你把这些吃透了,后面学三维变换就会轻松很多。