Page 1 of 1

Chart area unnecessarily compressed

Posted: Wed Aug 23, 2017 8:18 am
by 15681044
Hello,

When creating a chart where the bottom axis labels are rotated between 1 and 89 degrees, the chart area is only as high as it would be when the labels are rotated 90 degrees.
This means that there can be quite some unnecessary whitespace between the bottom axis title and the bottom axis labels.
I have added some screenshots of the behavior and a code snippet below to reproduce the behavior.

Is this behavior considered a bug, and are there some easy work-arounds to automatically avoid the unnecessary whitespace?

Best regards,
Steven

Code: Select all

Steema.TeeChart.Styles.Bar bar = new Steema.TeeChart.Styles.Bar(tChart1.Chart);
bar.Add(0, 10, "Category1");
bar.Add(1, 20, "Category2");
bar.Add(2, 30, "Quite long category 3");

tChart1.Chart.Axes.Bottom.Labels.CustomSize = 0;
tChart1.Chart.Axes.Bottom.Labels.Angle = 10;
tChart1.Chart.Axes.Bottom.Title.Caption = "X-axis labels at angle of 10 degrees";
teechart_xaxislabelrotation.png
bottom axis labels - different angles
teechart_xaxislabelrotation.png (40.55 KiB) Viewed 16421 times

Re: Chart area unnecessarily compressed

Posted: Mon Aug 28, 2017 2:30 pm
by Marc
Hello Steven,

Sorry for the delay with this reply.

The behaviour isn't considered a bug as with movement of the label angle constant changing of the axis position, might be considered as undesirable. Perhaps we could add a boolean to activate/deactivate auto-spacing.

You can control the space by adjusting the bottom margin. You can find the property in the editor under Panel:Margins or via this coded property:

Code: Select all

tChart1.Panel.MarginBottom = 0 (can use negative figures by code);

//optional pixel or percent control of this variable, default percent:
//tChart1.Panel.MarginUnits = Steema.TeeChart.PanelMarginUnits.Pixels;
Regards,
Marc

Re: Chart area unnecessarily compressed

Posted: Tue Sep 19, 2017 9:00 am
by 15681044
Hi Marc,

Sorry for the late reply from my side, I was on holiday.

Thank you for your reply.
Unfortunately, the suggested work-around by adjusting the bottom margin causes the bottom axis title to be cut (as can be seen in the screenshots below), so this work-around cannot be used.
teechart_xaxislabelrotation_reducedbottommargin.png
bottom margin reduced - axis title cut
teechart_xaxislabelrotation_reducedbottommargin.png (30.32 KiB) Viewed 16356 times
In researching possible solutions a bit further, I stumbled upon the AxisLabels:CustomSize property, which I can use in code to influence the space that is taken by the bottom axis labels:

Code: Select all

tChart1.Chart.Axes.Bottom.Labels.CustomSize = 20;
With this property, it seems that I can avoid the unnecessary whitespace if the custom size is chosen well (see screenshots below).
To correctly indicate this custom size, it seems however that I need to know the height of the largest rotated axis label.
Do you have any idea whether and how it is possible to calculate this?
teechart_xaxislabelrotation_axislabelscustomsize.png
bottom axis labels custom size
teechart_xaxislabelrotation_axislabelscustomsize.png (30.61 KiB) Viewed 16358 times

Re: Chart area unnecessarily compressed

Posted: Wed Sep 20, 2017 1:53 pm
by Christopher
Hello,

I think custom labels can handle this better - the following code:

Code: Select all

    Bar series;
    private void InitializeChart()
    {
      series = new Bar(tChart1.Chart);
      tChart1.Legend.Visible = false;

      for (int i = 0; i < 3; i++)
      {
        series.Add(i); //, "Quite Long Category " + i.ToString());
        tChart1.Axes.Bottom.Labels.Items.Add(i, "Quite Long Category " + i.ToString());
      }

      int degrees = 10;
      tChart1.Axes.Bottom.Labels.Angle = degrees;
      tChart1.Axes.Bottom.Title.Text = $"X-Axis labels with Angle of {degrees} degrees";
    }
