Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions htdocs/js/Plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,18 @@ const PGplots = {
}
},

// Override the default axis generateLabelText method so that 0 is displayed
// using MathJax if the axis is configured to show tick labels using MathJax.
// Override the default axis generateLabelText method to show custom tick labels if they are set, and so
// that 0 is displayed using MathJax if the axis is configured to show tick labels using MathJax.
generateLabelText(tick, zero, value) {
for (const axis of ['xAxis', 'yAxis']) {
if (
this === plot[axis]?.defaultTicks &&
typeof options[axis]?.ticks?.labels === 'object' &&
tick.usrCoords[1] in options[axis].ticks.labels
) {
return options[axis].ticks.labels[tick.usrCoords[1]];
}
}
if (JXG.exists(value)) return this.formatLabelText(value);
const distance = this.getDistanceFromZero(zero, tick);
return this.formatLabelText(Math.abs(distance) < JXG.Math.eps ? 0 : distance / this.visProp.scale);
Expand Down Expand Up @@ -216,7 +225,7 @@ const PGplots = {
strokeColor: options.grid.color ?? '#808080',
strokeOpacity: options.grid.opacity ?? 0.2,
insertTicks: false,
ticksDistance: options.xAxis?.ticks?.distance ?? 2,
ticksDistance: options.xAxis.ticks?.positions ?? options.xAxis.ticks?.distance ?? 2,
scale: options.xAxis?.ticks?.scale ?? 1,
minorTicks: options.grid.x.minorGrids ? (options.xAxis?.ticks?.minorTicks ?? 3) : 0,
ignoreInfiniteTickEndings: false,
Expand Down Expand Up @@ -280,7 +289,7 @@ const PGplots = {
strokeColor: options.grid.color ?? '#808080',
strokeOpacity: options.grid.opacity ?? 0.2,
insertTicks: false,
ticksDistance: options.yAxis?.ticks?.distance ?? 2,
ticksDistance: options.yAxis.ticks?.positions ?? options.yAxis.ticks?.distance ?? 2,
scale: options.yAxis?.ticks?.scale ?? 1,
minorTicks: options.grid.y.minorGrids ? (options.yAxis?.ticks?.minorTicks ?? 3) : 0,
ignoreInfiniteTickEndings: false,
Expand Down Expand Up @@ -352,7 +361,7 @@ const PGplots = {
? true
: false,
insertTicks: false,
ticksDistance: options.xAxis.ticks?.distance ?? 2,
ticksDistance: options.xAxis.ticks?.positions ?? options.xAxis.ticks?.distance ?? 2,
scale: options.xAxis.ticks?.scale ?? 1,
scaleSymbol: options.xAxis.ticks?.scaleSymbol ?? '',
minorTicks: options.xAxis.ticks?.minorTicks ?? 3,
Expand Down Expand Up @@ -451,7 +460,7 @@ const PGplots = {
? true
: false,
insertTicks: false,
ticksDistance: options.yAxis.ticks?.distance ?? 2,
ticksDistance: options.yAxis.ticks?.positions ?? options.yAxis.ticks?.distance ?? 2,
scale: options.yAxis.ticks?.scale ?? 1,
scaleSymbol: options.yAxis.ticks?.scaleSymbol ?? '',
minorTicks: options.yAxis.ticks?.minorTicks ?? 3,
Expand Down
40 changes: 39 additions & 1 deletion lib/Plots/Axes.pm
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,37 @@ difference between the C<max> and C<min> divided by the C<tick_num>. Default: 0

=item tick_labels

This can be either 1 (show) or 0 (don't show) the labels for the major ticks.
This can be set to 1 to show the labels for the major ticks, 0 to not show the
labels for the major ticks, or to a reference to a hash whose keys are tick
positions, and whose values are tick labels to be shown at those positions.
Default: 1

The following is an example of passing a reference to a hash for this option.

tick_labels => { 5 => '\(a\)' }

In this case if there is a major tick at 5, then the label that will be shown
there is 'a' and the label will be rendered via MathJax. Note that if there is
not a major tick at 5, then the label will be unused. At any other major tick
that is shown, the position will be shown for the label and will be formatted
according to the C<tick_label_format> option.

This option is most useful in combination with the C<tick_positions> option
below. With that option the precise list of major ticks to be shown can be
specified, and the labels for those ticks specified with this option. For
example,

tick_positions => [2, 4],
tick_labels => { 2 => 'a', 4 => 'b' },

would place a tick at 2 labeled 'a', and a tick at 4 labeled 'b'. No other ticks
would be shown on the axis.

Note that if the hash reference value is used, the C<tick_label_format> does not
apply. You are responsible for formatting the labels as you would like them to
appear. If you want the labels rendered via MathJax, then wrap the labels in
C<\(> and C<\)>.

=item tick_label_format

This can be one of "decimal", "fraction", "multiple", or "scinot". If this is
Expand Down Expand Up @@ -133,6 +161,15 @@ C<tick_delta>. Default: 1

This is appended to major tick labels. Default: ''

=item tick_positions

Set this to a reference to an array of values to be used for the positions of
ticks that will be shown on the axis. In this case the C<tick_delta>,
C<tick_distance>, and C<tick_scale> options will not be used to generate tick
positions. If this is set to 0 (or is not an array reference), then the tick
positions will be computed using the values of the C<tick_delta>,
C<tick_distance>, and C<tick_scale> options. Default: 0

=item show_ticks

This can be either 1 (show) or 0 (don't show) the tick lines. If ticks are
Expand Down Expand Up @@ -316,6 +353,7 @@ sub axis_defaults {
tick_distance => 0,
tick_scale => 1,
tick_scale_symbol => '',
tick_positions => 0,
show_ticks => 1,
tick_delta => 0,
tick_num => 5,
Expand Down
6 changes: 6 additions & 0 deletions lib/Plots/JSXGraph.pm
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ sub HTML {
$options->{xAxis}{ticks}{scale} = $axes->xaxis('tick_scale');
$options->{xAxis}{ticks}{distance} = $axes->xaxis('tick_distance');
$options->{xAxis}{ticks}{minorTicks} = $grid->{xminor};

my $xticks = $axes->xaxis('tick_positions');
$options->{xAxis}{ticks}{positions} = $xticks if ref $xticks eq 'ARRAY';
}

$options->{yAxis}{visible} = $yvisible;
Expand All @@ -100,6 +103,9 @@ sub HTML {
$options->{yAxis}{ticks}{scale} = $axes->yaxis('tick_scale');
$options->{yAxis}{ticks}{distance} = $axes->yaxis('tick_distance');
$options->{yAxis}{ticks}{minorTicks} = $grid->{yminor};

my $yticks = $axes->yaxis('tick_positions');
$options->{yAxis}{ticks}{positions} = $yticks if ref $yticks eq 'ARRAY';
}

if ($show_grid) {
Expand Down
80 changes: 56 additions & 24 deletions lib/Plots/Tikz.pm
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,41 @@ sub generate_axes {
my $x_tick_distance = $axes->xaxis('tick_distance');
my $x_tick_scale = $axes->xaxis('tick_scale') || 1;

my @xticks =
grep { $_ > $xmin && $_ < $xmax }
map { -$_ * $x_tick_distance * $x_tick_scale }
reverse(1 .. -$xmin / ($x_tick_distance * $x_tick_scale));
push(@xticks, 0) if $xmin < 0 && $xmax > 0;
push(@xticks,
grep { $_ > $xmin && $_ < $xmax }
map { $_ * $x_tick_distance * $x_tick_scale } (1 .. $xmax / ($x_tick_distance * $x_tick_scale)));
my $xtick_positions = $axes->xaxis('tick_positions');
my @xticks;
if (ref $xtick_positions eq 'ARRAY') {
@xticks = @$xtick_positions;
} else {
@xticks =
grep { $_ > $xmin && $_ < $xmax }
map { -$_ * $x_tick_distance * $x_tick_scale }
reverse(1 .. -$xmin / ($x_tick_distance * $x_tick_scale));
push(@xticks, 0) if $xmin < 0 && $xmax > 0;
push(@xticks,
grep { $_ > $xmin && $_ < $xmax }
map { $_ * $x_tick_distance * $x_tick_scale } (1 .. $xmax / ($x_tick_distance * $x_tick_scale)));
}

my $xtick_labels_value = $axes->xaxis('tick_labels');
my $xtick_labels =
$xvisible
&& $axes->xaxis('show_ticks')
&& $axes->xaxis('tick_labels')
? (",\nxticklabel shift=9pt,\nxticklabel style={anchor=center},\nxticklabels={"
. join(',', map { $self->formatTickLabelText($_ / $x_tick_scale, 'xaxis') } @xticks) . '}')
&& $xtick_labels_value
? (
",\nxticklabel shift=9pt,\nxticklabel style={anchor=center},\nxticklabels={" . (join(
',',
map {
ref $xtick_labels_value eq 'HASH' && defined $xtick_labels_value->{$_}
? $xtick_labels_value->{$_}
: $self->formatTickLabelText($_ / $x_tick_scale, 'xaxis')
} @xticks
))
. '}'
)
: ",\nxticklabel=\\empty";

my @xminor_ticks;
if ($grid->{xminor} > 0) {
if ($grid->{xminor} > 0 && ref $xtick_positions ne 'ARRAY') {
my @majorTicks = @xticks;
unshift(@majorTicks, ($majorTicks[0] // $xmin) - $x_tick_distance * $x_tick_scale);
push(@majorTicks, ($majorTicks[-1] // $xmax) + $x_tick_distance * $x_tick_scale);
Expand All @@ -246,25 +262,41 @@ sub generate_axes {
my $y_tick_distance = $axes->yaxis('tick_distance');
my $y_tick_scale = $axes->yaxis('tick_scale') || 1;

my @yticks =
grep { $_ > $ymin && $_ < $ymax }
map { -$_ * $y_tick_distance * $y_tick_scale }
reverse(1 .. -$ymin / ($y_tick_distance * $y_tick_scale));
push(@yticks, 0) if $ymin < 0 && $ymax > 0;
push(@yticks,
grep { $_ > $ymin && $_ < $ymax }
map { $_ * $y_tick_distance * $y_tick_scale } (1 .. $ymax / ($y_tick_distance * $y_tick_scale)));
my $ytick_positions = $axes->yaxis('tick_positions');
my @yticks;
if (ref $ytick_positions eq 'ARRAY') {
@yticks = @$ytick_positions;
} else {
@yticks =
grep { $_ > $ymin && $_ < $ymax }
map { -$_ * $y_tick_distance * $y_tick_scale }
reverse(1 .. -$ymin / ($y_tick_distance * $y_tick_scale));
push(@yticks, 0) if $ymin < 0 && $ymax > 0;
push(@yticks,
grep { $_ > $ymin && $_ < $ymax }
map { $_ * $y_tick_distance * $y_tick_scale } (1 .. $ymax / ($y_tick_distance * $y_tick_scale)));
}

my $ytick_labels_value = $axes->yaxis('tick_labels');
my $ytick_labels =
$yvisible
&& $axes->yaxis('show_ticks')
&& $axes->yaxis('tick_labels')
? (",\nyticklabel shift=-3pt,\nyticklabels={"
. join(',', map { $self->formatTickLabelText($_ / $y_tick_scale, 'yaxis') } @yticks) . '}')
&& $ytick_labels_value
? (
",\nyticklabel shift=-3pt,\nyticklabel style={anchor=left},\nyticklabels={" . (join(
',',
map {
ref $ytick_labels_value eq 'HASH' && defined $ytick_labels_value->{$_}
? $ytick_labels_value->{$_}
: $self->formatTickLabelText($_ / $y_tick_scale, 'yaxis')
} @yticks
))
. '}'
)
: ",\nyticklabel=\\empty";

my @yminor_ticks;
if ($grid->{yminor} > 0) {
if ($grid->{yminor} > 0 && ref $ytick_positions ne 'ARRAY') {
my @majorTicks = @yticks;
unshift(@majorTicks, ($majorTicks[0] // $ymin) - $y_tick_distance * $y_tick_scale);
push(@majorTicks, ($majorTicks[-1] // $ymax) + $y_tick_distance * $y_tick_scale);
Expand Down
Loading