计算几何——判断点是否在多边形内

 汇总篇:计算几何汇总 


 

判断点P是否在多边形中是计算几何中一个非常基本但是十分重要的算法。以点P为端点,向左方作射线L,由于多边形是有界的,所以射线L的左端一定在多边形外,考虑沿着L从无穷远处开始自左向右移动,遇到和多边形的第一个交点的时候,进入到了多边形的内部,遇到第二个交点的时候,离开了多边形,……所以很容易看出当L和多边形的交点数目C是奇数的时候,P在多边形内,是偶数的话P在多边形外。

 但是有些特殊情况要加以考虑。如图下图(a)(b)(c)(d)所示。在图(a)中,L和多边形的顶点相交,这时候交点只能计算一个;在图(b)中,L和多边形顶点的交点不应被计算;在图(c)和(d) 中,L和多边形的一条边重合,这条边应该被忽略不计。如果L和多边形的一条边重合,这条边应该被忽略不计。

点在多边形中

原文链接:https://dev.gameres.com/Program/Abstract/Geometry.htm#%E5%88%A4%E6%96%AD%E7%82%B9%E6%98%AF%E5%90%A6%E5%9C%A8%E5%A4%9A%E8%BE%B9%E5%BD%A2%E4%B8%AD 

以下代码部分为原创:

class point{
 	public:
	double x;
	double y;
	point(double x_=0,double y_=0):x(x_),y(y_){} 
	friend const point operator+(const point& p1,const point& p2){
		return point(p1.x+p2.x,p1.y+p2.y);
	};
	friend const point operator-(const point& p1,const point& p2){
		return point(p1.x-p2.x,p1.y-p2.y);
	};
	friend const point operator*(const point& p,const double& m){
		return point(p.x*m,p.y*m);
	};
	friend const point operator*(const double& m,const point& p){
		return point(p.x*m,p.y*m);
	};
	friend const point operator/(const point& p,const double& m){
		return point(p.x/m,p.y/m);
	};
	friend ostream& operator <<(ostream& out,point& a){
		printf("(%lf,%lf)",a.x,a.y);
		return out;
	};
};
typedef point vect2;//重命名,向量也是用坐标表示 

class line{
	public:
	point start;
	point end; 
	line(point s=point(0,0),point e=point(0,0)):start(s),end(e){}
};

double cross(point O,point A,point B){//叉乘 
	double oa_x=A.x-O.x;
	double oa_y=A.y-O.y;
	double ob_x=B.x-O.x;
	double ob_y=B.y-O.y;
	return oa_x*ob_y-oa_y*ob_x;
}
bool p_is_in_l(point O,line L){
	point S=L.start;
	point E=L.end;
	if(cross(O,S,E)==0//在直线L上 
	and min(S.x,E.x)<=O.x&&O.x<=max(S.x,E.x)
	and min(S.y,E.y)<=O.y&&O.y<=max(S.y,E.y))
		return true;
	else return false; 
} 

bool p_is_in_poly(point O,point *P,int n){
	int count = 0;
	for(int i=0;i<n;i++){ 
		line S(P[i],P[(i+1)%n]);
		if(p_is_in_l(O,S))
			return true;
		if(S.start.y!=S.end.y){//s不水平 
			if(max(S.start.y,S.end.y)==O.y)
				count++;
			else if(min(S.start.x,S.end.x)<O.x)
				count++;
		}
	}
	if(count%2)return true;
	else return false;	
}

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值