Page 1 of 1
TChart7.04 Get drawn YValue by known XValue
Posted: Tue Apr 12, 2005 9:51 am
by 9341182
I'm using TAreaSeries. How can I calculate the YValue on the drawn Line by a given XValue?
Example:
Point 1 in the Serie: X=1 Y=10
Point 2 in the Serie: X=3 Y=30
I'm geting the XValue=2 by the Cursortool(between two points). The result must be Y=20 if stairs:=false.
I've tried to calulate it myself, therefore I need the the Serie Values at the left and the right of the cursorposition.If tried it with 'GetCursorValueIndex',
but the function returns -1 sometimes.
Posted: Tue Apr 12, 2005 10:02 am
by narcis
Hi Achim,
If you're using a TCursorTool you can do something like:
Code: Select all
procedure TForm1.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
begin
if (Series1.Clicked(X,Y)<>-1) then
Chart1.Title.Text.Text:=FloatToStr(Series.YValues[Series.Clicked(X,Y)]);
end;
Posted: Tue Apr 12, 2005 1:19 pm
by 9341182
narcis wrote:Hi,
Code: Select all
procedure TForm1.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
begin
if (Series1.Clicked(X,Y)<>-1) then
Chart1.Title.Text.Text:=FloatToStr(Series.YValues[Series.Clicked(X,Y)]);
end;
Unfortunately 'Clicked' dosen't work, too.'Clicked' needs to hit the line _exactly_, but I need the point of intersection between the vertical line of the cursortool and the line of the series.
The reason is, I want to use two Charts, both with identical x-axis,
but different y-axis. Therefore I want to use two cursortools and
synchronize them by time. If the user move the cursor to a point at time X in Chart1, I want to show the YValue of the series in Chart2 at the choosen time X.
Here is sample code for the 'clicked' behavior:
Use a Form,TChart,Lineseries and cusortool.
Code: Select all
procedure TForm6.FormShow(Sender: TObject);
var
i:integer;
begin
ChartTool1.FollowMouse:=true;
ChartTool1.Style:=cssVertical;
ChartTool1.ClickTolerance:=100; // dosen't work
for i:= 0 to 59 do
begin
Series1.AddXY(i,i);
end;
end;
procedure TForm6.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
var
Index:integer;
begin
Index:=Series1.Clicked(x,y);
Chart1.Title.Text[0]:=IntToStr(Index);
end;
Posted: Tue Apr 12, 2005 4:36 pm
by narcis
Hi Achim,
Ah, ok, now I've understood what you want to do. Replacing your
ChartTool1Change implementation for the code below should do.
Code: Select all
procedure TForm1.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
begin
Chart1.Title.Text.Text:=FormatFloat('#.00',YValue);
end;
Posted: Tue Apr 12, 2005 10:31 pm
by 9341182
narcis wrote:
Code: Select all
procedure TForm1.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
begin
Chart1.Title.Text.Text:=FormatFloat('#.00',YValue);
end;
Hi NarcĂs,
Code like this, I've tried first.
But the YValue is the value of the mouse cursor, not the Value of the series line crossing by the vertical Cursortool line.
But I think, I have a solution. For everyone how has the same problem, here is it :
first some math:
X1,Y1 is a point on the line at the left side of XValue
X2,Y2 is a point on the line at the right side of XValue
YValue=m*XValue + b
with m=(y2-y1)/(x2-x1) and b=y1-m*x1
YValue=(XValue-x1)*(y2-y1)/(x2-x1)+y1
Code: Select all
procedure TForm6.FormShow(Sender: TObject);
var
i:integer;
begin
ChartTool1.FollowMouse:=true;
ChartTool1.Style:=cssVertical;
for i:= 0 to 59 do
begin
Series1.AddXY(i,i);
end;
end;
procedure TForm6.ChartTool1Change(Sender: TCursorTool; x, y: Integer;
const XValue, YValue: Double; Series: TChartSeries; ValueIndex: Integer);
Var
j:integer;
LeftIndex,RightIndex:integer;
found:boolean;
X1,X2:double;
Y1,Y2:double;
YV:double;
begin
if Series1.FirstValueIndex > 0 then
LeftIndex:=Series1.FirstValueIndex - 1 // FirstValueIndex is inside of the Chart
else
LeftIndex:=0;
RightIndex:=Series1.LastValueIndex; // LastValueIndex is outside of the chart
// search x1,x2,y1,y2
found:=false;
for j:= LeftIndex to RightIndex -1 do
begin
if (XValue >= Series1.XValue[j]) and
(XValue <= Series1.XValue[j+1]) then
begin
X1:=Series1.XValue[j];
Y1:=Series1.YValue[j];
X2:=Series1.XValue[j+1];
Y2:=Series1.YValue[j+1];
found:=true;
break;
end;
end;
// calculate
if found and (X2 <> X1) then
begin
YV:=(XValue-X1)*(Y2-Y1)/(X2-X1)+Y1; // YV is the result
Chart1.Title.Text.Text:=FloatToStrF(YV,ffFixed,5,2);
end;
end;