POJ-1584-A Round Peg in a Ground Hole-计算几何-凸多边形+多边形包含圆

http://poj.org/problem?id=1584

题意:顺时针或逆时针的点,让你先判断多边形是否为凸多边形,如果不是输出HOLE IS ILL-FORMED

如果是,判断能不能把一个给定大小和位置的圆完全包含

if (ok)
printf("PEG WILL FIT\n");
else
printf("PEG WILL NOT FIT\n");



1先把点都变成逆时针,

然后判凸,

然后判圆心是否在多边形内,是的话再看是否被包含


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std; 
const double pi=acos(-1.0);
double eps=1e-5;   
double tm[5][35];
double max(double a,double b)
{return a>b?a:b;}
double min(double a,double b)
{return a<b?a:b;}
struct POINT 
{ 
 double x; 
 double y; 
 POINT(double a=0, double b=0) { x=a; y=b;} //constructor 
}; 
struct LINESEG 
{ 
 POINT s; 
 POINT e; 
 LINESEG(POINT a, POINT b) { s=a; e=b;} 
 LINESEG() { } 
}; 
struct LINE           // 直线的解析方程 a*x+b*y+c=0  为统一表示,约定 a >= 0 
{ 
   double a; 
   double b; 
   double c; 
   LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;} 
}; 
double multiply(POINT sp,POINT ep,POINT op) 
{ 
 return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); 
} 
double area_of_polygon(int vcount,POINT polygon[]) 
{ 
 int i; 
 double s; 
 if (vcount<3) 
  return 0; 
 s=polygon[0].y*(polygon[vcount-1].x-polygon[1].x); 
 for (i=1;i<vcount;i++) 
  s+=polygon[i].y*(polygon[(i-1)].x-polygon[(i+1)%vcount].x); 
 return s/2; 
} 
// 如果输入顶点按逆时针排列,返回true 
bool isconterclock(int vcount,POINT polygon[]) 
{ 
 return area_of_polygon(vcount,polygon)>0; 
} 
void checkconvex(int vcount,POINT polygon[],bool bc[]) 
{ 
 int i,index=0; 
 POINT tp=polygon[0]; 
 for(i=1;i<vcount;i++) // 寻找第一个凸顶点 
 { 
  if(polygon[i].y<tp.y||(fabs(polygon[i].y- tp.y)<eps&&polygon[i].x<tp.x)) 
  { 
   tp=polygon[i]; 
   index=i; 
  } 
 } 
 int count=vcount-1; 
 bc[index]=1; 
 while(count) // 判断凸凹性 
 { 
  if(multiply(polygon[(index+1)%vcount],polygon[(index+2)%vcount],polygon[index%vcount])>=0 ) 
   bc[(index+1)%vcount]=1; 
  else 
   bc[(index+1)%vcount]=0; 
  index++; 
  count--; 
 } 
}
bool isconvex(int vcount,POINT polygon[]) 
{ 
 bool bc[1005]; 
 checkconvex(vcount,polygon,bc); 
 for(int i=0;i<vcount;i++) // 逐一检查顶点,是否全部是凸顶点 
  if(!bc[i]) 
   return false; 
 return true; 
} 
/* 求点p到线段l的最短距离,并返回线段上距该点最近的点np 
注意:np是线段l上到点p最近的点,不一定是垂足 */
double dist(POINT p1,POINT p2)                // 返回两点之间欧氏距离 
{ 
 return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) ); 
}  
double dotmultiply(POINT p1,POINT p2,POINT p0) 
{ 
 return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y)); 
} 
double relation(POINT p,LINESEG l) 
{ 
 LINESEG tl; 
 tl.s=l.s; 
 tl.e=p; 
 return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e)); 
} 
// 求点C到线段AB所在直线的垂足 P 
POINT perpendicular(POINT p,LINESEG l) 
{ 
 double r=relation(p,l); 
 POINT tp; 
 tp.x=l.s.x+r*(l.e.x-l.s.x); 
 tp.y=l.s.y+r*(l.e.y-l.s.y); 
 return tp; 
} 
double ptolinesegdist(POINT p,LINESEG l,POINT &np) 
{ 
 double r=relation(p,l); 
 if(r<0) 
 { 
  np=l.s; 
  return dist(p,l.s); 
 } 
 if(r>1) 
 { 
  np=l.e; 
  return dist(p,l.e); 
 } 
 np=perpendicular(p,l); 
 return dist(p,np); 
} 
/* 计算点到折线集的最近距离,并返回最近点. 
注意:调用的是ptolineseg()函数 */ 
double ptopointset(int vcount,POINT pointset[],POINT p,POINT &q) 
{ 
 int i; 
 double cd=double(2147483647),td; 
 LINESEG l; 
 POINT tq,cq; 

 for(i=0;i<vcount-1;i++) 
 { 
  l.s=pointset[i]; 

  l.e=pointset[i+1]; 
  td=ptolinesegdist(p,l,tq); 
  if(td<cd) 
  { 
   cd=td; 
   cq=tq; 
  } 
 } 
 q=cq; 
 return cd; 
} 
/* 判断圆是否在多边形内.ptolineseg()函数的应用2 */ 
bool CircleInsidePolygon(int vcount,POINT center,double radius,POINT polygon[]) 
{ 
 POINT q; 
 double d; 
 q.x=0; 
 q.y=0; 
 d=ptopointset(vcount,polygon,center,q); 
 if(d<radius||fabs(d-radius)<eps) 
  return false; 
 else 
  return true; 
} bool online(LINESEG l,POINT p) 
{ 
 return( fabs(multiply(l.e,p,l.s))<eps &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )

&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) ); 
} 
bool intersect(LINESEG u,LINESEG v) 
{ 
 return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&&                     //排斥实验 
   (max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&& 
   (max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&& 
   (max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&& 
   (multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=0)&&         //跨立实验 
   (multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0)); 
} 
//  (线段u和v相交)&&(交点不是双方的端点) 时返回true    
bool intersect_A(LINESEG u,LINESEG v) 
{ 
 return ((intersect(u,v))&& 
   (!online(u,v.s))&& 
   (!online(u,v.e))&& 
   (!online(v,u.e))&& 
   (!online(v,u.s))); 
} 
int insidepolygon(int vcount,POINT Polygon[],POINT q) 
{ 
 int c=0,i,n; 
 LINESEG l1,l2; 
 bool bintersect_a,bonline1,bonline2,bonline3; 
 double r1,r2; 

 l1.s=q; 
 l1.e=q; 
 l1.e.x=double(2147483647); 
 n=vcount; 
 for (i=0;i<vcount;i++) 
 { 
  l2.s=Polygon[i]; 
  l2.e=Polygon[(i+1)%n]; 
  if(online(l2,q))
   return 1; // 如果点在边上,返回1 
  if ( (bintersect_a=intersect_A(l1,l2))|| // 相交且不在端点 
  ( (bonline1=online(l1,Polygon[(i+1)%n]))&& // 第二个端点在射线上 
  ( (!(bonline2=online(l1,Polygon[(i+2)%n])))&& /* 前一个端点和后一个端点在射线两侧 */ 
  ((r1=multiply(Polygon[i],Polygon[(i+1)%n],l1.s)*multiply(Polygon[(i+1)%n],Polygon[(i+2)%n],l1.s))>0) ||    
  (bonline3=online(l1,Polygon[(i+2)%n]))&&     /* 下一条边是水平线,前一个端点和后一个端点在射线两侧  */ 
   ((r2=multiply(Polygon[i],Polygon[(i+2)%n],l1.s)*multiply(Polygon[(i+2)%n], 
  Polygon[(i+3)%n],l1.s))>0) 
    ) 
   ) 
  ) c++; 
 } 
 if(c%2 == 1) 
  return 0; 
 else 
  return 2; 
} 
POINT p[1005];
int main()
{
	int i,j,k;  
	int n;
	double r,x,y;
	while(cin>>n>>r>>x>>y)
	{ 
		if (n<3) break;
		double xx,yy;
		for (i=0;i<n;i++)
		{
			scanf("%lf%lf",&xx,&yy);
			p[i].x=xx;
			p[i].y=yy;
		}
		if (isconterclock(n,p)==false)		//先把点集变成逆时针
		{
			POINT TMP;
			for (i=0;i<n/2;i++)
			{
				TMP=p[i];
				p[i]=p[n-i-1];
				p[n-i-1]=TMP;
			}
		}
		bool flag=isconvex(n,p);		//判断是否多边形
		if (flag)
		{	
			POINT q(x,y);
			bool ok=CircleInsidePolygon(n,q,r,p);		//判断圆是否被包含,这里的判断方法是圆心到各边的距离中的最小值是否大于等于半径
			if (insidepolygon(n,p,q)!=0)				//所以需要先判断圆心是否被包含
				printf("PEG WILL NOT FIT\n");
			else
			{
				if (ok)
				printf("PEG WILL FIT\n");
			else
				printf("PEG WILL NOT FIT\n");
			}

		}
		else
			printf("HOLE IS ILL-FORMED\n");


	}

	
	
	return 0;
	
}


你可能感兴趣的:(POJ-1584-A Round Peg in a Ground Hole-计算几何-凸多边形+多边形包含圆)