Skip Menu |

This queue is for tickets about the Imager CPAN distribution.

Report information
The Basics
Id: 99959
Status: resolved
Priority: 0/
Queue: Imager

People
Owner: Nobody in particular
Requestors: denis.howe [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Imager::Matrix2d->rotate about (x, y) bug
Date: Sat, 1 Nov 2014 19:43:39 +0000
To: bug-Imager [...] rt.cpan.org
From: Denis Howe <denis.howe [...] gmail.com>
Thanks very much for your work on the fantastic Imager module. The rotate() method in Imager::Matrix2d v1.011 ( http://search.cpan.org/~tonyc/Imager-0.98/) says: return $class->translate('x'=>-$opts{'x'}, 'y'=>-$opts{'y'}) * $class->rotate(radians=>$angle) * $class->translate('x'=>$opts{'x'}, 'y'=>$opts{'y'}); meaning to rotate around (x,y), first translate by (-x, -y) then rotate around the origin then translate back by (x, y). Makes sense, *but *when applying transformations represented as matrices, you have to do it backwards: http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations Yes, order of multiplication matters for matrices. A work-around is to pass in (-x, -y) as the centre of rotation but the correct fix is to do the multiplications in the opposite order. The same would apply anywhere else you have composed transformation matrices using "*". It would be worth adding a note to this effect to the _mult() docs. Since this is rather unexpected, you might also consider providing a "then" operator or a "compose" function such that, for matrices M and N, M then N === compose(M, N) where compose(M1, M2, M3, ...) === ...*M3*M2*M1 HtH -- Denis Howe <denis.howe@gmail.com> http://foldoc.org/ T: 020 8450 9448 M: 07950 686 615
On Sat Nov 01 15:44:12 2014, denis.howe@gmail.com wrote: Show quoted text
> Thanks very much for your work on the fantastic Imager module. > > The rotate() method in Imager::Matrix2d v1.011 ( > http://search.cpan.org/~tonyc/Imager-0.98/) says: > > return $class->translate('x'=>-$opts{'x'}, 'y'=>-$opts{'y'}) > * $class->rotate(radians=>$angle) > * $class->translate('x'=>$opts{'x'}, 'y'=>$opts{'y'}); > > meaning to rotate around (x,y), first translate by (-x, -y) then > rotate > around the origin then translate back by (x, y). > > Makes sense, *but *when applying transformations represented as > matrices, > you have to do it backwards: > > http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations > > Yes, order of multiplication matters for matrices. > > A work-around is to pass in (-x, -y) as the centre of rotation but the > correct fix is to do the multiplications in the opposite order. > > The same would apply anywhere else you have composed transformation > matrices using "*". It would be worth adding a note to this effect to > the > _mult() docs. > > Since this is rather unexpected, you might also consider providing a > "then" > operator or a "compose" function such that, for matrices M and N, > > M then N === compose(M, N) > > where > > compose(M1, M2, M3, ...) === ...*M3*M2*M1 > > HtH
Thanks, fixed for the next release: http://git.imager.perl.org/imager.git/commit/f480f88 Tony
On Sat Nov 01 15:44:12 2014, denis.howe@gmail.com wrote: Show quoted text
> Thanks very much for your work on the fantastic Imager module. > > The rotate() method in Imager::Matrix2d v1.011 ( > http://search.cpan.org/~tonyc/Imager-0.98/) says: > > return $class->translate('x'=>-$opts{'x'}, 'y'=>-$opts{'y'}) > * $class->rotate(radians=>$angle) > * $class->translate('x'=>$opts{'x'}, 'y'=>$opts{'y'}); > > meaning to rotate around (x,y), first translate by (-x, -y) then > rotate > around the origin then translate back by (x, y). > > Makes sense, *but *when applying transformations represented as > matrices, > you have to do it backwards: > > http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations > > Yes, order of multiplication matters for matrices. > > A work-around is to pass in (-x, -y) as the centre of rotation but the > correct fix is to do the multiplications in the opposite order. > > The same would apply anywhere else you have composed transformation > matrices using "*". It would be worth adding a note to this effect to > the > _mult() docs. > > Since this is rather unexpected, you might also consider providing a > "then" > operator or a "compose" function such that, for matrices M and N, > > M then N === compose(M, N) > > where > > compose(M1, M2, M3, ...) === ...*M3*M2*M1
Fix relased in Imager 1.001. Thanks, Tony