# Orthogonal Basis in 3d is flipping.

1. Jul 30, 2011

### DrSammyD

I'm trying to create a circle in 3D based off of 4 inputs.

Position1
Position2
LineLength1
LineLength2

The lines start at the positions, and they meet at their very ends.

To do this I've gotten the distance between the points, found the radius of the circle, the position of the center of the circle, and I then create a Null Space matrix from the vector pointing from Position1 to Position2.

This is the code I've written to create the basis

Code (Text):

public List<Vector3> createBasis (Vector3 vec)
{
//Calculate orthogonal basis
int pivot = -1;
int free1 = -1;
int free2 = -1;
bool taken = false;

//Find Pivot and free variables
for (int i = 0; i <= 2; i++) {
taken = false;
if (pivot == -1 && vec[i] != 0) {
pivot = i;
taken = true;
}
if (free1 == -1 && !taken) {
free1 = i;
taken = true;
}
if (free2 == -1 && !taken) {
free2 = i;
taken = true;
}
}
if (pivot == -1)
pivot = 2;

Vector3 basis1 = new Vector3();
Vector3 basis2 = new Vector3();

//Setup basis vector 1
basis1[free1] = 1;
basis1[free2] = 0;
basis1[pivot] = vec[free1] / -vec[pivot];

//Setup basis vector 2
basis2[free2] = 1;
basis2[free1] = 0;
basis2[pivot] = vec[free2] / -vec[pivot];

//Calculate unit vector basis
basis1.Normalize();
basis2.Normalize();
List<Vector3> basis = new List<Vector3> ();

return basis;
}

This works perfectly for when the positions share any single axis e.g. x = x, y=y or z=z. But when ever they don't share any axis, something goes haywire when it get's close to sharing the x axis. The closer you get to sharing the x axis, the top of the circle starts to flip sides with the bottom.

video may help.

You see how the circle is being messed up when ever it approaches the x axis? But when it's on the x or z axis, it's perfect.

What's wrong with my basis?

Last edited by a moderator: Sep 25, 2014
2. Jul 30, 2011

### I like Serena

Hi DrSammyD!

Your problem occurs with small values for the x-coordinate.
In this case you pick your pivot to be the x-coordinate, where it swaps sign, which effectively inverts your basis.
And when the coordinate becomes zero, you will pick another coordinate as the pivot, meaning the base vectors are suddenly swapped around.

Btw, it's tricky to divide by values close to zero. That introduces the possibility of significant rounding errors.

An easy fix is to pick the pivot as the coordinate with the greatest absolute value.
This will yield consistent behavior and eliminate any significant rounding errors.

3. Jul 30, 2011

### DrSammyD

That makes it even worse, and now it's not just the x axis.

4. Jul 30, 2011

### I like Serena

Hmm, now that I think about it, I guess you were trying to set up an orthonormal set of vectors, starting from your vector argument.
What you would get however is not a proper orthonormal set.

Say your vector is (x, y, z).

Then use:
basis1 = (0, -z, y)
basis2 = (xz, xy, -y2-z2)
These still need to be normalized of course to unit length.

This will get you a proper orthonormal basis, although it doesn't work when you are exactly on the x axis.

If you're exactly on the x axis, you can use for instance:
basis1 = (z, 0, -x)
basis2 = (xy, x2+z2, yz)
These still need to be normalized to unit length.

Last edited: Jul 30, 2011
5. Jul 30, 2011

### DrSammyD

Now the top of the circle doesn't go through the bottom, but the circle still flips around. And it's not even orthogonal to the vector, It's askew. I need a way to calculate the null space consistently, since the null space is always orthogonal to the vector. How does matlab do it?

6. Jul 30, 2011

### I like Serena

Oops, sorry.
The formula should be:

vector = (x, y, z)
basis1 = (0, -z, y)
basis2 = (-y2-z2, xy, xz)

You can check that this is an orthogonal basis, by calculating the inner products of each pair of vectors - they will turn out as zero.

The second set should be:
vector = (x, y, z)
basis1 = (z, 0, -x)
basis2 = (xy, -x2-z2, yz)

7. Jul 30, 2011

### DrSammyD

Thanks a tril. Unfortunately, I have no idea why this is correct. Where would I learn more to truly grok it?

8. Jul 30, 2011

### I like Serena

This is linear algebra: calculations with vectors.
More specifically usage of the cross product.

The cross product of 2 vectors is always perpendicular to the vectors.
I used that to construct an orthogonal set of vectors.

9. Jul 30, 2011

### DrSammyD

How do you find the cross product of one vector? Just multiply it by itself? Or did you work backwards

10. Jul 30, 2011

### I like Serena

Ah no, I had to improvise a bit, since I needed a second vector.
I picked (1,0,0), which was just the first vector I could think of.

So I did:
$$\begin{pmatrix}1\\0\\0\end{pmatrix} \times \begin{pmatrix}x\\y\\z\end{pmatrix} = \begin{pmatrix}0\\-z\\y\end{pmatrix}$$

Now I do have 2 vectors, and I can complete the orthogonal basis with:
$$\begin{pmatrix}0\\-z\\y\end{pmatrix} \times \begin{pmatrix}x\\y\\z\end{pmatrix} = \begin{pmatrix}-y^2-z^2\\xy\\xz\end{pmatrix}$$

11. Jul 30, 2011

### DrSammyD

oh I get it, since the cross product of two vectors is orthogonal to both, you just picked one, and then used that to create the first one.

12. Jul 30, 2011

### I like Serena

Yep!

Does that mean you are already truly grokking it?

13. Jul 30, 2011

### DrSammyD

I had never used a cross product before, I thought dot products were the only meaningful thing to do with them.

but yeah, other than that, i grok it.

14. Jul 30, 2011

### DrSammyD

One last thing, for the second set of bases, did you use (0,1,0) as your first cross product to create those, in order to create something which would work on the x axis?

15. Jul 30, 2011

### I like Serena

Yep!
The first set works except when x is insignificantly small, in which case either y or z have to be significant.