您的位置:首页 > 其它

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

2016-02-08 16:24 423 查看
二维空间:

问题:

nyist 298 点的变换
http://acm.nyist.net/JudgeOnline/problem.php?pid=298
大意:给出n个,对其进行m个操作,平移,旋转,缩放,翻转。其中n<=1e4   m<=1e6
分析:对于旋转:



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
;
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轴旋转:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: