how to get unit vector perpendicular to normal surface

Started by
4 comments, last by ankhd 9 years ago

I have normal vector to the surface. And I want to receive vector perpendicular to this normal vector.

This perpendicular vector has to be normalized and lie towards x and z direction as normal one.

http://oi61.tinypic.com/4lsfb8.jpg

Any ideas for 3 equations which will serve to find the solution? I have only one as on the picture, so I need to have 2 more ones.

Advertisement

In 2D, you need the 'perp' product, perp( {x,y} ) = {-y,x}.

In 3D, there are an infinitely many perpendicular vectors. One possible way to construct a coordinate frame from a normal vector is this:


/// Return an orthogonal matrix defining a basis for the coordinate frame of a plane with the specified normal.
/**
  * The normal becomes the z-column of the resulting matrix, and X and Y columns
  * are generated robustly from the input normal vector. The normal vector must have
  * non-zero length.
  */
Matrix3D<T> planeBasis( const Vector3D<T>& normal )
{
	Vector3D<T> binormal;
	Vector3D<T> n = math::abs(normal);
	
	if ( n.x <= n.y )
	{
		if ( n.x <= n.z )
		{
			// X smallest.
			binormal.y = -normal.z;		binormal.z = normal.y;
		}
		else
		{
			// Z smallest.
			binormal.x = -normal.y;		binormal.z = normal.x;
		}
	}
	else if ( n.y <= n.z )
	{
		// Y smallest.
		binormal.x = -normal.z;		binormal.z = normal.x;
	}
	else
	{
		// Z smallest.
		binormal.x = -normal.y;		binormal.z = normal.x;
	}
	
	binormal = binormal.normalize();
	
	return Matrix3D<T>( math::cross( binormal, normal ), binormal, normal );
}

Generally I want to have vector which is perpendicular to the normal and parallel to slippery slope. Fz is gravity force which acts on the body which is located at slippery slope.

My current algorithm is.


Fz = (n.x, (n.x*n.x+n.z*n.z)/-n.y, n.z)
Then normalize Fz.
Then multiply it by body mass and -9.81 [ms]

However it doesn't work when slippery slope angle is about 90 degree as n.y is equal almost to 0. There is more and more impact of round errors when angle follow to 90 degree.

slope being close to 90 degree means almost all gravity is applied to y direction, in which case you should directly use Fz = (0,-1,0)


Generally I want to have vector which is perpendicular to the normal and parallel to slippery slope. Fz is gravity force which acts on the body which is located at slippery slope.

If you want a vector that is perpendicular to normal of the surface and yet likely in the direction of the Fz, then there is a solution.

I understand it that you want a vector orthogonal to normal of the surface and also lying in plane that Fz and the normal vector yield together.

Then just, normalize Fz vector to get a unit vector F, create a cross product between F and N(unit vector normal of the surface), normalize the result R, and then cross product the R and N vector resulting in D, the D if normalized wil be direction vector in your surface following your gravity direction the most of all vectors in the surface.

However it doesn't work when slippery slope angle is about 90 degree as n.y is equal almost to 0. There is more and more impact of round errors when angle follow to 90 degree.

If the slope is orthogonal to Fz, then the slippery vector is of size 0, in my solution you do not use divisions, so you can safely walk into 0 vector if you will watch for normalizations operations

Hi.

Some thing like this may help you.

.


float3 Perpendicular(float3 direction)
{
	//float3 a = float3(0.0, 1.0, 0.0);
	
	//float3 rt = cross(a, v1);
	//return rt;

 // to be filled in
    float3 quasiPerp;// a direction which is "almost perpendicular"
    float3 result;// the computed perpendicular to be returned

    // three mutually perpendicular basis vectors
    float3 i = float3(1, 0, 0);
    float3 j = float3(0, 1, 0);
    float3 k = float3(0, 0, 1);

    // measure the projection of "direction" onto each of the axes
    float id = dot(i, direction);//i.dot (direction);
    float jd = dot(j, direction);//j.dot (direction);
    float kd = dot(k, direction);//k.dot (direction);

    // set quasiPerp to the basis which is least parallel to "direction"
    if ((id <= jd) && (id <= kd))
    {
        quasiPerp = i;               // projection onto i was the smallest
    }
    else
    {
        if ((jd <= id) && (jd <= kd))
            quasiPerp = j;           // projection onto j was the smallest
        else
            quasiPerp = k;           // projection onto k was the smallest
    }

    // return the cross product (direction x quasiPerp)
    // which is guaranteed to be perpendicular to both of them
   // result.cross (direction, quasiPerp);
	result = cross(direction, quasiPerp);
	return result;

}//end Perpendicular
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

This topic is closed to new replies.

Advertisement