HDU 4087 三维上的平移缩放旋转矩阵变化

 题目大意:

就是根据它给的程序的要求,不断平移,缩放,旋转三维的点,最后计算出点的位置

这里主要是要列出三种转换方式的齐次矩阵描述

平移
translate tx ty tz
1 0 0 0
0 1 0 0
0 0 1 0
tx ty tz 1
缩放
scale a b c
a  0  0  0
0  b  0  0
0  0  c  0
0  0  0  1
绕任意轴(过原点)旋转(注意要把轴向量归一化,否则点在旋转轴上时有问题)

这里是以(x,y,z)向量指向我们人的方向逆时针旋转 d 的弧度
rotate x y z d
(1-cos(d))*x*x+cos(d)     (1-cos(d))*x*y-sin(d)*z   (1-cos(d))*x*z+sin(d)*y   0
(1-cos(d))*y*x+sin(d)*z   (1-cos(d))*y*y+cos(d)     (1-cos(d))*y*z-sin(d)*x   0
(1-cos(d))*z*x-sin(d)*y   (1-cos(d))*z*y+sin(d)*x   (1-cos(d))*z*z+cos(d)     0
          0                          0                          0              1

然后这里因为循环的问题,所以用矩阵快速幂加速

而循环是可能出现嵌套的

我没用递归,而是判断当前循环属于第几个矩阵下的计算,每次进入一个新的循环都会给当前新的循环设置一个编号,以便找到它的矩阵

每次退出循环,都会将当前矩阵和循环外那个矩阵相乘即可

最后输出+eps,防止 -0.0 , -0.0 , -0.0 的情况发生

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <algorithm>
  5 #include <iostream>
  6 using namespace std;
  7 #define N 1005
  8 #define eps 1e-6
  9 const double PI = acos(-1.0);
 10 char s[20];
 11 int rec[N];
 12 
 13 struct Matrix{
 14     double m[4][4];
 15     Matrix operator*(const Matrix &t) const {
 16         Matrix ans;
 17         for(int i=0 ; i<4 ; i++){
 18             for(int j=0 ; j<4 ; j++){
 19                 ans.m[i][j] = 0;
 20                 for(int k=0 ; k<4 ; k++){
 21                     ans.m[i][j]+=m[i][k]*t.m[k][j];
 22                 }
 23             }
 24         }
 25         return ans;
 26     }
 27     Matrix(){}
 28     Matrix(double p[][4])
 29     {
 30         for(int i=0 ; i<4 ; i++)
 31             for(int j=0 ; j<4 ; j++)
 32                 m[i][j] = p[i][j];
 33     }
 34     void init(){
 35         memset( m , 0 , sizeof(m));
 36         for(int i=0 ; i<4 ; i++) m[i][i] = 1;
 37     }
 38     void out(){
 39         for(int i=0 ; i<4 ; i++){
 40             for(int j=0 ; j<4 ; j++)
 41                 cout<<m[i][j]<<" ";
 42             cout<<endl;
 43         }
 44     }
 45 }mat[1005] , tmp;
 46 
 47 Matrix q_pow(Matrix a , int k)
 48 {
 49     Matrix ret;
 50     ret.init();
 51     while(k)
 52     {
 53         if(k&1) ret = ret*a;
 54         a = a*a;
 55         k>>=1;
 56     }
 57     return ret;
 58 }
 59 //当向量方向指向自己的时候逆时针旋转A的弧度 
 60 void Rotate(Matrix &p , double a , double b , double c , double A)
 61 {
 62     double len = sqrt(a*a+b*b+c*c);
 63     double x = a/len , y = b/len , z = c/len;
 64     double sine = sin(A) , cosine = cos(A);
 65     double m[][4] = {
 66         {cosine+(1-cosine)*x*x, x*y*(1-cosine)-z*sine, x*z*(1-cosine)+y*sine, 0},
 67         {y*x*(1-cosine)+z*sine, cosine+y*y*(1-cosine), y*z*(1-cosine)-x*sine, 0},
 68         {z*x*(1-cosine)-y*sine, z*y*(1-cosine)+x*sine, cosine+z*z*(1-cosine), 0},
 69         {0                    , 0                    , 0                    , 1}
 70     };
 71     p = Matrix(m);
 72 }
 73 
 74 void Trans(Matrix &p , double a , double b , double c)
 75 {
 76     p.init();
 77     p.m[3][0]=a , p.m[3][1]=b , p.m[3][2]=c;
 78 }
 79 
 80 void Scale(Matrix &p , double a , double b , double c)
 81 {
 82     p.init();
 83     p.m[0][0] = a , p.m[1][1] = b , p.m[2][2] = c;
 84 }
 85 
 86 int main()
 87 {
 88    // freopen("in.txt" , "r" , stdin);
 89     int n;
 90     double a,b,c,d;
 91 
 92     while(scanf("%d" , &n) , n){
 93         mat[0].init();
 94         int cnt = 0;//repeat次数
 95         while(scanf("%s" , s)){
 96             if(s[0]=='e' && cnt==0) break;
 97             if(s[0]=='e'){
 98               //  cout<<"id: "<<cnt<<": "<<endl;
 99               //  mat[cnt].out();
100                 mat[cnt] = q_pow(mat[cnt] , rec[cnt]);
101               //  cout<<"id: "<<cnt<<": "<<endl;
102               //  mat[cnt].out();
103                 mat[cnt-1] = mat[cnt-1]*mat[cnt];
104              //   cout<<"id: "<<cnt<<": "<<endl;
105               //  mat[cnt-1].out();
106                 cnt--;
107             }
108             if(s[0]=='r' && s[1]=='e') {
109                 scanf("%d" , &rec[++cnt]);
110                 mat[cnt].init();
111             }
112             else if(s[0]=='t'){
113                 scanf("%lf%lf%lf" , &a , &b , &c);
114                 Trans(tmp , a , b , c);
115              //   tmp.out();
116                 mat[cnt] = mat[cnt]*tmp;
117             }
118             else if(s[0]=='s'){
119                 scanf("%lf%lf%lf" , &a , &b , &c);
120                 Scale(tmp , a , b , c);
121                 mat[cnt] = mat[cnt]*tmp;
122             }
123             else if(s[0]=='r' && s[1]=='o'){
124                 scanf("%lf%lf%lf%lf" , &a , &b , &c , &d);
125                 Rotate(tmp , a , b , c , -d/180*PI);
126                 mat[cnt] = mat[cnt]*tmp;
127             }
128         }
129       //  mat[0].out();
130         for(int i=0 ; i<n ; i++){
131             double x , y , z , xx , yy , zz;
132             scanf("%lf%lf%lf" , &x , &y , &z);
133             xx = x*mat[0].m[0][0]+y*mat[0].m[1][0]+z*mat[0].m[2][0]+mat[0].m[3][0];
134             yy = x*mat[0].m[0][1]+y*mat[0].m[1][1]+z*mat[0].m[2][1]+mat[0].m[3][1];
135             zz = x*mat[0].m[0][2]+y*mat[0].m[1][2]+z*mat[0].m[2][2]+mat[0].m[3][2];
136             printf("%.2f %.2f %.2f
" , xx+eps , yy+eps , zz+eps);
137         }
138         puts("");
139     }
140     return 0;
141 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4678085.html