A while ago I wrote code to mathematically compose linear
transformations. I make no guarantee of its correctness or robustness,
but it might be useful to someone:

=head2 t_compose_linear

Mathematically compose transformations and combine the C<pre> and
C<post> translations into a single C<post> translation. The
C<t_compose> function just does the transformations in order, while
this function creates a single mathematical transformation.

=cut

sub t_compose_linear{
  my (@t_in) = @_;

  # set up the initial output matrix and post translation
  my $out_matrix = identity($t_in[-1]->{'params'}->{'matrix'});
  my $out_post = zeroes($out_matrix->dim(-1));

  foreach my $in (reverse @t_in) {
    # check to make sure we have the right type of transformation
    unless(UNIVERSAL::isa($in,'PDL::Transform::Linear')) {
      Carp::cluck( "PDL::Transform::t_inverse_linear:  ".
                   "got a transform that is not linear.\n"
                 );
      return undef;
    }
    unless(defined $in->{params}->{inverse}) {
      Carp::cluck( "PDL::Transform::t_inverse_linear:  ".
                   "got a transform with no inverse.\n"
                 );
      return undef;
    }

    my $in_matrix = $in->{'params'}->{'matrix'};

    # get the post and pre translations of the input xform
    my $in_post = topdl($in->{'params'}->{'post'});
    my $in_pre = topdl($in->{'params'}->{'pre'});
    $in_post = $in_post->copy();
    $in_pre = $in_pre->copy();

    # if they're single element piddles, make them vectors
    $in_post = $in_post * ones($in_matrix->dim(1))
      if ($in_post->nelem() < $in_matrix->dim(1));
    $in_pre = $in_pre * ones($in_matrix->dim(1))
      if ($in_pre->nelem() < $in_matrix->dim(1));

    # now combine the pre and post translations into a single post
    $in_post = $in_post + ($in_pre x $in_matrix);

    # and convert that into the combined post translation
    $out_post = $in_post + matmult($out_post,$in_matrix);
    $out_matrix = $out_matrix x $in_matrix;
  }


On Wed, Apr 30, 2008 at 8:52 AM, Craig DeForest
<[EMAIL PROTECTED]> wrote:
>
> That would be the part in NOTES where it says
>
>
>    Composition works OK but should probably be done in a more sophisticated
>     way so that, for example, linear transformations are combined at the
>     matrix level instead of just strung together pixel-to-pixel.
>
> For 100-10,000 coordinates you shouldn't worry.  That will fit entirely in
> the CPU cache for most modern machines, so the performance hit isn't bad.
> When I say build your own rotation matrix, I mean as a PDL using elementwise
> calculation or matrix multiplication.
>
> The comment in the notes, and the point I made, is that if you have three
> linear operators to string together, it is much faster (54 multiplications)
> to multiply your three 3x3 matrices together, than to apply each matrix in
> order with the data (27 times 3N multiplications).  But with only (say) 1000
> points, that means each operation will take under 9000 multiplications, or
> about 30-100 microseconds if you're using a recent machine and the data are
> in CPU cache.
>
> My suggestion: try it using the Transform composition; if it is too slow,
> you can make it faster by applying your composition Transform to the
> identity matrix, and then pass the resulting matrix into t_linear to make a
> single transform.
>
> Cheers,
> Craig
>
> On Apr 30, 2008, at 6:31 AM, Sina Türeli wrote:
>
> Okay this part seems important. Where in the documentation does it write
> that? So if to rotate around an arbitrary axis, I compose three rotation
> matrices T^-1.R.T<v>, where T takes the arbitrary axis to x axis, R does the
> rotation around x axis and T^-1 maps the arbitrary axis back to its original
> direction how much of an inefficiency are we talking about. This is likely
> to operate on a data set of anywhere between 100 to 10000 coordinates. These
> T and R operators are all t_linear rotation operator in PDL. When saying
> build your own rotation matrix do you mean from scratch and by just using
> multplication and inverse operations defined in PDL and not any t_linear
> opeartions...
>
> Thanks alot for your help
>
> On Tue, Apr 29, 2008 at 11:23 PM, Craig DeForest <[EMAIL PROTECTED]>
> wrote:
>
> >
> >
> > You can compose transformations to get to the axis you want, but as you
> will have seen in the documentation it is inefficient because the code just
> strings the transformations together. If your data are big then you will
> want instead to build your own rotation matrix (or extract the one in the
> transform) to minimize the number of passes. You can still use Transform to
> encapsulate the operations, which is good in case you later want to
> generalize.  t_linear will accept a matrix if you want.
> >
> >
> >
> >
> > On Apr 29, 2008, at 1:26 PM, "Sina Türeli" <[EMAIL PROTECTED]> wrote:
> >
> >
> >
> >
> > Thanks for the answers. One more question, is there any build in function
> for rotationa around an arbitrary axis of the object? If there isnt I am
> planning to first rotate all the object so that the arbitrary axis concides
> with say x axis, rotate the object around the x axis and apply the inverse
> of the first transformation to put the arbirtrary axis back in its place.
> But somehow this seems computationally really inefficient. I am might also
> think of a way to transform rotations around an arbitrary axis to their
> correspoding transformation angles around x,y,z axis that also is I assume
> possible...
> >
> >
> > On Tue, Apr 29, 2008 at 7:37 PM, Sina Türeli <[EMAIL PROTECTED]> wrote:
> >
> > >
> > >
> > > Ok, for a certain program I am writing (protein folding), I need to be
> able perform rotations. I was first planning to do it manually by defining
> rotation matrices and change of basis matrices etc but I think pdl might
> save me time. However I am not sure how to use its use PDL::Transform to do
> so. Here is a piece of code that I was using to experiment with pdl use PDL;
> > > use PDL::Transform;
> > >
> > > @a = [[1,0,0],[0,1,0],[0,0,1]];
> > >
> > > $c= pdl @a;
> > >
> > > $e = t_rot(45,45,45);
> > >
> > > $c = $e * $c
> > >
> > > print $c;
> > >
> > > I was hoping this would rotate my 1,1,1 vector in all directions by 45
> degrees but it gives the error. "Hash given as a pdl - but not {PDL} key!".
> I am not able to understand what this error is for? Also I have seen no
> tutorial where these rotationa matrices are explained so I would appreciate
> any help, thanks.
> > >
> > > --
> > > "Vectors have never been of the slightest use to any creature.
> Quaternions came from Hamilton after his really good work had been done; and
> though beautifully ingenious, have been an unmixed evil to those who have
> touched them in any way, including Maxwell." - Lord Kelvin
> > >
> > >
> > >
> > >
> >
> >
> >
> > --
> > "Vectors have never been of the slightest use to any creature. Quaternions
> came from Hamilton after his really good work had been done; and though
> beautifully ingenious, have been an unmixed evil to those who have touched
> them in any way, including Maxwell." - Lord Kelvin
> >
> > _______________________________________________
> >
> > Perldl mailing list
> > Perldl@jach.hawaii.edu
> > http://mailman.jach.hawaii.edu/mailman/listinfo/perldl
> >
>
>
>
> --
> "Vectors have never been of the slightest use to any creature. Quaternions
> came from Hamilton after his really good work had been done; and though
> beautifully ingenious, have been an unmixed evil to those who have touched
> them in any way, including Maxwell." - Lord Kelvin
>
> _______________________________________________
>  Perldl mailing list
>  Perldl@jach.hawaii.edu
>  http://mailman.jach.hawaii.edu/mailman/listinfo/perldl
>
>

_______________________________________________
Perldl mailing list
Perldl@jach.hawaii.edu
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to