2D场景下两三角形间transform matrix求解最后步骤缺失问题
2D/3D三角形映射变换矩阵求解方案
问题背景
- 核心需求:求解将源三角形映射为目标三角形的变换矩阵,优先落地2D场景实现,同步覆盖3D场景扩展思路
- 现有推导卡点:设定边长为1、最左顶点位于坐标原点的初始等边三角形对应单位矩阵(identity matrix)时,按照参考解法「待求变换矩阵=目标三角形B矩阵 × 初始三角形矩阵的逆」的逻辑,当初始矩阵为单位阵时计算结果等于B矩阵,该结论不符合预期,逻辑无法自洽
- 具体映射规则:源(蓝色)三角形有一个顶点位于坐标原点,目标(红色)三角形的变换锚点固定为距离原点最近的顶点;当前已完成锚点对齐步骤,缺失让两个三角形完全重合的最后一步变换逻辑
- 技术选型:基于C++ Eigen库实现变换计算
- 待解决两个核心问题:
- 前述推导过程遗漏了哪些关键信息?
- 给定上述约束条件,正确的变换矩阵如何计算?
- 映射规则参考问题附带的三角形变换示意图
推导过程遗漏的核心信息
- 对「三角形基矩阵」的构造规则理解错误
参考解法中用于求逆的矩阵不是直接堆砌顶点坐标生成的矩阵,必须严格按照仿射基规则构造:以锚点为原点,取从锚点出发的两条边作为线性基向量,追加齐次坐标维度和平移项。你默认边长为1的等边三角形对应单位阵,但该三角形从原点出发的两条边向量为(1, 0)和(0.5, √3/2),拼出来的基矩阵本身就不是单位阵,自然推导结果和预期不符。只有当源三角形从锚点出发的两条边刚好是二维标准基(1,0)、(0,1)(即锚点为直角顶点、直角边长为1的等腰直角三角形)时,对应的基矩阵才是单位阵。 - 漏了仿射变换的平移项分解
仿射变换的线性部分(旋转、缩放、剪切)仅绕坐标原点生效,必须遵循「源锚点平移到原点→做线性变换对齐边向量→平移到目标锚点位置」的流程,不能跳过平移步骤直接计算线性矩阵乘积。 - 顶点对应规则未严格对齐
M = B * inv(A)公式成立的前提是,A和B构造时使用的三个顶点必须严格一一对应,顶点顺序错乱会直接导致变换结果错误(比如出现镜像翻转)。
给定约束下的2D变换矩阵正确计算方法
前置约定
源三角形锚点(位于原点的顶点)记为s0,另外两个顶点按顺序记为s1、s2;目标三角形锚点(距离原点最近的顶点)记为t0,与s1、s2对应的顶点记为t1、t2,所有顶点顺序必须一一对应。
计算步骤
- 构造源三角形的3x3齐次仿射基矩阵A:
A = [s1.x - s0.x, s2.x - s0.x, s0.x] [s1.y - s0.y, s2.y - s0.y, s0.y] [0, 0, 1 ]
由于源三角形锚点s0在原点,第三列固定为(0, 0, 1),前两列直接取s1、s2的坐标即可。
2. 用完全相同的规则构造目标三角形的仿射基矩阵B:
B = [t1.x - t0.x, t2.x - t0.x, t0.x] [t1.y - t0.y, t2.y - t0.y, t0.y] [0, 0, 1 ]
- 最终变换矩阵满足
M * A = B,即M = B * A.inverse()。
如果你已经完成锚点对齐(s0 == t0),A和B的第三列完全一致,计算得到的M将只包含旋转、缩放、剪切的线性变换部分,刚好可以对齐两条边向量,实现两个三角形完全重合。
Eigen核心实现代码
#include <Eigen/Dense> // 输入源三角形三个顶点s0/s1/s2、目标三角形三个对应顶点t0/t1/t2,顶点顺序必须一一对应 Eigen::Matrix3f computeTri2DTransform( const Eigen::Vector2f& s0, const Eigen::Vector2f& s1, const Eigen::Vector2f& s2, const Eigen::Vector2f& t0, const Eigen::Vector2f& t1, const Eigen::Vector2f& t2 ) { Eigen::Matrix3f A = Eigen::Matrix3f::Identity(); A.block<2, 1>(0, 0) = s1 - s0; A.block<2, 1>(0, 1) = s2 - s0; A.block<2, 1>(0, 2) = s0; Eigen::Matrix3f B = Eigen::Matrix3f::Identity(); B.block<2, 1>(0, 0) = t1 - t0; B.block<2, 1>(0, 1) = t2 - t0; B.block<2, 1>(0, 2) = t0; return B * A.inverse(); }
3D场景扩展思路
- 2D场景下3个顶点提供6个约束,刚好匹配3x3齐次仿射矩阵的6个自由变量,因此三角形可以唯一确定2D仿射变换。3D场景下的仿射变换为4x4齐次矩阵,共12个自由变量,需要4个不共面的对应点才能唯一确定,仅靠三角形的3个顶点只能约束三角形所在平面内的变换,平面法向量方向的自由度无法消除。
- 如果是3D空间中共面三角形的映射,可以先将两个三角形投影到自身所在的2D局部平面,用上述2D方法计算平面内的变换,再补充法向量方向的变换逻辑即可;如果需要求解完整3D仿射变换,只需补充第四个不共面的对应点,按照相同逻辑构造4x4基矩阵,通过
M = B * A.inverse()即可算出结果。
内容的提问来源于stack exchange,提问作者Kroma
相关产品推荐
相关产品推荐

