Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

I have a plane equation in 3D, in the form $Ax+By+Cz+D=0$ (or equivalently, $\textbf{x}\cdot\textbf{n} = \textbf{a}\cdot\textbf{n}$), where $\textbf{n}=\left[A\:B\:C\right]^T$ is the plane normal, and $D=-\textbf{a}\cdot\textbf{n}$ with $\textbf{a}$ as a point in the plane, hence $D$ is negative perpendicular distance from the plane to the origin. I have some points in 3D space that I can project onto the plane, and I wish to express these points as 2D vectors within a local 2D coordinate system in the plane. The 2D coordinate system should have orthogonal axes, so I guess this is a case of finding a 2D orthonormal basis within the plane?

There are obviously an infinity of choices for the origin of the coordinate system (within the plane), and the in-plane $x$ axis $\textbf{i}$ may be chosen to be any vector perpendicular to the plane normal. The 3D unit vector of the in-plane $y$ axis $\textbf{j}$ could then be computed as the cross product of the $x$ axis 3D unit vector and the plane normal. One algorithm for choosing these could be:

  • Set origin as projection of $\left[0\:0\:0\right]^T$ on plane
  • Compute 2D $x$ axis unit vector $\textbf{i}$ direction as $\left[1\:0\:0\right]^T\times\textbf{n}$ (then normalize if nonzero)
  • If this is zero (i.e. $\textbf{n}$ is also $\left[1\:0\:0\right]^T$) then use $\textbf{i}$ direction as $\left[0\:1\:0\right]^T\times\textbf{n}$ instead (then normalize)
  • Compute $\textbf{j}=\textbf{i}\times\textbf{n}$

However, this all seems a bit hacky (especially the testing for normal along the 3D $x$ axis, which would need to deal with the near-parallel case on a fixed-precision computer, which is where I'll be doing these sums).

I'm sure there should be a nice, numerically stable, matrix-based method to find a suitable $\textbf{i}$ and $\textbf{j}$ basis within the plane. My question is: what might this matrix method be (in terms of my plane equation), and could you explain why it works?

Thanks,

Eric

share|improve this question
    
If I understand you correctly the offset $D$ has no impact on the basis you want to find. So we can just choose $D=0$ for the time being. Then you can choose basis of the subspace given by the plane and apply Gram-Schmidt. –  Simon Markett May 31 '12 at 15:46
    
If this helps I can write some more details,well also if not ;) –  Simon Markett May 31 '12 at 15:50
    
The only effect the offset $D$ has is on the origin point for the basis - choosing the direction vectors $\textbf{i}$ and $\textbf{j}$ only depends on the normal, so yes, we can assume $D=0$. Please could you give more details on Gram-Schmidt, specifically what the nicest way of computing the two 3D unit vectors for the new coordinate axes using $A$, $B$ and $C$ is? –  Eric Greveson May 31 '12 at 16:13

2 Answers 2

up vote 2 down vote accepted

As we discussed in the comments we can set $D=0$ for the time being, then the plane is not longer affine but a honest to god subspace of $\mathbb R^3$. There we can find two vectors which span this subspace. You want this basis to look nice (orthonormal) but the trick is that Gram-Schmidt allows us to deal with this later.

First we just have to find any two vectors which span then plane $Ax+By+Cz=0$. In other words we just need two linearly independent solutions of this equation. Assume wlog $A\neq 0$ (rearrange if necessary), then two solutions would be for example $(B/A,-1, 0)$ and $(C/A,0,-1)$. These two vectors span the plane. Then you can just apply Gram-Schmidt to these vectors to get a orthonormal basis.

It seems that you are looking for a way to implement this quickly. I am no expert on this but I know for sure that many languages have ready to use packages for Gram-Schmidt.

Edit: Maybe Gram-Schmidt is a really big word for such a low dimensional case. In fact what you do is the following. Call our vectors $b_1$ and $b_2$, then compute $b_1'=\frac {b_1}{|b_1|}$, i.e. make it into a length one vector. Then compute $b_2'=b_2-\left< b_1',b_2\right>b_1'$, this vector is now orthogonal to $b_1'$ and finally take $b_2''=\frac{b_2'}{|b_2'|}$. The vectors $b_1'$ and $b_2''$ are now an orthonormal basis.

share|improve this answer
    
Simon, thanks for the explanation. Gram-Schmidt therefore sounds very similar to the algorithm I described - the test for A not equal to zero, coming up with an initial vector in the plane based on this, etc. Thinking about it, I was hoping for an alternative method to "automagically" deal with such cases (e.g. if $A$ is very small), but I suppose as the axes are unconstrained due to the degree of freedom about the normal, this won't happen. Essentially I was hoping that there might be a method that uses $A$, $B$, and $C$, and no if-tests. –  Eric Greveson May 31 '12 at 17:06
    
Well you could sort $A,B,C$ wrt to their absolute value first and take the biggest one. –  Simon Markett May 31 '12 at 17:10
    
Or you could take the three vectors $(B,-A,0)$, $(C,0,-A)$ and $(0,C,-B)$ and find a different method to decide which one of those is superfluous (usually any one of the three, if any of the parameters is 0 you have limited choice) –  Simon Markett May 31 '12 at 17:16

Your original approach is fine, except for one small improvement: instead of choosing $\textbf{i}$ by default to obtain the first basis vector, you should choose the one of $\{\textbf{i}, \textbf{j}, \textbf{k}\}$ whose angle with $\textbf{n}$ is closest to 90°. This will be the one whose dot product with $\textbf{n}=(n_1, n_2, n_3)$ is smallest (by absolute value). Since $\textbf{i}\cdot \textbf{n} = n_1$ etc., simply choose the one that corresponds to the smallest $|n_i|$ (e.g. choose $\textbf{j}$ if $|n_2|$ is smallest). This guarantees a minimum angle (ca. 54°) between the two vectors and is therefore numerically robust.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.