| 1 | #!/usr/local/bin/webwork-perl |
1 | |
| 2 | |
2 | |
| 3 | =head1 NAME |
3 | =head1 NAME |
| 4 | |
4 | |
| 5 | PGgraphmacros -- in courseScripts directory |
5 | PGgraphmacros -- in courseScripts directory |
| 6 | |
6 | |
| … | |
… | |
| 26 | |
26 | |
| 27 | =cut |
27 | =cut |
| 28 | |
28 | |
| 29 | =head2 Other constructs |
29 | =head2 Other constructs |
| 30 | |
30 | |
| 31 | See F<PGbasicmacros> for definitions of C<image> and C<caption> |
31 | See F<PGbasicmacros> for definitions of C<image> and C<caption> |
| 32 | |
32 | |
| 33 | =cut |
33 | =cut |
| 34 | |
34 | |
| 35 | |
35 | |
| 36 | #my $User = $main::studentLogin; |
36 | #my $User = $main::studentLogin; |
| … | |
… | |
| 49 | |
49 | |
| 50 | my %images_created = (); # this keeps track of the base names of the images created during this session. |
50 | my %images_created = (); # this keeps track of the base names of the images created during this session. |
| 51 | # We tack on |
51 | # We tack on |
| 52 | # $imageNum = ++$images_created{$imageName} to keep from overwriting files |
52 | # $imageNum = ++$images_created{$imageName} to keep from overwriting files |
| 53 | # when we don't want to. |
53 | # when we don't want to. |
| 54 | |
|
|
| 55 | |
54 | |
| 56 | |
55 | |
| 57 | |
56 | |
|
|
57 | |
| 58 | =head2 init_graph |
58 | =head2 init_graph |
| 59 | |
59 | |
| 60 | =pod |
60 | =pod |
| 61 | |
61 | |
| 62 | $graphObject = init_graph(xmin,ymin,xmax,ymax,'ticks'=>[4,4],'axes'=>[0,0]) |
62 | $graphObject = init_graph(xmin,ymin,xmax,ymax,'ticks'=>[4,4],'axes'=>[0,0]) |
| 63 | options are |
63 | options are |
| 64 | 'grid' =>[8,8] or |
64 | 'grid' =>[8,8] or |
| 65 | # there are 8 evenly spaced lines intersecting the horizontal axis |
65 | # there are 8 evenly spaced lines intersecting the horizontal axis |
| 66 | 'ticks'=>[8,8] and/or |
66 | 'ticks'=>[8,8] and/or |
| 67 | # there are 8 ticks on the horizontal axis, 8 on the vertical |
67 | # there are 8 ticks on the horizontal axis, 8 on the vertical |
| 68 | 'axes' => [0,0] |
68 | 'axes' => [0,0] |
| 69 | # axes pass through the point (0,0) in real coordinates |
69 | # axes pass through the point (0,0) in real coordinates |
| 70 | 'size' => [200,200] |
70 | 'size' => [200,200] |
| 71 | # dimensions of the graph in pixels. |
71 | # dimensions of the graph in pixels. |
| 72 | 'pixels' =>[200,200] # synonym for size |
72 | 'pixels' =>[200,200] # synonym for size |
| 73 | |
73 | |
| 74 | Creates a graph object with the default size 200 by 200 pixels. |
74 | Creates a graph object with the default size 200 by 200 pixels. |
| 75 | If you want axes or grids you need to specify them in options. But the default values can be selected for you. |
75 | If you want axes or grids you need to specify them in options. But the default values can be selected for you. |
| 76 | |
76 | |
| 77 | |
77 | |
| 78 | =cut |
78 | =cut |
| 79 | BEGIN { |
79 | BEGIN { |
| … | |
… | |
| 85 | } |
85 | } |
| 86 | #sub _PGgraphmacros_export { |
86 | #sub _PGgraphmacros_export { |
| 87 | # |
87 | # |
| 88 | # my @EXPORT = ( |
88 | # my @EXPORT = ( |
| 89 | # '&init_graph', '&add_functions', '&plot_functions', '&open_circle', |
89 | # '&init_graph', '&add_functions', '&plot_functions', '&open_circle', |
| 90 | # '&closed_circle', '&my_math_constants', '&string_to_sub', |
90 | # '&closed_circle', '&my_math_constants', '&string_to_sub', |
| 91 | # ); |
91 | # ); |
| 92 | # @EXPORT; |
92 | # @EXPORT; |
| 93 | #} |
93 | #} |
| 94 | |
94 | |
| 95 | sub init_graph { |
95 | sub init_graph { |
| … | |
… | |
| 107 | my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; |
107 | my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; |
| 108 | # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. |
108 | # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. |
| 109 | my $imageNum = ++$main::images_created{$imageName}; |
109 | my $imageNum = ++$main::images_created{$imageName}; |
| 110 | # this provides a unique name for the graph -- it does not include an extension. |
110 | # this provides a unique name for the graph -- it does not include an extension. |
| 111 | $graphRef->imageName("${imageName}image${imageNum}"); |
111 | $graphRef->imageName("${imageName}image${imageNum}"); |
| 112 | |
112 | |
| 113 | $graphRef->xmin($xmin) if defined($xmin); |
113 | $graphRef->xmin($xmin) if defined($xmin); |
| 114 | $graphRef->xmax($xmax) if defined($xmax); |
114 | $graphRef->xmax($xmax) if defined($xmax); |
| 115 | $graphRef->ymin($ymin) if defined($ymin); |
115 | $graphRef->ymin($ymin) if defined($ymin); |
| 116 | $graphRef->ymax($ymax) if defined($ymax); |
116 | $graphRef->ymax($ymax) if defined($ymax); |
| 117 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; |
117 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; |
| … | |
… | |
| 130 | } |
130 | } |
| 131 | $graphRef->v_grid('gray',@x_values); |
131 | $graphRef->v_grid('gray',@x_values); |
| 132 | $graphRef->h_grid('gray',@y_values); |
132 | $graphRef->h_grid('gray',@y_values); |
| 133 | $graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','middle')); |
133 | $graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','middle')); |
| 134 | $graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f",$y_delta),'black','center','middle')); |
134 | $graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f",$y_delta),'black','center','middle')); |
| 135 | |
135 | |
| 136 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
136 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
| 137 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
137 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
| 138 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
138 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
| 139 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
139 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
| 140 | |
140 | |
| 141 | } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks |
141 | } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks |
| 142 | my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) |
142 | my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) |
| 143 | my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; |
143 | my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; |
| 144 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; |
144 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; |
| 145 | my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; |
145 | my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; |
| … | |
… | |
| 152 | } |
152 | } |
| 153 | $graphRef->v_ticks(0,'black',@x_values); |
153 | $graphRef->v_ticks(0,'black',@x_values); |
| 154 | $graphRef->h_ticks(0,'black',@y_values); |
154 | $graphRef->h_ticks(0,'black',@y_values); |
| 155 | $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); |
155 | $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); |
| 156 | $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); |
156 | $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); |
| 157 | |
157 | |
| 158 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
158 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
| 159 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
159 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
| 160 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
160 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
| 161 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
161 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
| 162 | } |
162 | } |
| 163 | |
163 | |
| 164 | if ($options{axes}) { # draw axis |
164 | if ($options{axes}) { # draw axis |
| 165 | my $ra_axes = $options{axes}; |
165 | my $ra_axes = $options{axes}; |
| 166 | $graphRef->h_axis($ra_axes->[1],'black'); |
166 | $graphRef->h_axis($ra_axes->[1],'black'); |
| 167 | $graphRef->v_axis($ra_axes->[0],'black'); |
167 | $graphRef->v_axis($ra_axes->[0],'black'); |
| 168 | } |
168 | } |
| 169 | |
169 | |
| 170 | |
170 | |
| 171 | $graphRef; |
171 | $graphRef; |
| 172 | } |
172 | } |
| 173 | |
173 | |
| 174 | sub init_graph_no_labels { |
174 | sub init_graph_no_labels { |
| 175 | my ($xmin,$ymin,$xmax,$ymax,%options) = @_; |
175 | my ($xmin,$ymin,$xmax,$ymax,%options) = @_; |
| … | |
… | |
| 186 | my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; |
186 | my $imageName = "$main::studentLogin-$main::psvnNumber-set${main::setNumber}prob${main::probNum}"; |
| 187 | # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. |
187 | # $imageNum counts the number of graphs with this name which have been created since PGgraphmacros.pl was initiated. |
| 188 | my $imageNum = ++$main::images_created{$imageName}; |
188 | my $imageNum = ++$main::images_created{$imageName}; |
| 189 | # this provides a unique name for the graph -- it does not include an extension. |
189 | # this provides a unique name for the graph -- it does not include an extension. |
| 190 | $graphRef->imageName("${imageName}image${imageNum}"); |
190 | $graphRef->imageName("${imageName}image${imageNum}"); |
| 191 | |
191 | |
| 192 | $graphRef->xmin($xmin) if defined($xmin); |
192 | $graphRef->xmin($xmin) if defined($xmin); |
| 193 | $graphRef->xmax($xmax) if defined($xmax); |
193 | $graphRef->xmax($xmax) if defined($xmax); |
| 194 | $graphRef->ymin($ymin) if defined($ymin); |
194 | $graphRef->ymin($ymin) if defined($ymin); |
| 195 | $graphRef->ymax($ymax) if defined($ymax); |
195 | $graphRef->ymax($ymax) if defined($ymax); |
| 196 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; |
196 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/8; |
| … | |
… | |
| 211 | $graphRef->h_grid('gray',@y_values); |
211 | $graphRef->h_grid('gray',@y_values); |
| 212 | #$graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','top')); |
212 | #$graphRef->lb(new Label($x_delta,0,sprintf("%1.1f",$x_delta),'black','center','top')); |
| 213 | #$graphRef->lb(new Label($x_delta,0,"|",'black','center','middle')); |
213 | #$graphRef->lb(new Label($x_delta,0,"|",'black','center','middle')); |
| 214 | #$graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f ",$y_delta),'black','right','middle')); |
214 | #$graphRef->lb(new Label(0,$y_delta,sprintf("%1.1f ",$y_delta),'black','right','middle')); |
| 215 | #$graphRef->lb(new Label(0,$y_delta,"-",'black','center','middle')); |
215 | #$graphRef->lb(new Label(0,$y_delta,"-",'black','center','middle')); |
| 216 | |
216 | |
| 217 | |
217 | |
| 218 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
218 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
| 219 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
219 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
| 220 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top','right')); |
220 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top','right')); |
| 221 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
221 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
| 222 | |
222 | |
| 223 | } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks |
223 | } elsif ($options{ticks}) { # draw ticks -- grid over rides ticks |
| 224 | my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) |
224 | my $xdiv = ${$options{ticks}}[0]? ${$options{ticks}}[0] : 8; # number of ticks (8 is default) |
| 225 | my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; |
225 | my $ydiv = ${$options{ticks}}[1]? ${$options{ticks}}[1] : 8; |
| 226 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; |
226 | my $x_delta = ($graphRef->xmax - $graphRef->xmin)/$xdiv; |
| 227 | my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; |
227 | my $y_delta = ($graphRef->ymax - $graphRef->ymin)/$ydiv; |
| … | |
… | |
| 234 | } |
234 | } |
| 235 | $graphRef->v_ticks(0,'black',@x_values); |
235 | $graphRef->v_ticks(0,'black',@x_values); |
| 236 | $graphRef->h_ticks(0,'black',@y_values); |
236 | $graphRef->h_ticks(0,'black',@y_values); |
| 237 | $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); |
237 | $graphRef->lb(new Label($x_delta,0,$x_delta,'black','right')); |
| 238 | $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); |
238 | $graphRef->lb(new Label(0,$y_delta,$y_delta,'black','top')); |
| 239 | |
239 | |
| 240 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
240 | $graphRef->lb(new Label($xmax,0,$xmax,'black','right')); |
| 241 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
241 | $graphRef->lb(new Label($xmin,0,$xmin,'black','left')); |
| 242 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
242 | $graphRef->lb(new Label(0,$ymax,$ymax,'black','top')); |
| 243 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
243 | $graphRef->lb(new Label(0,$ymin,$ymin,'black','bottom','right')); |
| 244 | } |
244 | } |
| 245 | |
245 | |
| 246 | if ($options{axes}) { # draw axis |
246 | if ($options{axes}) { # draw axis |
| 247 | my $ra_axes = $options{axes}; |
247 | my $ra_axes = $options{axes}; |
| 248 | $graphRef->h_axis($ra_axes->[1],'black'); |
248 | $graphRef->h_axis($ra_axes->[1],'black'); |
| 249 | $graphRef->v_axis($ra_axes->[0],'black'); |
249 | $graphRef->v_axis($ra_axes->[0],'black'); |
| 250 | } |
250 | } |
| 251 | |
251 | |
| 252 | |
252 | |
| 253 | $graphRef; |
253 | $graphRef; |
| 254 | } |
254 | } |
| 255 | |
255 | |
| 256 | |
256 | |
| 257 | |
257 | |
| … | |
… | |
| 259 | |
259 | |
| 260 | =pod |
260 | =pod |
| 261 | |
261 | |
| 262 | Usage: ($f1, $f2, $f3) = plot_functions($graph, $f1, $f2, $f3); |
262 | Usage: ($f1, $f2, $f3) = plot_functions($graph, $f1, $f2, $f3); |
| 263 | Synonym: add_functions($graph,$f1,$f2,$f3); |
263 | Synonym: add_functions($graph,$f1,$f2,$f3); |
| 264 | |
264 | |
| 265 | Where $f1 is a string of the form |
265 | Where $f1 is a string of the form |
| 266 | |
266 | |
| 267 | $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2! |
267 | $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2! |
| 268 | |
268 | |
| 269 | The phrase translates as: formula B<for> variable B<in> interval B<using> option-list. |
269 | The phrase translates as: formula B<for> variable B<in> interval B<using> option-list. |
| 270 | The option-list contains pairs of the form attribute:value. |
270 | The option-list contains pairs of the form attribute:value. |
| 271 | The default for color is "default_color" which is usually black. |
271 | The default for color is "default_color" which is usually black. |
| 272 | The default for the weight (pixel width) of the pen is 2 pixels. |
272 | The default for the weight (pixel width) of the pen is 2 pixels. |
| 273 | |
273 | |
| 274 | The string_to_sub subroutine is used to translate the formula into a subroutine. |
274 | The string_to_sub subroutine is used to translate the formula into a subroutine. |
| 275 | |
275 | |
| 276 | The functions in the list are installed in the graph object $graph and will appear when the graph object is next drawn. |
276 | The functions in the list are installed in the graph object $graph and will appear when the graph object is next drawn. |
| 277 | |
277 | |
| 278 | =cut |
278 | =cut |
| 279 | |
279 | |
| … | |
… | |
| 291 | foreach $fn (@function_list) { |
291 | foreach $fn (@function_list) { |
| 292 | |
292 | |
| 293 | # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2" |
293 | # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2" |
| 294 | if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) { |
294 | if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) { |
| 295 | my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options)= ($1, $2, $3, $4, $5, $6, $7); |
295 | my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options)= ($1, $2, $3, $4, $5, $6, $7); |
| 296 | |
296 | |
| 297 | my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options); |
297 | my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options); |
| 298 | my ($color, $weight); |
298 | my ($color, $weight); |
| 299 | if ( defined($options{'color'}) ){ |
299 | if ( defined($options{'color'}) ){ |
| 300 | $color = $options{'color'}; #set pen color |
300 | $color = $options{'color'}; #set pen color |
| 301 | } else { |
301 | } else { |
| 302 | $color = 'default_color'; |
302 | $color = 'default_color'; |
| 303 | } |
303 | } |
| 304 | if ( defined($options{'weight'}) ) { |
304 | if ( defined($options{'weight'}) ) { |
| 305 | $weight = $options{'weight'}; # set pen weight (width in pixels) |
305 | $weight = $options{'weight'}; # set pen weight (width in pixels) |
| 306 | } else { |
306 | } else { |
| 307 | $weight =2; |
307 | $weight =2; |
| 308 | } |
308 | } |
| 309 | |
309 | |
| 310 | my $subRef = string_to_sub($rule,$var); |
310 | my $subRef = string_to_sub($rule,$var); |
| 311 | my $funRef = new Fun($subRef,$graph); |
311 | my $funRef = new Fun($subRef,$graph); |
| 312 | $funRef->color($color); |
312 | $funRef->color($color); |
| 313 | $funRef->weight($weight); |
313 | $funRef->weight($weight); |
| 314 | $funRef->domain($left_end , $right_end); |
314 | $funRef->domain($left_end , $right_end); |
| … | |
… | |
| 316 | # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3> |
316 | # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3> |
| 317 | if ($left_br eq '[' ) { |
317 | if ($left_br eq '[' ) { |
| 318 | $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) ); |
318 | $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) ); |
| 319 | } elsif ($left_br eq '(' ) { |
319 | } elsif ($left_br eq '(' ) { |
| 320 | $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) ); |
320 | $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) ); |
| 321 | } |
321 | } |
| 322 | if ($right_br eq ']' ) { |
322 | if ($right_br eq ']' ) { |
| 323 | $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) ); |
323 | $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) ); |
| 324 | } elsif ($right_br eq ')' ) { |
324 | } elsif ($right_br eq ')' ) { |
| 325 | $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) ); |
325 | $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) ); |
| 326 | } |
326 | } |
| 327 | |
327 | |
| 328 | } else { |
328 | } else { |
| 329 | $error .= "Error in parsing: $fn $main::BR"; |
329 | $error .= "Error in parsing: $fn $main::BR"; |
| 330 | } |
330 | } |
| 331 | |
331 | |
| 332 | } |
332 | } |
| 333 | die ("Error in plot_functions: \n\t $error ") if $error; |
333 | die ("Error in plot_functions: \n\t $error ") if $error; |
| 334 | @functions; # return function references unless there is an error. |
334 | @functions; # return function references unless there is an error. |
| 335 | } |
335 | } |
| 336 | |
336 | |
| 337 | =head2 insertGraph |
337 | =head2 insertGraph |
| 338 | |
338 | |
| 339 | $filePath = insertGraph(graphObject); |
339 | $filePath = insertGraph(graphObject); |
| 340 | returns a path to the file containing the graph image. |
340 | returns a path to the file containing the graph image. |
| 341 | |
341 | |
| 342 | B<Note:> Because insertGraph involves writing to the disk, it is actually defined in dangerousMacros.pl. |
342 | B<Note:> Because insertGraph involves writing to the disk, it is actually defined in dangerousMacros.pl. |
| 343 | |
343 | |
| 344 | insertGraph(graphObject) writes a image file to the C<html/tmp/gif> directory of the current course. |
344 | insertGraph(graphObject) writes a image file to the C<html/tmp/gif> directory of the current course. |
| 345 | The file name is obtained from the graphObject. Warnings are issued if errors occur while writing to |
345 | The file name is obtained from the graphObject. Warnings are issued if errors occur while writing to |
| 346 | the file. |
346 | the file. |
| 347 | |
347 | |
| 348 | The permissions and ownership of the file are controlled by C<$main::tmp_file_permission> |
348 | The permissions and ownership of the file are controlled by C<$main::tmp_file_permission> |
| 349 | and C<$main::numericalGroupID>. |
349 | and C<$main::numericalGroupID>. |
| 350 | |
350 | |
| 351 | B<Returns:> A string containing the full path to the temporary file containing the image. |
351 | B<Returns:> A string containing the full path to the temporary file containing the image. |
| … | |
… | |
| 353 | |
353 | |
| 354 | |
354 | |
| 355 | InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$imageName.gif (or .png)" where |
355 | InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$imageName.gif (or .png)" where |
| 356 | the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure |
356 | the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure |
| 357 | that the correct directory separators are used for the platform and that the necessary directories |
357 | that the correct directory separators are used for the platform and that the necessary directories |
| 358 | are created if they are not already present. The directory address to the file is the result. |
358 | are created if they are not already present. The directory address to the file is the result. |
| 359 | |
359 | |
| 360 | The most common use of C,insertGraph> is |
360 | The most common use of C,insertGraph> is |
| 361 | |
361 | |
| 362 | TEXT(image(insertGraph($graph)) ); |
362 | TEXT(image(insertGraph($graph)) ); |
| 363 | |
363 | |
| … | |
… | |
| 365 | |
365 | |
| 366 | Another common usage is: |
366 | Another common usage is: |
| 367 | |
367 | |
| 368 | TEXT(htmlLink( alias(insertGraph($graph), "picture" ) ) ); |
368 | TEXT(htmlLink( alias(insertGraph($graph), "picture" ) ) ); |
| 369 | |
369 | |
| 370 | which inserts the URL pointing to the picture. |
370 | which inserts the URL pointing to the picture. |
| 371 | alias converts the directory address to a URL when serving HTML pages and insures that |
371 | alias converts the directory address to a URL when serving HTML pages and insures that |
| 372 | an eps file is generated when creating TeX code for downloading. (Image, automatically applies alias to its input |
372 | an eps file is generated when creating TeX code for downloading. (Image, automatically applies alias to its input |
| 373 | in order to obtain the URL.) |
373 | in order to obtain the URL.) |
| 374 | |
374 | |
| 375 | See the documentation in F<dangerousMacros.pl> for the latest details. |
375 | See the documentation in F<dangerousMacros.pl> for the latest details. |
| 376 | |
376 | |
| … | |
… | |
| 379 | =head2 'Circle' lables |
379 | =head2 'Circle' lables |
| 380 | |
380 | |
| 381 | Usage: $circle_object = open_circle( $x_position, $y_position, $color ); |
381 | Usage: $circle_object = open_circle( $x_position, $y_position, $color ); |
| 382 | $circle_object2 = closed_circle( $x_position, $y_position, $color ); |
382 | $circle_object2 = closed_circle( $x_position, $y_position, $color ); |
| 383 | |
383 | |
| 384 | Creates a small open (resp. filled in or closed) circle for use as a stamp in marking graphs. |
384 | Creates a small open (resp. filled in or closed) circle for use as a stamp in marking graphs. |
| 385 | For example |
385 | For example |
| 386 | |
386 | |
| 387 | $graph -> stamps($circle_object2); # puts a filled dot at $x_position, $y_position |
387 | $graph -> stamps($circle_object2); # puts a filled dot at $x_position, $y_position |
| 388 | |
388 | |
| 389 | =cut |
389 | =cut |
| … | |
… | |
| 410 | |
410 | |
| 411 | |
411 | |
| 412 | Usage: $string = my_math_constants($string) |
412 | Usage: $string = my_math_constants($string) |
| 413 | $subroutine_reference = my_string_to_sub($string) |
413 | $subroutine_reference = my_string_to_sub($string) |
| 414 | |
414 | |
| 415 | C<my_math_constants> |
415 | C<my_math_constants> |
| 416 | interprets pi, e as mathematical constants 3.1415926... and 2.71828... respectively. (Case is important). |
416 | interprets pi, e as mathematical constants 3.1415926... and 2.71828... respectively. (Case is important). |
| 417 | The power operator ^ is replaced by ** to conform with perl constructs |
417 | The power operator ^ is replaced by ** to conform with perl constructs |
| 418 | |
418 | |
| 419 | C<string_to_sub> |
419 | C<string_to_sub> |
| 420 | converts a string defining a single perl arithmetic expression with independent variable $XVAR into a subroutine. |
420 | converts a string defining a single perl arithmetic expression with independent variable $XVAR into a subroutine. |
| 421 | The string is first filtered through C<my_math_macros>. The resulting subroutine |
421 | The string is first filtered through C<my_math_macros>. The resulting subroutine |
| 422 | takes a single real number as input and produces a single output value. |
422 | takes a single real number as input and produces a single output value. |
| 423 | |
423 | |
| 424 | =cut |
424 | =cut |
| 425 | |
425 | |
| 426 | sub my_math_constants { |
426 | sub my_math_constants { |
| 427 | my($in) = @_; |
427 | my($in) = @_; |
| 428 | $in =~s/\bpi\b/(4*atan2(1,1))/g; |
428 | $in =~s/\bpi\b/(4*atan2(1,1))/g; |
| 429 | $in =~s/\be\b/(exp(1))/g; |
429 | $in =~s/\be\b/(exp(1))/g; |
| 430 | $in =~s/\^/**/g; |
430 | $in =~s/\^/**/g; |
| 431 | $in; |
431 | $in; |
| 432 | } |
432 | } |
| … | |
… | |
| 447 | warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag}; |
447 | warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag}; |
| 448 | $out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function. |
448 | $out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function. |
| 449 | |
449 | |
| 450 | } else { |
450 | } else { |
| 451 | my $in =$str_in; |
451 | my $in =$str_in; |
| 452 | |
452 | |
| 453 | $in =~ s/\b$var\b/\$XVAR/g; |
453 | $in =~ s/\b$var\b/\$XVAR/g; |
| 454 | $in = &my_math_constants($in); |
454 | $in = &my_math_constants($in); |
| 455 | my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } "); |
455 | my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } "); |
| 456 | if ($PG_eval_errors) { |
456 | if ($PG_eval_errors) { |
| 457 | die " ERROR while defining a function from the string:\n\n$main::BR $main::BR $str_in $main::BR $main::BR\n\n $PG_eval_errors" |
457 | die " ERROR while defining a function from the string:\n\n$main::BR $main::BR $str_in $main::BR $main::BR\n\n $PG_eval_errors" |
| 458 | } else { |
458 | } else { |
| 459 | $out = $subRef; |
459 | $out = $subRef; |
| 460 | } |
460 | } |
| 461 | |
461 | |
| 462 | } |
462 | } |
| 463 | $out; |
463 | $out; |
| 464 | } |
464 | } |
| 465 | |
465 | |
| 466 | |
466 | |