zju1081 判断点是否在简单多边型内(包括凹的情况)

题目:顺序输入一系列n个点,输入m个测试点,如果点在形内,那么输出Within,否则输出Outside;

算法:采用环顾法(汝亮书上的P381),用差积(测试点p和 多边形同向相邻两个顶点的差积 m),如果m> 0,就对求出来的夹角+,否则-(m==0,考虑p在线段上就跳出返回Within , 否则不在线段上,那么就忽略,继续) 最后 ,夹角和取绝对值 跟3.0比较,大于3.0,那么在里面,否则在外面。

//---以下是我的AC源码,之前wa了好久,原来就是忘了考虑输入的顺时针或逆时针,只要加上fabs()!
//就可以了,呵呵

#include < iostream.h >
#include
< math.h >
struct  Point
{
double x;
double y;
}
pt[ 1000 ]; // 依顺时针或逆时针存储简单多边形的点
int  n;
Point p;
double  MIN( double  a, double  b)
{
return a<b?a:b;
}

double  MAX( double  a, double  b)
{
return a>b?a:b;
}

double  mulpti(Point ps , Point pe , Point p)
{
double m;

m
=(pe.x-ps.x)*(p.y-ps.y)-(p.x-ps.x)*(pe.y-ps.y);

return m;
}

void  p_in_ploygon(Point p) // 要判断的点
{
int i;
double xa,ya,xb,yb;
double cos0;
double flag=0;//用于累加角度
bool tag=false;
double m;
for(i=n-1;i>=1;i--)
{
   
//差积判断点是否在线段
   m=mulpti(pt[i+1] , pt[i] , p);
   
if( m==0 )
   
{
    
if(p.x>=MIN(pt[i+1].x,pt[i].x) && p.x<=MAX(pt[i+1].x,pt[i].x) && p.y>=MIN(pt[i+1].y,pt[i].y) && p.y<=MAX(pt[i+1].y,pt[i].y) )
    
{
     tag
=true;
     
break;
    }

    
continue;
   }

   xa
=pt[i+1].x-p.x;
   ya
=pt[i+1].y-p.y;
   xb
=pt[i].x-p.x;
   yb
=pt[i].y-p.y;
   cos0
=(xa*xb + ya*yb)/(sqrt(xa*xa+ya*ya)* sqrt(xb*xb+yb*yb));
   
if( m > 0 )
   
{
    flag
+=acos(cos0);
   }

   
else
   
{
    flag
-=acos(cos0);
   }

}

if( fabs(flag)<3.0 && !tag) //注意求绝对值
{
   cout
<<"Outside"<<endl; 
}

else
{
   cout
<<"Within"<<endl;
}

}


void  s(Point p) // 当输入的多边形只有一个点
{
if(p.x == pt[1].x && p.y == pt[1].y )
   cout
<<"Within"<<endl;
else
   cout
<<"Outside"<<endl;
}

int  main()
{
int i,m;
int c=0;
while(cin>>n&&n!=0)
{
   cin
>>m;
   
for(i=1;i<=n;i++)
   
{
    cin
>>pt[i].x>>pt[i].y;
   }

   n
++;
   pt[n]
=pt[1];
   
if(c!=0)cout<<endl;
   cout
<<"Problem "<<++c<<":"<<endl;
   
for(i=1;i<=m;i++)
   
{
    cin
>>p.x>>p.y;
    
if(n==2)
    
{
     s(p);
    }

    
else
    
{
     p_in_ploygon(p);
    }

   }

}

return 0;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值