计算几何基础,点、线、面位置关系,模板



😎直线相交:
int lineInter(Line l1,Line l2){//两个直线是否相交 
	if(sgn((l1.s-l1.e)^(l2.s-l2.e))==0){//两直线方向平行
			if(sgn((l1.s-l2.e)^(l1.s-l1.e))==0) return 1; //l2的s点在直线l1上,两直线重合 
			else return 0; //两直线平行 
	}else return 2
}//平行为0,重合为1,相交为2

😎两个线段是否相交:1.x,y轴上两线段投影有重合
2.l2两个端点在l1两侧&&l1两个端点在l2两侧
bool segInter(Seg l1,Seg l2){//两个线段是否相交 
	return
	max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x) &&//x轴上l1的最大的大于l2最小的 
	max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x) &&//x轴上l2最大的大于 l1最小的 //x轴上投影l1和l2有重合 
	max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y) &&//y轴 
	max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y) &&
	sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0 &&//l2两个端点在直线l1的两侧 图1
	sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e))<=0;//图2
}

图1:
图2:

😎直线与线段相交
int lineInterSeg(Line l1,Seg l2){//直线与线段相交 
	if(sgn((l1.s-l1.e)^(l2.s-l2.e))==0){//两直线方向平行
			if(sgn((l1.s-l2.e)^(l1.s-l1.e))==0) return 1; //l1的s点在直线l2上,两直线重合 
			else return 0; //直线与线段平行 ,不相交 
	}else{
		if(sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0) return 2;//l2两个端点在直线l1的两侧 ,若严格相交去= 
		else return 0;//否则不相交,线段在直线的一侧 
	} 
	 
}//不相交为0,重合为1,相交为2

😎两直线(线段)的交点,必须事先确定两线相交
Point cross(Line a,Line b){//必须确定两个直线是相交的,或者线段 ,本函数不判断相交性 
	Point res=a.s;
	double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
	res.x+=(e.x-s.x)*t;
	res.y+=(e.y-s.y)*t;
	return res;
}



点是否在线段上
bool OnSeg(Point P,Line L){//点p是否在线l上 
	return
	sgn((L.s-P)^(L.e-P))==0 &&//叉积为0 ,代表的面积为0 
	sgn((P.x-L.s.x)*(P.x-L.e.x))<=0 &&//p的x比一个端点x大,比另一个端点小 
	sgn((P.y-L.s.y)*(P.y-L.e.y))<=0; //P点的x与y应当介于s和e的x与y之间,因为它是线段不是直线 
}
点是否在凸多边形内
//点是否在凸多边形内
//凸n多边形的点按逆时针给出, 
int inConvexPoly(Point a,Point p[],int n){
	for(int i=0;i<n;i++){
		if(sgn((p[i]-a)^(p[(i+1)%n]-a))<0) return -1; //<0,前向量顺时针到后向量,由于点按逆时针给,所以在凸多边形外 
		else if(OnSeg(a,Line(p[i],p[(i+1)%n]))) return 0; //在凸多边形边界上 
	}
	return 1; //在凸多边形内 
}

点是否在多边形内(任意的):
int inPoly(Point p,Point poly[],int n){//测试点,n边形的点集,n边形 
	int cnt;
	Line ray,side;//ray射线 
	cnt=0; ray.s=p;
	ray.e.y=p.y; 
	ray.e.x=-100000000000.0; //构造一条一点p为起始点的射线 ,射线方向为x负方向 
	for(int i=0;i<n;i++){ //枚举边 
		side.s=poly[i];
		side.e=poly[(i+1)%n];
		if(OnSeg(p,side)) return 0; //在边界上 
		//如果平行轴则不用考虑 
		if(sgn(side.s.y-side.e.y)==0) continue;//测试点在边的端点上 
		if(OnSeg(side.s,ray)){//射线穿过边的逆时针先端点 
			if(sgn(side.s.y-side.e.y)>0) cnt++;//边的先端点在后端点上不相同,即边不与射线平行,因为每次出现这样情况只记入一次,所以>0而不是!=0 
		}
		else if(OnSeg(side.e,ray)){//射线穿过边逆时针的后端点 
			if(sgn(side.e.y-side.s.y)>0) cnt++;//边的后端点在先端点的上 
		}
		else if(inter(ray,side)) cnt++;
	}
	if(cnt%2==1) return 1; //在多边形内 
	return -1; //在多边形外 
}

全部评论

相关推荐

09-27 10:54
重庆大学 C++
人已微死:致敬传奇耐测王。
投递小米集团等公司10个岗位
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务