判断点在线段的左边还是右边 判断线段是否相交

在recast中遇到的一个操作,判断点是在线段的左边还是右边
判断在左边和右边在很多场景都有用到,是计算机几何中比较基础的概念。比如判断是凹多边形还是凸多边形;判断点是凹点还是凸点;判断线段是否相交;判断两点是否在线段两侧等等。


https://blog.csdn.net/qiushangren/article/details/90446381
这篇博客所说,顺时针方向 三点组成的向量的叉积z值为负,逆时针方向三点组成的向量的叉积z值为正。这个可以反过来用于求点在线段的左右。
首先左右不能用客观的视角来定,应该从向量的角度去判断。所以先将线段转换成向量,需要注意的是向量是有方向的有起止的。

如上,在xy平面上有线段AB(注意A为起点,B为终点)组成向量AB,存在点C1和C2,组成三角形ABC2和三角形ABC1。很明显ABC2组成一个顺时针方向的三个点,ABC1 组成了逆时针方向的三个点(注意这里的三角形必须包含了 向量AB)。
根据上面链接的博客可以很轻松的看出,

ABxAC2>0 而 ABxAC1<0 (叉乘,不是点乘),(注意都是以A为起点,也就是以已知向量的起点为起点)。

如果线段AB组成向量为BA,则
BAxBC2<0 而 BAxBC1 >0(注意这里都是以B为起点,以已知向量的起点为起点)。

总结:如果以AB的方向来判定,那么C1就是在AB的右边,C2就是在AB的左边,假设三角形顶点顺序为ABC ,可以看到如果用ABC1组装三角形,那么就是顺时针的,如果ABC2组装三角形,那就是逆时针的;如果以BA来判定,那C2在BA右边,C1在BA的左边,假设三角形顶点顺序为BAC,BAC1为逆时针,BAC2位顺时针。可以推断如果在左边,那么顺序就是逆时针;如果在右边,那么顺序就是顺时针。反过来也一样,顺时针表示在右边,逆时针表示在左边。ABxAC(注意A为起始点),使用右手定则,顺时针为求出的结果(z)为负数,逆时针为求出的结果(z)正数。

//判断线段是否相交
static int overlapSegSeg2d(const float* a, const float* b, const float* c, const float* d)
{
	const float a1 = vcross2(a, b, d); 
	const float a2 = vcross2(a, b, c);
	if (a1*a2 < 0.0f) 
	{ //相乘结果为负,说明一左一右。 说明c和d分别分布在ab的两侧。c和d没有分布在两侧,肯定是不相交。
		float a3 = vcross2(c, d, a);
		float a4 = a3 + a2 - a1; //a4 = vcross2(c,d,b)。可以用四个点坐标计算一下,确实相等。
		if (a3 * a4 < 0.0f)
			return 1;//如果a和b也分布在cd两侧就说明相交
	}
	return 0;
}

//假设a(x1,y1) b(x2,y2) c(x3,y3) d(x4,y4)
//b-a = (x2-x1),(y2-y1) ,d-a=(x4-x1),(y4-y1) => 
//a1 = (b-a)x(d-a) = (x2-x1)*(y4-y1)-(x4-x1)*(y2-y1)
//a2 = (b-a)x(c-a) = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)
//a3 = (d-c)x(a-c) = (x4-x3)*(y1-y3)-(x1-x3)*(y4-y3)
//a4 = a3+a2-a1 =a3 +  (x2-x1)*(y3-y4)-(x3-x4)*(y2-y1)
// =a3 + (x4-x3)*(y2-y1)-(x2-x1)*(y4-y3) = (x4-x3)*(y2-y3)-(x2-x3)*(y4-y3) 

判断点是凹点还是凸点:取目标点和目标点相邻的两个点,按逆时针方向,将目标点与前面的点相连成线段,判断目标点后面的点是否在线段的左边还是右边,如果在左边,则说明是凸点,否则是凹点。

判断是凹多边形还是凸多边形:按逆时针方向判断所有 边的下一个点(逆时针方向与边相邻的点) 是否都在边的左边,如果都在左边说面是凸多边形。也可以按顺时针方向来,判断是否在右边。

判断两点是否在线段两侧:直接判断一个点在左边一个点在右边。

判断线段是否相交:假设两条线段a,b。先计算两线段的bound是否相交做个快速排除,再判断线段a的两个顶点是否都在线段b的两侧,再判断线段b的两个顶点是否在线段a的两侧,如果两个条件都满足,则a b相交,否则不相交。(求交点

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值