SGU 120 Archipelago (向量旋转)

给出n正多边形的两个顶点坐标n1,n2,求其余顶点坐标。


1、先求出中心坐标C。

2、根据中心坐标C和初始的一个顶点,进行一定角度的旋转,依次求出其他顶点。


对于1:由两点n1,n2(不妨设n2>n1)和中心可形成一个三角形,已知两点坐标,可求该三角形的一边长y以及其它两边与中心所形成的夹角a=2π/n*(n2-n1),另外两个角相等,设为B,亦可求矣。

然后根据余弦定理求另一边x,这样初始两点形成的边,以n2为中心逆时针旋转B,即到达中心与n2形成的边的位置,然后乘以比例x/y即可得到中心与n2形成的向量。然后可求中心坐标。


关于向量的旋转:


  我们对向量进行旋转变换可以通过矩阵完成,比如我要向量(x, y)绕原点逆时针旋转角度A:

                      [x, y] x  [cosA  sinA]     = [x*cosA-y*sinA  x*sinA+y*cosA]       

                                  [-sinA cosA]

      旋转后的向量为:[x*cosA-y*sinA  x*sinA+y*cosA]




#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 160
#define Pi acos(-1.0)
typedef double db;
struct P
{
    db x,y;
}p[N];
P rol(P s,P e,db a,db k)   //向量se,逆时针旋转a度后,乘上比例系数k,返回新的终点坐标
{
    P c;
    db x=e.x-s.x,y=e.y-s.y;
    c.x=s.x+k*(x*cos(a)-y*sin(a));
    c.y=s.y+k*(x*sin(a)+y*cos(a));
    return c;
}
P getc(P p1,P p2,int n1,int n2,int n)  //获取中心坐标
{
    db B=Pi*(0.5-1.0*(n2-n1)/n);
    return rol(p2,p1,B,0.5/cos(B));
}
int main()
{
    int i,n,n1,n2;
    scanf("%d%d%d",&n,&n1,&n2);
    scanf("%lf%lf%lf%lf",&p[n1].x,&p[n1].y,&p[n2].x,&p[n2].y);
    if(n1>n2) swap(n1,n2);    //注意这里的n1,n2不一定按顺序给出
    P c=getc(p[n1],p[n2],n1,n2,n);
    db deg=2.0*Pi/n;
    for(i=1;i<n;++i)
    {
        int j=(n1+i)%n;
        if(j==0) j=n;
        if(j==n2) continue;
        db tem=-deg*i;  //相当于顺时针旋转deg*i度
        p[j]=rol(c,p[n1],tem,1);
    }
    for(i=1;i<=n;++i) printf("%.6lf %.6lf\n",p[i].x,p[i].y);
    return 0;
}



你可能感兴趣的:(SGU 120 Archipelago (向量旋转))