判断三个数是否能构成三角形_几何|计算几何基础--判断点的位置

作者:henu_wxj

链接:https://blog.nowcoder.net/n/16a7f7a8cb4042278aacb509d205ce69

来源:牛客网

点的定位

点的定位属于几何查找,是计算几何中的一个重要的问题。其包括点在三角形内外,多边形内外判断,平面剖分中的位置等。

关于出现在这篇文章中但没有给出的自定义函数,如:

等,上篇博客有提到,向量叉乘。

判断点是否在线上:

我们可以用刚刚我们提到的叉积重要性质,即:两向量叉积为0,说明两向量在一条直线上。因此:

设点Q在线段

上。则:

1.

;(保证
在线段
上)

2.Q

在以
为对角顶点的矩形内。(保证
不在线段
的延长线上)。

d8dd9788bc11a4d468a1a7b3218bf1f3.png

(画出来大概是这样)

Code:

int OnLine(Point P1,Point P2,Point Q){
	if((Q.x-P1.x)*(P2.y-P1.y)==(P2.x-P1.x)*(Q.y-P1.y)){
		if(min(P1.x,P2.x)<=Q.x&&Q.x<=max(P1.x,P2.x)
		&&min(P1.y,P2.y)<=Q.y&&Q.y<=max(P1.x,P2.y)){
			return 1;
		}
	}return 0;
}

判断点在三角形的内外:

点在平面内与三角形三个顶点中任意两点构成三个三角形。可以通过计算这三个三角形的面积和与原三角形面积来比较判断点是否在三角形内。

,判断
是否在三角形内(包含在某条边上)。则:

,即可判定点
内。

。其中
为三角形三点所确定的两个向量。

Code:

int InTriangle(Triangle Tri,Point P){
	V AB,AC,PA,PB,PC;
	AB.start=Tri.A;AB.end=Tri.B;
	AC.start=Tri.A;AC.end=Tri.C;
	PA.start=P;PA.end=Tri.A;
	PB.start=P;PB.end=Tri.B;
	PC.start=P;PC.end=Tri.C;
	double Sabc=fabs(CroMul(AB,AC));
	double Spab=fabs(CroMul(PA,PB));
	double Spac=fabs(CroMul(PA,PC));
	double Spbc=fabs(CroMul(PB,PC));
	if(Spab+Spac+Spbc==Sabc) return 1;
	return 0;
}

判断点在多边形的内外:

点在几何图形内外的判断中,多边形的判断是通用情况,分三种方法:1.扫描法,2.叉积判别法,3.角度和判断法。

1.扫描法

设点

和多边形
,判断点
是否在多边形内。

877533d8b0b3440260f05fc93a18d96e.png

首先以

为端点,向任意方向作射线,由于多边形是有界的,所以射线一定会延伸到多边形外,若射线与多边形没有交点,则点在多边形外,若有1个交点,则在多边形内,若有两个交点,则在多边形外。

推论:当射线与多边形的交点数目是奇数时,

在多边形内;若交点个数为偶数时,
在多边形外。

d6817e14126f2ddffefaa95943710cce.png

我们用一个长的平行于

轴的线段来代替射线。

发现有一些情况要分类讨论,可以根据分类情况做出一些限制,例如:

1.多边形的水平边不做考虑。

2.对于与多边形顶点相交,如果该顶点是其所属边上纵坐标比较大的顶点,则计数,否则忽略。

3.对于

在多边形边上的情形,直接可判断
属于多边形。

Code:

int InPolygonScan(Point Q){//扫描法 
	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,P2,Q)) return 1;//在线上 
		if(Q.y>min(P1.y,P2.y)&&Q.y<=max(P1.y,P2.y)){//在线段内 
			if(Q.x<=max(P1.x,P2.x)){
				if(P1.y!=P2.y){
					xinters=(Q.y-P1.y)*(P2.x-P1.x)/(P2.y-P1.y)+P1.x;
					if(P1.x==P2.x||Q.x<=xinters) counter++;//符合要求 
				}
			}
		}P1=P2;
	}
	if(counter%2==0) return 0;
	return 1;
}
int main(){
	int t=0;Point Q;
	while(cin>>n){
		if(n==0) break;
		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>>Q.x>>Q.y;
			if(InPolygonScan(Q)) cout<<"Within"<<endl;
			else cout<<"Outside"<<endl;
		}
	}
}

2.叉乘判别法(只适用于凸多边形)

一个凸多边形,每条边都将整个平面划分成为左右两边。设这个多边形的边数为n,选一条边作为1号边,然后按照顺时针或者逆时针的顺序给每条边进行编号。

连接第i条边的第一个端点

和要测试的点
连接成一个向量
,连接
得向量
。做叉积。

除第一条边外,都与前一次运算得到的叉积做乘积。如果为正,继续判断,直到遍历所有的边。若全部满足,则证明点在多边形内,否则点在多变形外。

Code:

int InPolygonCroPro(Point Q){
//现在已经从选择一个点,逆时针||顺时针方向排好序了 
	int i;double pre,now;
	for(int i=0;i<n;++i){//逆时针||顺时针遍历所有的点 
		Point P1=Poly[i],P2=Poly[i+1];
		V v1=V(P1,Q),v2=V(P1,P2);
		now=CroMul(v1,v2);
		if(i>0){
			if(pre*now<0) return 0;
		}pre=now;
	}return 1;
}

3.角度和的判断法(适用于任意多边形,注意精度损失)

对于平面三角形来说,连接多边形内点与多边形所有顶点所形成的所有角的角度和在要求精度范围内应该=360°,如果大于||小于360°,则证明点不在多边形中。

Code:

int InPolygonAngle(Point Q){//角度判别法 
	double Angle=0;
	realPointList::interator iter1.begin();
	for(realPointList::interator iter2=(iter1+1);iter2<Points.end();++iter1,++iter2){
		double x1=(*iter1).x-Q.x,y1=(*iter1).y-Q.y;
		double x2=(*iter2).x-Q.x,y2=(*iter2).y-Q.y;
		Angle+=Angle2D(x1,x2,y1,y2);
	}
	if(fabs(Angle-span::PI2)<=0.01) return 1;
	return 0;
}

判断点是否在矩形||圆中。

矩形:只用判断

点的横坐标和纵坐标是否夹在矩形的左右边和上下边之间即可。

圆:只用判断圆心

的距离与半径之间的关系即可。

查看作者更多博客:https://blog.nowcoder.net/remil

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值