This is the class, heavily inspired by Math::3Space, and following discussions on interoperation between that and PDL (see https://github.com/nrdvana/perl-Math-3Space/pull/8). The basis and origin members are "subscribed" to both their own local basis and origin, and their parent's if any. The basis_update and origin_move methods only update the local members, both in terms of previous values.{package PDL::3Space; use PDL; sub new { my ($class, $parent) = @_; my $self = bless {basis_local=>identity(3), origin_local=>zeroes(3)} +, $class; if (defined $parent) { $self->{parent} = $parent; $self->{basis} = $self->{basis_local}->flowing x $parent->{basis}- +>flowing; $self->{origin} = ($self->{origin_local}->flowing x $self->{basis} +->flowing)->flowing + $parent->{origin}->flowing; } else { $self->{basis} = $self->{basis_local}; $self->{origin} = $self->{origin_local}->flowing x $self->{basis}- +>flowing; } $self; } use overload '""' => sub {$_[0]{basis}->glue(1,$_[0]{origin}).''}; sub basis_update { $_[0]{basis_local} .= $_[1] x $_[0]{basis_local} } sub origin_move { $_[0]{origin_local} += $_[1] } sub local { my $local = PDL::3Space->new; $local->{$_} .= $_[0]{$_} fo +r qw(basis_local origin_local); $local} }
The demonstrating code has a boat, and a bird within its frame of reference. Note that the "local" origin still gets affected by its local basis.
The basis and origin are always in global coordinates, and thanks to dataflow, are only recalculated on demand.
$rot_90_about_z = PDL->pdl([0,1,0], [-1,0,0], [0,0,1]); $boat = PDL::3Space->new; print "boat=$boat"; $bird = PDL::3Space->new($boat); print "bird=$bird"; # boat= # [ # [1 0 0] # [0 1 0] # [0 0 1] # [0 0 0] # ] # bird= # [ # [1 0 0] # [0 1 0] # [0 0 1] # [0 0 0] # ] $boat->basis_update($rot_90_about_z); print "after boat rot:\nboat=$boat"; print "bird=$bird"; # after boat rot: # boat= # [ # [ 0 1 0] # [-1 0 0] # [ 0 0 1] # [ 0 0 0] # ] # bird= # [ # [ 0 1 0] # [-1 0 0] # [ 0 0 1] # [ 0 0 0] # ] $boat->origin_move(PDL->pdl(1,0,0)); print "after boat move:\nboat=$boat"; print "bird=$bird"; print "bird local=".$bird->local; # after boat move: # boat= # [ # [ 0 1 0] # [-1 0 0] # [ 0 0 1] # [ 0 1 0] # ] # bird= # [ # [ 0 1 0] # [-1 0 0] # [ 0 0 1] # [ 0 1 0] # ] # bird local= # [ # [1 0 0] # [0 1 0] # [0 0 1] # [0 0 0] # ] $bird->basis_update($rot_90_about_z); $bird->origin_move(PDL->pdl(1,0,1)); print "after bird rot and move:\nbird=$bird"; print "bird local=".$bird->local; # after bird rot and move: # bird= # [ # [-1 0 0] # [ 0 -1 0] # [ 0 0 1] # [-1 1 1] # ] # bird local= # [ # [ 0 1 0] # [-1 0 0] # [ 0 0 1] # [ 0 1 1] # ] $boat->basis_update(PDL::MatrixOps::identity(3) * 2); print "after boat expand:\nboat=$boat"; print "bird=$bird"; # after boat expand: # boat= # [ # [ 0 2 0] # [-2 0 0] # [ 0 0 2] # [ 0 2 0] # ] # bird= # [ # [-2 0 0] # [ 0 -2 0] # [ 0 0 2] # [-2 2 2] # ]
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Example of PDL dataflow to implement 3D space calculations
by NERDVANA (Priest) on Jul 08, 2024 at 08:12 UTC | |
by etj (Priest) on Jul 12, 2024 at 18:39 UTC |