【问题标题】:Finding 3rd point in Triangle using JavaScript使用 JavaScript 在三角形中找到第三个点
【发布时间】:2017-07-20 06:38:22
【问题描述】:

好的,所以我需要在 JavaScript 中弄清楚如何在三角形上绘制第三个点。见下图。

A 和 B 将是随机点(可能是正数或负数,具体取决于它们相对于 0,0 原点的位置。)

因此 A 和 B 是已知点(x 和 y)。

我已经想出了如何根据 A 和 B 绘制 C。

我想要控制的 C 和 D 之间的距离。例如我想说“C和D之间的距离现在是20px...D在哪里?”

所以我想例如我们可以说 C&D 之间的距离是 20px。这意味着我有 CD 和 CB,但没有 DB。我也知道 C(x,y) 和 B(x,y)。

我现在需要找到 D...我不是一个数学头脑,所以请像我 5 岁一样向我解释它。我已经用谷歌搜索了多次,尝试使用多个示例,但我仍然丢失了...例如:我看到一些提到phi的方程式..什么是phi?如何在 JavaScript 术语中使用 phi 等...

总结:

A(x,y) is known (randomized)
B(x,y) is known (randomized)
C(x,y) is known (midpoint of AB)
CB is known (using distance formula)
CD = 20 pixels (or whatever I set it to).
DB = ???
D(x,y) = ???

这是我目前所拥有的,但它可能是错误的..

var Aeh = {x:50, y:75};
    var Bee = {x:300, y:175};
    var Cee = {x:0, y:0};
    var Dee = {x:0, y:0};

    window.onload = function(){ 
         refreshPoints();
         solveForC();
    } 
    function refreshPoints(){
        TweenLite.set("#pointA", {x:Aeh.x, y:Aeh.y});
        TweenLite.set("#pointB", {x:Bee.x, y:Bee.y});
        TweenLite.set("#pointC", {x:Cee.x, y:Cee.y});
        TweenLite.set("#pointD", {x:Dee.x, y:Dee.y});
    }
    function solveForC() {
        Cee.x = (Bee.x + Aeh.x)/2;
        Cee.y = (Bee.y + Aeh.y)/2;
        refreshPoints();
        solveForD();
    }
    function solveForD() {
        // Dee.x = AB * Cos(Φ) + x_1
        // Dee.y = AB * Sin(Φ) + y_1

        Dee.x = (Cee.x+Bee.x/2) * Math.cos((1 + Math.sqrt(5)) / 2) + Cee.x;
        Dee.y = (Cee.y+Bee.y/2) * Math.sin((1 + Math.sqrt(5)) / 2) + Cee.y;

        refreshPoints();
    }

【问题讨论】:

  • 你有没有试过任何代码?
  • 我根据其他人在网上发布的一些方程式尝试了上面发布的代码。不过,我有点在黑暗中拍摄,因为我不懂数学。
  • 你需要知道 C 到 A 或 B 之间的距离,除非 C 是 AB 的中点?而且我们还需要知道 AB D 的哪一边,否则会有两种解决方案。
  • C 是中点,所以我可以很容易地找到 C 和 B 之间的距离。我希望能够将 D 随机翻转到任一侧,所以,我不确定这将如何工作..我想我需要这两种解决方案.. 摘要:A 已知(随机) B 已知(随机) C = 已知(AB 的中点) CB 已知 CD = 20 像素(或我设置的任何值)。 DB = ???

标签: javascript html animation math trigonometry


【解决方案1】:

您有 A、B 和 C(中点),您知道从 C 到 D 的距离已设置(例如 20),并且从 C 到 D 的线与从 A 到 B 的线成直角。您可以使用它找到 D 的两个解决方案。最简单的理解方法是找到从 A 到 B 的直线的角度,并以此帮助计算 D。

var angleAB = Math.atan2(B.y - A.y, B.x - A.x);
// to get the angle of the line from C to D, add 90 degrees
// in radians, that is Math.PI / 2
var angleCD = angleAB + Math.PI / 2;

// now you can calculate one of D's solutions
// the 20 represents your distance from C to D, and can be changed if desired.
DeeOne.x = C.x + 20 * Math.cos(angleCD);
DeeOne.y = C.y + 20 * Math.sin(angleCD);

// a second solution can be found by going in the other direction from C
DeeTwo.x = C.x - 20 * Math.cos(angleCD);
DeeTwo.y = C.x - 20 * Math.sin(angleCD);

如果您只需要与图表保持一定距离(等),则可能有一些方法可以减少这种计算。希望这会有所帮助。

【讨论】:

  • 天啊,非常感谢!!!它起作用了..但是我应该注意到 Math.atan2 返回了“NaN”,但 Math.tan 似乎起作用了..两者之间是否有重要区别,或者“tan”对我的工作方式是否相同?
  • atanatan2 几乎是等价的...我认为在某些情况下(当 A 和 B 具有相同的 x 坐标时)atan2 可以工作,但 atan会破裂。但如果它有效,那就太好了!如果您要非常小心,请确保当 A 和 B 具有相同的 x 坐标时它可以工作。
  • 哦,我刚刚发现为什么 atan2 很有趣。 atan 接受一个带有 num / denom 的参数,但 atan2 期望它们分开。所以我应该写Math.atan2((B.y - A.y), (B.x - A.x)) 而不是Math.atan2((B.y - A.y) / (B.x - A.x))。如果可以的话,我会编辑...
【解决方案2】:

一种稍微更快、更准确的替代解决方案。

函数从线AB的中点找到点dist

D 位于行左侧 AB if left = 1(默认)否则 D 位于行右侧 if left = -1

function findD(A, B, dist, left = 1){ // if left = 1 the D is left of the line AB 
    const nx = B.x - A.x;
    const ny = B.y - A.y;
    dist /= Math.sqrt(nx * nx + ny * ny) * left;
    return {
        x : A.x + nx / 2 - ny * dist, 
        y : A.y + ny / 2 + nx * dist
    }
}

您可能很想将 Math.sqrt(nx * nx + ny * ny) 替换为 Math.hypot(nx,ny) 并保存 2 次乘法和一次加法。但是hypot 的速度非常慢。当我使用hypot 时,使用sqrt 的函数每秒执行1000 万次,下降到200 万次。还对另一个答案进行了计时(为了公平起见进行了优化),达到每秒 340 万个解决方案的峰值。

对于 javascript 使用 atan2sincos 并不是什么大问题,因为 64 位双精度浮点数使这些函数引入的错误无关紧要,在 ±1e-14 * 最长长度范围内侧,但如果你避免这些功能,错误可以减少(一点)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    相关资源
    最近更新 更多