分类
电脑/技术

JavaScript实现角距離:中心/重心/点距离/x与y距离/垂线与距离

前言

接下来开发新功能,称之为「角距離(かくきょり)」 ,中文称之为「角距(jiǎo jù)」 。引用百度百科的解释:

「角距,即角距离,也称为角分离、视距离、或视分离,在数学(特别是几何学和三角学)和自然科学(包括天文学、地质学等等),从不同于两个点物体的位置(即第三点)观察这两个物体,由观测者指向这两个物体的直线之间所夹角度的大小。角距离(或分离)与角度本身是同义的,但意义却是对两个天体(对恒星,是当从地球观测)之间线距离的建议(通常是很大或未知的)。」

大概印象如下:

1

而我们打算要实现的功能有:中心/重心/点距离/x与y距离/垂线与距离 。最终是通过JavaScript/canvas来实现的,因为还没开始写,这边先整理一下思路、公式之类的。

ここからやるよ

先理解一下canvas的坐标系。

2

canvas的坐标系是左上角(0,0)开始,所以都是正值,负值是看不见的,和中学时候学习的坐标系略有不同。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Canvas绘制直线</title>
    </head>
    <body>
        <canvas id="canvas" width="200" height="150" style="border: 0.0625rem;"></canvas>
    </body>
    <script>
        var canvas = document.getElementById("canvas");
        var cxt = canvas.getContext("2d");
        //画直线
        window.onload = function(){
            cxt.moveTo(80,20);
            cxt.lineTo(20,60);
            cxt.stroke();
        }
    </script>
</html>

2

上图左边是中学时学的坐标系(使用笛卡尔坐标系)将 (0,0) 放置在正中央,y 轴由下至上 x 轴由左至右。而上图右边的电脑窗口的坐标系在 y 轴的方向是相反的。(0,0) 被定义在左上角并往右边及往下延伸。

1. 中心

4

如图,A点和B点点中心点怎么求呢?直接 ${A}(x,y)-{B}(x,y)$ 就可以了。

//A点
var Ax = 80,
    Ay = 20;

//B点
var Bx = 20,
    By = 60;

//中心点
var Cx = Ax-Bx,
    Cy = Ay-By;

2. 重心

5

var Ax,Ay, //设置A点坐标
    Bx,By, //设置B点坐标
    Cx,Cy, //设置C点坐标
    CGx, //Center of gravity
    CGy; //重心
CGx = (Ax + Bx + Cx) / 3;
CGy = (Ay + By + Cy) / 3;

3. 两点距離

6

页面中有 AB 两个点,那么我们设两点坐标 A(x1, y1)、B(x2, y2)。我们可以将 AB 的连线看成是直角三角形的斜边,图中 C 为直角三角形的直角。现在我们已知 A、B 两点的坐标,那么边长 BC 就是 |x1 – x2|,边长 AC 就是 |y1 – y2|。

那么根据勾股定理 $a^2 + b^2 = c^2$ ,斜边 AB 就求得公式为 $|AB|=\sqrt{(x1-x2)^2+(y1-y2)^2}$ 公式已经知道了,下面用代码的形式写出来:

function getDistanceBetweenTwoPoints(x1, y1, x2, y2){
    var a = x1 - x2;
    var b = y1 - y2;

    // c^2 = a^2 + b^2
    // a^2 = Math.pow(a, 2)
    // b^2 = Math.pow(b, 2)
    var result = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));

    return result;
}

Math.sqrt方法是求平方根,Math.pow(n, 2)是求一个数的平方。上面的的方法就是根据两点的坐标求得两点的距离。

除了根据勾股定理之外,我们还可以根据一次函数的来得到斜边的长度,将斜边 AB 看成一个一次函数 y = kx + b,将 A、B 两点的坐标代入,我们就可以得到 $|AB|=\sqrt{1+k^2}|x1-x2|=\sqrt{1+\frac{1}{k^2}}|y1-y2|$ 。

4. xy座標距離

① x座標距離

7

手绘图,大概这么个意思。B(x,y)A(x,y) 的坐标,取结果 Distance(x,y) 的 x 就是了。

var Ax,Ay, //设置A点坐标
    Bx,By, //设置B点坐标
    Distancex, //距離x
    Distancey; //距離y
Distancex = Ax - Bx;
Distancey = Ay - By;

② y座標距離

8

也是手绘图,大概这么个意思。B(x,y)A(x,y) 的坐标,取结果 Distance(x,y) 的 y 就是了。

var Ax,Ay, //设置A点坐标
    Bx,By, //设置B点坐标
    Distancex, //距離x
    Distancey; //距離y
Distancex = Ax - Bx;
Distancey = Ay - By;

5. 直線の交叉点

10

如上图,已知四个点(Ax,Ay)(Bx,By)(Cx,Cy)(Dx,Dy),其中(Ax,Ay)(Bx,By)确定直线1(Cx,Cy)(Dx,Dy) 确定直线2,求直线1直线2的交点(CrossPointx,CrossPointy),公式如下:

$$CrossPointy=\frac{[(Ay-By)\times(Cy-Dy)\times Ax+(Cy-Dy)\times(Bx-Ax)\times Ay + (By-Ay)\times(Cy-Dy)\times Dx+(Dx-Cx)\times(By-Ay)\times Dy]}{[(Bx-Ax)\times(Cy-Dy)+(Ay-By)\times(Cx-Dx)]}$$

$$CrossPointx=Dx+\frac{(Cx-Dx)\times(CrossPointy-Dy)}{(Cy-Dy)}$$

//先求出CrossPointy
CrossPointy = ( (Ay-By)*(Cy-Dy)*Ax + (Cy-Dy)*(Bx-Ax)*Ay + (By-Ay)*(Cy-Dy)*Dx + (Dx-Cx)*(By-Ay)*Dy ) / ( (Bx-Ax)* (Cy-Dy) + (Ay-By)*(Cx-Dx) );
//求CrossPointx
CrossPointx = Dx + (Cx-Dx)*(CrossPointy-Dy) / (Cy-Dy);

6. 点直線間垂線と距離

垂线:当两条直线相交所成的四个角中,有一个角是直角时,即两条直线互相垂直,其中一条直线叫做另一直线的垂线,交点叫垂足。

垂足:如果两直线的夹角为直角,那么就说这两条直线互相垂直,其中一条直线叫做另一条直线的垂线,他们的交点叫做垂足,或者一条直线垂直交于另一直线,其交点称为该直线的垂足。

10

图上有 x y z 三个坐标轴,Unity 和 canvas 都可以画 2D 3D 的图。接下来画的是2D图,所以坐标用(x,y)就可以了。为了方便理解,把图重新画一下,以下图为准。

11

公式:

$$ T=\frac{(C-A)\times(A-B)}{(A-B)^2} $$

$$P=(A-B)\times T+A$$

var Ax,Ay, //设置A点坐标
    Bx,By, //设置B点坐标
    Cx,Cy, //设置C点坐标
    Px,Py,
        T;

① 点直線間垂線

//垂线就是 C点 和 P点 
T = ( (Cx-Bx)*(Ax-Bx) + (Cy-By)*(Ay-By) ) / ( (Ax-Bx)*(Ax-Bx) + (Ay-By)*(Ay-By) );
Px= (Ax-Bx)*T + Ax;
Py= (Ay-By)*T + Ay;

②点直線間距離

用勾股定理公式 $a^2 + b^2 = c^2$ 来算出两点的距离。

var a = Cx - Px;
var b = Cy - Py;
var Distance = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));

我自己也不清楚有没有错误的地方,未来的自己呀,如果看到错误的话,记得帮忙指正哦。