Math 根据已知的旋转角度计算其他角度

Math 根据已知的旋转角度计算其他角度,math,trigonometry,Math,Trigonometry,我正在OpenGL上制作一个机械系统动画,在根据已知的旋转角度a和点D的位置计算连杆的旋转角度时有点困难 我需要计算角度CDE和CBG,以及基于角度A和D的点E的位置。但是我的高中现在不及格。我试过几种方法,但都一无所获 段DA的长度也是已知的 你对怎么做有什么想法吗?我该怎么办?我不得不做一些假设,在寻找解决方案时,我忘了检查标签,因此下面是一张澄清点和线名称的图像,包括用于求解的红色几何体 假设 点A和B是固定的 行BC、FC和DC都是相同长度的L 点D被约束到线EG 角度未标记是您在

我正在OpenGL上制作一个机械系统动画,在根据已知的旋转角度a和点D的位置计算连杆的旋转角度时有点困难

我需要计算角度CDE和CBG,以及基于角度A和D的点E的位置。但是我的高中现在不及格。我试过几种方法,但都一无所获

段DA的长度也是已知的


你对怎么做有什么想法吗?我该怎么办?

我不得不做一些假设,在寻找解决方案时,我忘了检查标签,因此下面是一张澄清点和线名称的图像,包括用于求解的红色几何体

假设

  • AB是固定的
  • BCFCDC都是相同长度的L
  • D被约束到线EG
  • 角度未标记是您在问题中提到的角度
  • F位于以A为中心的圆上。我忘了标注半径和角度
  • A位于原点
    {x:0,y:0}
我还假设你知道向量数学的基础知识,问题不是求直线或向量之间的角度,而是求出给你带来麻烦的点CD(希望如此,因为这对我来说将是一个很长的答案)

解决 根据L的值和约束线EG的位置,可能不存在针对F的所有位置的解决方案。以下方法将导致某些值为
NaN
,或者D的位置不正确

查找C 轻松开始。当A位于原点时,则F位于
F.x=cos(角度)*半径
F.y=sin(角度)*半径

现在在直线上找到中间的mFB,直线的长度Bmb

这形成了直角三角形mBC,我们知道BC==L的长度,并且刚刚计算了线Bm=b的长度,因此线mC的长度是
(L*L-b*b)**0.5

创建从FB的单位向量(标准化),顺时针旋转90度,并按计算出的mC长度缩放。将该向量添加到点m,就得到了C

 // vector 
 nx = B.x - F.x;
 ny = B.y - F.y;
 
 // Normalize, scale, rotate and add to m to get C. shorthand
 // mC len of line mC
 s = mC  / (nx * nx + ny * ny) ** 0.5;
 C.x = m.x - ny * s;
 C.y = m.y + nx * s;

 // OR in steps

 // normalize
 len = (nx * nx + ny * ny) ** 0.5;
 nx /= len;
 ny /= len;

 // scale to length of mC
 nx *= mC;
 ny *= mC;

 // rotated 90CW and add to m to get C
 C.x = m.x - ny;
 C.y = m.y + nx;
找到D 现在我们有了点C,我们知道点D在约束线上EG。因此,我们知道点D位于C或半径L处的圆截取直线EG

然而,对于圆和直线的截距有两种解决方案,如果B位于直线EG上,则点B位于这些点之一。如果B不在EG行上,则必须从两种解决方案中选择您想要的。点D很可能距离B

有几种方法可以求直线和圆的截距。以下内容稍微复杂一些,但在选择要使用的点时会有所帮助

    // line EG as vec
    vxA = G.x - E.x;
    vyA = G.y - E.y;

    // square of length line EG
    lenA = vxA * vxA + vyA * vyA;

    // vector from E to C
    vxB = C.x - E.x;
    vyB = C.y - E.y;

    // square of length line EC
    lenB = vxB * vxB + vyB * vyB;

    // dot product A.B * - 2
    b = -2 * (vxB * vxA + vyB * vyA);

    // Stuff I forget what its called
    d = (b * b - 4 * lenA * (lenB - L * L)) ** 0.5; // L is length of CD

    // is there a solution if not we are done
    if (isNaN(d)) { return }

    // there are two solution (even if the same point)
    // Solutions as unit distances along line EG 
    u1 = (b - d) / (2 * lenA);
    u2 = (b + d) / (2 * lenA);  // this is the one we want
     
第二个单位距离适合您的布局示例。现在我们只需在EG线上找到
u2
处的点,我们就得到了最后一点D

    D.x = E.x + u2 * (G.x - E.x);
    D.y = E.y + u2 * (G.y - E.y);
天使 在你的问题中,你想要哪个角度对我来说有点模棱两可。所以我会给你们一个方法,求出线与线之间的夹角。例如
CB
CD

将两条线转换为向量。这些向量的叉积除以长度平方乘积的平方根,就得到了角度的sin。然而,我们仍然需要象限。我们通过检查两个向量的点积的符号来计算哪个象限

注意此方法将找到两条线之间的最小角度,并且对线的顺序不变

注意角度以弧度为单位

    // vector CB
    xA = B.x - C.x;
    yA = B.y - C.y;

    // vector CD
    xB = D.x - C.x;
    yB = D.y - C.y;

    // square root of the product of the squared lengths
    l = ((xa * xa + ya * ya) * (xb * xb + yb * yb)) ** 0.5;

    // if this is 0 then angle between lines is 0
    if (l === 0) { return 0 } // return angle

    angle = Math.asin((xa  * yb  - ya * xb) / l);  // get angle quadrant undefined

    // if dot of the vectors is < 0 then angle is in quadrants 2 or 3. get angle and return
    if (xa  * xb  + ya * yb < 0) { 
        return (angle< 0 ? -Math.PI: Math.PI) - angle;
    }
    
    // else the angle is in quads 1 or 4 so just return the angle
    return angle;
   

这不是一个真正的编程问题。。。这是一个数学问题,你可能会得到更好的结果,也就是说,你应该看看维基百科关于内积()的条目,特别是关于正交性的部分,它展示了如何计算两个向量之间的角度。如果D和E都有相同的y值,B和G也有相同的y值,那么你可以简化事情。谢谢你花时间用一些很好的示例代码写了这样一个完整的答案!正如你所说,我太专注于寻找角度,所以我看不到这里的问题是找到C点的位置。再次感谢你!