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