矩阵和线性变换之切变

矩阵和线性变换之切变

1. 什么是切变?

我们来看一幅图片。下面的图片,随着y增大,x的偏移会越来越大。这种类型的变换就叫切换。我们可以得到下图的公式x’ = x + sy。该公式转换成矩阵就得到了切变矩阵。 
切变

2. 切变效果的矩阵是怎样的?

在3D中,同样的道理,有如下右边三个矩阵,分别是随着z增大,x和y发生切变。随着y增大,x和z发生切变。随着z增大,x和y发生切变。 
切变矩阵

3. 切变矩阵示例代码

void Matrix3X3::setShear(E_Axis axis, float s, float t)
{
    switch(axis)
    {
    case Axis_x:
        {
            m11 = 1;    m12 = s;    m13 = t;
            m21 = 0;    m22 = 1;    m23 = 0;
            m31 = 0;    m32 = 0;    m33 = 1;
            break;
        }
    case Axis_y:
        {
            m11 = 1;    m12 = 0;    m13 = 0;
            m21 = s;    m22 = 1;    m23 = t;
            m31 = 0;    m32 = 0;    m33 = 1;
            break;
        }
    case  Axis_z:
        {
            m11 = 1;    m12 = 0;    m13 = 0;
            m21 = 0;    m22 = 1;    m23 = 0;
            m31 = s;    m32 = t;    m33 = 1;
            break;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

4. 切变矩阵程序完整示例代码

//MathUtil.h

#pragma once

#include <math.h>

enum E_Axis{Axis_x,Axis_y,Axis_z};
const float Pi = 3.14159f;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
//Vector3.h

#pragma once

class Vector3{
public:
    Vector3();
    Vector3(float X,float Y,float Z);

    //变为零向量
    void Zero();
    //求负向量
    Vector3 operator-() const;
    //求向量大小(长度或模)
    float Length() const;
    //标准化该向量
    void Normal();
    //向量的加法
    Vector3 operator+(Vector3 &rhs) const;
    Vector3& operator+=(Vector3 &rhs);
    //向量的减法
    Vector3 operator-(Vector3 &rhs) const;
    Vector3& operator-=(Vector3 &rhs);
    //向量乘标量
    Vector3 operator*(float scalar);
    //向量乘等于标量
    Vector3& operator*=(float scalar);
    //向量除以等于标量
    Vector3& operator/=(float scalar);
    //向量除以标量
    Vector3 operator/(float scalar);
    //距离公式
    float Distance(Vector3 &vec) const;
    //向量点乘
    float operator*(Vector3 &rhs) const;
    //向量叉积
    Vector3 CrossProduct(Vector3& vec) const;


public:
    float x,y,z;

};



//标量乘向量
Vector3 operator*(float scalar, Vector3& vec);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
//Vector3.cpp

#include "Vector3.h"
#include <cmath>

Vector3::Vector3():x(0.0),y(0.0),z(0.0)
{

}

Vector3::Vector3(float X,float Y,float Z):x(X),y(Y),z(Z)
{

}

void Vector3::Zero()
{
    x = y = z = 0;
}

Vector3 Vector3::operator-() const
{
    return Vector3(-x,-y,-z);
}

float Vector3::Length() const
{
    return sqrt(x*x+y*y+z*z);
}

Vector3 Vector3::operator*(float scalar)
{
    return Vector3(this->x * scalar, this->y * scalar, this->z * scalar);
}

Vector3& Vector3::operator*=(float scalar)
{
    return *this = *this * scalar;
}

Vector3& Vector3::operator/=(float scalar)
{
    return *this = *this / scalar;
}

Vector3 operator*(float scalar, Vector3& vec)
{
    return vec*scalar;
}

Vector3 Vector3::operator/(float scalar)
{
    float temp = 1/ scalar;
    return *this * temp;
}

void Vector3::Normal()
{
    //计算机计算乘法的速度比除法快
    float temp = 1 / Length();
    x *= temp;
    y *= temp;
    z *= temp;
}

Vector3 Vector3::operator+(Vector3& rhs) const
{
    return Vector3(x+rhs.x,y+rhs.y,z+rhs.z);
}

Vector3& Vector3::operator+=(Vector3& rhs)
{
    *this = *this + rhs;
    return *this;
}

Vector3 Vector3::operator-(Vector3& rhs) const
{
    return Vector3(x-rhs.x,y-rhs.y,z-rhs.z);
}

Vector3& Vector3::operator-=(Vector3& rhs)
{
    *this = *this - rhs;
    return *this;
}

float Vector3::Distance(Vector3& vec) const
{
    return (*this - vec).Length();
}

float Vector3::operator*(Vector3& rhs) const
{
    return this->x * rhs.x + this->y * rhs.y + this->z * rhs.z;
}

Vector3 Vector3::CrossProduct(Vector3& vec) const
{
    return Vector3(this->y * vec.z - this->z * vec.y,
        this->z * vec.x - this->x * vec.z,
        this->x * vec.y - this->y * vec.x);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
//Matrix3X3.h

#pragma once
#include "MathUtil.h"
#include "Vector3.h"


class Matrix3X3
{
public:
    //矩阵相乘
    Matrix3X3 operator*(Matrix3X3& rhs);
    //矩阵乘等矩阵
    Matrix3X3& operator*=(Matrix3X3& rhs);
    void setRotate(E_Axis axis,float theta);
    void setScale(Vector3 &vec);
    void setOrthProject(Vector3 &vec);
    void setReflect(E_Axis axis);
    void setReflect(Vector3 &vec);
    void setShear(E_Axis axis, float s, float t);
public:
    float m11,m12,m13;
    float m21,m22,m23;
    float m31,m32,m33;
};

//向量乘以矩阵
Vector3 operator*(Vector3& vec,Matrix3X3& mat);
//向量乘等矩阵
Vector3& operator*=(Vector3& vec,Matrix3X3& mat);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
//Matrix3X3.cpp

#include "Matrix3X3.h"
#include <assert.h>

Matrix3X3 Matrix3X3::operator*(Matrix3X3& rhs)
{
    Matrix3X3 tempMat;
    tempMat.m11 = this->m11 * rhs.m11 + this->m12 * rhs.m21 + this->m13 * rhs.m31;
    tempMat.m12 = this->m11 * rhs.m12 + this->m12 * rhs.m22 + this->m13 * rhs.m32;
    tempMat.m13 = this->m11 * rhs.m13 + this->m12 * rhs.m23 + this->m13 * rhs.m33;

    tempMat.m21 = this->m21 * rhs.m11 + this->m22 * rhs.m21 + this->m23 * rhs.m31;
    tempMat.m22 = this->m21 * rhs.m12 + this->m22 * rhs.m22 + this->m23 * rhs.m32;
    tempMat.m23 = this->m21 * rhs.m13 + this->m22 * rhs.m23 + this->m23 * rhs.m33;

    tempMat.m31 = this->m31 * rhs.m11 + this->m32 * rhs.m21 + this->m33 * rhs.m31;
    tempMat.m32 = this->m31 * rhs.m12 + this->m32 * rhs.m22 + this->m33 * rhs.m32;
    tempMat.m33 = this->m31 * rhs.m13 + this->m32 * rhs.m23 + this->m33 * rhs.m33;

    return tempMat;
}

Matrix3X3& Matrix3X3::operator*=(Matrix3X3& rhs)
{
    *this = *this * rhs;
    return *this;
}

Vector3 operator*(Vector3& vec,Matrix3X3& mat)
{
    Vector3 tempVec;
    tempVec.x = vec.x * mat.m11 + vec.y * mat.m21 + vec.z * mat.m31;
    tempVec.y = vec.x * mat.m12 + vec.y * mat.m22 + vec.z * mat.m32;
    tempVec.z = vec.x * mat.m13 + vec.y * mat.m23 + vec.z * mat.m33;
    return tempVec;
}

Vector3& operator*=(Vector3& vec,Matrix3X3& mat)
{
    vec = vec * mat;
    return vec;
}

void Matrix3X3::setRotate(E_Axis axis,float theta)
{
    float sinValue,cosValue;
    sinValue = sin(theta);
    cosValue = cos(theta);

    switch(axis)
    {
    case Axis_x:
        {
            m11 = 1;    m12 = 0;            m13 = 0;
            m21 = 0;    m22 = cosValue;     m23 = sinValue;
            m31 = 0;    m32 = -sinValue;    m33 = cosValue;
            break;
        }
    case Axis_y:
        {
            m11 = cosValue; m12 = 0;    m13 = -sinValue;
            m21 = 0;        m22 = 1;    m23 = 0;
            m31 = sinValue; m32 = 0;    m33 = cosValue;
            break;
        }
    case Axis_z:
        {
            m11 = cosValue;     m12 = sinValue; m13 = 0;
            m21 = -sinValue;    m22 = cosValue; m23 = 0;
            m31 = 0;            m32 = 0;        m33 = 1;
            break;
        }
    default:
        assert(false);
    }


}

void Matrix3X3::setScale(Vector3& vec)
{
    m11 = vec.x;    m12 = 0;        m13 = 0;
    m21 = 0;        m22 = vec.y;    m23 = 0;
    m31 = 0;        m32 = 0;        m33 = vec.z;
}

void Matrix3X3::setOrthProject(Vector3 &vec)
{
    assert(fabs(vec*vec) - 1 < 0.01f);
    m11 = 1 - vec.x*vec.x;
    m12 = m21 = -vec.x * vec.y;
    m13 = m31 = -vec.x * vec.z;

    m22 = 1 - vec.y * vec.y;
    m23 = m32 = -vec.y * vec.z;

    m33 = 1 -  vec.z * vec.z;

}

void Matrix3X3::setReflect(E_Axis axis)
{
    switch(axis)
    {
    case Axis_x:
        {
            m11 = -1; m12 = 0; m13 = 0;
            m21 = 0; m22 = 1; m23 = 0;
            m31 = 0; m32 = 0; m33 = 1;
            break;
        }
    case Axis_y:
        {
            m11 = 1; m12 = 0; m13 = 0;
            m21 = 0; m22 = -1; m23 = 0;
            m31 = 0; m32 = 0; m33 = 1;
            break;
        }
    case Axis_z:
        {
            m11 = 1; m12 = 0; m13 = 0;
            m21 = 0; m22 = 1; m23 = 0;
            m31 = 0; m32 = 0; m33 = -1;
            break;
        }
    }
}

void Matrix3X3::setReflect(Vector3 &vec)
{
    assert(fabs(vec*vec) - 1 < 0.01f);

    m11 = 1 - 2 * vec.x * vec.x;
    m12 = m21 = - 2 * vec.x * vec.y;
    m13 = m13 = -2 * vec.x * vec.z;
    m22 = 1 - 2 * vec.y * vec.y;
    m23 = m32 = -2 * vec.y * vec.z;
    m33 = 1 - 2 * vec.z * vec.z;
}

void Matrix3X3::setShear(E_Axis axis, float s, float t)
{
    switch(axis)
    {
    case Axis_x:
        {
            m11 = 1;    m12 = s;    m13 = t;
            m21 = 0;    m22 = 1;    m23 = 0;
            m31 = 0;    m32 = 0;    m33 = 1;
            break;
        }
    case Axis_y:
        {
            m11 = 1;    m12 = 0;    m13 = 0;
            m21 = s;    m22 = 1;    m23 = t;
            m31 = 0;    m32 = 0;    m33 = 1;
            break;
        }
    case  Axis_z:
        {
            m11 = 1;    m12 = 0;    m13 = 0;
            m21 = 0;    m22 = 1;    m23 = 0;
            m31 = s;    m32 = t;    m33 = 1;
            break;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168

#include <iostream>
#include "Vector3.h"
#include "Matrix3X3.h"

using namespace std;

float ToZero(float num)
{
    return (abs(num) < 0.0001 ? 0 : num);
}

void print_v(Vector3 v)
{
    cout << "[ " << ToZero(v.x) << ", " 
        << ToZero(v.y) << ", " 
        << ToZero(v.z) << " ]" << endl;
    cout << endl;
}

void print_m(Matrix3X3 m)
{
    cout << m.m11 << "\t" << m.m12 << "\t" << m.m13 << endl;
    cout << m.m21 << "\t" << m.m22 << "\t" << m.m23 << endl;
    cout << m.m31 << "\t" << m.m32 << "\t" << m.m33 << endl;
    cout << endl;
}

int main()
{
    Vector3 a(10,20,30),b;
    Matrix3X3 M;
    M.setShear(Axis_x,1,2);
    print_m(M);

    print_v(a);
    b = a * M;
    print_v(b);

    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

5. 程序运行结果

1       1       2
0       1       0
0       0       1

[ 10, 20, 30 ]

[ 10, 30, 50 ]

猜你喜欢

转载自blog.csdn.net/weixin_42339460/article/details/80729223