How to get YValue according to horiz. position of cursor?

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
ChartIt
Newbie
Newbie
Posts: 29
Joined: Tue Mar 13, 2007 12:00 am

How to get YValue according to horiz. position of cursor?

Post by ChartIt » Thu Nov 25, 2010 10:51 pm

Hello all,

I give up, after way too long time searching for a solution on my quite simple task!

With this code

tmpX, tmpY: Double;
Chart1[0].GetCursorValues(tmpX, tmpY);

I get the actual values under the mouse cursor, even though no series values are present under the cursor.

But how do I get the YValue of a series point equal to the horizontal position of the cursor?
I would like to use the function

Chart1[0].YValue[Index]

but how do I get the index of the YValue present on the vertical line of the cursor??
All functions I have found that return the actual cursor position seem to return the position in screen pixels.
I need the position in YValues (count)!

It all takes place in the MouseMove event, and the YValue must be "refreshed" all the time, which means that I can't use any Series.OnClicked events.

Hope I explained well, and thanks in advance!

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to get YValue according to horiz. position of cursor?

Post by Yeray » Fri Nov 26, 2010 12:42 pm

Hi ChartIt,

You can retrieve the Cursor's XValue and YValue directly:

Code: Select all

Chart1.Title.Text.Text:=FloatToStr((Chart1.Tools[0] as TCursorTool).XValue);
You can also convert pixels to values and vice versa with Axes' CalcPosPoint and CalcPosValue functions.

Pixels to Values:
For example, in OnMouseMove event, you have X and Y mouse position in pixels given as parameters, so you can do as follows:

Code: Select all

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var XValue: double;
begin
  XValue:=Chart1.Axes.Bottom.CalcPosPoint(X);
  Chart1.Title.Text.Text:=FloatToStr(XValue);
end;
Values to Pixels:
At any time (once the chart has been drawn) you can obtain the pixel where a value will be drawn:

Code: Select all

XPixel:=Chart1.Axes.Bottom.CalcPosValue(10);
You can also obtain the pixel for a determinate series' value, knowing it's index in the series:

Code: Select all

XPixel:=Chart1[0].CalcXPos(10);
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

ChartIt
Newbie
Newbie
Posts: 29
Joined: Tue Mar 13, 2007 12:00 am

Re: How to get YValue according to horiz. position of cursor?

Post by ChartIt » Fri Nov 26, 2010 2:42 pm

Hi Yeray,

