What is a formula to get a three dimensional vector B lying on the plane perpendicular to a vector A?
That is, given a vector A, what is a formula f(angle,modulus) which gives a vector that is perpendicular to A, with said modulus and rotated through an angle?
If the two vectors are perpendicular then their dot product is zero.
So:
v1(x1, y1, z1), v2(x2, y2, z2)
.You know
(x1, y1, z1)
. Put arbitraryx2
andy2
and you will receive the correspondingz2
:Be aware if
z1
is0
. Then you are in the plane.I believe that this should produce an arbitrary vector that is perpendicular to the given vector
vec
while remaining numerically stable regardless of the angle ofvec
(assuming that the magnitude ofvec
is not close to zero). Assume that Vec3D is a three dimensional vector of arbitrary numerical type.Informal explanation
Exactly 1 and only 1 of the bools get set;
bN
gets set if dimensionN
has magnitude strictly less than all subsequent dimensions and not greater than all previous dimensions. We then have a unit vector with a single non-zero dimension that corresponds to a dimension of minimum magnitude invec
. The cross product of this withvec
is orthogonal tovec
by defn of cross product. Consider now that the cross product is numerically unstable only when the two vectors are very closely aligned. Consider that our unit vector is large in only a single dimension and that that dimension corresponds to the dimension wherevec
was small. It's thus guaranteed to be loosely orthogonal tovec
before taking the cross product, with least orthogonality in the case where all dimensions ofvec
are equal. In this least-orthogonal case, we're still quite orthogonal given that our unit vector has all but one dimension 0 whereasvec
has all equal. We thus avoid the unstable case of taking the cross product of two nearly-aligned vectors.Calculate the cross product
AxC
with another vectorC
which is not collinear withA
.There are many possible directions in the plane perpendicular to
A
. If you don't really care, which one to pick, just create an arbitrary vectorC
not collinear withA
:One way would be to find a rotation transform from the positive z-axis (or any other axis) to your given vector. Then transform
<modulus * cos(angle), modulus * sin(angle), 0>
using this transform.To calculate the rotation matrix, see this article: WP: Rotation matrix from axis and angle
Another method would be to use quaternion rotation. It's a little more to wrap your head around, but it's less numbers to keep track of.
But this answer is not numerical stable when a,b are close to 0.
To avoid that case, use:
The above answer is numerical stable, because in case
c < a
thenmax(a,b) = max(a,b,c)
, thenvector(b,-a,0).length() > max(a,b) = max(a,b,c)
, and sincemax(a,b,c)
should not be close to zero, so is the vector. Thec > a
case is similar.q4w56's is almost there for a robust solution. Problems: 1) Doesn't take in account scaling. 2) Doesn't compare the magnitude between two variables when it should.
Scaling is important when dealing with very large or very small numbers. Plus in general you are better off doing floating point operations on values between 0 and 1.