Description

Given one triangle and one circle in the plane. Your task is to calculate the common area of these two figures.

Input

The input will contain several test cases. Each line of input describes a test case. Each test case consists of nine floating point numbers, x1y1x2y2x3y3x4y4 and r, where (x1y1), (x2y2) and (x3y3) are the three vertices of the triangle and (x4y4) is the center of the circle and r is the radius. We guarantee the triangle and the circle are not degenerate.

Output

For each test case you should output one real number, which is the common area of the triangle and the circle, on a separate line. The result should be rounded to two decimal places.

题目大意:求一个三角形和一个圆形的交的面积。

思路:圆心和三个三角形的三个点连线,把一个三角形划分为3个三角形,利用有向面积来算。然后就变成了求一个三角形和圆的交的面积,其中三角形的一个顶点为圆心。然后各种分情况讨论(但是要分的情况起码会比直接算一个普通三角形和圆形的交要少得多)。我的姿势似乎不是很高级,好像有些什么奇怪的公式……

PS:调了一下发现居然是以前用的模板错了……

代码(1938MS):

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std; const int MAXN = ;
const double EPS = 1e-;
const double PI = acos(-1.0);//3.14159265358979323846
const double INF = ; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} inline double sqr(double x) {
return x * x;
} struct Point {
double x, y, ag;
Point() {}
Point(double x, double y): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
bool operator == (const Point &rhs) const {
return sgn(x - rhs.x) == && sgn(y - rhs.y) == ;
}
bool operator < (const Point &rhs) const {
if(y != rhs.y) return y < rhs.y;
return x < rhs.x;
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y);
}
Point operator * (const double &b) const {
return Point(x * b, y * b);
}
Point operator / (const double &b) const {
return Point(x / b, y / b);
}
double operator * (const Point &rhs) const {
return x * rhs.x + y * rhs.y;
}
double length() {
return sqrt(x * x + y * y);
}
double angle() {
return atan2(y, x);
}
Point unit() {
return *this / length();
}
void makeAg() {
ag = atan2(y, x);
}
void print() {
printf("%.10f %.10f\n", x, y);
}
};
typedef Point Vector; double dist(const Point &a, const Point &b) {
return (a - b).length();
} double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
}
//ret >= 0 means turn right
double cross(const Point &sp, const Point &ed, const Point &op) {
return cross(sp - op, ed - op);
} double area(const Point& a, const Point &b, const Point &c) {
return fabs(cross(a - c, b - c)) / ;
}
//counter-clockwise
Point rotate(const Point &p, double angle, const Point &o = Point(, )) {
Point t = p - o;
double x = t.x * cos(angle) - t.y * sin(angle);
double y = t.y * cos(angle) + t.x * sin(angle);
return Point(x, y) + o;
} double includedAngle(const Point &a, const Point &b, const Point &o) {
double ret = abs((a - o).angle() - (b - o).angle());
if(sgn(ret - PI) > ) ret = * PI - ret;
return ret;
} struct Seg {
Point st, ed;
double ag;
Seg() {}
Seg(Point st, Point ed): st(st), ed(ed) {}
void read() {
st.read(); ed.read();
}
void makeAg() {
ag = atan2(ed.y - st.y, ed.x - st.x);
}
};
typedef Seg Line; //ax + by + c > 0
Line buildLine(double a, double b, double c) {
if(sgn(a) == && sgn(b) == ) return Line(Point(sgn(c) > ? - : , INF), Point(, INF));
if(sgn(a) == ) return Line(Point(sgn(b), -c/b), Point(, -c/b));
if(sgn(b) == ) return Line(Point(-c/a, ), Point(-c/a, sgn(a)));
if(b < ) return Line(Point(, -c/b), Point(, -(a + c) / b));
else return Line(Point(, -(a + c) / b), Point(, -c/b));
} void moveRight(Line &v, double r) {
double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y;
dx = dx / dist(v.st, v.ed) * r;
dy = dy / dist(v.st, v.ed) * r;
v.st.x += dy; v.ed.x += dy;
v.st.y -= dx; v.ed.y -= dx;
} bool isOnSeg(const Seg &s, const Point &p) {
return (p == s.st || p == s.ed) ||
(((p.x - s.st.x) * (p.x - s.ed.x) < ||
(p.y - s.st.y) * (p.y - s.ed.y) < ) &&
sgn(cross(s.ed, p, s.st)) == );
} bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) {
return (max(s1.x, e1.x) >= min(s2.x, e2.x)) &&
(max(s2.x, e2.x) >= min(s1.x, e1.x)) &&
(max(s1.y, e1.y) >= min(s2.y, e2.y)) &&
(max(s2.y, e2.y) >= min(s1.y, e1.y)) &&
(cross(s2, e1, s1) * cross(e1, e2, s1) >= ) &&
(cross(s1, e2, s2) * cross(e2, e1, s2) >= );
} bool isIntersected(const Seg &a, const Seg &b) {
return isIntersected(a.st, a.ed, b.st, b.ed);
} bool isParallel(const Seg &a, const Seg &b) {
return sgn(cross(a.ed - a.st, b.ed - b.st)) == ;
} //return Ax + By + C =0 's A, B, C
void Coefficient(const Line &L, double &A, double &B, double &C) {
A = L.ed.y - L.st.y;
B = L.st.x - L.ed.x;
C = L.ed.x * L.st.y - L.st.x * L.ed.y;
}
//point of intersection
Point operator * (const Line &a, const Line &b) {
double A1, B1, C1;
double A2, B2, C2;
Coefficient(a, A1, B1, C1);
Coefficient(b, A2, B2, C2);
Point I;
I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
return I;
} bool isEqual(const Line &a, const Line &b) {
double A1, B1, C1;
double A2, B2, C2;
Coefficient(a, A1, B1, C1);
Coefficient(b, A2, B2, C2);
return sgn(A1 * B2 - A2 * B1) == && sgn(A1 * C2 - A2 * C1) == && sgn(B1 * C2 - B2 * C1) == ;
} double Point_to_Line(const Point &p, const Line &L) {
return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed));
} double Point_to_Seg(const Point &p, const Seg &L) {
if(sgn((L.ed - L.st) * (p - L.st)) < ) return dist(p, L.st);
if(sgn((L.st - L.ed) * (p - L.ed)) < ) return dist(p, L.ed);
return Point_to_Line(p, L);
} double Seg_to_Seg(const Seg &a, const Seg &b) {
double ans1 = min(Point_to_Seg(a.st, b), Point_to_Seg(a.ed, b));
double ans2 = min(Point_to_Seg(b.st, a), Point_to_Seg(b.ed, a));
return min(ans1, ans2);
} struct Circle {
Point c;
double r;
Circle() {}
Circle(Point c, double r): c(c), r(r) {}
void read() {
c.read();
scanf("%lf", &r);
}
double area() const {
return PI * r * r;
}
bool contain(const Circle &rhs) const {
return sgn(dist(c, rhs.c) + rhs.r - r) <= ;
}
bool contain(const Point &p) const {
return sgn(dist(c, p) - r) <= ;
}
bool intersect(const Circle &rhs) const {
return sgn(dist(c, rhs.c) - r - rhs.r) < ;
}
bool tangency(const Circle &rhs) const {
return sgn(dist(c, rhs.c) - r - rhs.r) == ;
}
Point pos(double angle) const {
Point p = Point(c.x + r, c.y);
return rotate(p, angle, c);
}
}; double CommonArea(const Circle &A, const Circle &B) {
double area = 0.0;
const Circle & M = (A.r > B.r) ? A : B;
const Circle & N = (A.r > B.r) ? B : A;
double D = dist(M.c, N.c);
if((D < M.r + N.r) && (D > M.r - N.r)) {
double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
double alpha = * acos(cosM);
double beta = * acos(cosN);
double TM = 0.5 * M.r * M.r * (alpha - sin(alpha));
double TN = 0.5 * N.r * N.r * (beta - sin(beta));
area = TM + TN;
}
else if(D <= M.r - N.r) {
area = N.area();
}
return area;
} int intersection(const Seg &s, const Circle &cir, Point &p1, Point &p2) {
double angle = includedAngle(s.ed, cir.c, s.st);
double B = dist(cir.c, s.st);
double a = , b = - * B * cos(angle), c = sqr(B) - sqr(cir.r);
double delta = sqr(b) - * a * c;
if(sgn(delta) < ) return ;
double x1 = (-b - sqrt(delta)) / ( * a), x2 = (-b + sqrt(delta)) / ( * a);
Vector v = (s.ed - s.st).unit();
p1 = s.st + v * x1;
p2 = s.st + v * x2;
return + sgn(delta);
} double CommonArea(const Circle &cir, Point p1, Point p2) {
if(cir.contain(p1) && cir.contain(p2)) {
return area(cir.c, p1, p2);
} else if(!cir.contain(p1) && !cir.contain(p2)) {
Point q1, q2;
int t = intersection(Line(p1, p2), cir, q1, q2);
if(t == ) {
double angle = includedAngle(p1, p2, cir.c);
return 0.5 * sqr(cir.r) * angle;
} else {
double angle1 = includedAngle(p1, p2, cir.c);
double angle2 = includedAngle(q1, q2, cir.c);
if(isOnSeg(Seg(p1, p2), q1))return 0.5 * sqr(cir.r) * (angle1 - angle2 + sin(angle2));
else return 0.5 * sqr(cir.r) * angle1;
}
} else {
if(cir.contain(p2)) swap(p1, p2);
Point q1, q2;
intersection(Line(p1, p2), cir, q1, q2);
double angle = includedAngle(q2, p2, cir.c);
double a = area(cir.c, p1, q2);
double b = 0.5 * sqr(cir.r) * angle;
return a + b;
}
} struct Triangle {
Point p[];
Triangle() {}
Triangle(Point *t) {
for(int i = ; i < ; ++i) p[i] = t[i];
}
void read() {
for(int i = ; i < ; ++i) p[i].read();
}
double area() const {
return ::area(p[], p[], p[]);
}
Point& operator[] (int i) {
return p[i];
}
}; double CommonArea(Triangle tir, const Circle &cir) {
double ret = ;
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
ret += sgn(cross(tir[], cir.c, tir[])) * CommonArea(cir, tir[], tir[]);
return abs(ret);
} struct Poly {
int n;
Point p[MAXN];//p[n] = p[0]
void init(Point *pp, int nn) {
n = nn;
for(int i = ; i < n; ++i) p[i] = pp[i];
p[n] = p[];
}
double area() {
if(n < ) return ;
double s = p[].y * (p[n - ].x - p[].x);
for(int i = ; i < n; ++i)
s += p[i].y * (p[i - ].x - p[i + ].x);
return s / ;
}
};
//the convex hull is clockwise
void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top]
sort(p, p + n);
top = ;
stk[] = ; stk[] = ;
for(int i = ; i < n; ++i) {
while(top && cross(p[i], p[stk[top]], p[stk[top - ]]) <= ) --top;
stk[++top] = i;
}
int len = top;
stk[++top] = n - ;
for(int i = n - ; i >= ; --i) {
while(top != len && cross(p[i], p[stk[top]], p[stk[top - ]]) <= ) --top;
stk[++top] = i;
}
}
//use for half_planes_cross
bool cmpAg(const Line &a, const Line &b) {
if(sgn(a.ag - b.ag) == )
return sgn(cross(b.ed, a.st, b.st)) < ;
return a.ag < b.ag;
}
//clockwise, plane is on the right
bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) {
int i, n;
sort(v, v + vn, cmpAg);
for(i = n = ; i < vn; ++i) {
if(sgn(v[i].ag - v[i-].ag) == ) continue;
v[n++] = v[i];
}
int head = , tail = ;
deq[] = v[], deq[] = v[];
for(i = ; i < n; ++i) {
if(isParallel(deq[tail - ], deq[tail]) || isParallel(deq[head], deq[head + ]))
return false;
while(head < tail && sgn(cross(v[i].ed, deq[tail - ] * deq[tail], v[i].st)) > )
--tail;
while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + ], v[i].st)) > )
++head;
deq[++tail] = v[i];
}
while(head < tail && sgn(cross(deq[head].ed, deq[tail - ] * deq[tail], deq[head].st)) > )
--tail;
while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + ], deq[tail].st)) > )
++head;
if(tail <= head + ) return false;
res.n = ;
for(i = head; i < tail; ++i)
res.p[res.n++] = deq[i] * deq[i + ];
res.p[res.n++] = deq[head] * deq[tail];
res.n = unique(res.p, res.p + res.n) - res.p;
res.p[res.n] = res.p[];
return true;
} //ix and jx is the points whose distance is return, res.p[n - 1] = res.p[0], res must be clockwise
double dia_rotating_calipers(Poly &res, int &ix, int &jx) {
double dia = ;
int q = ;
for(int i = ; i < res.n - ; ++i) {
while(sgn(cross(res.p[i], res.p[q + ], res.p[i + ]) - cross(res.p[i], res.p[q], res.p[i + ])) > )
q = (q + ) % (res.n - );
if(sgn(dist(res.p[i], res.p[q]) - dia) > ) {
dia = dist(res.p[i], res.p[q]);
ix = i; jx = q;
}
if(sgn(dist(res.p[i + ], res.p[q]) - dia) > ) {
dia = dist(res.p[i + ], res.p[q]);
ix = i + ; jx = q;
}
}
return dia;
}
//a and b must be clockwise, find the minimum distance between two convex hull
double half_rotating_calipers(Poly &a, Poly &b) {
int sa = , sb = ;
for(int i = ; i < a.n; ++i) if(sgn(a.p[i].y - a.p[sa].y) < ) sa = i;
for(int i = ; i < b.n; ++i) if(sgn(b.p[i].y - b.p[sb].y) < ) sb = i;
double tmp, ans = dist(a.p[], b.p[]);
for(int i = ; i < a.n; ++i) {
while(sgn(tmp = cross(a.p[sa], a.p[sa + ], b.p[sb + ]) - cross(a.p[sa], a.p[sa + ], b.p[sb])) > )
sb = (sb + ) % (b.n - );
if(sgn(tmp) < ) ans = min(ans, Point_to_Seg(b.p[sb], Seg(a.p[sa], a.p[sa + ])));
else ans = min(ans, Seg_to_Seg(Seg(a.p[sa], a.p[sa + ]), Seg(b.p[sb], b.p[sb + ])));
sa = (sa + ) % (a.n - );
}
return ans;
} double rotating_calipers(Poly &a, Poly &b) {
return min(half_rotating_calipers(a, b), half_rotating_calipers(b, a));
} /*******************************************************************************************/ Triangle tir;
Circle cir; int main() {
while(scanf("%lf%lf", &tir[].x, &tir[].y) != EOF) {
tir[].read();
tir[].read();
cir.read();
//cout<<Point_to_Line(cir.c, Line(tir[0], tir[1]))<<endl;
if(sgn(cross(tir[], tir[], tir[])) == ) puts("0.00");
else printf("%.2f\n", CommonArea(tir, cir) + EPS);
}
}

