Skip to content

Commit 4494715

Browse files
committed
Add fill_min_y and fill_max_y options.
These options allow restricting the fill region in the y range when filling between curves. Furthermore, these options can be combined with the fill_min and fill_max options to restrict the fill region to a rectangle.
1 parent 2755fcf commit 4494715

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

lib/Plots/JSXGraph.pm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ sub add_curve {
326326
if ($curve_name) {
327327
my $fill_min = $data->str_to_real($data->style('fill_min'));
328328
my $fill_max = $data->str_to_real($data->style('fill_max'));
329+
my $fill_min_y = $data->str_to_real($data->style('fill_min_y'));
330+
my $fill_max_y = $data->str_to_real($data->style('fill_max_y'));
329331
my $fill_layer = $self->get_layer($data, 1) // $self->get_layer($data);
330332
my $fillOptions = Mojo::JSON::encode_json({
331333
strokeWidth => 0,
@@ -361,12 +363,24 @@ sub add_curve {
361363
".filter(p => {"
362364
. "return p.usrCoords[1] >= $fill_min && p.usrCoords[1] <= $fill_max ? true : false" . "})";
363365
}
366+
if ($fill_min_y ne '' && $fill_max_y ne '') {
367+
$self->{JS} .=
368+
".filter(p => {"
369+
. "return p.usrCoords[2] >= $fill_min_y && p.usrCoords[2] <= $fill_max_y ? true : false"
370+
. "})";
371+
}
364372
$self->{JS} .= ";const points2 = curve_${fill}.points";
365373
if ($fill_min ne '' && $fill_max ne '') {
366374
$self->{JS} .=
367375
".filter(p => {"
368376
. "return p.usrCoords[1] >= $fill_min && p.usrCoords[1] <= $fill_max ? true : false" . "})";
369377
}
378+
if ($fill_min_y ne '' && $fill_max_y ne '') {
379+
$self->{JS} .=
380+
".filter(p => {"
381+
. "return p.usrCoords[2] >= $fill_min_y && p.usrCoords[2] <= $fill_max_y ? true : false"
382+
. "})";
383+
}
370384
$self->{JS} .=
371385
";this.dataX = points1.map( p => p.usrCoords[1] ).concat("
372386
. "points2.map( p => p.usrCoords[1] ).reverse());"

lib/Plots/Tikz.pm

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -685,18 +685,27 @@ sub draw {
685685
# Make sure this is the name from the data style attribute, and not an internal name.
686686
my $name = $data->style('name');
687687
if ($name) {
688-
my $opacity = $data->style('fill_opacity') || 0.5;
689-
my $fill_min = $data->style('fill_min');
690-
my $fill_max = $data->style('fill_max');
688+
my $opacity = $data->style('fill_opacity') || 0.5;
689+
my $fill_min = $data->style('fill_min');
690+
my $fill_max = $data->style('fill_max');
691+
my $fill_min_y = $data->style('fill_min_y');
692+
my $fill_max_y = $data->style('fill_max_y');
693+
my $fill_reverse = $data->style('fill_reverse');
691694
my $fill_range =
692-
$fill_min ne '' && $fill_max ne '' ? ", soft clip={domain=$fill_min:$fill_max}" : '';
695+
$fill_min ne '' && $fill_max ne '' && $fill_min_y ne '' && $fill_max_y ne ''
696+
? ", soft clip={($fill_min, $fill_min_y) rectangle ($fill_max, $fill_max_y)}"
697+
: $fill_min ne '' && $fill_max ne '' ? ", soft clip={domain=$fill_min:$fill_max}"
698+
: $fill_min_y ne '' && $fill_max_y ne '' ? ", soft clip={domain y=$fill_min_y:$fill_max_y}"
699+
: '';
693700
my $fill_layer = $data->style('fill_layer') || $layer;
701+
my $reverse = $fill_reverse eq '' ? '' : $fill_reverse ? ', reverse' : 'reverse=false';
694702
$tikzCode .=
695703
"\\begin{scope}[/tikz/fill between/on layer=$fill_layer]\\begin{pgfonlayer}{$fill_layer}"
696704
. "\\clip\\axisclippath;\n"
697705
if $fill_layer;
698706
$tikzCode .=
699-
"\\addplot[$fill_color, fill opacity=$opacity] fill between[of=$name and $fill$fill_range];\n";
707+
"\\addplot[$fill_color, fill opacity=$opacity] "
708+
. "fill between[of=$name and $fill$fill_range$reverse];\n";
700709
$tikzCode .= "\\end{pgfonlayer}\\end{scope}\n" if $fill_layer;
701710
} else {
702711
warn q{Unable to create fill. Missing 'name' attribute.};

macros/graph/plots.pl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,23 @@ =head2 DATASET OPTIONS
473473
fill_opacity => 0.2,
474474
);
475475
476+
The following fills the area between the two curves x = 4 - y^2 and x = y^2 - 4,
477+
and only fills in the area between y=-2 and y=2:
478+
479+
$plot->add_function(['4 - y^2', 'y'], 'y', -3, 3,
480+
color => 'blue',
481+
name => 'A'
482+
);
483+
$plot->add_function(['y^2 - 4', 'y'] 'y', -3, 3,
484+
color => 'blue',
485+
name => 'B',
486+
fill => 'A',
487+
fill_min_y => -2,
488+
fill_max_y => 2,
489+
fill_color => 'green',
490+
fill_opacity => 0.2,
491+
);
492+
476493
=item fill_color
477494
478495
The color used when filling the region. Default: C<color>
@@ -487,6 +504,30 @@ =head2 DATASET OPTIONS
487504
not defined, then the fill will use the full domain of the function.
488505
Default: undefined
489506
507+
=item fill_min_y, fill_max_y
508+
509+
The minimum and maximum y-values to fill between. If either of these are
510+
not defined, then the fill will use the full y range of the function.
511+
Default: undefined
512+
513+
Note that fill_min, fill_max, fill_min_y, and fill_max_y can be defined, and
514+
this will result in the region filled being restricted to the rectangle defined
515+
by those ranges.
516+
517+
=item fill_reverse
518+
519+
This should only be used if the TikZ output is filling the wrong region when
520+
filling between two curves. By default the pgfplots fillbetween library
521+
attempts to autodetect if one of the curves needs to be reversed in order to
522+
obtain the fill region between the curves. However, the heuristic used for the
523+
autodetection is sometimes wrong. Particularly when filling between two
524+
functions x of y using the C<fill_min_y> and C<fill_max_y> options. In that case
525+
set this option to either 0 or 1. If set to 1, then a reversal of one of the
526+
curves is forced. If set to 0, then no reversal will occur. If this is unset,
527+
then the pgfplots fillbetween library will attempt to auto detect if a reversal
528+
is needed. If the correct region is being filled as compared to the JSXGraph
529+
output, then leave this unset. Default: undefined
530+
490531
=item layer
491532
492533
The layer to draw on. Available layers are "axis background", "axis grid",

0 commit comments

Comments
 (0)