首页 > ACM题库 > HDU-杭电 > HDU 2898-旋转-计算几何-[解题报告]HOJ
2014
02-17

HDU 2898-旋转-计算几何-[解题报告]HOJ

旋转

问题描述 :

求空间中一个点绕一穿过原点的轴线旋转一定角度后的坐标,沿着旋转轴往原点看旋转的角度为顺时针(Angles are measured clockwise when looking along the rotation axis toward the origin. )。

输入:

一个点的3个坐标 x,y,z,
轴线上除原点外的一点 xn,yn,zn
角度 angle(弧度)

输出:

一个点的3个坐标 x,y,z,
轴线上除原点外的一点 xn,yn,zn
角度 angle(弧度)

样例输入:

2.0 3.0 6.0
5.0 5.0 5.0 
3.14 
100.0 200.0 300.0
500.0 600.0 700.0 
1.25

样例输出:

5.336 4.330 1.334
185.988 132.594 296.357


求空间中一个点绕一穿过原点的轴线旋转一定角度后的坐标,沿着旋转轴往原点看旋转的角度为顺时针(Angles are measured clockwise when looking along the rotation axis toward the origin. )。

思路:通过旋转把轴和z轴重合,在新的坐标系中旋转点,再把轴和点转回去。

1、二维坐标系中把点(x,y)绕原点顺时转t角度新点的坐标(x1,y1)为,我们记 R(x,y,t)
x1=xcos(t)+ysin(t)
y1=-xsin(t)+ycos(t)
2、对于(x,y,z)轴线,我们把(x,y)在xoy平面的旋转,使(x,y)落在x轴上。
具体操作:计算一下(x,y)的辐角t1,进行旋转操作R(x,y,t1)
这时轴线就落在了xoz平面上。
3、把轴线旋转与z轴重合 (x,y,z是当前坐标)
具体操作:计算一下(x,z)的辐角t2,进行旋转操作R(x,z,t2-PI/2)
这时轴线与z轴重合。
注意以上对轴进行的操作,对点(xn,yn,zn)也要进行相应操作。
4、点(xn,yn,zn)绕z轴旋转t角度,只要进行操作R(xn,yn,t)   ??
5、把轴转回去
(x,y,z是当前坐标)
对轴和点进行操作R(x,z,PI/2-t2)
(x,y,z是当前坐标)
对轴和点进行操作R(x,y,-t1)
所以写一个旋转函数和计算辐角函数即可解决这个问题。
用旋转矩阵来理解也很方便。

其中第4点存有疑问,R操作我定义的是顺时旋转,题意中点也应该是绕轴顺时转的,那么R(xn,yn,t)应该为所求,可是我把这步改成R(xn,yn,-t)(也就是逆时旋)才能过样例。 解题参考:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cmath>
using namespace std;

struct point 
{
    double x,y,z;
};

point rollptoline1(point p,double angle)//顺时针旋转 
{
    point ans=p;
    ans.x=p.x*cos(angle)+p.y*sin(angle);
    ans.y=-p.x*sin(angle)+p.y*cos(angle);
    return ans;
}
point rollptoline2(point p,double angle)//逆时针旋转 
{
    point ans=p;
    ans.x=p.x*cos(angle)+p.z*sin(angle);
    ans.z=-p.x*sin(angle)+p.z*cos(angle);
    return ans;
}
double anle(double x,double y)
{
    return atan(y/x);
}
int main()
{
    point t1,t2;
    double du;
    //double pi=3.1415926;
    double pi=acos(-1.0);
    while(scanf("%lf %lf %lf",&t1.x,&t1.y,&t1.z)!=EOF)
    {
        scanf("%lf %lf %lf",&t2.x,&t2.y,&t2.z);
        scanf("%lf",&du);
        double d1=anle(t2.x,t2.y);
        t2=rollptoline1(t2,d1);
        t1=rollptoline1(t1,d1);
    //    printf("%.3lf %.3lf %.3lf\n",t2.x,t2.y,t2.z);
        double d2=anle(t2.z,t2.x);
        t2=rollptoline2(t2,-d2);
        t1=rollptoline2(t1,-d2);

        //printf("%.3lf %.3lf %.3lf\n\n",t2.x,t2.y,t2.z);
        t1=rollptoline1(t1,-du);
        t1=rollptoline2(t1,d2);
        t1=rollptoline1(t1,-d1);
    //    t2=rollptoline2(t2,d2);
        //printf("%.3lf %.3lf %.3lf\n",t2.x,t2.y,t2.z);
    //    t2=rollptoline1(t2,-d1);
        printf("%.3lf %.3lf %.3lf\n",t1.x,t1.y,t1.z);
    }
    return 0;
}

  1. 我没看懂题目
    2
    5 6 -1 5 4 -7
    7 0 6 -1 1 -6 7 -5
    我觉得第一个应该是5 6 -1 5 4 输出是19 5 4
    第二个是7 0 6 -1 1 -6 7输出是14 7 7
    不知道题目例子是怎么得出来的

  2. 您没有考虑 树的根节点是负数的情况, 若树的根节点是个很大的负数,那么就要考虑过不过另外一边子树了

  3. Often We don’t set up on weblogs, but I would like to condition that this established up really forced me individually to do this! considerably outstanding publish