问题描述:
已知一个全局坐标系,还有若干局部坐标系,如何将局部坐标系的坐标转成全局坐标系的坐标?反过来又如何进行?
这里的坐标系都是直角坐标系。
本文通过下面几个方面的研究来回答上面的问题。
1、简单示例
2、求解过程
3、nodejs编程验证
简单示例
已知点A(6,6),B(14,14),C(-2,14),G(12,12),求当A为原点 ,AB为X轴,AC为Y轴时 G点的坐标。可以见下图:
通过查看图形,我们可以很快的计算出点G新的坐标如下:
但是如果G为任意一点,我们还能轻松求出来么?显然我们不行。我们需要一种通用的方法来一次到位,这里就引入了矩阵变换的概念。
求解过程
重新理解坐标系的(x,y)。看下图:
我们的某个点的坐标实际上表达的是坐标轴单位向量的个数。x表示X轴单位向量个数,y表示Y轴单位向量个数。有了这个概念之后,我们重新来看待上面的问题:
假设AB单位向量为p(px,py),AC单位向量为q(qx,qy)。点G在新坐标系下为(x1,y1)
换成矩阵计算的写法:
由于AG向量可以很容易的求出来,单位向量p,q也很容易求出来,所以我们的新的坐标系下面的(x1,y1)也可以很容易求出来。通过逆矩阵变换可以求出下面公式:
就这样,我们通过重新理解坐标x和y的含义,通过引入了一个变换矩阵就轻松解决了坐标系的变换,是不是非常简单?这也是出乎我意料之外的,开始我也觉得好难好难。不过上述方法每次需要先求出AG的向量再进行计算,我们能否做到一步到位?当时答案是肯定的,我们通过引入一个三维矩阵,就可以轻松搞定。
我们将上述变换矩阵由二维扩展到三维,如下:假设A点的坐标为(Ax,Ay)。点G新坐标下(x1,x2),老坐标下(x0,y0)
这里我们换成三维矩阵的表达形式:
最左边的三维变换矩阵可以很容易求出来,那么我们可以根据G新坐标求出老坐标。再通过逆矩阵也可以根据老坐标求出新坐标。
总结:
解决这个问题非常简单只需要两步就搞定了。
第一步:我们需要求出新坐标系的x轴和y轴的单位向量,
第二步:构建一个三维变换矩阵,完成坐标的转换。
nodejs编程验证
这里通过编程的方式来验证变换矩阵的正确性,验证的示例就是上面简单示例。
这里矩阵计算我们采用gl-matrix库,github地址如下:
https://github.com/toji/gl-matrix
安装如下:这个库不需要再安装ts的定义,已经自带了。
npm i gl-matrix
第一步:定义点
let A = gl.vec3.fromValues(6, 6, 1)
let B = gl.vec3.fromValues(14, 14, 1)
let C = gl.vec3.fromValues(-2, 14, 1)
let G = gl.vec3.fromValues(12, 12, 1)
第二步:求新坐标系的X轴和Y轴的单位向量
let AB: gl.vec3 = gl.vec3.create()
let AC: gl.vec3 = gl.vec3.create()
gl.vec3.subtract(AB, B, A)
gl.vec3.subtract(AC, C, A)
let UnitAB: gl.vec3 = gl.vec3.create()
let UnitAC: gl.vec3 = gl.vec3.create()
gl.vec3.normalize(UnitAB, AB)
gl.vec3.normalize(UnitAC, AC)
第三步:构造计算矩阵
let mat = gl.mat3.fromValues(
UnitAB[0],
UnitAB[1],
UnitAB[2],
UnitAC[0],
UnitAC[1],
UnitAC[2],
A[0],
A[1],
A[2]
)
第四步:求逆矩阵
let matInvert: gl.mat3 = gl.mat3.create()
gl.mat3.invert(matInvert, mat)
第五步:求新坐标系下的坐标G1
let G1: gl.vec3 = gl.vec3.create()
gl.vec3.transformMat3(G1, G, matInvert)
第六步:根据新求出的坐标反过来求原坐标系坐标G2
let G2 = gl.vec3.create()
gl.vec3.transformMat3(G2, G1, mat)
第七步:设置人工算出的值G3
let G3 = gl.vec3.fromValues(3 * Math.sqrt(8), 0, 1)
输出结果如下:验证矩阵变换结果符合预期
G:12,12,1
G1:8.485280990600586,0,1
G2:12,12,1
G3:8.485280990600586,0,1