题目大意:
空间直角坐标系中有
M(M<=100000)
个点,然后有一个操作集合,集合大小为
N(N<=1000)
,操作包括平移,关于原点放缩,还有绕向量旋转。要你求出所有点操作完后的坐标。
解题思路:
显然这需要把
具体的操作方法再次不赘述了,主要是点绕向量旋转是一个问题。
我们令向量为
t→
,点为
p
,因为题目保证
AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const double PI=acos(-1);
struct Point
{
double x,y,z;
Point(){x=y=z=0;};
Point(double x_,double y_,double z_)
{x=x_,y=y_,z=z_;}
double operator^(Point a1)
{return x*a1.x+y*a1.y+z*a1.z;}
Point operator-(Point a1)
{return Point(x-a1.x,y-a1.y,z-a1.z);}
Point operator+(Point a1)
{return Point(x+a1.x,y+a1.y,z+a1.z);}
Point operator*(Point a1)
{return Point(y*a1.z-a1.y*z,z*a1.x-a1.z*x,x*a1.y-a1.x*y);}
Point operator*(double a1)
{return Point(x*a1,y*a1,z*a1);}
void scanling(double a,double b,double c)
{x*=a,y*=b,z*=c;}
double Lenth()
{return sqrt(x*x+y*y+z*z);}
void rotate(Point a1,double X)
{
Point cnt=Point(x,y,z);
Point tmp=a1*((cnt^a1)/(a1^a1));
cnt=cnt-tmp;
Point M=a1*cnt;
if(M.Lenth()<=1e-10) return;
M=M*(cnt.Lenth()/M.Lenth());
x=cnt.x*cos(X)+M.x*sin(X)+tmp.x;
y=cnt.y*cos(X)+M.y*sin(X)+tmp.y;
z=cnt.z*cos(X)+M.z*sin(X)+tmp.z;
}
};
void Readch(char &ch)
{
for(ch=getchar();ch=='\n' || ch=='\r' || ch==' ';ch=getchar());
return;
}
int main()
{
char ch='\0';
int N;
scanf("%d",&N);
struct Point P[4];
P[1]=Point(1,0,0);P[2]=Point(0,1,0),P[3]=Point(0,0,1);
for(int i=1;i<=N;i++)
{
Readch(ch);
if(ch=='T')
{
double a,b,c;
scanf("%lf%lf%lf",&a,&b,&c);
P[0]=P[0]+Point(a,b,c);
}
else if(ch=='S')
{
double a,b,c;
scanf("%lf%lf%lf",&a,&b,&c);
for(int i=0;i<=3;i++) P[i].scanling(a,b,c);
}
else if(ch=='R')
{
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
d=d/180*PI;
for(int j=0;j<=3;j++)
P[j].rotate(Point(a,b,c),d);
}
}
int M;
scanf("%d",&M);
for(int i=1;i<=M;i++)
{
double a,b,c;
scanf("%lf%lf%lf",&a,&b,&c);
Point prt=Point(a,b,c);
prt=P[1]*prt.x+P[2]*prt.y+P[3]*prt.z+P[0];
printf("%lf %lf %lf\n",prt.x,prt.y,prt.z);
}
return 0;
}