POJ 3808 Malfatti Circles(计算几何)

Malfatti Circles

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 250   Accepted: 125   Special Judge

Description

The con?guration of three circles packed inside a triangle such that each circle is tangent to the other two circles and to two of the edges of the triangle has been studied by many mathematicians for more than two centuries. Existence and uniqueness of such
circles for an arbitrary triangle are easy to prove. Many methods of numerical calculation or geometric construction of such circles from an arbitrarily given triangle have been discovered. Today, such circles are called the Malfatti circles.

Figure 7 illustrates an example. The Malfatti circles of the triangle with the vertices (20, 80), (-40, -20) and (120, -20) are approximately

the circle with the center (24.281677, 45.219486) and the radius 21.565935,

the circle with the center (3.110950, 4.409005) and the radius 24.409005, and

the circle with the center (54.556724, 7.107493) and the radius 27.107493.

Figure 8 illustrates another example. The Malfatti circles of the triangle with the vertices (20, -20), (120, -20) and (-40, 80) are approximately

the circle with the center (25.629089, -10.057956) and the radius 9.942044,

the circle with the center (53.225883, -0.849435) and the radius 19.150565, and

the circle with the center (19.701191, 19.203466) and the radius 19.913790.

Your mission is to write a program to calculate the radii of the Malfatti circles of the given triangles.

Input

The input is a sequence of datasets. A dataset is a line containing six integers x1, y1, x2, y2, x3 and y3 in this order, separated by a space. The coordinates of the vertices of the given triangle are (x1, y1), (x2, y2) and (x3, y3), respectively. You can
assume that the vertices form a triangle counterclockwise. You can also assume that the following two conditions hold.

All of the coordinate values are greater than -1000 and less than 1000.

None of the Malfatti circles of the triangle has a radius less than 0.1.

The end of the input is indicated by a line containing six zeros separated by a space.

Output

For each input dataset, three decimal fractions r1, r2 and r3 should be printed in a line in this order separated by a space. The radii of the Malfatti circles nearest to the vertices with the coordinates (x1, y1), (x2, y2) and (x3, y3) should be r1, r2 and
r3, respectively.

None of the output values may have an error greater than 0.0001. No extra character should appear in the output.

Sample Input

20 80 -40 -20 120 -20
20 -20 120 -20 -40 80
0 0 1 0 0 1
0 0 999 1 -999 1
897 -916 847 -972 890 -925
999 999 -999 -998 -998 -999
-999 -999 999 -999 0 731
-999 -999 999 -464 -464 999
979 -436 -955 -337 157 -439
0 0 0 0 0 0

Sample Output

21.565935 24.409005 27.107493
9.942044 19.150565 19.913790
0.148847 0.207107 0.207107
0.125125 0.499750 0.499750
0.373458 0.383897 0.100456
0.706768 0.353509 0.353509
365.638023 365.638023 365.601038
378.524085 378.605339 378.605339
21.895803 22.052921 5.895714

题意:给出一个三角形的三个顶点的坐标,求三角形的三个内切圆,它们两两相切,并且每个顶点附近的圆和连接这个顶点的两条边也相切。求着三个内切圆的半径。

分析:套公式。

其中r为三角形内切圆的半径,s为半周长。

#include <cstdio>
#include <cmath>
using namespace std;

struct Point {
    double x, y;
} A, B, C, I;

double get_dis(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

int main() {
    while(~scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y)) {
        if(A.x == 0 && A.y == 0 && B.x == 0 && B.y == 0 && C.x == 0 && C.y == 0) break;
        double a = get_dis(B, C);
        double b = get_dis(A, C);
        double c = get_dis(A, B);
        double s = (a + b + c) / 2;  // 半周长
        I.x = (a * A.x + b * B.x + c * C.x) / (a + b + c);
        I.y = (a * A.y + b * B.y + c * C.y) / (a + b + c); // 内切圆圆心坐标
        double r = sqrt((s - a) * (s - b) * (s - c) / s); // 内切圆半径
        double IA = get_dis(A, I);
        double IB = get_dis(B, I);
        double IC = get_dis(C, I);
        double r1 = r / (2 * (s - a)) * (s - r + IA - IB - IC);
        double r2 = r / (2 * (s - b)) * (s - r + IB - IA - IC);
        double r3 = r / (2 * (s - c)) * (s - r + IC - IA - IB);
        printf("%.6lf %.6lf %.6lf\n", r1, r2, r3);
    }
    return 0;
}

