PREP 2015 Question Authoring - Archived

How to get more points plotted on a curve to get better looking curves.

How to get more points plotted on a curve to get better looking curves.

by Gary Church -
Number of replies: 4
Hello,

I'm trying to create a problem using graphs. I can get my graph (a sine function) to plot but it is "janky"; not enough points are chosen for the plot to create a nice smooth graph (see below). Is there any way to increase the number of points chosen in the domain to get a smoother graph?
Church-4345-setChurch-Homework3prob4image1.png

Here's my code for the problem:
DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGgraphmacros.pl",
"PGML.pl",
"AnswerFormatHelp.pl",
"PGcourse.pl",
);

TEXT(beginproblem());
$showPartialCorrectAnswers = 1;
$refreshCachedImages = 1;

Context("Point");

$pix = 400;

# Create the canvas 
#$pixels=>[2000,2000];
$gr = init_graph(-10,-10,10,10,  # xmin, ymin, xmax, ymax
axes=>[0,0], grid=>[20,20], size=>[$pix,$pix]);
$gr -> lb('reset'); # remove default labels

# axes labels
$gr->lb( new Label(9.5,0,'x', 'black', 'center', 'bottom'));
$gr->lb( new Label(0.1,9.5,'y', 'black', 'left', 'middle'));

# axes labels
foreach my $i (-10..10) {
  $gr->lb( new Label($i,0, $i, 'black', 'center', 'top'));
  $gr->lb( new Label(-0.1,$i, $i, 'black', 'right', 'middle'));
}

# plot a function

$d = random(-9,9,1);

if (abs($d - 10) < abs($d + 10)) {
   $a = random(0.5, abs($d - 10), 0.5); }
else {
   $a = random(0.5, abs($d + 10), 0.5); }

$b = random(0.5,5,0.5);
$c = random(0,$b,0.25);

#$f = Formula("$a*sin(2*pi/$b * (x - $c)) + $d");
$f = Formula("3*sin(2*pi/3 * (x - 1)) + 3");
add_functions($gr, "$f for x in <-10,10> using color:blue and weight:2");

$answer = Point("(0,$b)");

BEGIN_PGML
[%What are the coordinates of the vertex of the parabola in the graph?
[____________]{$answer} [@ AnswerFormatHelp("points") @]*%]

>> [@ image(insertGraph($gr), width=>$pix, height=>$pix, tex_size=>800) @]*  
A sine graph. <<
END_PGML


COMMENT("MathObject version.  Uses PGML.");

ENDDOCUMENT();
In reply to Gary Church

Re: How to get more points plotted on a curve to get better looking curves.

by Paul Pearson -
Hi Gary,

This has been on my personal annoyance list since the very first semester I used WeBWorK.  Since WeBWorK only plots N points on the domain you specify, one way to get more samples is to plot the function in two (or more) parts.  For instance, the code below plots the function $f on -10 <= x <= 0 and again on 0 <= x <= 10 and achieves a pretty good looking result.  

###### begin PG code ###########

$f = Formula("3*sin(2*pi/3 * (x - 1)) + 3");
add_functions($gr, "$f for x in <-10,0> using color:blue and weight:2");
add_functions($gr, "$f for x in <0,10> using color:blue and weight:2");

###### end PG code ###########

Another, more complicated, option would be to generate the plot points yourself and connect them by line segments.  This is illustrated in the code below.

###### begin PG code ##########

$g = Formula("3*sin(2*pi/3 * (x - 1)) - 3");
@x = map { $_/10 } (-100..100); # take the integers from -100 to 100 and divide them each by 10
#@y = map { $g->eval(x=>$_) } @x; # this works, but the perlFunction on the next line should be faster
@y = map { &{$g->perlFunction}($_) } @x; # evaluate the function g at the points in @x
$gr -> moveTo( $x[0], $y[0] ); # move the plotting cursor
foreach my $i (1..$#x) { $gr->lineTo($x[$i],$y[$i],'red',2); } # connecting line segments

###### end PG code ############

I have included a complete PG file below with both of these options plotted.  The file displays to the student some of the properties of @x and @y, which I used as a means for debugging.

Best regards,

Paul Pearson

############### begin PG file ###############

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGgraphmacros.pl",
"PGML.pl",
"AnswerFormatHelp.pl",
"PGcourse.pl",
);

