sgu265:Wizards(计算几何)

来源:互联网 发布:六边形战士 知乎 编辑:程序博客网 时间:2024/04/30 18:33

题目大意:
      一个空间直角坐标系内,对一个点有三种操作:
      1.平移(x,y,z)(x+a,y+b,z+c)
      2.缩放(x,y,z)(ax,by,cz)
      3.绕一个向量(x,y,z)顺时针旋转α(角度制)
      对空间内的m个点给出n个操作,求每个点在操作后的坐标。

分析:
      我们用i,j,k表示x,y,z轴上的单位向量,和一个记录平移的p向量(根据二维的仿射变换可以知道平移是不影响缩放和旋转的)
      平移直接给p平移即可;
      缩放对p,i,j,k依次缩放;
      旋转对p,i,j,k依次旋转;
      对于每个点(x,y,z),操作后就是(xi,yj,zk)+p

      关键就是怎样旋转。
      对于点pq旋转α,求出pq上的投影t,令p=pt,那么m=q×pp构成的平面与q垂直,将m调整为p的长度,旋转后的点即为 cos(α)p+sin(α)m+t.

分析:

#include <cstdio>#include <cmath>typedef double DB;using namespace std;const DB PI = acos(-1.0);const DB eps = 1e-10;struct pot{    DB x, y, z;    pot(DB x = 0, DB y = 0, DB z = 0):x(x),y(y),z(z){}    void read() {scanf("%lf%lf%lf", &x, &y, &z);}    void print() {printf("%lf %lf %lf\n", x, y, z);}    void trans(DB tx, DB ty, DB tz) {x += tx, y += ty, z += tz;}    void scal(DB tx, DB ty, DB tz) {x *= tx, y *= ty, z *= tz;}    void rotate(const pot &a, DB alpha)    {        pot p = *this, tmp;        tmp = a*((a*p)/(a*a));        p = p-tmp;pot m = a^p;        if(m.len() < eps) return ;         m.adjust(p.len());        *this = p*cos(alpha)+m*sin(alpha)+tmp;    }    friend pot operator + (const pot &a, const pot &b) {return pot(a.x+b.x, a.y+b.y, a.z+b.z);}    friend pot operator - (const pot &a, const pot &b) {return pot(a.x-b.x, a.y-b.y, a.z-b.z);}    friend pot operator * (const pot &a, DB k) {return pot(a.x*k, a.y*k, a.z*k);}    friend pot operator / (const pot &a, DB k) {return pot(a.x/k, a.y/k, a.z/k);}    friend DB operator * (const pot &a, const pot &b) {return a.x*b.x+a.y*b.y+a.z*b.z;}    friend pot operator ^ (const pot &a, const pot &b) {return pot(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);}    DB len() {return sqrt((*this)*(*this));}    void adjust(DB l) {*this = *this*(l/len());}}p[4], v;int main(){    #ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    freopen("output.txt", "w", stdout);    #endif    int n, m;    scanf("%d", &n);    p[1].x = p[2].y = p[3].z = 1;    while(n--)    {        DB x, y, z, a;        char q[3] = "\0";        scanf("%s", q);        scanf("%lf%lf%lf", &x, &y, &z);        if(q[0] == 'T') p[0].trans(x, y, z);        else if(q[0] == 'S')             for(int i = 0; i < 4; ++i)                p[i].scal(x, y, z);         else        {            scanf("%lf", &a);a *= PI/180;            for(int i = 0; i < 4; ++i)                p[i].rotate(pot(x, y, z), a);        }    }    scanf("%d", &m);    while(m--)    {        v.read();        v = p[0]+p[1]*v.x+p[2]*v.y+p[3]*v.z;        v.print();    }    #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);    #endif    return 0;}
0 0
原创粉丝点击