标签:
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; const int MAXN = 1e3+7; const double EPS = 1e-8; const double oo = 1e10+7; struct Point { double x, y; Point(double x=0, double y=0):x(x),y(y){} Point operator - (const Point &tmp)const{ return Point(x-tmp.x, y-tmp.y); } double operator ^(const Point &tmp)const{ return x*tmp.y - y*tmp.x; } double operator *(const Point &tmp)const{ return x*tmp.x + y*tmp.y; } }; double Dist(Point a, Point b) {///两点间的距离 return sqrt((a-b)*(a-b)); } int Sign(double t) { if(t > EPS)return 1; if(fabs(t) < EPS)return 0; return -1;///负数 } struct Segment { Point S, E; Segment(Point S=0, Point E=0):S(S), E(E){} bool OnSeg(const Point &p) {///点是否在线段上 if(Sign( (S-E)^(p-E) ) == 0)///共线 if(Sign( (p.x-S.x)*(p.x-E.x) ) <= 0)///位于线段的中间或者端点 if(Sign( (p.y-S.y)*(p.y-E.y) ) <= 0) return true; return false; } bool Inter(const Segment &tmp) {///只考虑完全相交的情况 return Sign((S-E)^(tmp.S-E)) * Sign((S-E)^(tmp.E-E)) == -1; } Point NearPoint(const Point &p) {///点到线段最近的点 Point res; double r = ((E-S)*(p-S)) / ((E-S)*(E-S)); if(r > EPS && (1.0 - r) > EPS ) {///点在线段的投影在线段上 res.x = S.x + r * (E.x-S.x); res.y = S.y + r * (E.y-S.y); } else {///求离最近的端点 if(Dist(p, S) < Dist(p, E)) res = S; else res = E; } return res; } }; struct Poly { int N; Point vertex[MAXN]; bool IsConvex() {///判断是否是凸多边形,可以共线 int vis[3] = {0}; for(int i=0; i<N; i++) {///如果同时出现整数和负数,说明存在凹的 int k = Sign((vertex[(i+1)%N]-vertex[i])^(vertex[(i+2)%N]-vertex[i])); vis[k+1] = 1; if(vis[0] && vis[2]) return false; } return true; } int InPoly(const Point &Q) {///判断点Q是否在多边形内,射线法,奇数在内,偶数在外 ///在圆上返回0, 圆外-1, 圆内 1 Segment ray(Point(-oo, Q.y), Q);///构造射线的最远处 int cnt=0;///统计相交的边数 for(int i=0; i<N; i++) { Segment edge(vertex[i], vertex[(i+1)%N]); if(edge.OnSeg(Q) == true) return 0;///点在边上 if(ray.OnSeg(vertex[i]) == true) {///如果相交连接点,那么取y值小的点 if(vertex[(i+1)%N].y - vertex[i].y > EPS) cnt++; } else if(ray.OnSeg(vertex[(i+1)%N]) == true) { if(vertex[i].y - vertex[(i+1)%N].y > EPS) cnt++; } else if(ray.Inter(edge) && edge.Inter(ray)) cnt++; } if(cnt % 2) return 1; else return -1; } }; struct Circle { Point center;///圆心 double R;///半径 }; bool Find(Poly &a, Circle &c) {///判断圆是否在多边形内 if(a.InPoly(c.center) == -1) return false;///如果圆心在多边形外面 for(int i=0; i<a.N; i++) { Segment edge(a.vertex[i], a.vertex[(i+1)%a.N]); double len = Dist(c.center, edge.NearPoint(c.center)); if(Sign(len-c.R) < 0) return false; } return true; } int main() { Poly a;///定义多边形 Circle c;///定义圆 while(scanf("%d", &a.N) != EOF && a.N > 2) { scanf("%lf%lf%lf", &c.R, &c.center.x, &c.center.y); for(int i=0; i<a.N; i++) scanf("%lf%lf", &a.vertex[i].x, &a.vertex[i].y); if(a.IsConvex() == false) printf("HOLE IS ILL-FORMED\n"); else if(Find(a, c) == false) printf("PEG WILL NOT FIT\n"); else printf("PEG WILL FIT\n"); } return 0; }
A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&判断点在多边形内&判断圆在多边形内)
标签:
原文地址:http://www.cnblogs.com/liuxin13/p/4799667.html