Convert Vector to Euler (Cardan) Angles

Started by
10 comments, last by alvaro 17 years, 10 months ago
Think that I have it figured out. And my suspicions were correct.

Taking the vector rVec and determining its main axis direction (if two values are the same, any of the two main axes will probably work similarly) tells me which axis to consider as the 'Roll' axis. Both vectors, rVec and eVec, are rotated so that their main axes (X or Y) are now the Z-axis. With that, I can calculate using the standard DirectionVector-to-EulerAngles maths. Then I just assign the Euler vector angles to the appropriate x,y,z. Now the rotations are 'minimal' and the 'Roll' axis as determined for the vector is always 0.0.

	// e- is the conformeE, r- is the conformeR	// - Make both endpoints local to world origin	Vector	eVec =	bc->GetVector(IPP_ENDPOINT) - bc->GetVector(IPP_ORIGIN);	BaseContainer*	bbc =	base->GetDataInstance();	Vector	rVec =	bbc->GetVector(IPP_ENDPOINT) - bbc->GetVector(IPP_ORIGIN);	// - If equivalent or either is zero vector (no direction), no more processing required	if (VectorEqual(eVec, rVec, EPSILONL))	return;	if (VectorEqual(eVec, zVec, EPSILONL))	return;	if (VectorEqual(rVec, zVec, EPSILONL))	return;	// - Determine main direction axis for vector	UCHAR	axis;	Vector	ar =	Vector(Abs(rVec.x), Abs(rVec.y), Abs(rVec.z));	// -- X	if ((ar.x > ar.y) && (ar.x > ar.z))	{		Matrix	align =	MatrixRotX(RAD_90) * MatrixRotZ(RAD_90) * MatrixScale(Vector(1.0));		// new y is old x, new z is old y, new x is old z		rVec *=	align;		eVec *=	align;		axis =	0;	}	// -- Y	else if (ar.y > ar.z)	{		// new x is old y, new z is old x, new y is old z		Matrix	align =	MatrixRotY(-RAD_90) * MatrixRotZ(-RAD_90) * MatrixScale(Vector(1.0));		rVec *=	align;		eVec *=	align;		axis =	1;	}	// -- Z	else	axis =	2;	// - Calculate angular offset between eVec/rVec Vectors in Rotation Order	// -- Calculate Euler angles of Conformer	Real	r;	Vector	eAngle;	Vector	rAngle;	r =	Sqrt(rVec.x*rVec.x + rVec.z*rVec.z);	rAngle.z =	0.0f;														// roll	rAngle.y =	(r < EPSILONS) ? 0.0f : Support::Angle(rVec.z, rVec.x);		// yaw	rAngle.x =	-Support::Angle(rVec.y, r);									// pitch	// -- Concatenate Rotation-order specific matrix	Matrix	mat =	MatrixMove(zVec) * MatrixRotX(rAngle.x) * MatrixRotY(rAngle.y) * MatrixRotZ(rAngle.z) * MatrixScale(Vector(1.0));	// -- Calculate Euler angles of Conformee	// Note that eVec is placed in the coordinate system where rVec is unrotated	eVec *=		!mat;	r =		Sqrt(eVec.x*eVec.x + eVec.z*eVec.z);	// These are the rotation angles from Conformee to Conformer Endpoint	eAngle.z =	0.0f;														// roll	eAngle.y =	(r < EPSILONS) ? 0.0f : -Support::Angle(eVec.z, eVec.x);	// yaw	eAngle.x =	Support::Angle(eVec.y, r);									// pitch	// Reorder rotations to avoid roll rotations	Vector	rotVec;	if (axis == 0)	{		rotVec.x =	eAngle.z;		rotVec.y =	eAngle.x;		rotVec.z =	eAngle.y;	}	else if (axis == 1)	{		rotVec.x =	eAngle.y;		rotVec.y =	eAngle.z;		rotVec.z =	eAngle.x;	}	else	{		rotVec.x =	eAngle.x;		rotVec.y =	eAngle.y;		rotVec.z =	eAngle.z;	}


Tests so far have all been positive. There is a likelyhood of finding an exception to this - a vector with equal non-zero values like v(10,10,10) would prove an interesting situation - but it should default to standard Z-axis Roll for better or worse.

Thanks,
Robert
Advertisement
I still don't understand why my post or Bob Janova's are not what you needed. You seem to have problems explaining your problem in precise terms.

This topic is closed to new replies.

Advertisement