POJ 2986 A Triangle and a Circle(三角形和圆形求交)的更多相关文章

  1. POJ 2986 A Triangle and a Circle 圆与三角形的公共面积

    计算几何模板 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h& ...

  2. POJ 2986 A Triangle and a Circle

    题意:给定一个三角形,以及一个圆的圆心坐标和半径,求圆和三角形的相交面积. 思路: 用三角剖分,三角形上每个线段都变成这个线段与圆心的三角形,然后算出每个三角形与圆的相交面积,然后根据有向面积的正负累 ...

  3. poj 1090:The Circumference of the Circle(计算几何,求三角形外心)

    The Circumference of the Circle Time Limit: 2 Seconds      Memory Limit: 65536 KB To calculate the c ...

  4. ray与triangle/quad求交二三事

    引擎中,ray与quad求交,算法未细看,但有求解二次方程,不解.ray与triangle求交,使用的是97年经典算法,仔细看过论文,多谢小武同学指点,用到了克拉默法则求解线性方程组.想模仿该方法,做 ...

  5. 光线求交-面、三角形、球 (Ray intersection)

    光线求交 光线定义:position \(a(t)\) = \(o\) + \(t\vec{d}\); 球定义: center p, radius r; 平面定义:normal \(\vec{n}\) ...

  6. CSS 三角形与圆形

    1. 概述 1.1 说明 通过边框(border)的宽度与边框圆角(border-radius)来设置所需的三角形与圆形. 1.2 边框 宽高都为0时,边框设置的不同结果也不同,如下: 1.四个边框都 ...

  7. python应用-已知三角形的边长求他的面积和周长

    """ 已知三角形的边长求他的面积和周长 Author:罗万财 Date:2017-3-3 """ import math a=float( ...

  8. C语言:已知三角形三边长求面积

    //已知三角形三边长求面积 #include <stdio.h> #include <math.h> int main() { float a,b,c,p,s; int x=0 ...

  9. POJ - 2079:Triangle (旋转卡壳,求最大三角形)

    Given n distinct points on a plane, your task is to find the triangle that have the maximum area, wh ...

随机推荐

  1. java获取客户端信息

    创建JSP页面 clientinfo <%@page import="java.util.StringTokenizer"%> <%@ page language ...

  2. 【读书笔记 - Effective Java】03. 用私有构造器或者枚举类型强化Singleton属性

    实现Singleton(代表本质上唯一的系统组件)的三种方法: 1. 保持私有构造器,导出公有的静态成员,客户端访问该类的唯一实例. 2. 保持私有构造器,公有的成员是静态工厂方法. 3. 单元素的枚 ...

  3. spring-quartz 定时器 给targetMethod传递参数

    今天在做一个项目的时候,要给一个定时器任务的执行方法传递参数,在网上找了一下资料,可以使用arguments参数:   <bean id="subsidyJobDetail" ...

  4. 新人成长之入门Vue.js常用指令介绍(一)

    写在前面 作为一个刚步入职场工作的新人,对于公司中所用的技术和框架基本上不懂,只能从最基础的开始做起,进入公司接触的第一个框架就是前端框架Vue.js,几个功能做下来,觉得Vue.js首先学习起来真的 ...

  5. ie 8在打印网页的时候打印预览是空白的

    win 7专业版系统中的ie 8在打印网页的时候打印预览是空白的,打印出来也是空白的,但是用别的浏览器打印没有问题 根据您的描述,该问题主要是由于保护模式下%Temp%\Low不正常工作引起的. 建议 ...

  6. checked和unchecked转换

    static unsafe void Main(string[] args) { unchecked //checked 运行时候引发异常 { int n = int.MaxValue; n++; C ...

  7. LCD触屏驱动

    tiny4412多点触摸屏驱动程序(基于I2C协议): #include <linux/kernel.h> #include <linux/module.h> #include ...

  8. consonant_爆破音

    consonant_爆破音_[p]和[b].[t]和[d].[k]和[g] 声带震动:发音的重要作用. 爆破音:发音在一瞬间,不会延长气流. [p]:声带不震动,嘴唇咬在一起,有明显的气流.map.p ...

  9. mfc和qt的区别

    注:引用来源 http://wenda.chinabaike.com/b/30934/2013/1208/707410.html QT使用的编译器是MinGW,即Linux下的GCC移植到window ...

  10. (杭电 1014)Uniform Generator

    Uniform Generator Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...