### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Recent

#### majid.ebru

• Sr. Member
• Posts: 405
« on: February 09, 2018, 07:31:31 pm »
Hi

i have many primary Questions  about TChart.

how can i fix min and max axis ?

how can i have mult color line?

how can i change value of X axis to Srtinf Text?

how can i show value of point?

« Last Edit: February 09, 2018, 07:35:39 pm by majid.ebru »

#### majid.ebru

• Sr. Member
• Posts: 405
##### Re: primary Questions about TChart
« Reply #1 on: February 09, 2018, 07:32:29 pm »
and

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #2 on: February 09, 2018, 08:08:06 pm »
how can i fix min and max axis ?
Set the Extent of the chart (can be done by code like below, or directly in the Object Inspector)
Code: Pascal  [Select][+][-]
1.   Chart1.Extent.YMax := 100;
2.   Chart1.Extent.YMin := 0;
3.   Chart1.Extent.UseYMax := true;
4.   Chart1.Extent.UseYMin := true;

how can i change value of X axis to Srtinf Text?
What you probably need is an event handler for the event OnMarkToText of the axis. Example
Code: Pascal  [Select][+][-]
1. procedure TForm1.Chart1AxisList1MarkToText(var AText: String; AMark: Double);
2. begin
3.   if AMark = 0.0 then AText := 'zero';
4. end;

