webentwicklung-frage-antwort-db.com.de

Was ist eine Formel, um einen Vektor senkrecht zu einem anderen Vektor zu erhalten?

Was ist eine Formel, um einen dreidimensionalen Vektor B zu erhalten, der in der Ebene senkrecht zu einem Vektor A liegt?

Das heißt, wenn ein Vektor A gegeben ist, was ist eine Formel f (Winkel, Modul), die einen Vektor ergibt, der senkrecht zu A ist, mit dem Modul und um einen Winkel gedreht?

6
MaiaVictor

Wenn die beiden Vektoren senkrecht sind, ist ihr Skalarprodukt Null.

Also: v1(x1, y1, z1), v2(x2, y2, z2).

=> x1 * x2 + y1 * y2 + z1 * z2 = 0

Sie kennen (x1, y1, z1). Geben Sie einen beliebigen x2 undy2 ein und Sie erhalten den entsprechenden z2:

z1 * z2 = -x1 * x2 - y1 * y2
=> z2 = (-x1 * x2 - y1 * y2) / z1

Seien Sie sich bewusst, ob z10 ist. Dann bist du im Flugzeug.

11
Petar Minchev

Berechnen Sie das KreuzproduktAxC mit einem anderen Vektor C, der nicht mit A kollinear ist.

Es gibt viele mögliche Richtungen in der Ebene senkrecht zu A. Wenn Sie sich nicht wirklich darum kümmern, welchen Sie auswählen sollen, erstellen Sie einfach einen beliebigen Vektor C, der nicht mit A kollinear ist:

if (A2 != 0 || A3 != 0)
    C = (1, 0, 0);
else
    C = (0, 1, 0);
B = A x C; 
7
Henrik
function (a,b,c)
{
    return (-b,a,0)
}

Diese Antwort ist jedoch nicht numerisch stabil, wenn a, b nahe bei 0 liegen.

Um diesen Fall zu vermeiden, verwenden Sie:

function (a,b,c) 
{
    return  c<a  ? (b,-a,0) : (0,-c,b) 
}

Die obige Antwort ist numerisch stabil, da im Fall c < a dann max(a,b) = max(a,b,c) dann vector(b,-a,0).length() > max(a,b) = max(a,b,c) und da max(a,b,c) nicht nahe Null sein sollte, ist auch der Vektor. Der c > a Fall ist ähnlich.

5
golopot

q4W56 ist fast da für eine robuste Lösung. Probleme: 1) Berücksichtigt nicht die Skalierung. 2) Vergleicht nicht die Größe zwischen zwei Variablen, wenn es sein sollte.

scale = |x| + |y| + |z|

if scale == 0:
  return (0,0,0)

x = x/scale
y = y/scale
z = z/scale

if |x| > |y|:
  return (z, 0,-x)
else:
  return (0, z,-y)

Die Skalierung ist wichtig, wenn Sie mit sehr großen oder sehr kleinen Zahlen arbeiten. Im Allgemeinen ist es besser, Gleitkommaoperationen mit Werten zwischen 0 und 1 durchzuführen.

1
lessthanoptimal

Eine Möglichkeit besteht darin, eine Rotationstransformation von der positiven Z-Achse (oder einer beliebigen anderen Achse) in den angegebenen Vektor zu finden. Dann transformiere <modulus * cos(angle), modulus * sin(angle), 0> mit dieser Transformation.

def getPerpendicular(v1,modulus,angle):
    v2 = vector(0,0,1)
    v1_len = v2.length()

    axis = v1.cross_product(v2)
    sinAngle = axis.length() / v1_len       # |u x v| = |u| * |v| * sin(angle)
    cosAngle = v1.dot_product(v2) / v1_len  # u . v = |u| * |v| * cos(angle)
    axis = axis.normalize()
    # atan2(sin(a), cos(a)) = a, -pi < a < pi
    angle = math.atan2(sinAngle, cosAngle)

    rotationMatrix = fromAxisAngle(axis, angle)

    # perpendicular to v2
    v3 = vector(modulus*cos(angle),modulus*sin(angle),0)

    return rotationMatrix.multiply(v3);

Informationen zur Berechnung der Rotationsmatrix finden Sie in diesem Artikel: WP: Rotationsmatrix aus Achse und Winkel

Eine andere Methode wäre die Verwendung von Quaternion Rotation . Es ist ein bisschen mehr, um den Kopf zu wickeln, aber es sind weniger Zahlen, die man im Auge behalten muss.

1
Markus Jarderot

Ich glaube, dass dies einen willkürlichen Vektor erzeugen sollte, der senkrecht zu dem gegebenen Vektor vec ist, während er numerisch stabil bleibt, ungeachtet des Winkels von vec (unter der Annahme, dass die Größe von vec nicht nahe bei Null liegt). Angenommen, Vec3D ist ein dreidimensionaler Vektor beliebigen numerischen Typs.

Vec3D arbitrary_orthogonal(Vec3D vec)
{
  bool b0 = (vec[0] <  vec[1]) && (vec[0] <  vec[2]);
  bool b1 = (vec[1] <= vec[0]) && (vec[1] <  vec[2]);
  bool b2 = (vec[2] <= vec[0]) && (vec[2] <= vec[1]);

  return cross(vec, Vec3D(int(b0), int(b1), int(b2)));
}
1
sircolinton