获取一条线段未知端点的角度

3

简短版:

基本上,我想通过Line AB 的末端点(Point B)来确定未知点C的X和Y值

我尝试使用atan2(B.y,B.x),但它给出相对于X轴的角度,导致坐标错误。我想到需要获取由Line BC和虚拟水平轴形成的角度(Angle P)。有没有办法获得那个角度?如果获取该角度不能实现我的目标,那么应该怎么做?

详细版:

我正在使用C++进行一些数学计算,遇到了这个问题。

我有两个向量:Vector AVector B(由Point APoint B表示,并形成line AB)。现在,我想要得到Vector CPoint C),它距离Vector B(由Line BC表示)有L单位远。

Case 1: Get point if B.y > A.y

我寻找了一些资料,读了一些书,并获得了这个公式来获取所需的点。

/* Let:
 * L = length from B to C
 * ( B.x, B.y ) = start point
 * ( C.x, C.y ) = end point 
 * theta = angle respective to X-Axis ( using atan2( B.y, B.x ) )
 */

// To get C.x use formula cos( theta ) = ( C.x - B.x ) / L then derive
C.x = ( L * cos( theta ) ) + B.x;

// To get C.y use formula sin( theta ) = ( C.y - B.y ) / L then derive
C.y = ( L * sin( theta ) ) + B.y;

然而,这并不会导致如上所示的Point C,因为得到的C将与X轴相关。在阅读更多内容后,我发现需要获取Line BC(淡红色线)和虚拟水平轴(青色线)之间的角度(由紫色Angle P表示),虚拟水平轴包含Point B
另一个例子: Case 2: Get point if B.y < A.y 在这种情况下,使用上述公式会导致C错位(在(X,5)上方)。
我不确定获取Angle P是否能达到我的要求,如果您知道更合适的答案,请告诉我。
3个回答

4

针对此问题,您无需使用三角函数,只需使用简单的比例关系即可。我找到一个方便的规则,即如果您发现自己正在使用sin、cos和atan2,则您可能是在错误地操作。

以下是如何不使用三角函数来解决问题的方法:

dx = B.x - A.x;
dy = B.y - A.y;
dist = sqrt(dx*dx + dy*dy);
C.x = B.x + L*(dx/dist);
C.y = B.y + L*(dy/dist);

谢谢,它起作用了。你能解释一下它是如何发生的吗?提供一个解释的链接就可以了。我感觉将来会经常使用向量。 - alxcyl
1
@LanceGray 这只是基本的直线几何,不是吗?恐怕我没有任何解释的链接,但基本上您正在按比例将线段AB延长L/(AB长度)的量。 - john

3
首先要做的是创建一个tempB,就像A是原点一样(这样你就可以找到B到A的角度等)。
从B中减去A的值。
tempB.x = B.x - A.x
tempB.y = B.y - A.y

然后,您可以使用 atan2 以及 sin/cos(您的公式)来获得 C.x 和 C.y。
theta = atan2(tempB.y, tempB.x)
C.x = ( L * cos( theta ) ) + B.x;
C.y = ( L * sin( theta ) ) + B.y;

另一种选择是获取tempB的单位向量。

magnitude = sqrt( pow(tempB.x,2) + pow(tempB.y,2))
unit.x = tempB.x/magnitude
unit.y = tempB.y/magnitude

将此单位向量乘以L,可以得到从B开始的偏移量。
C.x = B.x + unit.x * L
C.y = B.y + unit.y * L

那么,我应该使用 tempB.xtempB.y 替代 sin/cos 公式中的 B.xB.y 吗? - alxcyl
@LanceGray 只在 atan2 调用中。tempB 仅用于确定角度。偏移量(C.x = ( L * cos( theta ) ) + B.x;) 仍然使用 B.x - user406009
已经实现并且可以运行。但是有点难以理解,因为它使用了三角函数(而我并不是很擅长)。谢谢。 - alxcyl
@LanceGray 嗯,当然关键是你不需要使用三角函数。Ethan的第二个解决方案(就像我的解决方案一样)不使用三角函数。这很有用,因为你说你不太擅长它。 - john

1
你需要的(向量术语)是 C = B + L*normalize(B-A)。如果你将会经常进行这种计算,那么使用一个向量库来编写代码就非常值得了。否则,你可以使用John的答案,它将相同的计算分解为其基本步骤。
编辑:这里有一个你可以很容易地使用的库(只是头文件):GLM

我正在阅读一本关于使用代码进行动画制作的书,但它是用AS 3.0编写的,并包括编写自定义向量类,其中包括clone()truncate()normalize()和其他方法。我无法将其重写为C++,所以只能求助于三角学。 - alxcyl
1
如果你对编写动画代码感兴趣,熟悉使用向量值得花费时间。我已经编辑了我的答案,并附上了一个库的链接,你可以使用它,而不是自己重新编写normalize()等函数。 - Martin Stone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接