Lazarus

Programming => Graphics and Multimedia => TAChart => Topic started by: Davidous on July 09, 2019, 02:47:28 pm

Title: BarWidthStyle
Post by: Davidous on July 09, 2019, 02:47:28 pm
Hello,

I noticed an interesting and strange thing in my graph.
My bar series are set to BarWidthStyle:=bwPercentMin.
When there are only very few data in my given series, then bwPercentMin does not seem to work properly.
I marked it with a red rectangle on the attached picture.
Why could that be?
Title: Re: BarWidthStyle
Post by: wp on July 09, 2019, 08:31:04 pm
Sorry I don't understand what you are expecting and what is happening. Could you post a simple demo showing the issue?

Bar widths are difficult to control because they are specified as a percentage of the data point x distance to the "next" data point. The "next" data point is the next data point in the chart source. You must be aware that when data points are not sorted in x then this probably is not the "next" data point on the chart! Always work with an sorted datasource for bar series. TAChart of Lazarus trunk has many improvements regarding sorting.

Suppose you combine two charts of the same width, each one with a bar series. The first chart displays 2 bars, the second chart displays 3 bars. Then the bars of the second chart will be narrower than those of the first chart even if BarWidthStyle is bwPercentMin in both cases. If you want them to appear with same width then you must adjust the BarWidthPercent value, the calculation for it is a good brain exercise I think...

But as I said above this is just guessing, I don't know what you want to achieve.
Title: Re: BarWidthStyle
Post by: Davidous on July 31, 2019, 09:49:32 am
Hello,

I already solved this problem by adding some extra data points to each series and then the bwPercentMin works correctly.
But I have an other question.
When the chart is not zoomed and I have many datapoints, not all of the bars are displeyed in my bar series. So it can happen, that I don't see any bars at a certain point of the chart and when I zoom in, then it turns out, that there are many bars. Is there a way to tell the chart to display all bars even if the chart is unzoomed (for example with a minimum width)? When I make a line series with the same points I can see everything and nothing is hidden...
Title: Re: BarWidthStyle
Post by: wp on July 31, 2019, 10:22:18 am
Again I don't understand. When there are so many data points that they overlap in the chart or even are coincident within the finite screen resolution, it is clear that you cannot distinguish them individually. This should happen for TBarSeries as well as for TLineSeries.
Title: Re: BarWidthStyle
Post by: Davidous on July 31, 2019, 10:39:11 am
I attached a picture for the better understanding :)
You can see the same series with bar series (upper one) and with line series (lower one). I marked some differences with red rectangles.
Some points cannot be seen on the chart with bar series and I would like to know why? Why does the chart automaticly hide some bars?
Title: Re: BarWidthStyle
Post by: wp on July 31, 2019, 11:24:34 am
Sorry the color selection in this chart makes it difficult to see the data points in particular for the red rectangles.

But anyway. You seem to use a bar chart because you want vertical lines from the zero level up to the data point. I think that TBarSeries is too complex for this purpose, and I also think that the bar width is not under your full control, in a transition region it may happen that the thinnest bars are 1 pixel or 2 pixels wide.

Instead of a TBarSeries I'd use a TUserDrawnSeries which allows you to draw the series by yourself. Sounds complicated but it's only a few lines of code. I am assuming that you store the data points in a TListChartSource.

The event "OnDraw" must do the entire painting, i.e. iterate through all data points and draw vertical lines to the base line. Set the pen color here, calculate the pixel coordinates of the zero level and those of each data point and just draw a vertical line of 1 pixel:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1UserDrawnSeries1Draw(ACanvas: TCanvas; const ARect: TRect);
  2. var
  3.   i: Integer;
  4.   P: TPoint;
  5.   y0: Integer;
  6. begin
  7.   ACanvas.Pen.Color := clRed;
  8.   ACanvas.Pen.Width := 1;
  9.   ACanvas.Pen.Style := psSolid;
  10.   y0 := Chart1.YGraphToImage(0);
  11.   for i:=0 to ListChartSource1.Count-1 do begin
  12.     P := Chart1.GraphToImage(ListChartSource1[i]^.Point);
  13.     ACanvas.Line(P.x, y0, P.x, P.y);
  14.   end;
  15. end;

