判断一个点是否在多边形内部

本文介绍了一种判断点是否位于多边形内的算法。该算法通过检查从目标点出发的水平射线与多边形边界的交点数量来确定位置关系。如果交点数量为奇数,则点位于多边形内;反之则在外。文章还详细讨论了特殊情形的处理方法,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判断一个点P是否在多边形内部,有下面一个简单有效的算法:
注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。
所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。
还有一些特殊情况要考虑。
假如考虑边(P1,P2)
1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况
2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。
3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。
4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。

相关题目可以看下: http://acm.zju.edu.cn/show_problem.php?pid=1081

my code:
#include  < iostream >
using   namespace  std;
#define  eps 1.0e-5

inline 
double  max( double  a, double  b)  return a>b?a:b; }
inline 
double  min( double  a, double  b)  return a<b?a:b; }
inline 
double  dabs( double  a)  return a<0?-a:a; }
struct  Point  {
    
double x,y;
}
;

Point poly[
110 ];
int  n,m;

bool  online( const  Point &  p1, const  Point &  p2, const  Point &  p3)  {
    
if(p2.x>=min(p1.x,p3.x)&&p2.x<=max(p1.x,p3.x)
        
&&p2.y>=min(p1.y,p3.y)&&p2.y<=max(p1.y,p3.y)) {
        
if(dabs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))<=eps)
            
return true;
    }

    
return false;
}


bool  insidepolygon(Point p)  {
    
int counter=0;
    
double xinters;
    Point p1,p2;

    p1
=poly[0];
    
for(int i=1;i<=n;i++{
        p2
=poly[i%n];
        
if(online(p1,p,p2)) return true;
        
if(p.y>min(p1.y,p2.y)) {
            
if(p.y<=max(p1.y,p2.y)) {
                
if(p.x<=max(p1.x,p2.x)) {
                    
if(p1.y!=p2.y) {
                        xinters
=(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
                        
if(p1.x==p2.x||p.x<=xinters) counter++;
                    }

                }

            }

        }

        p1
=p2;
    }

    
if(counter%2==0)
        
return false;
    
return true;
}


int  main()  {
    
int t=0;
    Point p;
    
while(cin>>n) {
        
if(n==0break;
        
if(t++>0) cout<<endl;
        cout
<<"Problem "<<t<<":"<<endl;
        cin
>>m;
        
for(int i=0;i<n;i++)
            cin
>>poly[i].x>>poly[i].y;
        
for(int i=0;i<m;i++{
            cin
>>p.x>>p.y;
            
if(insidepolygon(p)) 
                cout
<<"Within"<<endl;
            
else
                cout
<<"Outside"<<endl;
        }

    }

    
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值