POJ1584 A Round Peg in a Ground Hole 判断多边形是否为凸多边形,判断凸多边形是否在圆内
转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1309142308
大致题意:
按照顺时针或逆时针方向输入一个n边形的顶点坐标集,先判断这个n边形是否为凸包。
再给定一个圆形(圆心坐标和半径),判断这个圆是否完全在n变形内部。
解题思路:
题意已经很直白了。。就是那个思路。。。
注意输入完顶点集后,要封闭多边形,方便后面枚举边。
封闭方法:
定义点集数组Vectex[1~n]记录n个顶点,再令Vectex[0]=Vectex[n],Vectex[n+1]=Vectex[1]
1、判断凸包:
由于点集已经按某个时针方向有序,因此可以先定义一个方向系数direction=0
两两枚举n边形的边,用叉积判断这两条边的转向(右螺旋或左螺旋),由于存在散点共线的情况,因此当且仅当叉积的值temp第一次不为0时,direction=temp,direction的值此后不再改变。(direction>0 则为右螺旋逆时针,direction<0则为左螺旋顺时针)
此后继续枚举剩下的边,只要判断direction*temp>=0即可,当存在一个direction*temp<0的边,说明这是凹多边形,就不是凸包了。
2、判断圆心与多边形的关系:
用环顾法:
设圆心为P,逐条枚举n边形的边AB,利用 
计算PA和PB的夹角,最后求和得到的就是环顾角。
(1) 圆心在多边形内部时,环顾角=±360
(2) 圆心在多边形外部时,环顾角=0
(3) 圆心在多边形边上时(不包括顶点),环顾角=±180
(4) 圆心在多边形顶点时,环顾角为(0,360)之间的任意角,其实就是圆心所在的顶点的两条邻接边的夹角。
3、当圆心在圆内时,判断圆与多边形的关系
设圆心为P,逐条枚举n边形的边AB,利用
得到△PAB的面积,
再根据公式S=0.5*|AB|*h,可以得到
枚举所有h与圆的半径R比对,只要所有的边都有R-h>=0,则说明圆在多边形内
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; #define eps 10e-8 #define pi acos(-1.0) int n; struct point { double x, y; }; point p[4], peg; double r; double crossdet(double x1, double y1, double x2, double y2) { return x1 * y2 - x2 * y1; } double cross(point o, point a, point b) { return crossdet(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } double dotdet(double x1, double y1, double x2, double y2) { return x1 * x2 + y1 * y2; } double dot(point o, point a, point b) { return dotdet(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } int dblcmp(double x) { if( fabs(x) < eps) return 0; return x > 0 ? 1 : -1; } double ff(double x) { return x * x; } double dis(point a, point b) { return sqrt(ff(a.x - b.x) + ff(a.y - b.y)); } bool convexbag()//判断多边形是否凸包 { int dir = 0, tmp, i; for(i = 1; i <= n; i++) { tmp = dblcmp( cross(p[i], p[i+1], p[i+2]) ); if(!dir) dir = tmp; if(dir * tmp < 0)return 0; } return 1; } bool in()//判断圆心是否在多边形里 { double angle = 0; int i; for(i = 1; i <= n; i++) if( dblcmp( cross(peg, p[i], p[i+1]) ) >= 0) angle += acos( dot(peg, p[i], p[i+1])/dis(peg, p[i])/dis(peg, p[i+1]) ); else angle -= acos( dot(peg, p[i], p[i+1])/dis(peg, p[i])/dis(peg, p[i+1]) ); if( dblcmp(angle + 2 * pi) == 0 || dblcmp(angle - 2 * pi) == 0)return 1; return 0; } bool fit()//判断圆是不是在凸多边形中 { int i, k; for(i = 1; i <= n; i++) { k = dblcmp( fabs( cross(peg, p[i], p[i+1])/dis(p[i], p[i+1]) ) - r ); if(k < 0)return 0; } return 1; } int main() { int i, j; while( ~scanf("%d", &n) ) { if(n < 3)break; scanf("%lf%lf%lf", &r, &peg.x, &peg.y); for(i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y); p[n + 1].x = p[1].x; p[n + 1].y = p[1].y; p[n + 2].x = p[2].x; p[n + 2].y = p[2].y; if(!convexbag()){ printf("HOLE IS ILL-FORMED\n"); continue;} if( fit() && in() ) printf("PEG WILL FIT\n"); else printf("PEG WILL NOT FIT\n"); } return 0; }


浙公网安备 33010602011771号