ch_g

ECUST_ACMer —— ch_g
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[Harbin Online Contest 2010][Cubic Rotation][三维坐标旋转]

Posted on 2011-02-26 17:42  ch_g  阅读(277)  评论(0编辑  收藏  举报
/*
题目:Cubic Rotation
题目来源:Harbin Online Contest 2010
http://acm.hrbeu.edu.cn/index.php?act=problem&id=1006&cid=16
题目难度:中等
题目内容或思路:
三维空间坐标旋转
没有什么特别的技巧就是把旋转矩阵算出来
参考自http://dumbear.com/blog/?p=143
题目Sample有问题,Sample Input 中第二个Sample的“275”改成“270”
做题日期:2011.2.26
*/
#include
<cstdio>
#include
<cstdlib>
#include
<climits>
#include
<iostream>
#include
<algorithm>
#include
<cstring>
#include
<string>
#include
<queue>
#include
<map>
#include
<vector>
#include
<bitset>
#include
<cmath>
#include
<set>
using namespace std;

const double eps = 1e-8;
const double pi = acos(-1.0);

struct cpoint {
double x, y;
cpoint(
double xx = 0, double yy = 0): x(xx), y(yy) {}
};

int dcmp(double x) {
if (x < -eps) return -1; else return x > eps;
}

double cross(cpoint p0, cpoint p1, cpoint p2) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

int PointEqual(cpoint a, cpoint b) {
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double sqr(double x) { return x * x; }

double dissqr(cpoint a, cpoint b) {
return sqr(a.x - b.x) + sqr(a.y - b.y);
}

cpoint bp;

int PolarCmp(const cpoint &p1, const cpoint &p2) {
int u = dcmp(cross(bp, p1, p2));
return u > 0 || (u == 0 && dcmp(dissqr(bp, p1) - dissqr(bp, p2)) < 0);
}

void graham(cpoint pin[], int n, cpoint ch[], int &m) {
int i, j, k, u, v;
memcpy(ch, pin, n
* sizeof(cpoint));
for (i = k = 0; i < n; ++i) {
u
= dcmp(ch[i].x - ch[k].x);
v
= dcmp(ch[i].y - ch[k].y);
if (v < 0 || (v == 0 && u < 0)) k = i;
}
bp
= ch[k];
sort(ch, ch
+ n, PolarCmp);
n
= unique(ch, ch + n, PointEqual) - ch;
if (n <= 1) { m = n; return ;}
if (dcmp(cross(ch[0], ch[1], ch[n - 1])) == 0) {
m
= 2; ch[1] = ch[n - 1]; return;
}
ch[n
++] = ch[0];
for (i = 1, j = 2; j < n; ++j) {
while (i > 0 && dcmp(cross(ch[i - 1], ch[i], ch[j])) <= 0) i--;
ch[
++i] = ch[j];
}
m
= i;
}

double PolygonArea(cpoint p[], int n) {
if (n < 3) return 0;
double s = p[0].y * (p[n - 1].x - p[1].x);
for (int i = 1; i < n; ++i)
s
+= p[i].y * (p[i - 1].x - p[(i + 1) % n].x);
return fabs(s / 2);
}


struct vpoint {
double x, y, z;
vpoint(
double xx = 0, double yy = 0, double zz = 0)
: x(xx), y(yy), z(zz) {}
};

double dis(vpoint a, vpoint b) {
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y) + sqr(a.z - b.z));
}

// 三维点a绕向量p0p1旋转后坐标(旋转按照右手定则)
vpoint rotate(vpoint a, vpoint p0, vpoint p1, double angle) {
double d, s, c, x, y, z, x1, y1, z1;
d
= dis(p0, p1); s = sin(angle); c = cos(angle);
x
= (p1.x - p0.x) / d; x1 = a.x - p0.x;
y
= (p1.y - p0.y) / d; y1 = a.y - p0.y;
z
= (p1.z - p0.z) / d; z1 = a.z - p0.z;
p0.x
+= x1*(c+x*x*(1-c)) + y1*(x*y*(1-c)-z*s) + z1*(x*z*(1-c)+y*s);
p0.y
+= y1*(c+y*y*(1-c)) + z1*(y*z*(1-c)-x*s) + x1*(y*x*(1-c)+z*s);
p0.z
+= z1*(c+z*z*(1-c)) + x1*(z*x*(1-c)-y*s) + y1*(z*y*(1-c)+x*s);
return p0;
}

int dir[8][3] = {
{
0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
{
0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}
};

void solve() {
vpoint v[
8], s, e;
cpoint cp[
8];
double len, x, y, z, angle;
scanf(
"%lf%lf%lf%lf", &len, &x, &y, &z);
scanf(
"%lf%lf%lf", &s.x, &s.y, &s.z);
scanf(
"%lf%lf%lf", &e.x, &e.y, &e.z);
scanf(
"%lf", &angle);
angle
*= pi / 180;
for (int i = 0; i < 8; ++i) {
v[i].x
= x + dir[i][0] * len;
v[i].y
= y + dir[i][1] * len;
v[i].z
= z + dir[i][2] * len;
v[i]
= rotate(v[i], s, e, angle);
cp[i]
= cpoint(v[i].x, v[i].y);
}
cpoint ch[
10];
int m;
graham(cp,
8, ch, m);
printf(
"%.2lf\n", PolygonArea(ch, m));
}

int main() {
#ifndef ONLINE_JUDGE
freopen(
"D:\\in.txt", "r", stdin);
#endif
int cas;
scanf(
"%d", &cas);
while (cas--) {
solve();
}
return 0;
}