produces the following chart for me here:
TChart636415122361345058.png
TChart636415122361345058.png (9.33 KiB) Viewed 16342 times

Re: Chart area unnecessarily compressed

Posted: Mon Sep 25, 2017 6:44 am
by 15681044
Hello Christopher,

Thank you for your reply.
I'm afraid though, it doesn't help with the issue I'm facing. As you can see in your own screenshot, there is still a large blank area between the axis labels and the axis title, even when using custom labels.
Possibly it is easier to calculate the height of the labels when using custom labels, so I can use it in combination with the CustomSize property?

Re: Chart area unnecessarily compressed

Posted: Mon Sep 25, 2017 9:42 am
by Christopher
Hello,

for pixel precise positioning of text under the bottom axis's labels when these are rotated you could consider using code similar to the following:

Code: Select all

    Bar series;
    int degrees, height;
    AxisLabelItem longestLabel;
    string title;

    private void InitializeChart()
    {
      series = new Bar(tChart1.Chart);
      tChart1.Legend.Visible = false;

      string[] extra = new string[] { "one", "twotwotwotwotwo", "three"};
      int longestString = 0;
      for (int i = 0; i < 3; i++)
      {
        string text = "Quite Long Category " + extra[i];
        int length = text.Count();
        series.Add(i);
        tChart1.Axes.Bottom.Labels.Items.Add(i, text);
        if (length > longestString)
        {
          longestString = length;
          longestLabel = tChart1.Axes.Bottom.Labels.Items[i];
        }
      }

      degrees = 10;
      tChart1.Axes.Bottom.Labels.Angle = degrees;
      title = $"X-Axis labels with Angle of {degrees} degrees";
      tChart1.BeforeDrawSeries += TChart1_BeforeDrawSeries;
      Bitmap bmp = tChart1.Bitmap;

    }


    private void TChart1_BeforeDrawSeries(object sender, Graphics3D g)
    {
      Func<AxisLabelItem, int, int> CalcRotatedHeight = (label, angle) =>
      {
        Matrix m = g.GDIplusCanvas.Transform;
        m.RotateAt((float)(360 - angle), new Point(label.Left, label.Top));
        g.GDIplusCanvas.MultiplyTransform(m);
        Point[] shapePolygonBounds = new Point[] { new Point(label.ShapeBounds.Left, label.ShapeBounds.Top), new Point(label.ShapeBounds.Right, label.ShapeBounds.Top),
                new Point(label.ShapeBounds.Right, label.ShapeBounds.Bottom), new Point(label.ShapeBounds.Left, label.ShapeBounds.Bottom), new Point(label.ShapeBounds.Left, label.ShapeBounds.Top)};
        m.TransformPoints(shapePolygonBounds);
        g.GDIplusCanvas.ResetTransform();
        return g.PolygonBounds(shapePolygonBounds).Height;
      };

      height = CalcRotatedHeight(longestLabel, degrees);

      int middle = (tChart1.Axes.Bottom.IEndPos - tChart1.Axes.Bottom.IStartPos) / 2;
      int width = Utils.Round(g.TextWidth(title));

      g.TextOut(middle - (width / 2), tChart1.Axes.Left.IEndPos + height, title);
      tChart1.Panel.MarginUnits = PanelMarginUnits.Pixels;
      tChart1.Panel.MarginBottom = (height - width) + 20; //20 pixels between text and bottom of chart
    }
which gives me:
TChart636419363212450918.png
TChart636419363212450918.png (11.23 KiB) Viewed 16304 times
I will look into the possibility of incorporating this technique (or similar) to ensure precise axis title positioning with rotated labels.

Re: Chart area unnecessarily compressed

Posted: Mon Sep 25, 2017 10:54 am
by Christopher
Christopher wrote:I will look into the possibility of incorporating this technique (or similar) to ensure precise axis title positioning with rotated labels.
FYI: I have now entered this issue into our issue-tracking software with id=1922.

Re: Chart area unnecessarily compressed

Posted: Mon Sep 25, 2017 11:53 am
by 15681044
Hello,

Thank you very much for the reply. This sounds very promising.
Thanks as well for entering the issue in the issue-tracker, so we can hope that this calculation code on our side might become unnecessary in the future.