[system] / trunk / pg / lib / VectorField.pm Repository:
ViewVC logotype

View of /trunk/pg/lib/VectorField.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2274 - (download) (as text) (annotate)
Mon Jun 7 23:53:45 2004 UTC (15 years, 7 months ago) by sh002i
File size: 8005 byte(s)
got rid of remaining calls to "wwerror". Fixes bug #530.

    1 
    2 =head1 NAME
    3 
    4   VectorField
    5 
    6 =head1 SYNPOSIS
    7 
    8   use Carp;
    9   use GD;
   10   use WWPlot;
   11   use Fun;
   12   $fn = new Fun( rule_reference);
   13   $fn = new Fun( rule_reference , graph_reference);
   14   $fn = new Fun ( x_rule_ref, y_rule_ref );
   15   $fn = new Fun ( x_rule_ref, y_rule_ref, graph_ref );
   16 
   17 =head1 DESCRIPTION
   18 
   19 This module defines a phase plane vector field.  It can also be used to define direction fields
   20 for differenential equations.
   21 
   22 The following functions are provided:
   23 
   24 =head2  new  (direction field version)
   25 
   26 =over 4
   27 
   28 =item $fn = new VectorField( dy_rule_ref);
   29 
   30 rule_reference is a reference to a subroutine which accepts a pair of numerical values
   31 and returns a numerical value.
   32 The Fun object will draw the direction field associated with this subroutine.
   33 
   34 The new method returns a reference to the vector field object.
   35 
   36 =item $fn = new Fun( rule_reference , graph_reference);
   37 
   38 The vector field is also placed into the printing queue of the graph
   39  object pointed to by graph_reference and the
   40 domain of the vector field object is set to the domain of the graph.
   41 
   42 =back
   43 
   44 =head2  new  (phase plane version)
   45 
   46 =over 4
   47 
   48 =item $fn = new VectorField ( dx_rule_ref, dy_rule_ref );
   49 
   50 A vector field object is created where the subroutines refered to by dx_rule_ref and dy_rule_ref define
   51 the x and y components of the vector field at (x,y).  Both subroutines must be functions of two variables.
   52 
   53 =item $fn = new VectorField ( x_rule_ref, y_rule_ref, graph_ref );
   54 
   55 This variant inserts the vector field object into the graph object referred to by graph_ref.  The domain
   56 of the vector field object is set to the domain of the graph.
   57 
   58 =back
   59 
   60 =head2 Properites
   61 
   62   All of the properties are set using the construction $new_value = $fn->property($new_value)
   63   and read using $current_value = $fn->property()
   64 
   65 =over 4
   66 
   67 =item xmin, xmax, ymin, ymax
   68 
   69 The domain of the vector field defined by these values.
   70 
   71 =item x_steps y_steps
   72 
   73 This gives the number of intervals in the x direction (respectively the y direction) for plotting the vector
   74 field arrows.
   75 
   76 =item arrow_color, dot_color
   77 
   78 The colors of the arrow bodies and the dot "base" of the arrow are
   79  specified by a word such as 'orange' or 'yellow'.
   80 C<$vf->arrow_color('blue'); $vf->dot_color('red');> sets the drawing color to blue for the arrow body, with
   81 a red dot at the base of the arrow.  The RGB values for the color are defined in the graph
   82 object in which the vector field is drawn.  If the color, e.g. 'mauve', is not defined by the graph object
   83 then the function is drawn using the color 'default_color' which is always defined (and usually black).
   84 
   85 =item dx_rule
   86 
   87 A reference to the subroutine used to calculate the dx value of the phase plane field.
   88 This is set to the constant function 1
   89 when using the function object in direction field mode.
   90 
   91 =item dy_rule
   92 
   93 A reference to the subroutine used to calculate the dy value of the phase plane field.
   94 
   95 =item arrow_weight, dot_weight
   96 
   97 The width in pixels of the pen used to draw the arrow (respectively the dot).
   98 
   99 =back
  100 
  101 =head2 Actions which affect more than one property.
  102 
  103 =over 4
  104 
  105 
  106 =item domain
  107 
  108 $array_ref = $fn->domain(-1,-2,1,2) sets xmin to -1, ymin to -2, xmax to 1, and ymax to 2.
  109 
  110 
  111 =item draw
  112 
  113 $fn->draw($graph_ref) draws the vector field in the graph object pointed to by $graph_ref.
  114 
  115 The graph object must
  116 respond to the methods below.  The draw call is mainly for internal
  117 use by the graph object. Most users will not
  118 call it directly.
  119 
  120 =over 4
  121 
  122 =item   $graph_ref->{colors}
  123 
  124 a hash containing the defined colors
  125 
  126 =item $graph_ref ->im
  127 
  128 a GD image object
  129 
  130 =item $graph_ref->lineTo(x,y, color_number)
  131 
  132 draw line to the point (x,y) from the current position using the specified color.  To obtain the color number
  133 use a construction such as C<$color_number = $graph_ref->{colors}{'blue'};>
  134 
  135 =item $graph_ref->lineTo(x,y,gdBrushed)
  136 
  137 draw line to the point (x,y) using the pattern set by SetBrushed (see GD documentation)
  138 
  139 =item $graph_ref->moveTo(x,y)
  140 
  141 set the current position to (x,y)
  142 
  143 =back
  144 
  145 =back
  146 
  147 =cut
  148 
  149 BEGIN {
  150   be_strict(); # an alias for use strict.  This means that all global variable must contain main:: as a prefix.
  151 }
  152 
  153 package VectorField;
  154 
  155 
  156 #use "WWPlot.pm";
  157 #Because of the way problem modules are loaded 'use' is disabled.
  158 
  159 
  160 
  161 
  162 
  163 @VectorField::ISA = qw(WWPlot);
  164 # import gdBrushed from GD.  It unclear why, but a good many global methods haven't been imported.
  165 sub gdBrushed {
  166   &GD::gdBrushed();
  167 }
  168 
  169 my $GRAPH_REFERENCE = "WWPlot";
  170 my $VECTORFIELD_REFERENCE = "VectorField";
  171 
  172 my %fields =(
  173     xmin      =>  -4,
  174     xmax      =>  4,
  175     ymin          =>  -4,
  176     ymax          =>   4,
  177     x_steps     =>  10,
  178     y_steps     =>  10,
  179     arrow_color   =>  'blue',
  180     arrow_weight    =>  1,  #line thickness
  181     dot_color       =>  'red',
  182     dot_radius      =>  1.5,
  183     dt        =>  0.1,
  184     dx_rule       => sub{1;},
  185     dy_rule       => sub{1;},
  186     rf_arrow_length => sub{my($dx,$dy)=@_;
  187                                return(0) if sqrt($dx**2 + $dy**2) ==0;
  188                                0.5*1/sqrt($dx**2 + $dy**2);
  189                           },
  190 
  191 );
  192 
  193 
  194 sub new {
  195   my $class         = shift;
  196 
  197   my $self      = {
  198         _permitted  =>  \%fields,
  199         %fields,
  200   };
  201 
  202   bless $self, $class;
  203   $self -> _initialize(@_);
  204   return $self;
  205 }
  206 
  207 sub identity {  # the identity function
  208   shift;
  209 }
  210 
  211 
  212 sub _initialize {
  213   my  $self   =   shift;
  214   my  ($xrule,$yrule, $rule,$graphRef);
  215   my @input = @_;
  216   if (ref($input[$#input]) eq $GRAPH_REFERENCE ) {
  217     $graphRef = pop @input;  # get the last argument if it refers to a graph.
  218     $graphRef->fn($self);    # Install this vector field in the graph.
  219     $self->{xmin} = $graphRef->{xmin};
  220     $self->{xmax} = $graphRef->{xmax};
  221     $self->{ymin} = $graphRef->{ymin};
  222     $self->{ymax} = $graphRef->{ymax};
  223   }
  224     if ( @input == 1 ) {        # only one argument left -- this is a non parametric function
  225         $rule = $input[0];
  226     if ( ref($rule) eq $VECTORFIELD_REFERENCE ) {  # clone another function
  227       my $k;
  228       foreach $k (keys %fields) {
  229         $self->{$k} = $rule->{$k};
  230       }
  231     } else {
  232       $self->{dx_rule} = sub {1; };
  233       $self->{dy_rule} = $input[0] ;
  234     }
  235   } elsif (@input == 2 ) {   #  two arguments -- parametric functions
  236       $self->{dx_rule} = $input[0] ;
  237       $self->{dy_rule} = $input[1] ;
  238 
  239   } else {
  240     die "VectorField.pm:_initialize: Can't call VectorField with more than two arguments";
  241   }
  242 }
  243 sub draw {
  244     my $self = shift;  # this function
  245   my $g = shift;   # the graph containing the function.
  246   warn "This vector field is not being called from an enclosing graph" unless defined($g);
  247   my $arrow_color;   # get color scheme from graph
  248   if ( defined( $g->{'colors'}{$self->arrow_color} )  ) {
  249     $arrow_color = $g->{'colors'}{$self->arrow_color};
  250   } else {
  251     $arrow_color = $g->{'colors'}{'blue'};  # what you do if the color isn't there
  252   }
  253   my $dot_color = $self ->dot_color;  # colors are defined differently for Circles, then for lines.
  254   my $dot_radius  = $self->dot_radius;
  255   my $brush = new GD::Image($self->arrow_weight,$self->arrow_weight);
  256   my $brush_color = $brush->colorAllocate($g->im->rgb($arrow_color));  # transfer color
  257   $g->im->setBrush($brush);
  258     my $x_steps = 10;
  259   my $xmin = $self->xmin;
  260   my $x_stepsize = ( $self->xmax - $self->xmin )/$x_steps;
  261   my $y_steps = 10;
  262   my $ymin = $self->ymin;
  263   my $y_stepsize = ( $self->ymax - $self->ymin )/$y_steps;
  264   my $dt = $self->dt;
  265   my $rf_arrow_length = $self->rf_arrow_length;
  266 
  267     foreach my $i (0..$x_steps) {
  268       my $x = $xmin + $i*$x_stepsize;
  269       foreach my $j (0..$y_steps) {
  270         my $y = $ymin + $j*$y_stepsize;
  271         my $dx = $dt*&{$self->dx_rule}($x,$y);
  272         my $dy = $dt*&{$self->dy_rule}($x,$y);
  273         $g->moveTo($x,$y);
  274         $g->stamps(new Circle($x, $y, $dot_radius,$dot_color,$dot_color) );
  275         $g->lineTo($x+$dx*&$rf_arrow_length($dx,$dy), $y+$dy*&$rf_arrow_length($dx,$dy),gdBrushed);
  276 
  277       }
  278     }
  279 }
  280 
  281 sub domain {
  282   my $self =shift;
  283   my @inputs = @_;
  284     $self->{xmin} = $inputs[0];
  285     $self->{ymin} = $inputs[1];
  286     $self->{xmax} = $inputs[2];
  287   $self->{ymax} = $inputs[3];
  288 }
  289 
  290 
  291 sub DESTROY {
  292   # doing nothing about destruction, hope that isn't dangerous
  293 }
  294 
  295 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9