<br>thank you, I'm putting versors on my list of things to look at.<br><br>cheers, Michael<br><br><div class="gmail_quote">On Tue, Mar 30, 2010 at 3:35 PM, Luis Ibanez <span dir="ltr"><<a href="mailto:luis.ibanez@kitware.com">luis.ibanez@kitware.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hi Michiel,<br>
<br>
This is actually the reason why using Euler angles is a bad idea.<br>
<br>
The lack of a standard for the order of<br>
application of the individual rotations.<br>
<br>
plus their vulnerability to the gimbal lock problem:<br>
<br>
<a href="http://en.wikipedia.org/wiki/Gimbal_lock" target="_blank">http://en.wikipedia.org/wiki/Gimbal_lock</a><br>
<br>
<a href="http://en.wikipedia.org/wiki/Gimbal_lock#Loss_of_a_degree_of_freedom_with_Euler_angles" target="_blank">http://en.wikipedia.org/wiki/Gimbal_lock#Loss_of_a_degree_of_freedom_with_Euler_angles</a><br>
<br>
<br>
---<br>
<br>
I would strongly encourage you to use itk::Versors instead.<br>
<br>
Versors (Unit Quaternions) are an unambiguous representation of<br>
rotations.<br>
<br>
<br>
Regards,<br>
<br>
<br>
Luis<br>
<br>
<br>
------------------------------------------------------------------------<br>
On Tue, Mar 30, 2010 at 9:11 AM, michiel mentink<br>
<div><div></div><div class="h5"><<a href="mailto:michael.mentink@st-hughs.ox.ac.uk">michael.mentink@st-hughs.ox.ac.uk</a>> wrote:<br>
> in<br>
> /itkEuler3DTransform.txx<br>
> the rotation is applied either in X Y Z order, or Z X Y order (standard),<br>
> where Y rotation is applied first.<br>
><br>
> Indeed, if I try different orders of rotation, I get different outcomes. I<br>
> suppose this is due to round-off<br>
> errors.<br>
> Why is Z X Y chosen as the standard way of multiplication?<br>
><br>
><br>
> Z Y X<br>
> image->GetDirection():<br>
> 0.999695 0.0171452 0.0177517<br>
> -0.0174497 0.999701 0.0171452<br>
> -0.0174524 -0.0174497 0.999695<br>
><br>
> X Y Z<br>
> image->GetDirection():<br>
> 0.999695 0.0174497 0.0174524<br>
> -0.0177543 0.99969 0.0174497<br>
> -0.0171425 -0.0177543 0.999695<br>
><br>
> Z X Y<br>
> image->GetDirection():<br>
> 0.99969 0.0174497 0.0177543<br>
> -0.0177543 0.999695 0.0171425<br>
> -0.0174497 -0.0174524 0.999695<br>
><br>
> cheers,<br>
><br>
> Michael<br>
><br>
><br>
><br>
><br>
><br>
> On Tue, Mar 30, 2010 at 12:18 PM, michiel mentink<br>
> <<a href="mailto:michael.mentink@st-hughs.ox.ac.uk">michael.mentink@st-hughs.ox.ac.uk</a>> wrote:<br>
>><br>
>> ah just after posting I found it (figures!)<br>
>><br>
>> complete and correct code now:<br>
>><br>
>> const ImageType::DirectionType & direction = image->GetDirection()<br>
>> std::cout << "direction: " << std::endl << direction << std::endl <<<br>
>> std::endl;<br>
>><br>
>> float angleX, angleY, angleZ;<br>
>> angleX = angleY = angleZ = 1 * vnl_math::pi / 180.0; //<br>
>> in this case: rotation = 1 degree<br>
>><br>
>> const double cx = vcl_cos(angleX);<br>
>> const double sx = vcl_sin(angleX);<br>
>><br>
>> typedef itk::Matrix<double,3,3> Matrix;<br>
>> Matrix RotationX;<br>
>> Matrix FinalRotation = image->GetDirection();<br>
>><br>
>> std::cout << "sin: " << sx << " Cos: " << cx << std::endl;<br>
>><br>
>> RotationX[0][0] = 1; RotationX[0][1] = 0; RotationX[0][2] = 0;<br>
>> RotationX[1][0] = 0; RotationX[1][1] = cx; RotationX[1][2] = sx;<br>
>> RotationX[2][0] = 0; RotationX[2][1] = -sx; RotationX[2][2] = cx;<br>
>><br>
>> FinalRotation = direction*RotationX;<br>
>><br>
>> std::cout << "image->GetDirection(): " << std::endl <<<br>
>> image->GetDirection() << std::endl;<br>
>> std::cout << "RotationX: " << std::endl << RotationX << std::endl;<br>
>> std::cout << "FinalRotation: " << std::endl << FinalRotation <<<br>
>> std::endl;<br>
>><br>
>> image->SetDirection(FinalRotation);<br>
>><br>
>> std::cout << "image->GetDirection(): " << std::endl <<<br>
>> image->GetDirection() << std::endl;<br>
>><br>
>><br>
>> cheers, Michael<br>
>><br>
>><br>
>><br>
>><br>
>><br>
>> On Tue, Mar 30, 2010 at 12:10 PM, michiel mentink<br>
>> <<a href="mailto:michael.mentink@st-hughs.ox.ac.uk">michael.mentink@st-hughs.ox.ac.uk</a>> wrote:<br>
>>><br>
>>> Hello Frederic,<br>
>>><br>
>>> thanks for your suggestion.<br>
>>><br>
>>> although my code was working, I tried your suggestion. Unfortunately, it<br>
>>> produces<br>
>>><br>
>>> error: no match for ‘operator*’ in<br>
>>> ‘image.itk::SmartPointer<TObjectType>::operator-> [with TObjectType =<br>
>>> itk::Image<float, 3u>]()->itk::ImageBase<VImageDimension>::GetDirection<br>
>>> [with unsigned int VImageDimension = 3u] * RotationX’<br>
>>><br>
>>><br>
>>> Anyway, I forgot to mention to use:<br>
>>><br>
>>> float angleX, angleY, angleZ;<br>
>>> angleX = angleY = angleZ = 1 * (3.14/180);<br>
>>><br>
>>> (multiply by pi and divide by 180 degrees, because ITK internally works<br>
>>> with radians instead of degrees)<br>
>>><br>
>>> Which leads me to the question: vnl has a pi constant, and I remember<br>
>>> vaguely having seen it somewhere as vnl::PI or something.<br>
>>> Does anyone know how to convince vnl to hand me pi constant?<br>
>>><br>
>>> cheers, Michael<br>
>>><br>
>>><br>
>>><br>
>>> On Tue, Mar 30, 2010 at 11:55 AM, Frederic Perez <<a href="mailto:fredericpcx@gmail.com">fredericpcx@gmail.com</a>><br>
>>> wrote:<br>
>>>><br>
>>>> Hello Michiel,<br>
>>>><br>
>>>> perhaps you could use a const Matrix object after all, since it looks to<br>
>>>> me that FinalRotation is first built with image->GetDirection() but this<br>
>>>> value is not actually used, and that the signature of itk::Image's is<br>
>>>> SetDirection(const DirectionType direction).<br>
>>>><br>
>>>> So here you are, my quickly written proposal (caution, I haven't<br>
>>>> compiled it):<br>
>>>><br>
>>>> float angleX, angleY, angleZ;<br>
>>>> angleX = angleY = angleZ = 5;<br>
>>>><br>
>>>> const double cx = vcl_cos(angleX);<br>
>>>> const double sx = vcl_sin(angleX);<br>
>>>><br>
>>>> typedef itk::Matrix<double,3,3> Matrix;<br>
>>>> Matrix RotationX;<br>
>>>> // Matrix FinalRotation = image->GetDirection(); -- Commented now<br>
>>>><br>
>>>> RotationX[0][0] = 1; RotationX[0][1] = 0; RotationX[0][2] = 0;<br>
>>>> RotationX[1][0] = 0; RotationX[1][1] = cx; RotationX[1][2] = sx;<br>
>>>> RotationX[2][0] = 0; RotationX[2][1] = -sx; RotationX[2][2] = cx;<br>
>>>><br>
>>>> const Matrix FinalRotation = direction*RotationX;<br>
>>>><br>
>>>> std::cout << "image->GetDirection(): " << std::endl <<<br>
>>>> image->GetDirection() << std::endl;<br>
>>>> std::cout << "RotationX: " << std::endl << RotationX << std::endl;<br>
>>>> std::cout << "FinalRotation: " << std::endl << FinalRotation <<<br>
>>>> std::endl;<br>
>>>><br>
>>>> image->SetDirection(FinalRotation);<br>
>>>><br>
>>>> std::cout << "image->GetDirection(): " << std::endl <<<br>
>>>> image->GetDirection() << std::endl;<br>
>>>><br>
>>>> Cheers,<br>
>>>><br>
>>>> Frederic<br>
>>>><br>
>>><br>
>><br>
><br>
><br>
</div></div></blockquote></div><br>