I think we misunderstand each other.
As seen on the enclosed screen shot (from a measurement program I'm about to "copy") I want to get the YValue that is on the same horizontal position as the cursor, but not necessarily on the same vertical position.

You wrote:
>>You can also obtain the pixel for a determinate series' value, knowing it's index in the series:
>>XPixel:=Chart1[0].CalcXPos(10);

My question is now:
How can I obtain the Index of the YValue in the series?

Do you get it?
Attachments
Measurement.JPG
Measurement.JPG (52.09 KiB) Viewed 20886 times

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to get YValue according to horiz. position of cursor?

Post by Yeray » Fri Nov 26, 2010 2:46 pm

Hi ChartIt,

Take a look at the example at All Features\Welcome !\Chart Styles\Standard\Line (Strip)\Interpolating Line Series in the New Features demo included with the installation.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

ChartIt
Newbie
Newbie
Posts: 29
Joined: Tue Mar 13, 2007 12:00 am

Re: How to get YValue according to horiz. position of cursor?

Post by ChartIt » Mon Nov 29, 2010 7:45 am

Hi Yeray,

Thanks for that, but I don't want/need to interpolate the value between the points, just get the value closest to the cursor.
I'm pretty sure it is just a very simple line of code that I need to retrieve that index as described above, but which code? :?

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to get YValue according to horiz. position of cursor?

Post by Yeray » Mon Nov 29, 2010 8:43 am

Hi ChartIt,
ChartIt wrote:Thanks for that, but I don't want/need to interpolate the value between the points, just get the value closest to the cursor.
I'm pretty sure it is just a very simple line of code that I need to retrieve that index as described above, but which code? :?
Then, it sounds like you are looking for something like TNearestTool. Take a look at the demo at All Features\Welcome !\Tools\Nearest Point
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

ChartIt
Newbie
Newbie
Posts: 29
Joined: Tue Mar 13, 2007 12:00 am

Re: How to get YValue according to horiz. position of cursor?

Post by ChartIt » Thu Dec 02, 2010 12:48 pm

Hi Yeray,

I don't think that's the function I need, and it sounds like overkill to use a separate Tool in my case.
I'm actually still pretty sure that I'm just missing one line of code.
As discussed above:

You wrote:
>>You can also obtain the pixel for a determinate series' value, knowing it's index in the series:
>>XPixel:=Chart1[0].CalcXPos(10);

My question is still:
How can I obtain the Index of the YValue in the series?

Maybe something like:
YValueIndex := Chart1[0].CalcYValueIndex(CursorsXPositionInPixel);

Then I could use this YValueIndex to finally get my value:
Result := Chart1[0].YValue[YValueIndex]; :D :D :D

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to get YValue according to horiz. position of cursor?

Post by Yeray » Thu Dec 02, 2010 2:27 pm

Hi ChartIt,
ChartIt wrote:My question is still:
How can I obtain the Index of the YValue in the series?

Maybe something like:
YValueIndex := Chart1[0].CalcYValueIndex(CursorsXPositionInPixel);

Then I could use this YValueIndex to finally get my value:
Result := Chart1[0].YValue[YValueIndex]; :D :D :D
There isn't a method like the one you suggest (CalcYValueIndex nor with another name) because it wouldn't be enough generic. For example, what Index should this function return for an Horizontal Line Series?
That's why we propose to do the same manually in the Interpolating Line Series example in the features demo mentioned above. Actually, we loop in the series until we find the two points where the mouse is between, and we calculate the Y value with trigonometry arithmetic.

Code: Select all

function TLineInterpolateForm.InterpolateLineSeries(Series: TChartSeries;
  XValue: Double): Double;
begin
  result:=InterpolateLineSeries(Series,Series.FirstDisplayedIndex,Series.LastValueIndex,XValue);
end;

function TLineInterpolateForm.InterpolateLineSeries(Series: TChartSeries;
  FirstIndex, LastIndex: Integer; XValue: Double): Double;
var
  Index: Integer;
  dx,dy: Double;
begin
  for Index:=FirstIndex to LastIndex do
    if Series.XValues.Value[Index]>XValue then break;

  //safeguard
  if (Index<1) then Index:=1
  else if (Index>=Series.Count) then Index:=Series.Count-1;

  // y=(y2-y1)/(x2-x1)*(x-x1)+y1
  dx:=Series.XValues.Value[Index] - Series.XValues.Value[Index-1];
  dy:=Series.YValues.Value[Index] - Series.YValues.Value[Index-1];

  if (dx<>0) then
    result:=dy*(XValue - Series.XValues.Value[Index-1])/dx + Series.YValues.Value[Index-1]
  else result:=0;
end;

procedure TLineInterpolateForm.Chart1AfterDraw(Sender: TObject);
var xs, ys, i: Integer;
begin
  if CheckBox1.Checked then
  begin
    xs := Chart1.Axes.Bottom.CalcXPosValue(xval);

    for i:=0 to Chart1.SeriesCount - 1 do
    begin
      ys := Chart1[i].GetVertAxis.CalcYPosValue(InterpolateLineSeries(Chart1[i],xval));
      Chart1.Canvas.Brush.Color := Chart1[i].Color;
      Chart1.Canvas.Ellipse(xs-4,ys-4,xs+4,ys+4);
    end;
  end;
end;

procedure TLineInterpolateForm.ChartTool1Change(Sender: TCursorTool; x,
  y: Integer; const XValue, YValue: Double; Series: TChartSeries;
  ValueIndex: Integer);
var
  i: Integer;
begin
  xval := XValue;

  With Chart1.Title.Text do
  begin
    Clear;
    for i:=0 to Chart1.SeriesCount - 1 do
        Add(Chart1[i].Name + ': Y('+FloatToStrF(XValue, ffNumber, 8, 2)+')= ' +
            FloatToStrF(InterpolateLineSeries(Chart1[i],XValue), ffNumber, 8, 2)+#13#10);
  end;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

ChartIt
Newbie
Newbie
Posts: 29
Joined: Tue Mar 13, 2007 12:00 am

Re: How to get YValue according to horiz. position of cursor?

Post by ChartIt » Fri Dec 03, 2010 8:39 am

I got it!!!

I just used the Cursor Tool that I'm using anyway!

with Chart1.Tools.Add(TCursorTool) as TCursorTool do
begin
FollowMouse := True;
ScopeStyle := scsEmpty;
Pen.Visible := False;
Series := Chart1[0]; //A series must be assigned to show cross hair with cursor tool.
Style := cssVertical;
end;

YValueIndex := (Chart1.Tools.Items[0] as TCursorTool).NearestPoint(cssVertical, Dummy);

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to get YValue according to horiz. position of cursor?

Post by Yeray » Fri Dec 03, 2010 1:56 pm

Hi ChartIt,
ChartIt wrote:I got it!!!

I just used the Cursor Tool that I'm using anyway!
I'm glad to hear it! ^^
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply