Forum > TAChart

[possible bug] adding a mark always changes axis range min/max

(1/3) > >>

Muso:
I stumbled over an issue that is possibly a bug:

- take the attached example and run it- double-click on the left chart axis and in the appearing dialog uncheck autoscaling and use 2.00 as max range for the axisresult: everything looks fine, see attached

- now add a mark by Ctrl+Click on a datapoint in the chart
result: the y-axis max is now 2.2 instead of the specified 2.0. So my max setting is overwritten and looking at the chart, see attached there is no need to change the range because the mark does not consume this space

The axis range is set in my example in the file ceAxisFrame and there in "TChartAxisFrame.seMaximumChange" I have
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---FAxis.Range.Max := seMaximum.Value; So I think I made everything correctly.
maybe there is a way to disable the automatic range max/min change by the marks? if so, what could the side effects?

Muso:

--- Quote from: Muso on July 15, 2022, 02:51:40 pm ---result: the y-axis max is now 2.2 instead of the specified 2.0.

--- End quote ---

I found now out that setting the marks property "AutoMargins" to "False" the problem goes away.

However, for AutoMargins I cannot find a documentation therefore I don't know what side effect this change would have.
Does anybody know this?

I see that when I disable it and a mark would need more y-space to be shown, it might be invisible.

So I think the AutoMargins feature should work this way:- if a new mark needs more y- space, the axis range max is adjusted- if its top edge is lower than the max y-value of the series, the axis range max is not changed.

wp:
This is intended. The algorithm does not check whether the mark would fit into the axis range defined and therefore automatically creates space for the worst case. Positioning of the marks per series can be controlled by the MarkPositions property; I had thought that the lmpInside option puts the marks in the space BETWEEN max and min, but as I see the axis is rescaled here as well - maybe this is a bug, I'll have to investigate.

Setting AutoMargins to false is not a solution in case of default settings because the label will be truncated if it is placed near the maximum of the series. What you can do is to provide extra margin either by increasing the Left.Axis.Range (Chart.LeftAxis.Range.Max := 1.2, .Min := -1.2, .UseMax := true, .UseMin := true), or by increasing the Margins.Top and . Bottom of the chart. The latter is a bit more predictable: Font height is about 10 px, the length of the link line (Distance) is 10, the mark.Margins.Top and .Bottom are 2 each, plus 2px for the Marks border --> 36 px, plus some safety margin --> 40 px should work for a single-line mark.

wp:
I think I found a fix for the issue that the axis range expands when Marks are displayed even with MarkPositions=lmpInside. Before I commit I would ask you to open unit TACustomSeries and find the procedure TBasicPointSeries.UpdateMargins. Before "m[dir] := Max(m[dir], dist + scMarksDistance);" add "if MarkPositions <> lmpInside then". The center part of the method should be like this now:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TBasicPointSeries.UpdateMargins(  ADrawer: IChartDrawer; var AMargins: TRect);...      UpdateLabelDirectionReferenceLevel(i, j, center);      dir := GetLabelDirection(TDoublePointBoolArr(gp)[not IsRotated], center);      with Marks.MeasureLabel(ADrawer, labelText) do        dist := IfThen(dir in [ldLeft, ldRight], cx, cy);      if Marks.DistanceToCenter then        dist := dist div 2;       if MarkPositions <> lmpInside then     // <--- ADDED        m[dir] := Max(m[dir], dist + scMarksDistance);       if (Source.YCount > 1) and (j = 0) then begin        if FStacked then begin... 
Please test with Series.MarkPositions = lmpInside: The axis limits should not move any more (provided that the range covered by the data is large enough to contain the marks).

Muso:

--- Quote from: wp on July 15, 2022, 06:13:03 pm ---Before I commit I would ask you to open unit TACustomSeries

--- End quote ---

Many thanks! Yes, this fixes the issue for me with lmpInside.

For my application however I realized that I  cannot use lmpInside because this looks awful since the main use case is to have several similar LineSeries, just with a small y-offset. (ideally this offset should even be zero) Therefore lmpOutside looks better for my application.

Then it is important to get in every case the range one wants. Data is more important than the marks and when scaling in one is interested in the data.

As wish, these things would be cool:
- being able to set a short text for the mark and by hovering the mouse over the mark, one gets the full text. This would be cool, because sometimes one need more text but don't wand to clutter the chart with large text

- easier selection of existing marks, so that one can e.g. double-click on a mark to alter it

Navigation

[0] Message Index

[#] Next page

Go to full version