1.点到直线的距离
如上图所示,点C为直线AB外一点,CD⊥AB,那么CD的模长就是点C到直线AB的距离。所以求点到直线得距离,就是求CD得长度。
作辅助线如上图所示,要求得线段CD得长度,需要知道点D得坐标,剩下求两点距离就变得简单了。
为求得点D得坐标。
**令A(xa,ya),B(xb,yb),C(xc,yc),D(xd,yd)**其中,A,B,C的坐标已知(如果不已知也没法求呀)。
dx = xb - xa;
dy = yb - ya;
设q = |AD|/|AB|,使得
xd = xa + q·dx;
yd = ya + q·dy;
令|AC| = m,|AD| = n,|CD|=o,
根据两点距离公式得出:
方程a: m2 = (xc - xa)2 + (yc - ya)2;
方程b: n2 = (xd - xa)2 + (yd - ya)2;
方程c: o2 = (xd - xc)2 + (yd - yc)2;
根据勾股定理得知,
m2=n2+o2;
将方程a,b,c代入上式,得:
(xc - xa)2 + (yc - ya)2 = (xd - xa)2+(yd - ya)o2 + (xd - xc)2+(yd - yc)2
展开化简得出:
方程d: -xa·xc - yc·ya = xd2 + xa2- xd·xa+ yd2 - yd·ya - xd·xc - yd·yc;
将xd = xa + q·dx;yd = ya + q·dy代入方程d,
求得: q = (dx(xc - xa) + dy(yc - ya))/(dx2 + dy2);
又 xd = xa + q·dx;yd = ya + q·dy;
所以:
xd = (dx(xc - xa) + dy(yc - ya))/(dx2+ dy2) * dx + xa;
yd = (dx(xc - xa) + dy(yc - ya))/(dx2 + dy2) * dy + ya;
这个求方程的过程可以自己导一下。
求得D得坐标,就可以根据两点间距离公式得到点到直线得距离。
TS代码实现如下:
/**
* 求C到直线AB得距离
* @param C 直线外一点
* @param A 直线上一点
* @param B 直线上一点
*/
static pointToLineDistance(C, A, B) {
let dx = B.x - A.x;
let dy = B.y - A.y;
let d = dx*dx + dy*dy;
let D;
if(d === 0){ // |AB| = 0,说明A与B共点
D = A;
}else{
let q = ((C.x - A.x) * dx + (C.y - A.y) * dy) / d; // 求出q得值
D = {x:A.x + q * dx, y:A.y + q * dy};// 得到D得坐标
}
dx = D.x - C.x;
dy = D.y - C.y;
return Math.sqrt(dx*dx + dy*dy);
}
2.点到线段的距离
这边拓展一下点到线段得距离,当C到AB得垂足D,不在A,B之间得时候,求出点C到线段AB两端点最近得距离。
分析上图
当D在AB的左侧时,C点距离A点更近,如绿色的CD所示;此时返回|AC|的长度;
当D在AB的右侧时,C点距离B点更近,如蓝色的CD所示;此时返回|BC|的长度;
那如何判断D在AB的左侧还是右侧呢?
因为B,C,D共线,如图中所示
当xd < xa && yd < ya时,D在AB的左侧;
当xd > xb && yd > yb时,D在AB的右侧;
(有人可能会问,你上面的图直线的斜率k是大于0的,如果小于0的话,这个就不成立了!)
借用上面的方程,设dx,dy均不等于0。
dx = xb - xa;
dy = yb - ya;
xd = xa + q·dx;
yd = ya + q·dy;
分析得到:
当xd < xa && yd < ya时,q < 0;
当xd < xa && yd < ya时,q > 1;(xb = xa + dx);
(这边如果直线斜率k < 0,那么dy一定是小于0的,负负得正,又刚好满足条件)
所以,求点到线段的长度代码实现如下
/**
* 求C到线段AB得距离
* @param C 线段外一点
* @param A 线段上一点
* @param B 线段上一点
*/
static pointToLineSegmentDistance(C, A, B) {
let dx = B.x - A.x;
let dy = B.y - A.y;
let d = dx*dx + dy*dy;
let D;
if(d === 0){ // |AB| = 0,说明A与B共点,D可以直接给A
D = A;
}else{
let q = ((C.x - A.x) * dx + (C.y - A.y) * dy) / d; // 求出q得值
if (q < 0) D = A; //垂足在AB左边
else if (q > 1) D = B; //垂足在AB右边
else D = {x:A.x + q * dx, y:A.y + q * dy}; // 得到D得坐标
}
dx = D.x - C.x;
dy = D.y - C.y;
return Math.sqrt(dx*dx + dy*dy);