2

我有一个由两个向量组成的线段,比如说 v1 和 v2,一个向量 v3 和一个角度a。如何在 Java 中编写一个方法(我也使用 Apache Commons Math 来表示一个向量),它给了我一个向量 v4,以便线段 v1-v2 和 v3-v4 成角度a 有无限的 v4 元素,如果我可以为该方法指定一个大小,以便线段 v3-v4 具有该大小,那就更好了。(都在二维空间中,角度可以是弧度或度数,没关系)

编辑:正如承诺的那样,我已经包含了我正在尝试解决的问题的图像。我有一个由 2 个向量定义的线段(这条线有点长,但没关系)、一个角度和第三个点。我需要绘制第二条线,它与第一条线以角度a相交。由于 Javafx 中的所有线条(我在这里使用)都是通过定义两个点来绘制的,因此我需要找到红点(或任何可能的红点)。 问题的可视化表示

编辑:使用阿里的回答,我得到了以下方法,它可以满足我的需要:

public Pair<Vector2D, Vector2D> calculateFourthPoint(Vector2D v1, Vector2D v2, Vector2D v3, double angleInDegrees) {
    Vector2D r = v1.subtract(v2);
    double rx = r.getX();
    double ry = r.getY();
    double angle = toRadians(angleInDegrees);

    double a = pow(rx, 2) + pow(ry, 2);
    double b = 2 * sqrt(pow(rx, 2) + pow(ry, 2)) * cos(angle) * rx;
    double c = pow(rx, 2) * pow(cos(angle), 2) + pow(ry, 2) * pow(cos(angle), 2) - pow(ry, 2);
    double discriminant = sqrt(pow(b, 2) - (4 * a * c));

    double sx1 = (-b + discriminant) / (2 * a);
    double sx2 = (-b - discriminant) / (2 * a);

    double sy1 = sqrt(1 - pow(sx1, 2));
    double sy2 = sqrt(1 - pow(sx2, 2));

    Vector2D s1 = new Vector2D(sx1, sy1);
    Vector2D s2 = new Vector2D(sx2, sy2);

    Vector2D v4_1 = v3.subtract(s1);
    Vector2D v4_2 = v3.subtract(s2);

    return new Pair<Vector2D, Vector2D>(v4_1, v4_2);
}
4

2 回答 2

2

我不知道 Apache Commons Math,所以我用伪代码编写。让vxvy分别表示向量 的xy分量v

r=v1-v2s=v3-v4。您有 2 个未知数(即sxsy; 和v4=v3-s),因此您需要 2 个方程。这些应该是:

dot_product(r,s)=length(r)*cos a // forces the desired angle

dot_product(s,s)=1 // just sets the length of s to 1

为了说明这一点,上面的等式是:

(1)    rx*sx + ry*sy = sqrt(rx^2+ry^2)*cos a

(2)    sx^2 + sy^2 = 1

sx第一个方程在和中都是线性的sy。让我们从第一个方程中消除sy(假设它ry不为零)

 sy = (1/ry)*(sqrt(rx^2+ry^2)*cos a - rx*sx)

并将其代sy入第二个等式。你得到一个二次方程sy(我不想在这里写它,因为它很复杂),它有两个解。您可以通过将值代入(假设不为零)来获得相应sx的值:syrx

 sx = (1/rx)*(sqrt(rx^2+ry^2)*cos a - ry*sy).

最后,v4=v3-s. 您得到 v4 的 2 个解,一个用于二次方程的每个解。(在我的回答中忽略了退化的情况,例如作为r空向量。)

于 2012-08-09T20:19:03.747 回答
2

很遗憾我们不能在这里做 LaTeX 风格的方程式(或者我们可以吗?我不知道,从来没有在这里做过......),但这里有:

v1-v2 · v3-v4 = |v1-v2| * |v3-v4| * cos(a)   (by definition)

定义|v3-v4|为单位向量,因此

v1-v2 · v3-v4 = |v1-v2|*1*cos(a) = |v1-v2|*cos(a)

将左手侧向外工作

v1·v4 + v2·v4 = |v1-v2|*cos(a) - v1·v3 + v2·v3

或者

(v1+v2)·v4 = |v1-v2|*cos(a) - (v1-v2)·v3 

尽管

|v3-v4| = (v3-v4)·(v3-v4) = 1    

因此,在 2 个未知数中有 2 个方程。现在,为简洁起见,

aa  = (v1+v2|x
bb  = (v1+v2|y
x1 = v4|x
x2 = v4|y
A  = |v1-v2|*cos(a) - (v1-v2)·v3 

where|x表示x-component 等。有了这个,微不足道的替换给了我们

( (A-aa*x1)/bb )^2 + (aa*x1)^2 = 1     (-> 2 solutions)
( (A-bb*x2)/aa )^2 + (bb*x2)^2 = 1     (-> another 2 solutions) 

解决方案有点过于混乱,无法在此处写下,但它们是可以轻松求解的简单二次方程。

然后你有4 个独特的向量,它们位于一个单位圆上v3(见图)。这 4 个向量仅导致 2 个不同的线,但找到所有 4 个向量仍然是一个好主意(作为自检,并提高稳健性 - 可能存在一些边缘情况,其中一个向量是这样的就像发生灾难性的取消一样)。

哪条线最适合您,当然取决于您的用例。

无论您选择哪种解决方案,您当然应该始终验证是否

arccos(((v1-v2)·(v3-v4))/|v1-v2|) = a

应该是这样。

情景草图

于 2012-08-10T09:39:11.847 回答