问题
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?
回答1:
If the two vectors are perpendicular then their dot product is zero.
So: v1(x1, y1, z1), v2(x2, y2, z2)
.
=> x1 * x2 + y1 * y2 + z1 * z2 = 0
You know (x1, y1, z1)
. Put arbitrary x2
andy2
and you will receive the corresponding z2
:
z1 * z2 = -x1 * x2 - y1 * y2
=> z2 = (-x1 * x2 - y1 * y2) / z1
Be aware if z1
is 0
. Then you are in the plane.
回答2:
Calculate the cross product AxC
with another vector C
which is not collinear with A
.
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 vector C
not collinear with A
:
if (A2 != 0 || A3 != 0)
C = (1, 0, 0);
else
C = (0, 1, 0);
B = A x C;
回答3:
function (a,b,c)
{
return (-b,a,0)
}
But this answer is not numerical stable when a,b are close to 0.
To avoid that case, use:
function (a,b,c)
{
return c<a ? (b,-a,0) : (0,-c,b)
}
The above answer is numerical stable, because in case c < a
then max(a,b) = max(a,b,c)
, then vector(b,-a,0).length() > max(a,b) = max(a,b,c)
, and since max(a,b,c)
should not be close to zero, so is the vector. The c > a
case is similar.
回答4:
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 of vec
(assuming that the magnitude of vec
is not close to zero). Assume that Vec3D is a three dimensional vector of arbitrary numerical type.
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)));
}
回答5:
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.
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);
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.
回答6:
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.
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)
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.
来源:https://stackoverflow.com/questions/11132681/what-is-a-formula-to-get-a-vector-perpendicular-to-another-vector