The other event is "OnGetBounds". It tells the chart the range of the data values covered by the series:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1UserDrawnSeries1GetBounds(var ABounds: TDoubleRect);
  2. begin
  3.   ABounds := ListChartSource1.Extent;
  4. end;
Title: Re: BarWidthStyle
Post by: Davidous on July 31, 2019, 03:16:34 pm
Hello wp,

thank you for your detailed answer.
I did a bit of research and I managed to solve my problem.

In my TASeries unit I found these lines:

// Draw a line instead of an empty rectangle.
// if Bottom = Top then Dec(Top);
// if Left = Right then Inc(Right);

I deleted the comment lines from the lower 2 lines and now the display is as I want it.
Title: Re: BarWidthStyle
Post by: wp on July 31, 2019, 03:50:45 pm
I see. The lines were commented to avoid drawing a 1-pixel line if the bar height is 0. It conflicted with the requirement of drawing ultra-narrow bars, but was fixed some months ago. The code is now:
Code: Pascal  [Select][+][-]
  1.       // Draw a line instead of an empty rectangle.
  2.       if (Bottom = Top) and IsRotated then Dec(Top);
  3.       if (Left = Right) and not IsRotated then Inc(Right);
I don't remember if this was backported to fixes. Please test if this fixes your issue, too (it should).
Title: Re: BarWidthStyle
Post by: Davidous on August 01, 2019, 08:13:53 am
Thank you wp!
This solves my problem too. :)
Title: Re: BarWidthStyle
Post by: Davidous on August 01, 2019, 10:34:29 am
An interesting thing again...
I attached a picture. The zero level of my bars should be 0.0.
For some reason they are lifted up a bit. Why is that?
Title: Re: BarWidthStyle
Post by: wp on August 01, 2019, 11:53:30 am
It's hard to see from the screenshot where the 0 label is plotted. But I suspect this is due to the Chart.Margins. Which values do you see in the Object Inspector for its sub-properties? By default, they are 4 - this means that a margin of 4 pixels is kept out of data around the chart area. Set Chart.Margins.Bottom = 0.
Title: Re: BarWidthStyle
Post by: Davidous on August 01, 2019, 12:11:21 pm
It must be something else, because the margins are already 0.
I have another graph, where the vertical axis is inverted. The zeropoint on the inverted axis should also be 0, but the bars are shifted a bit under upwards.
Title: Re: BarWidthStyle
Post by: wp on August 01, 2019, 01:21:12 pm
Sorry, without compilable code I cannot help. There are too many possibilities which can be wrong.
Title: Re: BarWidthStyle
Post by: Davidous on August 05, 2019, 12:43:02 pm
I found out, that changing the ZPosition of some bar series causes them to shift a bit upwards. As I see it, it is like some kind of 3D effect, but I don't want it. Can you please help me with this? I want to have a 2D graph. When every ZPosition is 0, then everything seems to be OK, but when I change them, then the given series shift up a bit. ZPosition is important in this case, because I also have line series on the same graph and when I want to display both bars and lines, I want the bars to be in the background.
Title: Re: BarWidthStyle
Post by: wp on August 05, 2019, 01:10:34 pm
I don't understand. ZPosition should not cause a vertical shift of the series. Since you mention a "3D effect": Is Depth still at 0? (although I cannot imagine that it would cause a vertical shift).

You really should take the time to extract a publishable demo out of your project which shows the issue. When doing this the bug is often found automatically. If not, I have something to chew on.
Title: Re: BarWidthStyle
Post by: Davidous on August 05, 2019, 01:16:05 pm
Depth is 0.
I'm afraid I won't be able to publish this project in any form. That means, that I need to chew on it for a little while :D
Title: Re: BarWidthStyle
Post by: wp on August 05, 2019, 03:17:39 pm
I did not mean that you should publish your project. You just should write a small chart demo application. In the chart, use dummy data which you plot in the same way as you do in your real project, this does not reveal anything about your real project. Make sure that this demo shows the same issue as your project. Upload the demo here and I can have a look and give you much more specific advice.
TinyPortal © 2005-2018