更多解释请见http://en.wikipedia.org/wiki/Malfatti_circles

时间: 2024-08-28 23:06:44

POJ 3808 Malfatti Circles(计算几何)的相关文章

UVA LIVE-4642 - Malfatti Circles

目录(?)[+] Input Output Sample Input Sample Output 给出三角形三个顶点,求出三个互切的圆的半径 虽然大白鼠说可以推出公式,可是这个公式只怕没那么容易推--我左看右看上看下看也推不出. 应该是要做辅助线什么的,那也-- 由于很容易就推出了关于三个半径的三元方程组,那么就试试搜索吧,搜其中任意一个半径,只要满足这个方程组就可以了, 那么就二分搜索吧,当然,这个单调性呢? 看图可知,比方说,我们搜最靠近最上面的顶点的圆的半径r1,由于,下面两圆的r2,r3

【POJ】2318 TOYS ——计算几何+二分

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10281   Accepted: 4924 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

Poj 1556 The Doors 计算几何+最短路

其实本题非常的无脑,无脑拍完1A,写到blog里只因为TM无脑拍也拍了很久啊= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdl

POJ 3304 Segments(计算几何:直线与线段相交)

POJ 3304 Segments 大意:给你一些线段,找出一条直线能够穿过所有的线段,相交包括端点. 思路:遍历所有的端点,取两个点形成直线,判断直线是否与所有线段相交,如果存在这样的直线,输出Yes,但是注意去重. struct Point { double x, y; } P[210]; struct Line { Point a, b; } L[110]; double xmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.

转载::POJ 2991 线段树+计算几何(有c++结构体操作)

POJ 2991 线段树+计算几何 (2011-02-27 21:13:44) 转载▼ 标签: 杂谈 分类: OI 话说这一题真的是很恶心很恶心,不过确实改变了我对线段树的一些看法,算是很经典的题目. 题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度.然后有一些操作a. b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标. 首先要用到一个计算几何的知识(没学过..请教而来)

POJ 2405 Beavergnaw (计算几何-简单题)

Beavergnaw Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6203   Accepted: 4089 Description When chomping a tree the beaver cuts a very specific shape out of the tree trunk. What is left in the tree trunk looks like two frustums of a co

poj 2398 Toy Storage (计算几何,判断点和线段关系)

http://poj.org/problem?id=2398 题意大概是说将一个盒子用n个board分成n+1 部分 然后往里面放toy,给定盒子,board,和toy的坐标 问所有的toy放完后,有多少部分中有t个toy; 简单计算几何 需要判断的是点和直线的关系. 判断 某一点在直线左右侧 左右方向是相对前进方向的,只要指定了前进方向就可以知道左右(比如指定前进方向是从直线的起点到终点).判断点在直线的左侧还是右侧是计算几何里面的一个最基本算法.使用矢量来判断. 定义:平面上的三点P1(x1

POJ 3449 Geometric Shapes --计算几何,线段相交

题意: 给一些多边形或线段,输出与每一个多边形或线段的有哪一些多边形或线段. 解法: 想法不难,直接暴力将所有的图形处理成线段,然后暴力枚举,相交就加入其vector就行了.主要是代码有点麻烦,一步一步来吧. 还有收集了一个线段旋转的函数. Vector Rotate(Point P,Vector A,double rad){ //以P为基准点把向量A旋转rad return Vector(P.x+A.x*cos(rad)-A.y*sin(rad),P.y+A.x*sin(rad)+A.y*co

POJ 1905-Expanding Rods(二分+计算几何)

题目地址:POJ 1905 题意:一根某种材料做的直杆被夹在两面墙之间,当他受热时长度变长,就会因两面墙的挤压而向上隆起.长度变化函数为 L'=(1+n*C)*L,给定L,C,n,求向上拱起的高度H. 思路: 手动计算出这两个公式,然后用二分查找h值. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #