【UVA11178】Morley's Theorem——Morley 定理

Morleys theorem states that that the lines
trisecting the angles of an arbitrary plane
triangle meet at the vertices of an equilateral
triangle. For example in the figure
below the tri-sectors of angles A, B and C
has intersected and created an equilateral
triangle DEF.

Of course the theorem has various generalizations,
in particular if all of the trisectors
are intersected one obtains four
other equilateral triangles. But in the
original theorem only tri-sectors nearest
to BC are allowed to intersect to get point
D, tri-sectors nearest to CA are allowed to intersect point E and tri-sectors nearest to AB are intersected
to get point F. Trisector like BD and CE are not allowed to intersect. So ultimately we get only
one equilateral triangle DEF. Now your task is to find the Cartesian coordinates of D, E and F given
the coordinates of A, B, and C.
Input
First line of the input file contains an integer N (0 < N < 5001) which denotes the number of
test cases to follow. Each of the next lines contain six integers XA, YA, XB, YB, XC , YC . This six
integers actually indicates that the Cartesian coordinates of point A, B and C are (XA, YA),(XB, YB)
and (XC , YC ) respectively. You can assume that the area of triangle ABC is not equal to zero, 0 ≤
XA, YA, XB, YB, XC , YC ≤ 1000 and the points A, B and C are in counter clockwise order.
Output
For each line of input you should produce one line of output. This line contains six floating point
numbers XD, YD, XE, YE, XF , YF separated by a single space. These six floating-point actually means
that the Cartesian coordinates of D, E and F are (XD, YD),(XE, YE) ,(XF , YF ) respectively. Errors
less than 10−5 will be accepted.

Sample Input

2
1 1 2 2 1 2
0 0 100 0 50 50

Sample Output

1.316987 1.816987 1.183013 1.683013 1.366025 1.633975
56.698730 25.000000 43.301270 25.000000 50.000000 13.397460

题意:三角形每个内角的三等分线相交的三角形为等边三角形,求交点坐标。

分析:向量旋转和直线的相交。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

const double eps = 1e-6;

const double PI = acos(-1.0);

typedef struct Point
{
    double x,y;

    Point(double x= 0 ,double y = 0 ):x(x),y(y){}

    Point operator + (const Point &a)const {return Point(a.x+x,y+a.y);}

    Point operator - (const Point &a)const {return Point(x-a.x,y-a.y);}

    Point operator * (const double &a)const {return Point(x*a,y*a);}

    Point operator / (const double &a)const {return Point(x/a,y/a);}

    bool operator < (const Point &a)const {return x<a.x||(x==a.x&&y<a.y);}


}Vector;

int dbcmp(double x)
{
    if(fabs(x)<eps) return 0;

    return x>0?1:-1;
}

bool operator == (const Point &a,const Point  b) //判断点的相等
{
    return dbcmp(a.x-b.x)==0 && dbcmp(a.y-b.y)==0;
}

double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;} //点积

double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} //叉积

double Length(Vector A) {return sqrt(Dot(A,A));}//向量长度

double Angle(Vector A,Vector B) {return acos(Dot(A,B)/Length(A)/Length(B));}//向量之间的夹角

double Area2(Point A,Point B,Point C) {return Cross(B-A,C-A);} //求平行四边形面积

Vector Rotate (Vector A,double rad) {return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));} //二维向量逆时针旋转rad

Point GetLineIntersection(Point P,Vector v,Point Q,Point w) //求两直线Pv,Qw交点,保证直线只有唯一的一个交点。
{
    Vector u = P-Q;

    double t = Cross(w,u)/Cross(v,w);

    return P+v*t;
}

double DistanceToLine(Point P,Point A,Point B) //点P到直线AB的距离
{
    Vector v1 = B-A,v2 = P - A;

    return fabs(Cross(v1,v2)/Length(v1));
}

double DistanceToSegment(Point P,Point A,Point B) //点到线段的最短距离
{
    if(A == B) return Length(P-A);


    Vector v1 = B - A,v2 = P-A,v3 = P-B;

    if(dbcmp(Dot(v1,v2))<0) return Length(v2);//在A端点的外面

    else if(dbcmp(Dot(v1,v3))>0) return Length(v3);//在B端点的外面

    else return fabs(Cross(v1,v2)/Length(v1));
}

Point GetLineProjection(Point P,Point A,Point B) //点在线段上的投影的坐标
{
    Vector v = B-A;

    return A+v*(Dot(v,P-A)/Dot(v,v));
}

bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2) //判断线段规范相交
{
    double c1 = Cross(a2-a1,b1-a1),c2 = Cross(a2-a1,b2-a1),c3 = Cross(b2-b1,a1-b1),c4 = Cross(b2-b1,a2-b1);

    return dbcmp(c1)*dbcmp(c2)<0&&dbcmp(c3)*dbcmp(c4)<0;
}

bool OnSegment(Point P,Point A,Point B) { return dbcmp(Cross(A-P,B-P)) == 0 && dbcmp(Dot(A-P,B-P)) < 0;} //判断点P是不是在线段AB上

double PolygonArea(Point *p,int n)//求多边形的有向面积
{
    double Area = 0;

    for(int i = 1;i < n-1; i++) Area += Cross(p[i]-p[0],p[i+1]-p[0]);

    return Area/2;
}

Point GetMorley(Point A,Point B,Point C)
{
    Vector v1  = C-B;

    double a1 = Angle(A-B,v1);

    v1 = Rotate(v1,a1/3);



    Vector v2 = B-C;


    double a2 = Angle(A-C,v2);

    v2 = Rotate(v2,-a2/3);


    return GetLineIntersection(B,v1,C,v2);
}

int main()
{
    Point a[4],b[4];

    int T;

    scanf("%d",&T);

    while(T--)
    {
        for(int i = 0;i<3;i++)
        {
            scanf("%lf %lf",&a[i].x,&a[i].y);
        }

        b[0] = GetMorley(a[0],a[1],a[2]);

        b[1] = GetMorley(a[1],a[2],a[0]);

        b[2] = GetMorley(a[2],a[0],a[1]);

        for(int i = 0; i < 3; i++)
        {
            if(i)
                printf(" ");

            printf("%.6f %.6f",b[i].x,b[i].y);
        }

        printf("\n");
    }

    return 0;
}

你可能感兴趣的:(【UVA11178】Morley's Theorem——Morley 定理)