POJ 1584 A Round Peg in a Ground Hole 判断凸多边形,点到线段距离,点在多边形内
ACM博客_kuangbin
POJ 1584 A Round Peg in a Ground Hole(判斷凸多邊形,點到線段距離,點在多邊形內)
| A Round Peg in a Ground Hole
Description The DIY Furniture company specializes in assemble-it-yourself furniture kits. Typically, the pieces of wood are attached to one another using a wooden peg that fits into pre-cut holes in each piece to be attached. The pegs have a circular cross-section and so are intended to fit inside a round hole.? Input Input consists of a series of piece descriptions. Each piece description consists of the following data:? Output For each piece description, print a single line containing the string:? Sample Input 5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.0 1.0 3.0 0.0 2.0 5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.5 1.0 3.0 0.0 2.0 1Sample Output HOLE IS ILL-FORMED PEG WILL NOT FITSource Mid-Atlantic 2003 |
題意:
給出N個點,一個圓的半徑和圓心坐標:
分析:
首先是判斷給出了多邊形是不是凸多邊形。然后判斷圓包含在凸多邊形中。
一定要保證圓心在凸多邊形里面,然后判斷圓心到每條線段的距離要大于等于半徑。
#include <stdio.h> #include <math.h> #include <algorithm> #include <string.h> #include <math.h> using namespace std;const double eps = 1e-8; int sgn(double x) {if(fabs(x) < eps)return 0;if(x < 0)return -1;else return 1; } struct Point {double x,y;Point(){}Point(double _x,double _y){x = _x;y = _y;}Point operator -(const Point &b)const{return Point(x - b.x,y - b.y);}//叉積double operator ^(const Point &b)const{return x*b.y - y*b.x;}//點積double operator *(const Point &b)const{return x*b.x + y*b.y;}void input(){scanf("%lf%lf",&x,&y);} }; struct Line {Point s,e;Line(){}Line(Point _s,Point _e){s = _s;e = _e;}//兩直線相交求交點//第一個值為0表示直線重合,為1表示平行,為0表示相交,為2是相交//只有第一個值為2時,交點才有意義pair<int,Point> operator &(const Line &b)const{Point res = s;if(sgn((s-e)^(b.s-b.e)) == 0){if(sgn((s-b.e)^(b.s-b.e)) == 0)return make_pair(0,res);//重合else return make_pair(1,res);//平行}double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));res.x += (e.x-s.x)*t;res.y += (e.y-s.y)*t;return make_pair(2,res);} };//*判斷線段相交 bool inter(Line l1,Line l2) {returnmax(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; }//兩點距離 double dist(Point a,Point b) {return sqrt((a-b)*(a-b)); }//判斷凸多邊形,允許共線邊 //點的編號0~n-1,可以是順時針和逆時針 bool isConvex(Point poly[],int n){bool s[3];memset(s,false,sizeof s);for(int i=0;i<n;i++){s[sgn( (poly[(i+1)%n]-poly[i])^(poly[(i+2)%n]-poly[i]) )+1]=true;if(s[0]&&s[2]) return false;}return true; }//點到線段的距離,返回點到線段最近的點 Point NearestPointToLineSeg(Point p,Line L) {Point result;double t=((p-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));if(t>=0&&t<=1){result.x=L.s.x+(L.e.x-L.s.x)*t;result.y=L.s.y+(L.e.y-L.s.y)*t;}else{if(dist(p,L.s)<dist(p,L.e))result=L.s;elseresult=L.e;}return result; }//判斷點在線段上 bool OnSeg(Point P,Line L) {returnsgn((L.s-P)^(L.e-P)) == 0 &&sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0; }//*判斷點在凸多邊形內 //點形成一個凸包,而且按逆時針排序(如果是順時針把里面的<0改為>0) //點的編號:0~n-1 //返回值: //-1:點在凸多邊形外 //0:點在凸多邊形邊界上 //1:點在凸多邊形內 int inConvexPoly(Point a,Point p[],int n) {for(int i = 0;i < n;i++){if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0)return -1;else if(OnSeg(a,Line(p[i],p[(i+1)%n])))return 0;}return 1; }//*判斷點在任意多邊形內 //射線法,poly[]的頂點數要大于等于3,點的編號0~n-1 //返回值 //-1:點在凸多邊形外 //0:點在凸多邊形邊界上 //1:點在凸多邊形內 int inPoly(Point p,Point poly[],int n) {int cnt;Line ray,side;cnt = 0;ray.s = p;ray.e.y = p.y;ray.e.x = -100000000000.0;//-INF,注意取值防止越界for(int i = 0;i < n;i++){side.s = poly[i];side.e = poly[(i+1)%n];if(OnSeg(p,side))return 0;//如果平行軸則不考慮if(sgn(side.s.y - side.e.y) == 0)continue;if(OnSeg(side.s,ray)){if(sgn(side.s.y - side.e.y) > 0)cnt++;}else if(OnSeg(side.e,ray)){if(sgn(side.e.y - side.s.y) > 0)cnt++;}else if(inter(ray,side))cnt++;}if(cnt % 2 == 1)return 1;else return -1; }int n; Point o;//圓心 double R;//半徑 Point p[110]; int main() {while(scanf("%d",&n)!=EOF){if(n<3) break;scanf("%lf%lf%lf",&R,&o.x,&o.y);for(int i=0;i<n;i++)p[i].input();if(!isConvex(p,n)){//不是凸多邊形printf("HOLE IS ILL-FORMED\n");continue;}//圓心不在凸多邊形內if(inPoly(o,p,n)<0){printf("PEG WILL NOT FIT\n");continue;}bool flag=false;for(int i=0;i<n;i++){if(sgn(dist(o,NearestPointToLineSeg(o,Line(p[i],p[(i+1)%n]))) -R ) <0 ){flag=true;break;}}if(flag) printf("PEG WILL NOT FIT\n");else printf("PEG WILL FIT\n");}return 0; }?
總結
以上是生活随笔為你收集整理的POJ 1584 A Round Peg in a Ground Hole 判断凸多边形,点到线段距离,点在多边形内的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二维计算几何基础知识
- 下一篇: POJ3348 Cows【凸包+多边形求