Page 1 of 1

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

Posted: Thu Nov 25, 2010 10:51 pm
by 9244525
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!

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

Posted: Fri Nov 26, 2010 12:42 pm
by yeray
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);

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

Posted: Fri Nov 26, 2010 2:42 pm
by 9244525
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?

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

Posted: Fri Nov 26, 2010 2:46 pm
by yeray
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.

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

Posted: Mon Nov 29, 2010 7:45 am
by 9244525
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? :?

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

Posted: Mon Nov 29, 2010 8:43 am
by yeray
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

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

Posted: Thu Dec 02, 2010 12:48 pm
by 9244525
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

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

Posted: Thu Dec 02, 2010 2:27 pm
by yeray
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;

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

Posted: Fri Dec 03, 2010 8:39 am
by 9244525
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);

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

Posted: Fri Dec 03, 2010 1:56 pm
by yeray
Hi ChartIt,
ChartIt wrote:I got it!!!

I just used the Cursor Tool that I'm using anyway!
I'm glad to hear it! ^^