PSLG,直线切割凸多边形,和判断圆与多边形相交
来源:互联网 发布:mac系统能玩lol吗 编辑:程序博客网 时间:2024/05/16 23:38
分析:
除了圆盘之外,本题的输入也是一个PSLG,因此可以按照前面叙述的算法求出各个区域。但由于本题的特殊性,不难发现把线段改成直线后答案不变,因此每个块都是凸多边形,
可以用切割凸多边形的方法求解:每读入一条线段,都把它当做直线,切割所有块。这样,我们最终得到了若干凸多边形,需要分别判断是否与圆盘相交。
如何让判断多边形是否和圆盘相交?,显然,如果多边形的边和圆周规范相交,圆盘和多变性一定相交,但反过来却不成立——圆盘和多边形相交,多边形的边和圆周不一定规范相交。
(1)即使完全没有公共点的时候,圆盘和多边形也可以相交,原因是二者可以相互内含。因此,需要判断多边形是否有顶点在圆内,还需要判断圆心是否在多边形内。
(2)如果是非规范相交,需要分情况讨论。在图中,待判断的线段(用粗线表示)完全在圆外;在图中待判断的线段则是完全在内部。判断方法很简单,只需判断线段中点是否在圆内即可。
直接切割多边形~ 判断多边形和园盘是否有公共点(面积>0)
1 内含的情况--只要多边形poly[0] 在圆内、或者圆心在多边形内
2 相交的情况-如果不是规范相交,那么不是内含,却有非零公共面积只有一种情况,就是两个点都在圆上,只有判断中点在圆上即可。
每一个案例忘记输出空行 并不提示Presentation Error ,wa每次pieces更新的时候,newpieces 需要清零
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<cctype>#include<string>#include<set>#include<map>#include<queue>#include<stack>#include<vector>using namespace std;const double eps=1e-6;int dcmp(double x){ if(fabs(x)<eps) return 0; return x>0?1:-1; //return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);}struct point{ double x; double y; point(){} point(double x,double y):x(x),y(y){} void in() { cin>>x>>y; } void out() { cout<<x<<' '<<y<<endl; } point operator + (const point &t) const { return point(x+t.x,y+t.y); } point operator - (const point &t) const { return point(x-t.x,y-t.y); } point operator * (const double &t) const { return point(x*t,y*t); } point operator / (const double &t) const { return point(x/t,y/t); } bool operator < (const point &t) const { return (dcmp(x-t.x)<0||(dcmp(x-t.x)==0&&dcmp(y-t.y)<0)); } bool operator == (const point &t) const { return dcmp(x-t.x) ==0 &&dcmp(y-t.y)==0; }};double cross(point a,point b){ return a.x*b.y-a.y*b.x;}double dot(point a,point b){ return a.x*b.x+a.y*b.y;}double length(point a){ return sqrt(dot(a,a));}point nomal(point t){ double l=length(t); return point(-t.y/l,t.x/l);}struct line{ point p; point v; double ang; line() {} line(point p,point v):p(p),v(v){ ang=atan2(v.y,v.x); } bool operator < (const line &l) const { return ang<l.ang; } point ppoint(double t) { return point(p+v*t); }};struct Circle{ point c; double r; Circle(point c=point(0,0),double r=0):c(c),r(r) {} point ppoint(double a) { return point(c.x+r*cos(a),c.y+r*sin(a)); }};int getLineCircleIntersection(line l,Circle C,double &t1,double &t2,vector<point> &sol){ double a=l.v.x; double b=l.p.x-C.c.x; double c=l.v.y; double d=l.p.y-C.c.y; double e=a*a+c*c; double f=2*(a*b+c*d); double g=b*b+d*d-C.r*C.r; double delta=f*f-4*e*g; if(dcmp(delta)<0) return 0; if(dcmp(delta)==0) { t1=t2=-f/(2*e); sol.push_back(l.ppoint(t1)); return 1; } else { t1=(-f-sqrt(delta))/(2*e); t2=(-f+sqrt(delta))/(2*e); sol.push_back(l.ppoint(t1)); sol.push_back(l.ppoint(t2)); return 2; }}bool onleft(line l,point p){ return cross(l.v,p-l.p)>0;}point getintersection(line a,line b){ point u=a.p-b.p; double t=cross(b.v,u)/cross(a.v,b.v); return a.p+a.v*t;}bool sgementproperintersection(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 dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;}bool onsegment(point p,point a1,point a2){ return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0;}typedef vector<point> Polygon;double PolygonArea(Polygon poly){ double area=0; int n=poly.size(); for(int i=1;i<n-1;i++) { area+=cross(poly[i]-poly[0],poly[(i+1)%n]-poly[0]); } return area/2;}vector<Polygon> pieces,newpieces;Polygon CutPolygon(Polygon poly,point a,point b){ Polygon newPoly; int n=poly.size(); for(int i=0;i<n;i++) { point c=poly[i]; point d=poly[(i+1)%n]; if(dcmp(cross(b-a,c-a))>=0) newPoly.push_back(c); if(dcmp(cross(b-a,d-c))!=0) { point ip=getintersection(line(c,d-c),line(a,b-a)); if(onsegment(ip,c,d)) newPoly.push_back(ip); //此时必须用不含端点的“在线段上" } } return newPoly;}void cut(point a,point b){ newpieces.clear(); //仅仅是一个temp 记得清空 for(int i=0;i<pieces.size();i++) { Polygon poly=pieces[i]; Polygon left=CutPolygon(poly,a,b); Polygon right=CutPolygon(poly,b,a); if(left.size()>=3) newpieces.push_back(left); if(right.size()>=3) newpieces.push_back(right); } pieces=newpieces;}bool isPointInPolygon(point p,Polygon poly){ int wn=0; int n=poly.size(); for(int i=0;i<n;i++) { if(onsegment(p,poly[i],poly[(i+1)%n])) return -1; int k=dcmp(cross(poly[(i+1)%n]-poly[i],p-poly[i])); int d1=dcmp(poly[i].y-p.y); int d2=dcmp(poly[(i+1)%n].y-p.y); if(k>0&&d1<=0&&d2>0) wn++; if(k<0&&d2<=0&&d1>0) wn--; } if(wn!=0) return 1; else return 0;}double length2(point a){ return dot(a,a);}bool inCircle(Circle C,point p) //圆周不算{ if(dcmp(length2(p-C.c)-C.r*C.r)<0) return 1; else return 0;}bool CircleSegIntersection(Circle C,point a,point b) //线段端点不算{ double t1,t2; vector<point> sol; if(getLineCircleIntersection(line(a,b-a),C,t1,t2,sol)<=1) return 0; if(dcmp(t1)>0&&dcmp(t1-1)<0) return 1; if(dcmp(t2)>0&&dcmp(t2-1)<0) return 1; return 0;}bool CirclePolyIntersection(Circle C,Polygon poly){ if(isPointInPolygon(C.c,poly)) return 1; if(inCircle(C,poly[0])) return 1; point a,b; int n=poly.size(); for(int i=0;i<n;i++) { a=poly[i]; b=poly[(i+1)%n]; if(CircleSegIntersection(C,a,b)) return 1; if(inCircle(C,(a+b)/2)) return 1; } return 0;}void Query(Circle circle){ vector<double> ans; for(int i=0;i<pieces.size();i++) if(CirclePolyIntersection(circle,pieces[i])) { ans.push_back(fabs(PolygonArea(pieces[i]))); } sort(ans.begin(),ans.end()); cout<<ans.size(); for(int i=0;i<ans.size();i++) { printf(" %.2f",ans[i]); } cout<<endl;}int main(){ int n,m,l,w; Circle C; while(cin>>n>>m>>l>>w) { if(!n) break; pieces.clear(); Polygon bbox; bbox.push_back(point(0,0)); bbox.push_back(point(l,0)); bbox.push_back(point(l,w)); bbox.push_back(point(0,w)); pieces.push_back(bbox); point a,b; for(int i=0;i<n;i++) { a.in(); b.in(); cut(a,b); } for(int i=0;i<m;i++) { cin>>C.c.x>>C.c.y>>C.r; Query(C); } printf("\n"); } return 0;}
0 0
- PSLG,直线切割凸多边形,和判断圆与多边形相交
- Uva 12296 - Pieces and Discs 切割多边形 ,判断多边形和圆相交
- 切割凸多边形,圆与多边形(块和圆盘,UVA 12296)
- zju1010判断直线相交,求多边形面积
- poj1584 A Round Peg in a Ground Hole 凸多边形判断 和多边形与圆的位置
- 凸多边形和凹多边形的判断
- 判断直线与矩形相交
- POJ 1269 判断直线与直线相交
- 判断是否是凸多边形,判断点是否在多边形内,点到直线的距离
- uva 11177(凸多边形和圆的相交)
- hdu 5130(圆和凸多边形相交面积)
- POJ 3304 判断直线与线段相交
- POJ 3304 判断线段 与 直线 相交
- poj 3304 判断直线与线段相交
- POJ 3304 直线与线段相交判断
- BZOJ 1091([SCOI2003]切割多边形-切割直线)
- POJ 3304 判断线段和直线相交
- POJ 3449 判断多边形与多边形是否相交
- C#中运用正则表达式获取字符串
- C语言位运算
- 第三天
- 使用VB.NET开发多线程
- 【FZU】Problem 2056 最大正方形
- PSLG,直线切割凸多边形,和判断圆与多边形相交
- 并查集
- C# 对数组进行分组统计
- 黑马程序员_06. 抽像类与接口
- 一些项目——啤酒和饮料
- C语言要注意的几点
- 九度-wa-原因
- C语言中的回调
- grails webservice