package Vector::Group; use strict; use Vector; use Carp; use vars qw( $VERSION $AUTOLOAD); $VERSION = "0.01"; sub AUTOLOAD { my $self = shift; my $element; $AUTOLOAD =~ s/.*:://; return if $AUTOLOAD eq 'DESTROY'; # don't fake these! segfault city my $new_group = $self->new; my $i; my @args = @_; foreach $element ($self->get_vectors) { #$new_group->set_vector($i++, $element->$AUTOLOAD(@_)); $new_group->set_vector($i++, $element->$AUTOLOAD(@args)); } return $new_group; } #sub Vector::Group::new sub new { my $implicit_argument = shift; my $class = ref($implicit_argument) || $implicit_argument; my $self = { vectors=>[] }; bless $self, $class; $self->add_vectors( @_ ) if (scalar(@_)); return $self; } sub add_vectors { my $self = shift; my $ref; foreach $ref (@_) { my $vector; unless (ref($ref)){ carp __PACKAGE__."::add_vectors is ignoring <$ref> since it isn't a ref to an array or some other object"; next; } $vector = Vector->new($ref) if ref($ref) eq 'ARRAY'; push @{$$self{vectors}}, $vector || $ref; } } sub set_vector { my $self = shift; my $index = shift; my $vectoray = shift; my $derived_vector; if (ref($vectoray) eq 'ARRAY') { $derived_vector = Vector->new($vectoray); } $$self{vectors}->[$index] = $derived_vector || $vectoray; #TODO make it return the number of vectors this added to the group } sub as_string { my $self = shift; my $string; my @vectors = $self->get_vectors; my $vector; $string = '[ '; foreach $vector (@vectors) { $string .= $vector->as_string; $string .= ' '; } $string .= ']'; return $string; } sub get_vectors { my $self = shift; if (! scalar(@_)) { return @{$$self{vectors}}; } # do we need this? elsif (scalar(@_) == 1) { return $$self{vectors}[$_[0]]; } else { #give them an array slice if they give us multiple indices return @{$$self{vectors}}[@_]; } } sub first { my $self = shift; return $self->{vectors}[0]; } sub last { my $self = shift; return $self->{vectors}[ $#{$$self{vectors}} ]; } #sub NdPoly::setPoint # #sub NdPoly::as_string # # #sub NdPoly::shift #{ # my $self = shift; # my $addend = shift; # my $last = scalar(@$addend) - 1; # my $point; # my $i; # # foreach $point ($self->getPoints) # { # foreach $i (0..$last) # { # $$point[$i] += $$addend[$i]; # } # } # #} sub smear { my $self = shift; my $smear_by_in = shift; # we're not sure what this is yet my $smear_by; # this will be the vector we're smearing by if (!ref($smear_by_in)) { croak ( 'Vector::Group::smear (called as '. ref($self) .'::smear)' .'needs either an array ref or something equivalent to a Vector'); } if (ref($smear_by_in) eq 'ARRAY') { $smear_by = new Vector($smear_by_in); } else { $smear_by = $smear_by_in; } # $new_group will be the "smeared" group that we return my $new_group = $self->new; # first, copy the whole group that was passed in, creating # the front face of the box $new_group->add_vectors( $self->get_vectors ); # now, we want to create the back face of the box as well # as the lines connecting each corner of the front face to # the back face. We will do this by going, one corner at # a time, down to the back face, along the edge of the # back face, up to the front face and back down to the # back face (the edges get drawn twice). # at this poing, we have already drawn the front face, # and the pen is at the last vector. So # we want to travel backwards through the vectors that # were passed in (which we will now call the "old vectors") # to draw the back face my @old_vectors = reverse $new_group->get_vectors; # the loop assumes the pen is at the back face, so we # will get that started here: # pull off the last of the old vectors... my $last_shall_be_first_vector = shift @old_vectors; # ...and add it's smeared value to the new_group $new_group->add_vectors( $last_shall_be_first_vector->plus($smear_by)); #$self->add_vector( ${shift @old_vectors}->plus($smear_by)); my $new_guy; my $vector; # now, as we go backwards through the rest of the # old vectors... foreach $vector ( @old_vectors) { # ..first get the smeared version of the old vector $new_guy = $vector->plus($smear_by); # add that to the group, drawing the edge of the back face $new_group->add_vectors($new_guy); # then go back up to the old vector and add that, # drawing the line connecting the corner $new_group->add_vectors($vector); # then back down the same line to the back face, so we're # ready for the next smeared one in the loop $new_group->add_vectors($new_guy); } # we already took care of the last vector by adding it's smeared # version in the beginning, so we're done, just return the # group return $new_group; } 1; __END__ # here's the docs =head1 NAME Vector::Group 0.01 - Groups of vectors =head1 SYNOPSIS use Vector::Group; $group = new Vector::Group; $a = new Vector ( [1,0,0] ); $b = new Vector ( [0,2,0] ); $c = new Vector ( [0,0,3] ); $group->add_vectors($a, $b, $c); $spin_test = $group->rotate([1,1,1], 2*$PI/3); print $spin_test->as_string; # sorry, POD isn't done sub new sub add_vectors sub set_vector sub as_string sub get_vectors sub smear =back =cut