线性变换

矩阵的线性变换

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))
posted @ 2020-10-15 22:32  pluscat  阅读(357)  评论(0编辑  收藏  举报