Recent

Author Topic: LineTool  (Read 4728 times)

kapibara

  • Hero Member
  • *****
  • Posts: 523
LineTool
« on: December 14, 2013, 11:25:57 pm »
wp, your last message gave me ideas. I have started to work on a TLineTool with features I need:

  • Multiple lines on the chart.
  • Lines are selectable, movable and resizable.
  • Toggling of line visibility.
  • Derived from TUserDefinedTool

The position of the line is decided by the user when he is doing the drawing. There could be an option to calculate the line in relation to a series. But I dont need that yet, so manual drawing should work first.

Lazarus trunk / fpc 3.0.4 / Debian 10 - 64 bit

kapibara

  • Hero Member
  • *****
  • Posts: 523
Re: LineTool
« Reply #1 on: December 15, 2013, 08:47:35 pm »
Here is the first pre-alpha version of the LineTool with limited functionality. The code is in a separate unit with three small classes and doesnt yet descend from TUserDefinedTool.

Click and hold while moving mouse gives a permanent line when the mouse button is released.

If also Ctrl is pressed then you get the wanted rubberband effect.

It puzzles me why the charts mousemove event doesnt fire if not Ctrl key is pressed? I want chart mousemove to fire by pressing just the ssLeft mousebutton. Shift and ALT also make the event fire if ssLeft is pressed. I must have missed something obvious. :)

Tomorrow I will try to make the line selectable and movable. When selected, it will be "dotted line" until it is deselected and goes back to solid. Any idea how to find the lineseries when clicking in the chart?
Lazarus trunk / fpc 3.0.4 / Debian 10 - 64 bit

wp

  • Hero Member
  • *****
  • Posts: 7334
Re: LineTool
« Reply #2 on: December 16, 2013, 10:36:38 am »
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

kapibara

  • Hero Member
  • *****
  • Posts: 523
Re: LineTool
« Reply #3 on: December 17, 2013, 09:54:46 pm »
TChartSeries has two functions that I now use from the MouseDown event to select the TrendLine:

Series.GetXImgValue(Index)
Series.GetYImgValue(Index)

That returns Image values for the series points at Index, and makes selection of the line work.

So far so good. But for the moving and resizing of the line I need to convert mouse x,y integer values and put into the series points. This is done from the MouseMove event of TChart.

How to do that? Is there a function that converts from mouse position to series values?

EDIT: Probably ImageToGraph? To send in the X,Y as a TPoint and use the X,Y of the returned TDoublePoint?
« Last Edit: December 17, 2013, 10:26:48 pm by kapibara »
Lazarus trunk / fpc 3.0.4 / Debian 10 - 64 bit

wp

  • Hero Member
  • *****
  • Posts: 7334
Re: LineTool
« Reply #4 on: December 17, 2013, 11:41:02 pm »
Quote
Series.GetXImgValue(Index)
Series.GetYImgValue(Index)
These are just wrappers for Chart.XImageToGraph and Chart.YImageToGraph. Use whatever is convenient.

Quote
Is there a function that converts from mouse position to series values?
EDIT: Probably ImageToGraph?
Certainly. I think you used that in the other projects we discussed here.

Please note however, that this is not the most general case. If you use transformations you have to consider these as well. The "graph" coordinates are relative to the unique x/y coordinates spanning some kind of invisible axes behind the chart. When you use a transformation the values stored in the series ("axis coordinates") are mapped to this axis. Create a simple project with a logarithmic axis, and you'll see the difference: if your data points range between 1 and 1 million ("axis" coordinates), the "graph" coordinates range between 0 (= log(1)) and 6 (= log (1 million)).

The transformations class does all the conversions. It has methods AxisToGraph and GraphToAxis. The axis, moreover, provides the method GetTransform to determine the selected transformation chain (there can be several transformations per axis) (or 1:1 identity if transformations are not used). The most general way therefore is

Code: [Select]
var
  x,y: Integer;  // Mouse coordinates, in pixels (or "image coordinates")
  P: TDoublePoint;
begin
  P.x := Chart.XImageToGraph(x);  // P is in "graph" coordinates
  P.y := Chart.YImageToGraph(y);
  // Now convert "graph" to "axis" coordinates
  P.x := Chart.BottomAxis.GetTransform.GraphToAxis(P.X);  // P is in "axis" coordinates now
  P.y := Chart.LeftAxis.GetTransform.GraphToAxis(P.Y);

  { or, in a single line:
  P.x :=  Chart.BottomAxis.GetTransform.GraphToAxis(Chart.XImageToGraph(x));
  P.y := Chart.LeftAxis.GetTransform.GraphToAxis(Chart.YImageToGraph(y));}
end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

 

TinyPortal © 2005-2018