how can i show value of point?
Set the Marks.Style of the series to smsValue. The settings of Marks.Style define the combinations of the data point parameters (x, y, text) which will be shown as datapoint label (http://wiki.lazarus.freepascal.org/TAChart_documentation#Mark_labels):
Code: Pascal  [Select][+][-]
1. type
2.   TSeriesMarksStyle = (
3.     smsCustom,         { user-defined }
4.     smsNone,           { no labels }
5.     smsValue,          { 1234 }
6.     smsPercent,        { 12 % }
7.     smsLabel,          { Cars }
8.     smsLabelPercent,   { Cars 12 % }
9.     smsLabelValue,     { Cars 1234 }
10.     smsLegend,         { ? }
11.     smsPercentTotal,   { 12 % of 1234 }
12.     smsLabelPercentTotal, { Cars 12 % of 1234 }
13.     smsXValue);        { 21/6/1996 }
Change the format string in Marks.Format to limit the number of decimal places, e.g. '%.2f' for 2 decimals only.

I'll have to think about the other questions.
- What does the last image (06.png) mean?
- In image 05.png you have a chart with a line series, and there's a horizontal dividing line. The parts of the line series above the dividing line should be painted in a different color than the parts below the dividing line. Correct? Will be dividing line be fixed, or should it be user-changeable?
« Last Edit: February 09, 2018, 10:14:03 pm by wp »

#### taazz

• Hero Member
• Posts: 5364
##### Re: primary Questions about TChart
« Reply #3 on: February 09, 2018, 08:16:55 pm »
how can i have mult color line?
There is no reason for multi colour lines. lines are not part of the data only points are the data lines are there to sombolize an idea only it is either negative or positive it can't be both. Don't waste your time on a illogical case.
how can i show value of point?
select the series of the chart and change the marks.style to what ever you need make sure that the marks are visible.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #4 on: February 09, 2018, 09:48:13 pm »
how can i have mult color line?
Drawing the segments of a lineseries in different colors is not supported. But you can use a TUserDrawnSeries instead of the TLineSeries in which you can draw whatever you want - see attached demo.
• FormCreate defines some dummy data in an array of TDataRec records (record of x and y values) and calculates the range covered by the x and y values (Extent)
• The Extent has to be passed to the series in its event OnGetBounds.
• The event OnDraw expects code which paints the entire series. My code simply iterates through the data point array, calculates the image coordinates of each data point (by calling the chart's method GraphToImage) and draws the line segments in the color which is assigned to the current point index in the COLORS array. I should mention that using a Canvas in the OnDraw event is not up to the standard of TAChart which has introduced dedicated drawers. But there's nothing else at the moment, and you hopefully do not want to paint on exotic output devices.
This probably is also the way to answer the question related to image 05.png where the series changes color above and below a dividing line. The only code which has to be added is the calculation of the intersection point of the line segment with the dividing line.
« Last Edit: February 09, 2018, 10:05:39 pm by wp »

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #5 on: February 09, 2018, 10:01:53 pm »
how can i have mult color line?
There is no reason for multi colour lines. lines are not part of the data only points are the data lines are there to sombolize an idea only it is either negative or positive it can't be both. Don't waste your time on a illogical case.
I don't quite understand what you mean, but I could imagine several use cases of multi-colored line segments. For example to highlight segments for which the slope exceeds a given limit. Or - if the series displays a road - the color symbolizes the number of accidents on each segment.
« Last Edit: February 09, 2018, 10:07:30 pm by wp »

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #6 on: February 10, 2018, 09:52:01 pm »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)
« Last Edit: February 10, 2018, 10:57:05 pm by wp »

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #7 on: February 11, 2018, 12:18:42 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

#### majid.ebru

• Sr. Member
• Posts: 405
##### Re: primary Questions about TChart
« Reply #8 on: February 11, 2018, 07:29:39 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

Thankyou

but i can't compile your project?

waht do i do?

i should update my TChart element?

#### majid.ebru

• Sr. Member
• Posts: 405
##### Re: primary Questions about TChart
« Reply #9 on: February 11, 2018, 07:31:07 am »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)

it's perfect

how can i do that?

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #10 on: February 11, 2018, 10:49:35 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

Thankyou

but i can't compile your project?

waht do i do?

i should update my TChart element?
It seems that you don't use Laz 1.8. You should upgrade, there are many new features.

If you don't want to, just remove the line causing the trouble.

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #11 on: February 11, 2018, 11:48:16 am »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)

it's perfect

how can i do that?
You must install the trunk version of Lazarus (this is the developer version). The easiest way is using the fpcupdeluxe program (https://github.com/newpascal/fpcupdeluxe/releases/tag/v1.6.0n).
« Last Edit: February 11, 2018, 12:12:33 pm by wp »

#### corpsman

• New member
• Posts: 9
##### Re: primary Questions about TChart
« Reply #12 on: April 30, 2022, 06:19:05 pm »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

The sample is cool but your intersect routine has some errors
here is my version that works better
Code: Pascal  [Select][+][-]
1. Function Intersect(p1, p2: TPoint; y: Integer): Integer;
2. Begin
3.   If p1.y = p2.y Then // fixed catch of div by zero
4.     Result := (p1.x + p2.x) Div 2
5.   Else
6.     Result := round(((p2.x - p1.x) * (y - p1.y)) / (p2.y - p1.y) + p1.x); // reorder to divide "larger" numbers is more stable.
7. End;
8.

And the Routine that does the rending changed to this:

Code: Pascal  [Select][+][-]
1.
2. Procedure TForm1.Chart1UserDrawnSeries1Draw(ACanvas: TCanvas;
3.   Const ARect: TRect);
4.
5.   Procedure DrawCircle(p: TPoint; AColor: TColor; R: Integer);
6.   Begin
7.     Chart1.Drawer.SetBrushParams(bsSolid, AColor);
8.     Chart1.Drawer.Ellipse(P.x - R, P.y - R, P.x + R, P.y + R);
9.   End;
10.
11.   Function GetColor(y, yref: Integer): TColor;
12.   Begin
13.     If y > yref Then
14.       Result := COLOR_BELOW
15.     Else
16.       Result := COLOR_ABOVE;
17.   End;
18.
19. Var
20.   i: Integer;
21.   gp: TDoublePoint;
22.   p1, p2, p3: TPoint;
23.   yref: Integer;
24.   x: Integer;
25.   showDataPoints: Boolean;
26. Begin
27.   showDataPoints := Checkbox1.Checked;
28.   pen.Width := 4;
29.   Chart1.Drawer.Pen := Pen;
30.   yref := Chart1.YGraphToImage(Chart1ConstantLine1.Position);
31.
32.   i := 0;
33.   gp := DoublePoint(Data[i].X, Data[i].Y);
34.   p1 := Chart1.GraphToImage(gp);
35.   If showDataPoints Then Begin
36.     Chart1.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref));
37.     DrawCircle(p1, GetColor(p1.y, yref), RADIUS); // Fix copy paste index error 2->1
38.   End;
39.   For i := 1 To High(Data) Do Begin // draw from second to last point (index of by one correction)
40.     gp := DoublePoint(Data[i].X, Data[i].Y);
41.     p2 := Chart1.GraphToImage(gp);
42.     If (p2.y - yref) * (p1.y - yref) < 0 Then Begin
43.       p3 := Point(Intersect(p1, p2, yref), yref);
44.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref), 2);
45.       Chart1.Drawer.Line(p1, p3);
46.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref), 2);
47.       Chart1.Drawer.Line(p3, p2);
48.     End
49.     Else Begin
50.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref), 2);
51.       Chart1.Drawer.Line(p1, p2);
52.     End;
53.     If showDataPoints Then
55.     p1 := p2;
56.   End;
57. End;
58.
59.

Thanks a lot for publishing your code.
--
Just try it.

#### wp

• Hero Member
• Posts: 9906
##### Re: primary Questions about TChart
« Reply #13 on: April 30, 2022, 11:07:47 pm »
Thanks for pointing out these bugs. I committed the fix to git-main (except for the reordering of multiplication and division - this really makes no difference with floats).
« Last Edit: May 01, 2022, 11:12:35 am by wp »