-
Notifications
You must be signed in to change notification settings - Fork 981
Description
Issue:
When calculating the size of the panel for the axis, the MeasureTicks function does not account for rotation for custom tick labels. This causes X axis tick labels to be cut off because the panel is not large enough in height. The Y axis width is wider than it needs to be for rotated custom tick labels.
With axis.TickLabelStyle.Rotation = 0 for all axes.
Panel sizing is correct for both X and Y axis, though X axis labels overlap.

With axis.TickLabelStyle.Rotation = 90 for all axes.
Panel sizing is incorrect for both X and Y axis. Labels are cut off on the X axis and additional white space is visible on the Y axis.

ScottPlot Version:
ScottPlot.Avalonia version 5.0.21
ScottPlot version 5.0.21
Code Sample: See http://scottplot.net/faq/repro/ for tips about creating reproducible code samples
This is how I am setting the ticks on the axis.
// create a manual tick generator and add ticks
ScottPlot.TickGenerators.NumericManual ticks = new();
// add major ticks with their labels
foreach (var kvp in results.Labels)
{
ticks.AddMajor(kvp.Value, kvp.Key);
}
// tell the axis to use the custom tick genrator
axis.TickGenerator = ticks;
// rotate the tick marks
axis.TickLabelStyle.Rotation = 90;
axis.TickLabelStyle.OffsetY = 0;
axis.TickLabelStyle.Alignment = Alignment.MiddleLeft;In XAxisBase.MeasureTicks only the height of the label is considered without regard for rotation.
private float MeasureTicks()
{
using SKPaint paint = new();
TickLabelStyle.ApplyToPaint(paint);
float largestTickHeight = 0;
foreach (Tick tick in TickGenerator.Ticks)
{
PixelSize tickLabelSize = Drawing.MeasureString(tick.Label, paint);
largestTickHeight = Math.Max(largestTickHeight, tickLabelSize.Height + 10);
}
return largestTickHeight;
}I worked around this for the X axis by setting the minimal panel height based on the XAxisBase.Measure function.
using SKPaint paint = new();
axis.TickLabelStyle.ApplyToPaint(paint);
float largestTickHeight = 0;
double degrees = axis.TickLabelStyle.Rotation;
double angle = Math.PI * degrees / 180.0;
float sinRotation = (float)Math.Abs(Math.Sin(angle));
float cosRotation = (float)Math.Abs(Math.Cos(angle));
foreach (Tick tick in axis.TickGenerator.Ticks)
{
ScottPlot.PixelSize tickLabelSize = Drawing.MeasureString(tick.Label, paint);
var rotatedTickLabelHeight = tickLabelSize.Width * sinRotation;
var rotatedTickLabelWidth = tickLabelSize.Height * cosRotation;
var rotatedTickHeight = rotatedTickLabelHeight + rotatedTickLabelWidth;
largestTickHeight = Math.Max(largestTickHeight, rotatedTickHeight + 10);
}The YAxisBase.MeasureTicks function only using tickLabelSize.Width and not using the rotation.
There may be a better way to calculate the tick label width and height, but this is what I did.