JS:求点与线段的最短距离,并返回该最短距离在线段上的坐标。

直接上代码:

function PointToLineDistance (xx, yy, x1, y1, x2, y2) {

let ang1, ang2, ang, m;

let result = 0;

// 分别计算三条边的长度

const a = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));

if (a === 0) {

return [0, { x: x1,

y: y1 }];

}

const b = Math.sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy));

if (b === 0) {

return [0, { x: x2,

y: y2 }];

}

const c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

// 如果线段是一个点则退出函数并返回距离

if (c === 0) {

result = a;

return [result, { x: x1,

y: y1 }];

}

// 如果点(xx,yy到点x1,y1)这条边短

if (a < b) {

// 如果直线段AB是水平线。得到直线段AB的弧度

if (y1 === y2) {

if (x1 < x2) {

ang1 = 0;

} else {

ang1 = Math.PI;

}

} else {

m = (x2 - x1) / c;

if (m - 1 > 0.00001) {

m = 1;

}

ang1 = Math.acos(m);

if (y1 > y2) {

ang1 = Math.PI * 2 - ang1;

}// 直线(x1,y1)-(x2,y2)与折X轴正向夹角的弧度

}

m = (xx - x1) / a;

if (m - 1 > 0.00001) {

m = 1;

}

ang2 = Math.acos(m);

if (y1 > yy) {

ang2 = Math.PI * 2 - ang2;

}// 直线(x1,y1)-(xx,yy)与折X轴正向夹角的弧度

ang = ang2 - ang1;

if (ang < 0) {

ang = -ang;

}

if (ang > Math.PI) {

ang = Math.PI * 2 - ang;

}

// 如果是钝角则直接返回距离

if (ang > Math.PI / 2) {

return [a, { x: x1,

y: y1 }];

}

// 返回距离并且求得当前距离所在线段的坐标

if (x1 === x2) {

return [b * Math.sin(ang), { x: x1,

y: yy }];

} else if (y1 === y2) {

return [b * Math.sin(ang), { x: xx,

y: y1 }];

}

// 直线的斜率存在且不为0的情况下

let x = 0,

y = 0;

const k1 = ((y2 - y1) / x2 - x1);

const kk = -1 / k1;

const bb = yy - xx * kk;

const b1 = y2 - x2 * k1;

x = (b1 - bb) / (kk - k1);

y = kk * x + bb;

return [a * Math.sin(ang), { x,

y }];

}

// 如果两个点的纵坐标相同,则直接得到直线斜率的弧度

if (y1 === y2) {

if (x1 < x2) {

ang1 = Math.PI;

} else {

ang1 = 0;

}

} else {

m = (x1 - x2) / c;

if (m - 1 > 0.00001) {

m = 1;

}

ang1 = Math.acos(m);

if (y2 > y1) {

ang1 = Math.PI * 2 - ang1;

}

}

m = (xx - x2) / b;

if (m - 1 > 0.00001) {

m = 1;

}

ang2 = Math.acos(m);// 直线(x2-x1)-(xx,yy)斜率的弧度

if (y2 > yy) {

ang2 = Math.PI * 2 - ang2;

}

ang = ang2 - ang1;

if (ang < 0) {

ang = -ang;

}

if (ang > Math.PI) {

ang = Math.PI * 2 - ang;

}// 交角的大小

// 如果是对角则直接返回距离

if (ang > Math.PI / 2) {

return [b, { x: x2,

y: y2 }];

}

// 如果是锐角,返回计算得到的距离,并计算出相应的坐标

if (x1 === x2) {

return [b * Math.sin(ang), { x: x1,

y: yy }];

} else if (y1 === y2) {

return [b * Math.sin(ang), { x: xx,

y: y1 }];

}

// 直线的斜率存在且不为0的情况下

let x = 0,

y = 0;

const k1 = ((y2 - y1) / x2 - x1);

const kk = -1 / k1;

const bb = yy - xx * kk;

const b1 = y2 - x2 * k1;

x = (b1 - bb) / (kk - k1);

y = kk * x + bb;

return [b * Math.sin(ang), { x,

y }];

}

猜你喜欢

转载自blog.csdn.net/Highning0007/article/details/81218886