Parent Directory
|
Revision Log
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 |