圆与多边形的面积交
https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/7/CGL_7_H
int sgn(double x) {
if(fabs(x)<eps)return 0;
return x<0?-1:1;
}
struct Point { //定义点和基本运算
double x,y;
double ang;
Point() {}
Point(double x,double y):x(x),y(y) {}
Point operator + (Point B) {
return Point(x+B.x,y+B.y);
}
Point operator - (Point B) {
return Point(x-B.x,y-B.y);
}
Point operator * (double k) {
return Point(x*k,y*k); //长度增大k倍
}
Point operator / (double k) {
return Point(x/k,y/k); //长度缩小k倍
}
bool operator == (Point B) {
return sgn(x-B.x)==0 && sgn(y-B.y)==0;
}
double operator ^(Point B) {
return x*B.y-y*B.x;
}
double distance(Point p) {
return hypot(x-p.x,y-p.y);
}
double len() {
return hypot(x,y);//库函数
}
Point trunc(double r) {
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}//点积
double operator *(const Point &b)const {
return x*b.x + y*b.y;
}
double len2() {
return x*x + y*y;
}
double rad(Point a,Point b) {
Point p = *this;
return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
}
};
typedef Point Vector;
double Cross(Vector A,Vector B) {
return A.x*B.y - A.y*B.x; //叉积
}
struct Line {
//返回长度的平方
Point s,e;
Line() {}
Line(Point _s,Point _e) {
s = _s;
e = _e;
}
double length() {
return s.distance(e);
}
double dispointtoline(Point p) {
return fabs((p-s)^(e-s))/length();
}
Point lineprog(Point p) {
return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
}
};
struct Circle {
Point p;//圆心
double r;//半径
Circle() {}
Circle(Point p,double r):p(p),r(r) {}
Circle(double x,double y,double _r) {
p=Point(x,y);
r = _r;
}
int relationcircle(Circle v) {
double d = p.distance(v.p);
if(sgn(d-r-v.r) > 0)return 5;
if(sgn(d-r-v.r) == 0)return 4;
double l = fabs(r-v.r);
if(sgn(d-r-v.r)<0 && sgn(d-l)>0)return 3;
if(sgn(d-l)==0)return 2;
if(sgn(d-l)<0)return 1;
}
int relationline(Line v) {
double dst = v.dispointtoline(p);
if(sgn(dst-r) < 0)return 2;
else if(sgn(dst-r) == 0)return 1;
return 0;
}
//点和圆的关系
//0 圆外
//1 圆上
//2 圆内
int relation(Point b) {
double dst = b.distance(p);
if(sgn(dst-r) < 0)return 2;
else if(sgn(dst-r)==0)return 1;
return 0;
}
//求直线和圆的交点,返回交点个数
int pointcrossline(Line v,Point &p1,Point &p2) {
if(!(*this).relationline(v))return 0;
Point a = v.lineprog(p);
double d = v.dispointtoline(p);
d = sqrt(r*r-d*d);
if(sgn(d) == 0) {
p1 = a;
p2 = a;
return 1;
}
p1 = a + (v.e-v.s).trunc(d);
p2 = a - (v.e-v.s).trunc(d);
return 2;
}
double areatriangle(Point a,Point b) {
if(sgn((p-a)^(p-b)) == 0)return 0.0;
Point q[5];
int len = 0;
q[len++] = a;
Line l(a,b);
Point p1,p2;
if(pointcrossline(l,q[1],q[2])==2) {
if(sgn((a-q[1])*(b-q[1]))<0)q[len++] = q[1];
if(sgn((a-q[2])*(b-q[2]))<0)q[len++] = q[2];
}
q[len++] = b;
if(len == 4 && sgn((q[0]-q[1])*(q[2]-q[1]))>0)swap(q[1],q[2]);
double res = 0;
for(int i = 0; i < len-1; i++) {
if(relation(q[i])==0||relation(q[i+1])==0) {
double arg = p.rad(q[i],q[i+1]);
res += r*r*arg/2.0;
}
else {
res += fabs((q[i]-p)^(q[i+1]-p))/2.0;
}
}
return res;
}
};
struct polypon {
int n;
Point p[N];
Line l[N];
double areacircle(Circle c) {
double ans = 0;
for(int i = 0; i < n; i++) {
int j = (i+1)%n;
if(sgn( (p[j]-c.p)^(p[i]-c.p) ) >= 0)
ans += c.areatriangle(p[i],p[j]);
else ans -= c.areatriangle(p[i],p[j]);
}
return fabs(ans);
}
};
polypon pp;
Circle c;
void work() {
scanf("%d",&pp.n);
scanf("%lf",&c.r);
c.p=Point(0,0);
for(int i=0; i<pp.n; i++) {
scanf("%lf%lf",&pp.p[i].x,&pp.p[i].y);
}
double ans=pp.areacircle(c);
printf("%.6f
",ans);
}