矩阵乘法经典应用之坐标变化

二维空间:

问题:
nyist 298 点的变换
http://acm.nyist.net/JudgeOnline/problem.php?pid=298
大意:给出n个,对其进行m个操作,平移,旋转,缩放,翻转。其中n<=1e4   m<=1e6
分析:对于旋转:
矩阵乘法经典应用之坐标变化_第1张图片
x'=rcos(p+r)=xcosp-ysinp
y'=rsin (p+r)=xsinp+ycosp
然后是超时问题。想过用一个“基向量”先进行变换操作,然后再给每一个坐标进行变化,但是这样的“基向量”表示不了旋转变化操作。设想“基向量”是(1,1),各种问题出现了。。
矩阵是个好东西。它完全可以替代那个二维的“基向量”,实现操作压缩,后变化坐标。一个 O(n*m)的算法程序变成了 O(n+m)
旋转:

平移:

缩放:

绕X:

绕Y:


#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=1e4+10;
const double eps=1e-7,  PI=acos(-1.0);
struct point {
    double x,y;
}pt[N];
struct matrix{
    double m[3][3];
    matrix(){  // 不写的话随机数字
          for(int i=0;i<3;i++)
             for(int j=0;j<3;j++)  m[i][j]=0;
    }
};
matrix multi(matrix a,matrix b){
    matrix ans;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            ans.m[i][j]=0;
            for(int k=0;k<3;k++){
                ans.m[i][j]+=a.m[i][k]*b.m[k][j];
            }
        }
    }
    return ans;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n,m;
    while(cin>>n>>m){
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&pt[i].x,&pt[i].y);
        }
        matrix A;
        for(int i=0;i<3;i++){
            A.m[i][i]=1;
        }
        char str[5];
        for(int i=0;i<m;i++){
            scanf("%s",str);
            matrix B;
            for(int i=0;i<3;i++) B.m[i][i]=1;
            if(str[0]=='M'){
                double xx,yy;
                scanf("%lf%lf",&xx,&yy);
                B.m[0][2]=xx;
                B.m[1][2]=yy;
            }
            else if(str[0]=='X'){
                B.m[1][1]=-1;
            }
            else if(str[0]=='Y'){
                B.m[0][0]=-1;
            }
            else if(str[0]=='S'){
                double p;
                scanf("%lf",&p);
                B.m[0][0]=p;
                B.m[1][1]=p;
            }
            else if(str[0]=='R'){
                double al;
                scanf("%lf",&al);
                al=al/180*PI;
                B.m[0][0]=cos(al);
                B.m[0][1]=-sin(al);
                B.m[1][0]=sin(al);
                B.m[1][1]=cos(al);
            }
            A=multi(B,A);  //multi(A,B);  左边是转换矩阵 右边是待转化答案
        }
        for(int i=0;i<n;i++){
            double px=A.m[0][0]*pt[i].x+A.m[0][1]*pt[i].y+A.m[0][2];
            double py=A.m[1][0]*pt[i].x+A.m[1][1]*pt[i].y+A.m[1][2];
            printf("%.1lf %.1lf\n",px,py);  // +0.05 错了?
        }
    }
    return 0;
}

奇怪的答案:
    double a=0.0;
    printf("%.1lf\n",a+0.05);
   -->  0.1

三维空间:

立体几何中的坐标变化:
平移:

缩放:

绕X轴旋转:

绕Y轴旋转:

绕Z轴旋转:




你可能感兴趣的:(Matrix)