看到这个题目,估计很多人都会说,这么简单的问题,还写个日志。呵呵
当然,大多人的想法自然是用数学公式来计算了,我也是,而且是用的最笨的方法,看吧:
一条直线段由两个点确定,假设他们叫a和c,一个点b在这个线段上的条件是,b到a的距离和b到c的距离之和等于a到c的距离。以下假设在二维平面下。
b到a的距离 d1=sqrt((b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y))
d到c的距离 d2=sqrt((c.x-b.x)*(c.x-b.x) + (c.y-b.y)*(c.y-b.y))
a到c的距离 d=sqrt((c.x-a.x)*(c.x-a.c) + (c.y-a.y)*(c.y-a.y))
只要 d=d1+d2 就表示点b在a-c线段上;计算机判断嘛,这样肯定不行,大家都知道要判断容差,即:
fabs(d-d1-d2) < epsilon
很多人都是这样就完成了判断,包括我。显然,计算效率非常低下。
今天看一段代码,里面有个函数也是判断点在直线段上的,但是他的写法很简单,经过推敲,原来如此。
So easy! So quickly!
感谢PolyBoolean的作者Michael Leonov。
下面我就来推导一下简单的方法:
还是上面的式子,只不过再进一步简化而已。呵呵
令 d1=b.x-a.x
d2=b.y-a.y
d3=c.x-b.x
d4=c.y-b.y
判断条件就可以写为:
sqrt(d1*d1+d2*d2) + sqrt(d3*d3+d4*d4) = sqrt((d1+d3)*(d1+d3) + (d2+d4)*(d2+d4))
两边平方:
d1*d1 + d2*d2 + d3*d3 + d4*d4 + 2sqrt((d1*d1+d2*d2)*(d3*d3+d4*d4))
= (d1+d3)*(d1+d3) + (d2+d4)*(d2+d4)
= d1*d1 + d3*d3 + 2d1*d3 + d2*d2 + d4*d4 + 2d2*d4
==> sqrt((d1*d1+d2*d2)*(d3*d3+d4*d4)) = d1*d3 + d2*d4
两边再平方并展开:
d1*d1*d3*d3 + d2*d2*d4*d4 + d1*d1*d4*d4 + d2*d2*d3*d3
------------ ===========
= d1*d3*d1*d3 + d2*d4*d2*d4 + 2d1*d2*d3*d4
----------- ===========
==> d1*d1*d4*d4 + d2*d2*d3*d3 = 2d1*d2*d3*d4
==> (d1*d4 - d2*d3)^2 = 0
==> d1*d4 - d2*d3 = 0
到这里,问题得到了简化。不是么?
所以判断条件变成:
fabs(d1*d4 - d2*d3) < epsilon
即:
fabs((b.x-a.x)*(c.y-b.y) - (b.y-a.y)*(c.x-b.x)) < epsilon
运算量大幅减少,最重要的是不用开平方了,你懂得。