TEXT(beginproblem());
$showPartialCorrectAnswers = 1;
$refreshCachedImages = 1;

Context("Point");

$pix = 400;

# Create the canvas 
#$pixels=>[2000,2000];
$gr = init_graph(-10,-10,10,10,  # xmin, ymin, xmax, ymax
axes=>[0,0], grid=>[20,20], size=>[$pix,$pix]);
$gr -> lb('reset'); # remove default labels

# axes labels
$gr->lb( new Label(9.5,0,'x', 'black', 'center', 'bottom'));
$gr->lb( new Label(0.1,9.5,'y', 'black', 'left', 'middle'));

# axes labels
foreach my $i (-10..10) {
  $gr->lb( new Label($i,0, $i, 'black', 'center', 'top'));
  $gr->lb( new Label(-0.1,$i, $i, 'black', 'right', 'middle'));
}

# plot a function

$d = random(-9,9,1);

if (abs($d - 10) < abs($d + 10)) {
   $a = random(0.5, abs($d - 10), 0.5); }
else {
   $a = random(0.5, abs($d + 10), 0.5); }

$b = random(0.5,5,0.5);
$c = random(0,$b,0.25);

#$f = Formula("$a*sin(2*pi/$b * (x - $c)) + $d");

$f = Formula("3*sin(2*pi/3 * (x - 1)) + 3");
add_functions($gr, "$f for x in <-10,0> using color:blue and weight:2");
add_functions($gr, "$f for x in <0,10> using color:blue and weight:2");

$g = Formula("3*sin(2*pi/3 * (x - 1)) - 3");
@x = map { $_/10 } (-100..100);
#@y = map { $g->eval(x=>$_) } @x; # this works, but the perlFunction on the next line should be faster
@y = map { &{$g->perlFunction}($_) } @x;
$gr -> moveTo( $x[0], $y[0] );
foreach my $i (1..$#x) { $gr->lineTo($x[$i],$y[$i],'red',2); }

$answer = Point("(0,$b)");

BEGIN_PGML
+ length of @x: [@ scalar(@x); @]*
+ x-values: [@ join(', ' , @x) @]*
+ length of @y: [@ scalar(@y); @]*
+ y-values: [@ join(', ' , @y) @]*


[%What are the coordinates of the vertex of the parabola in the graph?
[____________]{$answer} [@ AnswerFormatHelp("points") @]*%]

>> [@ image(insertGraph($gr), width=>$pix, height=>$pix, tex_size=>800) @]*  
A sine graph. <<
END_PGML


COMMENT("MathObject version.  Uses PGML.");

ENDDOCUMENT();

############### end PG file #####################

In reply to Paul Pearson

Re: How to get more points plotted on a curve to get better looking curves.

by Paul Pearson -
Hi (again),

I just remembered that the parametric graphing utilities in WeBWorK could also be used for this and they do provide the user control over the number of points plotted.  For instance, modifying the example at

http://webwork.maa.org/wiki/PolarGraph1

to use 

########### begin pg code ############

$x = Formula("t"); 
$y = Formula("cos(t)");
...
$f->domain(-10,10);
$f->steps(100);

########### end pg code #############

should plot the graph of y=cos(x) with 100 sample points (steps).

Best regards,

Paul Pearson
In reply to Paul Pearson

Re: How to get more points plotted on a curve to get better looking curves.

by Davide Cervone -
You actually can control the steps even for the standard graphics commands. If $gr is the graph object, and a function has been added to it using add_functions(), then $gr->fn will return an array consisting of function objects (not MathObject functions, but WWPlot functions) that will be plotted, and you can use those to set the number of steps for the plotting.

In your example, there is only one function, so you could add

($gr->fn)[0]->steps(200);
right after the add_functions() call to use 200 intervals rather than the default 50.
In reply to Davide Cervone

Re: How to get more points plotted on a curve to get better looking curves.

by Gary Church -
Brilliant!

Thanks so much for all of your thoughtful solutions (Paul and Davide) approve