题意:
给 定 三 角 形 A B C 三 个 顶 点 A 、 B 、 C 的 坐 标 , 如 上 图 给定三角形ABC三个顶点A、B、C的坐标,如上图 给定三角形ABC三个顶点A、B、C的坐标,如上图
求 出 三 个 角 的 三 等 分 线 的 交 点 构 成 的 △ D E F 的 三 个 顶 点 D 、 E 、 F 的 坐 标 。 求出三个角的三等分线的交点构成的\triangle DEF的三个顶点D、E、F的坐标。 求出三个角的三等分线的交点构成的△DEF的三个顶点D、E、F的坐标。
输入:
T 组 测 试 数 据 , T组测试数据, T组测试数据,
每 组 测 试 数 据 包 括 六 个 整 数 , 依 次 为 A 、 B 、 C 三 个 顶 点 的 横 纵 坐 标 。 每组测试数据包括六个整数,依次为A、B、C三个顶点的横纵坐标。 每组测试数据包括六个整数,依次为A、B、C三个顶点的横纵坐标。
输出:
六 个 浮 点 数 , 依 次 表 示 D 、 E 、 F 的 横 纵 坐 标 。 六个浮点数,依次表示D、E、F的横纵坐标。 六个浮点数,依次表示D、E、F的横纵坐标。
Sample Input
2 1 1 2 2 1 2 0 0 100 0 50 50Sample 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分析:
莫利定理(Morley’s theorem),也称为莫雷角三分线定理。将三角形的三个内角三等分,靠近某边的两条三分角线相交得到一个交点,则这样的三个交点可以构成一个正三角形。这个三角形常被称作莫利正三角形。
先 根 据 A 、 B 、 C 三 个 顶 点 的 坐 标 , 计 算 出 三 个 角 的 大 小 , 接 着 得 到 角 的 三 等 分 线 对 应 的 向 量 , 先根据A、B、C三个顶点的坐标,计算出三个角的大小,接着得到角的三等分线对应的向量, 先根据A、B、C三个顶点的坐标,计算出三个角的大小,接着得到角的三等分线对应的向量,
根 据 这 些 向 量 计 算 出 对 应 的 交 点 坐 标 。 根据这些向量计算出对应的交点坐标。 根据这些向量计算出对应的交点坐标。
代码:
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <fstream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-10; const double pi = acos(-1.0); struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) {} }; int dcmp(double x) { if (fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } //点与向量 typedef Point Vector; Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); } Vector operator - (Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); } Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); } Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); } bool operator < (const Point& a, const Point& b) { return a.x < b.x || (!dcmp(a.x - b.x) && a.y < b.y); } bool operator == (const Point& a, const Point& b) { return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0; } double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; } double Length(Vector A) { return sqrt(Dot(A, A)); } double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); } //A和B夹角 double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; } //若A到B逆时针则为正,否则为负 double Area2(Point A, Point B, Point C) { return Cross(B - A, C - A); } //三角形ABC的面积的两倍(有方向) double angle(Vector v) { return atan2(v.y, v.x); } //arctan(y/x) double dis2(Point A, Point B) { return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y); } Vector Rotate(Vector A, double rad) //向量A逆时针旋转rad度 { return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); } Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) //求过点P的向量v方向上的直线与过点Q的向量w上的直线的交点 { Vector u = P - Q; double t = Cross(w, u) / Cross(v, w); return P + v * t; } int T; Point A, B, C; int main() { scanf("%d", &T); while (T--) { scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y); Vector AB = B - A, AC = C - A, BC = C - B; double angA = Angle(AB, AC), angB = Angle(A - B, BC), angC = Angle(A - C, B - C); Vector A1 = Rotate(AB, 1.0 / 3 * angA), A2 = Rotate(AB, 2.0 / 3 * angA), B1 = Rotate(BC, 1.0 / 3 * angB), B2 = Rotate(BC, 2.0 / 3 * angB), C1 = Rotate(A - C, 1.0 / 3 * angC), C2 = Rotate(A - C, 2.0 / 3 * angC); Point F = GetLineIntersection(A, A1, B, B2), E = GetLineIntersection(A, A2, C, C1), D = GetLineIntersection(B, B1, C, C2); printf("%lf %lf %lf %lf %lf %lf\n", D.x, D.y, E.x, E.y, F.x, F.y); } return 0; }