给定初始和最终位置以及起始速度矢量在3d空间中的路径上的点

时间:2011-07-01 16:14:04

标签: math 3d geometry

假设我在3d空间中有一个实体,我知道它的位置矢量(x,y,z)及其速度矢量(因此它在空间中的方向)。

从已知点A开始,我希望分两步到达已知点B:

a)沿着具有已知半径R的圆形路径转弯,直到点C

b)从C点直接到最终B点。

速度(标量值)并不重要。速度(矢量)是已知的,所以我猜它应该定义圆所在的平面,与它相切,以及A和B之间的直线......

我想知道如何找到C的坐标(x,y,z)和那里的实体的速度矢量。

3 个答案:

答案 0 :(得分:4)

Update: see the working demo!

如果我理解正确,您的情况(在包含A,B和 v 的平面中)如下图所示。给出点A和B,矢量 v 和距离 r 。你想找到C点。

enter image description here

好吧,让矢量 w =(-v y ,v x )是垂直于 v <的单位矢量/ strong>即可。然后O = A + r w

现在,| C - O | = r 和(C - B)·(C - O)= 0(其中·是点积)。将这些组合起来得到一个二次方程,你可以求解它找到C的两个可能位置。然后选择一个带有正确符号的(C - B)×(C - O)。

(圆圈的中心有第二个选择,O = A - r w ,表示顺时针转动而不是逆时针转动。这为C提供了另一种可能性我猜你必须使用一些启发式方法来决定你喜欢哪一个:也许是最小的∠AOC。)


St0rM在3D中请求帮助(参见注释)。这很简单!包含A,B和 v 的平面具有法向量 n =(A - B)× v 。设 = n × v 是一个垂直于 n v 的向量,让 w = û u 方向的单位向量)。

你还需要考虑C与A的相同平面的约束:C· n = A. n 和“右边”符号(C - B)×(C - O)“成为”(C - B)×(C - O)· n 的正确符号。


无法解决这个方程组?

那么,如果(C - B)·(C - O)= 0,那么(C - O + O - B)·(C - O)= 0,因此(C - O)·(C - O )+(O - B)·(C - O)= 0,因此C·(O - B)= O·(O - B) - r 2

你会注意到这是一个平面的等式,C· n = A. n 也是如此。将这两个平面相交(see Wikipedia for details - 您可以使用更简单的解决方案,因为平面是正交的并且可以很容易地正交)以获得C所在的线的等式:C = H +λL,例如, L = n ×(B - O)。然后使用(C - O)·(C - O)= r 2 将其转换为λ中的二次方程。你会发现,如果你将线的等式重写为C = H +λL+ O,那么二次方程会简化很多,以便“-O”的出现消失。

enter image description here

这是Python中使用numpy来执行向量代数的实现。我相信你可以弄清楚如何将它转换成你选择的语言。

import math
from numpy import cross, dot
from numpy.linalg import norm

def unit(v):
    """Return a unit vector in the same direction as v."""
    return v / norm(v)

def turnpoints(A, B, v, r):
    """Generate possible turning instructions for a path from A to B
that starts out in direction v, turns through part of a circle of radius
r until it reaches a point C (to be determined), then heads straight for
B. Return each instruction in the form (sense, C) where sense is -1 for
clockwise and +1 for anticlockwise."""
    n = unit(cross(A - B, v))   # Unit normal to plane containing A, B, v.
    w = unit(cross(n, v))       # Unit normal to v lying in that plane.
    for sense in (-1, +1):      # Turn clockwise or anticlockwise?
        O = A + sense * r * w   # Centre of turning circle.
        BB = B - O
        m = unit(BB)
        # C lies on the line H + l*L + O
        H = dot(A, n) * n + (r**2 / norm(BB)) * m
        L = cross(n, m)
        # |C - O| = r**2 gives quadratic eqn in l with coefficients a=1, b=0, c.
        c = dot(H, H) - r**2
        disc = - 4 * c          # Discriminant of quadratic eqn.
        if disc < 0:
            continue            # No tangents (B inside circle).
        elif disc == 0:         # One tangent (B on circle).
            C = H + O
            yield (sense, C)
        else:                   # Two tangents (B outside circle)
            for sign in (-1, +1):
                l = sign * math.sqrt(disc) / 2
                C = H + l * L + O
                # Only one choice for C is correct (the other involves
                # reversing direction).
                if dot(cross(C - B, C - O), n) * sense > 0:
                    yield (sense, C)

答案 1 :(得分:1)

呜,这很有趣。

  1. 找到指向A,B的平面,并且实体的速度存在。一切都会在这个平面上发生,所以现在你可以把问题想象成2D,虽然数学仍然是3D。
  2. 找到实体将在飞机上行进的圆的中心点。该中心点将垂直于实体的速度,距离为R.实际上有2个不同的位置可以放置圆圈,您需要根据哪个更靠近B进行选择。
  3. 找到B中与圆相切的两条线。这些线与圆相交的点是C的两种可能性。确定哪个点允许你的实体在到达它时离开圆圈(另一个点将使实体完全反向)。
  4. 由此,您应该能够获得C的位置,并且我相当确定,如果实体没有改变速度,则向量应该是从C到B的单位向量乘以原始速度矢量的大小。

    任何或所有这些都可能是错误的。我只是在一张纸上乱涂乱画。

答案 2 :(得分:1)

也许这是一个较短的版本。您可以从以下位置计算C:

H = O +(r ^ 2)/ | BB |)* m

C = H + l *(sqrt(r ^ 2 - | HO | ^ 2))//这只是应用Pytagora来找出HC幅度

作为概念证明:

   cml::vector3f A( 4, 3, 2);
   cml::vector3f B( 1, 5, 0);

   cml::vector3f v( 1, 0, 0);
   float r = 1.4142;

   cml::vector3f n = cml::cross((A-B),v);
   n.normalize();
   cout << "n: " << n << endl;

   cml::vector3f w = cml::cross(n,v);
   w.normalize();
   cout << "w: " << w << endl;

   cml::vector3f O = A + r*w;
   cout << "O: " << O << endl;

   cml::vector3f m = B-O;
   m.normalize();
   cout << "m: " << m << endl;

   cml::vector3f OB = B - O;
   cml::vector3f H = O + m * ( pow(r,2) / OB.length() );
   cout << "H: " << H << endl;

   cml::vector3f l = cml::cross(m,n);;
   l.normalize();
   cout << "l: " << l << endl;

   cml::vector3f OH = H - O;
   cml::vector3f C = H + l * ( sqrt( pow(r,2)-pow(OH.length(),2) ) );
   cout << "C: " << C << endl;