矩阵的线性变换
1. 旋转
2. 缩放
3. 投影
4. 镜像
5. 切变
旋转矩阵
aM = b 向量与一个矩阵相乘得到一个新的向量
R(theta) = [p, q]^T = [ cosTheta, sinTheta
-sinTheta, cosTheta
]
3D旋转
确定旋转方向
1. 左手坐标系
大拇指指向旋转轴的正向,其他手指向内弯曲,弯曲的方向就是旋转轴的正向
2. 右手坐标系
3D旋转矩阵
每个轴的基向量的长度都为1
当前矩阵根据左手坐标系进行旋转
x y z
[ 1 0 0 ] xaxis
[ 0 1 0 ] yaxis
[ 0 0 1 ] zaxis
绕x轴旋转,绕x轴旋转,其他轴变,x轴不变
x y z
[ 1 0 0 ] xaxis
[ 0 cos sin] yaxis
[ 0 -sin cos ] zaxis
绕y轴旋转
x y z
[ cos 0 -sin ] xaxis
[ 0 1 0 ] yaxis
[ sin 0 cos ] zaxis
绕z轴旋转
x y z
[ cos sin 0 ] xaxis
[ -sin cos 0 ] yaxis
[ 0 0 1 ] zaxis
class Matrix {
constructor(...components) {
this.rows = components
}
columns() {
return this.rows[0].map((_, i) => this.rows.map(row => row[i]))
}
mult(other) {
if (this.rows[0].length !== other.rows.length) {
throw new Error('该矩阵的列数不等于给定矩阵的行数')
}
const sum = arr => arr.reduce((el, next) => el + next, 0)
// 将矩阵转置
const columns = other.columns()
const newRows = this.rows.map(row => (
columns.map(column => (
sum(row.map((element, i) => element * column[i]))
))
))
return new Matrix(...newRows)
}
transpose() {
return new Matrix(...this.columns())
}
scaleMult(number) {
const newRows = this.rows.map(row => (
row.map(element => element * number)
))
return new Matrix(...newRows)
}
}
const log = console.log
const toRadians = degress => degress * Math.PI / 180
const angle90 = toRadians(90)
const one = new Matrix(
[10, 0, 0],
)
// 绕z轴旋转
const rotateZAxis = new Matrix(
[Math.cos(angle90), Math.sin(angle90), 0],
[Math.sin(angle90 * -1), Math.cos(angle90), 0],
[0, 0, 1]
)
// Matrix { rows: [ [ 6.123233995736766e-16, 10, 0 ] ] } 向量旋转90度后与y轴垂直
log(
one.mult(rotateZAxis)
)
缩放矩阵
x y. z
[kx 0. 0] xaxis
[0. ky 0] yaxis
[0 0 kz] zaxis
const one = new Matrix(
[10, 20, 30],
)
const scaleMatrix = new Matrix(
[1,0,0],
[0,2,0],
[0,0,3]
)
log(one.mult(scaleMatrix))
切变矩阵
// 2D切变矩阵
Hx(s) = [1 0]
[s 1]
x' = x + sy
// xy被z坐标切变
Hxy(s,t) = [1 0 0]
[0 1 0]
[s t 1]
// y轴切变
Hxz(s,t) = [1 0 0]
[s 1 t]
[0 0 1]
// x轴切变
Hyz(s,t) = [1 s t]
[0 1 0]
[0 0 1]
const one = new Matrix(
[10, 20, 30]
)
// x轴切变
const other = new Matrix(
[1, 1, 2],
[0, 1, 0],
[0, 0, 1]
)
// y' = y + sx y' = 20 + 1*10
// z' = z + sx z' = 30 + 2*10
log(one.mult(other))