3、坐标系的数学基础:欧几里得空间、仿射变换、齐次坐标入门
聊到消息延迟,很多人第一反应是网络抖动、CPU负载。但在我做UI框架那几年,踩过最大的坑,反而是坐标系变换带来的延迟问题。你想想看,一个触摸点从屏幕坐标系映射到世界坐标系,中间但凡少算一个变换,延迟就凭空多出几毫秒。
所以这一章,咱们把数学底子打牢。说白了,就是搞明白三件事:点在哪、怎么动、怎么算得快。
3.1 欧几里得空间:我们熟悉的“平面世界”
欧几里得空间,就是你我从小在纸上画坐标轴的那个世界。二维的叫E²,三维的叫E³。它的核心就两条:距离能算、角度能量。
举个例子,屏幕上两个像素点(100, 200)和(300, 500),它们之间的距离:
dx = 300 - 100 = 200
dy = 500 - 200 = 300
距离 = sqrt(200² + 300²) ≈ 360.55 像素
这个公式你肯定熟,勾股定理嘛。但在计算机图形学里,我们不光要算距离,还要算向量点积来判断方向是否一致。
重要概念:欧几里得空间里,平移、旋转、缩放都是“刚性”或“相似”变换。说白了,就是图形不会扭曲,直线还是直线,角度保持不变。
我在项目中遇到过一个问题:用欧几里得距离算两个触摸点的移动速度,结果发现不同DPI的屏幕上数值完全对不上。后来才意识到,像素空间不是欧几里得空间——它受屏幕物理尺寸和分辨率影响。所以做跨平台UI时,一定要先归一化到逻辑坐标系。
3.2 仿射变换:平移、旋转、缩放一锅端
仿射变换,说白了就是“线性变换 + 平移”。它保证两样东西:直线还是直线,平行线还是平行线。
常见的仿射变换有四种:
- 平移:把点(x, y)挪到(x+tx, y+ty)
- 旋转:绕原点转个角度θ
- 缩放:沿x轴和y轴分别放大Sx、Sy倍
- 剪切:把矩形拉成平行四边形(UI里用得少,但3D投影常用)
你可能会问:为什么不能直接用矩阵乘法搞定平移?嗯,这里有个坑——平移不是线性变换。线性变换要求原点必须映射到原点,但平移把原点挪走了。所以我们需要一个“作弊”手段。
我的习惯:在UI框架里,我通常把仿射变换拆成两步:先算旋转缩放矩阵(2x2),再加平移向量。这样调试时能一眼看出是哪部分出了问题。
3.3 齐次坐标:用升维解决降维问题
齐次坐标,是我见过最优雅的数学技巧之一。它的核心思想很简单:给二维点加一个维度,变成三维。
具体来说:
- 二维点(x, y) → 齐次坐标(x, y, 1)
- 二维向量(dx, dy) → 齐次坐标(dx, dy, 0)
为什么要这么干?因为这样一来,平移就能写成矩阵乘法了。你看:
// 传统方式:平移需要加法
x' = x + tx
y' = y + ty
// 齐次坐标方式:全是乘法
| x' | | 1 0 tx | | x |
| y' | = | 0 1 ty | | y |
| 1 | | 0 0 1 | | 1 |
这样一来,平移、旋转、缩放全都能用3x3矩阵表示。多个变换叠加,就是矩阵连乘。GPU最喜欢这种运算——一次计算,全部搞定。
我曾经踩过的坑:在做手势识别时,忘了把触摸点的w分量从1归一化回0。结果所有坐标都飘到了无穷远。调试了整整一个下午才发现,是齐次坐标转回笛卡尔坐标时忘了除以w。
记住:齐次坐标(x, y, w)转回二维点,要算(x/w, y/w)。w=1时不用除,但w≠1时必须除。
3.4 三种坐标系的实战对比
为了让你看得更清楚,我整理了一张表:
| 特性 | 欧几里得空间 | 仿射变换 | 齐次坐标 |
|---|---|---|---|
| 核心运算 | 距离、角度 | 矩阵乘法+加法 | 纯矩阵乘法 |
| 平移处理 | 单独加法 | 向量加法 | 矩阵乘法 |
| GPU友好度 | 低 | 中 | 高 |
| 典型应用 | 碰撞检测 | 2D动画 | 3D渲染、UI变换 |
你想想看,在消息延迟的场景里,一个触摸事件从硬件到应用层,至少要经过3次坐标系变换:屏幕物理坐标 → 逻辑像素坐标 → 视图局部坐标 → 世界坐标。每一步如果用齐次坐标,都能用矩阵连乘一次算完,延迟自然就降下来了。
3.5 知识体系总览
下面这张图,是我手绘的本章知识结构。你看一眼就能明白三者的关系:
从这张图你能看到,三个概念层层递进。欧几里得空间给了我们“度量”的能力,仿射变换给了我们“操作”的能力,而齐次坐标则给了我们“高效计算”的能力。三者缺一不可。
我的建议:如果你刚开始接触这些概念,别急着背公式。先在纸上画一个点,手动算一遍平移、旋转、缩放。再用齐次坐标算一遍。感受一下“加法变乘法”带来的统一性。这一步走通了,后面讲变换矩阵、投影矩阵时,你会觉得特别顺。
好了,这一章就到这里。数学基础打牢了,下一章我们就能放开手脚,聊聊真正的延迟优化技巧了。
可可精品资料库