Perpendicular normal to a line

Started by
7 comments, last by K_I_L_E_R 18 years, 4 months ago
Hi Everyone, I was wondering, if I have a line, well a line in 3D...two points, p0 and p1. I can calculate its direction. i.e. vDir = p1 - p0; Where p0 and p1 are 3d points (x,y and z) Now I want to get a normal which is perpendicular to this line...how would I go about doing this? I was thinking of the cross product, but this usually requires two angles. As I'm trying to draw a circle around point p0, but need to create a set of points which are perpendicular to the lines direction. This is probably a very trivial question...just can't seem to see it in my mind. Thanks, Ben
Advertisement
Lines don't actually have normals. You were right with the cross prod idea, but you need a plane for that. Is it reasonable to define a plane instead of a line for this problem?

EDIT: Not sure if this is what you are asking but you can draw a circle in 2D space with the following:
	// Calculate how much we have to increment the angle by each frame	float fAngInc = 360 / a_iTess;	float fCurAng = 0.0f;	// Set the generic attributes	for (int count = 0; count < a_iTess + 1; count++)	{		// Position		m_pvertsCircle[count].m_v3Translation.x = a_v3Pos.x + (float)sin((double)DEG2RAD(fCurAng)) * a_fRad;		m_pvertsCircle[count].m_v3Translation.y = a_v3Pos.y + (float)cos((double)DEG2RAD(fCurAng)) * a_fRad;			// Increment the angle for the next round		fCurAng += fAngInc;	}

Matt

[Edited by - matthughson on December 3, 2005 11:30:30 PM]
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
Quote:Original post by bkenwright
Now I want to get a normal which is perpendicular to this line...how would I go about doing this?
There's an infinite number of vectors (normals) perpendicular to a line. I presume you are okay with any one of them.

You were thinking about using the cross product, which was the right idea. You have a vector in the direction d, d = p2 - p1, of the line. If you had another vector v, not parallel to d, the cross product u of d and v, u = cross(d, v), would give a vector perpendicular to d (as well as v).

Thus, all you have to do is pick any vector v not parallel to d and compute the cross product. For example, you can pick one of the axis vectors (1,0,0), (0,1,0), or (0,0,1).

For reasons of numerical robustness you want to try to pick the vector v such that it is as perpendicular to d as possible (or as little parallel as possible, if you prefer).

One way to pick between (1,0,0), (0,1,0), and (0,0,1) is to look at the component of d that has the largest magnitude, here largest absolute value. Let's say that the x component has the largest absolute value. This means that d points more in the direction of the x-axis than along the y or z axis. Thus, don't cross d with (1,0,0) because they are the most parallel. Similarly, don't cross d with the axis with which it is secondmost most parallel. Instead cross d with the axis it is the least parallel with, which must be the axis corresponding to the component of d with the least magnitude!

Thus, your code would look something like this (untested):

Vector GetPerpendicularToLine(Point p1, Point p2){    Vector d = p2 - p1;    if (Abs(d.x) <= Abs(d.y) && Abs(d.x) <= Abs(d.z)) {        // x has the smallest magnitude, so cross with (1,0,0)        return Cross(d, Vector(1.0f, 0.0f, 0.0f));    } else if (Abs(d.y) <= Abs(d.x) && Abs(d.y) <= Abs(d.z)) {        // y has the smallest magnitude, so cross with (0,1,0)        return Cross(d, Vector(0.0f, 1.0f, 0.0f));    }    // z has the smallest magnitude, so cross with (0,0,1)    return Cross(d, Vector(0.0f, 0.0f, 1.0f));}

If you want the result normalized, you would have to normalize the vector returned by this function.
Well I've been thinking what Christer said...you can take any other direction...choose for example the largest one, then we use the cross product and we've got a vector perpendicular to our ray.

So, p0 and p1, our two points

vDir = p1 - p0.

pX a direction other than parrallel to vDir

vPerp = cross( pDir, pX )


Now we have vPerp...which points at 90 degrees to vDir.

Now if I did a point at p0 + vDir, this would give us a point...now how would I go about rotating vDir around in a cirle, while keeping it perpendicular to vDir?

Any ideas?

Thanks again,

Ben

Quote:Original post by bkenwright
Well I've been thinking what Christer said...you can take any other direction...choose for example the largest one, then we use the cross product and we've got a vector perpendicular to our ray.

So, p0 and p1, our two points

vDir = p1 - p0.

pX a direction other than parrallel to vDir

vPerp = cross( pDir, pX )


Now we have vPerp...which points at 90 degrees to vDir.

Now if I did a point at p0 + vDir, this would give us a point...now how would I go about rotating vDir around in a cirle, while keeping it perpendicular to vDir?

Any ideas?

Thanks again,

Ben
The last sentence there is a bit confusing (perhaps you mistyped something?), but if you're wanting to create a circle around some point along the line, and perpendicular to the line, you're almost there. The first thing you need is a pair of basis vectors for the circle, rather than just one. Using Christer's function, you might do something like this:
Vector3 x = GetPerpendicularToLine(p2-p1);x.Normalize();Vector3 y = (p2-p1).Cross(x);y.Normalize();
We can now adapt Matt's code to suit your needs ('hope you don't mind, Matt...):
float fAngInc = 360 / a_iTess;float fCurAng = 0.0f;for (int count = 0; count < a_iTess + 1; count++){    float s = (float)sin((double)DEG2RAD(fCurAng));    float c = (float)cos((double)DEG2RAD(fCurAng));    // Remember, 'x' and 'y' are the vectors you computed earlier...    m_pvertsCircle[count].m_v3Translation = a_v3Pos + c*radius*x + s*radius*y;    fCurAng += fAngInc;}
And that ought to do it.
Thanks all for your idea...still getting some strange results though...not sure if its my perpendicular vector or something...but I'm working on it.

Would I be able to use the Perpendicular vector values, i.e. the individual components, x,y,z to rotate a point around the origin, then translate it to the position of the line?

Hmmmm

I mean I can create a circle and translate it to the line..just a matter of rotating it in the x,y and z so that it aligns with the lines direction.

Thanks for your help,

Ben

:)
Quote:Original post by bkenwright
Would I be able to use the Perpendicular vector values, i.e. the individual components, x,y,z to rotate a point around the origin, then translate it to the position of the line?
Not sure exactly what you mean by this, but if your intention is simply to draw a circle perpendicular to the line and centered at a point on the line, the previous code samples are about the simplest way to do it.
Quote:Original post by jyk
We can now adapt Matt's code to suit your needs ('hope you don't mind, Matt...):


Heh, not at all, glad it could be used [wink]

@OP: If this stuff still isn't helping, maybe draw what you want the final result to look like and post it here.

Matt

__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
Why wouldn't you just get the vector and rotate it by 90 degrees?
That would give you an orthoganal vector.

This topic is closed to new replies.

Advertisement