# [vtkusers] Bug in vtkQuaternion

David Gobbi david.gobbi at gmail.com
Fri Dec 6 01:50:24 EST 2013

```The slerp function looks suspicious to me, too, but for a different
reason.  A quaternion slerp function should _not_ convert the
quaternions to an angle & axis representation in order to do the
slerp.  It should be computing the slerp via quaternion algebra,
not via trigonometry.

On Thu, Dec 5, 2013 at 10:51 PM, Mengda Wu <wumengda at gmail.com> wrote:
> BTW, I think the slerp function in vtkQuaternion also has issues:
>
> What if I would like to interpolate an identity quaternion (no rotation)
> with an slightly non-identity (a slight rotation). Then axis0=(0,0,0) and
> e.g. axis1=(1,0,0), will the result be wrong?
>
>
> On Thu, Dec 5, 2013 at 5:30 PM, David Gobbi <david.gobbi at gmail.com> wrote:
>>
>> The unit quaternion is qw,qx,qy,qz = (1,0,0,0).  But (qx,qy,qz) is not
>> the "axis".  The axis is what you get when you divide (qx,qy,qz) by
>> sin(theta/2).
>>
>> An identity quaternion is (1, 0, 0, 0), but it is wrong to say that
>> for the identity quaternion the axis is (0,0,0).  The axis of an
>> identity quaternion could be anything, because the axis of an identity
>> quaternion is (0,0,0) / sin(0/2), hence "undefined".
>>
>>
>>
>> On Thu, Dec 5, 2013 at 3:05 PM, Mengda Wu <wumengda at gmail.com> wrote:
>> > OK. I am a little confused.
>> > For an identity quaternion. The code is now
>> > template<typename T> void vtkQuaternion<T>::ToIdentity()
>> >
>> > {
>> >   this->Set(1.0, 0.0 ,0.0, 0.0);
>> > }
>> >
>> > which means the axis is (0,0,0). Isn't (0,0,0) a good way to represent
>> > undefined axis?
>> > So how to represent an identity matrix (no rotation) with a quaternion?
>> > Should it be (1, 0, 0, 0) or (0, 0, 0, 0)?
>> >
>> >
>> >
>> >
>> > On Thu, Dec 5, 2013 at 4:30 PM, David Gobbi <david.gobbi at gmail.com>
>> > wrote:
>> >>
>> >> You say that for the identity quaternion the axis is (0,0,0) but that
>> >> is not really true.  For the identity quaternion, the axis is
>> >> undefined.
>> >>
>> >> If you call SetRotationAngleAndAxis(1,0,0,0), then you are passing
>> >> invalid parameters to the method.  To get the identity quaternion, you
>> >> need to set the angle to zero, not to one.
>> >>
>> >> I agree that the code should have an extra check, but it should be the
>> >> opposite of what you have in your sample code.  It should give the
>> >> identity quaternion if the angle is zero:
>> >>
>> >>    else if ( angle == 0.0 )
>> >>      {
>> >>      this->Set(1.0, 0.0, 0.0, 0.0);
>> >>      }
>> >>   else
>> >>     {
>> >>     this->Set(0.0, 0.0, 0.0, 0.0);
>> >>     }
>> >>
>> >>  David
>> >>
>> >> On Thu, Dec 5, 2013 at 2:14 PM, Mengda Wu <wumengda at gmail.com> wrote:
>> >> >
>> >> > But for the identity quaternion (1, 0, 0, 0), the axis is indeed
>> >> > (0,0,0).
>> >> > This is related to GetRotationAngleAndAxis, that function will give a
>> >> > nozero
>> >> > angle and axis (0,0,0) for the identity quaternion.
>> >> > Then if I plug this result to SetRotationAngleAndAxis, I will get a
>> >> > quaternion (0,0,0,0), which does not make sense.
>> >> > Then if I use ToMatrix3x3 on the quaternion (0,0,0,0), which will be
>> >> > wrong.
>> >> >
>> >> > So I suggest to change
>> >> >
>> >> > template<typename T> void
>> >> > vtkQuaternion<T>::SetRotationAngleAndAxis (const T& angle,
>> >> >                                            const T& x,
>> >> >                                            const T& y,
>> >> >                                            const T& z)
>> >> > {
>> >> >   T axisNorm = x*x + y*y + z*z;
>> >> >   if (axisNorm != 0.0)
>> >> >     {
>> >> >     T w = cos(angle / 2.0);
>> >> >     this->SetW(w);
>> >> >
>> >> >     T f = sin( angle / 2.0);
>> >> >     this->SetX((x / axisNorm) * f);
>> >> >     this->SetY((y / axisNorm) * f);
>> >> >     this->SetZ((z / axisNorm) * f);
>> >> >     }
>> >> >   else if ( angle != 0.0 )
>> >> >     {
>> >> >     this->Set(1.0, 0.0, 0.0, 0.0);
>> >> >     }
>> >> >  else
>> >> >    {
>> >> >    this->Set(0.0, 0.0, 0.0, 0.0);
>> >> >    }
>> >> > }
>> >> >
>> >> > How is that?
>> >> >
>> >> > Mengda
>> >> >
>> >> >
>> >> > On Thu, Dec 5, 2013 at 4:04 PM, David Gobbi <david.gobbi at gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Hi Mengda,
>> >> >>
>> >> >> The SetRotationAngleAndAxis(angle, x, y, z) method does not
>> >> >> directly set the quaternion elements, for that you would use the
>> >> >> method Set(w, x, y, z).
>> >> >>
>> >> >> For SetRotationAngleAndAxis, it does not make sense to specify
>> >> >> xyz=(0,0,0) with a nonzero angle because (0,0,0) is not a valid
>> >> >> axis.
>> >> >>
>> >> >>   David
>> >> >>
>> >> >> On Thu, Dec 5, 2013 at 1:53 PM, Mengda Wu <wumengda at gmail.com>
>> >> >> wrote:
>> >> >> > Hi all,
>> >> >> >
>> >> >> >    I think there is a bug in
>> >> >> > vtkQuaternion<T>::SetRotationAngleAndAxis.
>> >> >> > What
>> >> >> > if I want to
>> >> >> > set angle=1.0 and xyz=(0, 0, 0)? I need an identity matrix from
>> >> >> > this
>> >> >> > quaternion. Should it call this->Set(1.0, 0.0, 0.0, 0.0) instead
>> >> >> > of
>> >> >> > this->Set(0.0, 0.0, 0.0, 0.0) in this case?
>> >> >> >
>> >> >> > Thanks,
>> >> >> > Mengda
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > The code is pasted here:
>> >> >> >
>> >> >> > template<typename T> void
>> >> >> > vtkQuaternion<T>::SetRotationAngleAndAxis (const T& angle,
>> >> >> >                                            const T& x,
>> >> >> >                                            const T& y,
>> >> >> >                                            const T& z)
>> >> >> > {
>> >> >> >   T axisNorm = x*x + y*y + z*z;
>> >> >> >   if (axisNorm != 0.0)
>> >> >> >     {
>> >> >> >     T w = cos(angle / 2.0);
>> >> >> >     this->SetW(w);
>> >> >> >
>> >> >> >     T f = sin( angle / 2.0);
>> >> >> >     this->SetX((x / axisNorm) * f);
>> >> >> >     this->SetY((y / axisNorm) * f);
>> >> >> >     this->SetZ((z / axisNorm) * f);
>> >> >> >     }
>> >> >> >   else
>> >> >> >     {
>> >> >> >     this->Set(0.0, 0.0, 0.0, 0.0);
>> >> >> >     }
>> >> >> > }
```