Page 1 of 1

Calculate terrain XY coordinates from mouse click on TChart

Posted: Fri Jan 05, 2007 8:54 pm
by 9038118
I have written a mapping application uses a Tchart where I have plotted several series of data that represent ground points and Aerial camera XY stations. On this graph, I would like to be able to click anywhere on the screen and then get the real world XY ground (terrain) coordinates of where the mouse was when the user clicked the screen. I did a search in the forum and found suggested code which I modified as follows:

procedure TfrmGraphBackend.Chart1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Terrain_X, Terrain_Y : double;
msg : string;
begin
If (AeroMatchUsed) then
begin
if (AutoCorrelate) then
begin
If (Button = mbRight) then
begin
Terrain_X := chart1.Axes.Bottom.CalcXPosValue(X);
Terrain_Y := chart1.Axes.Left.CalcYPosValue(Y);

msg := Format('Clicked at: X = %14.3f (meters), Y = %14.3f (meters)',
[Terrain_X,Terrain_Y]);

ShowMessage( msg );
end;
end;
end;
end;

Unfortunately, this does not compute the correct XY coordinates. When a I click on a known camera station symbol that is displayed in an existing plotted series, I get the following (incorrect) coordinates:

X = -197492 Y = 1328142

Where the true coordinates should be (approximately) :

X = 628810 Y = 4761040

Is it possible to make a call to one of Tcharts native methods to compute the correct coordinates?

Another possibility is to compute a coordinate transformation using a simple 2-dimensional conformal coordinate transformation. For a given chart, the user would have to click on 2 diagonally opposition known points to compute a transformation from the Chart1 axis coordinate to the real world system, but would this change if the user changed the zoom setting on the chart?

Thanks in advance,

Matt

Posted: Mon Jan 08, 2007 8:22 am
by narcis
Hi Matt,

As you already said in an e-mail you already solved that issue, don't you? You may be interested in posting the solution so that other users can benefit from it.

Thanks in advance.

Posted: Mon Jan 08, 2007 3:57 pm
by 9038118
Hi all (again),

I made some searches in the forum and found another similar question that gave me an idea, so i wrote two small routines that now give me the values that i need (see below in blue). What I am wrestling with now is how or which mouse click action to associate with this calculation. I tried the right mouse click, but that is already paired with panning. A double click would be OK, but that is also paired with zooming using a marque, which is redundant with a simple mouse click and drag. So I think I would like to disable ( unlink) the double click from the zooming, but need to retain the ability to zoom via click and drag. How does one unlink or trap the present double click action?

Thanks in advance,

Matt


var //globals

pts_2d : TpointArray;
Trans2D : TcoordTrans2D;
coef_a : double;
coef_b : double;
coef_c : double;
coef_d : double;

procedure TfrmGraphBackend.Chart1DblClick(Sender: TObject);
var
Terrain_X, Terrain_Y : double;
X,Y : double;
msg : string;
begin
If (AeroMatchUsed) then
begin
if (AutoCorrelate) then
begin
ComputeScaleRealWorld;
X := MouseX;
Y := MouseY;
Terrain_X := (coef_a * X) - (coef_b * Y) + coef_c;
Terrain_Y := (coef_a * Y) + (coef_b * X) + coef_d;
end;
end;
end;

procedure TfrmGraphBackend.ComputeScaleRealWorld;
var
x1,x2,y1,y2 : double;
cx1,cx2,cy1,cy2 : double;
begin
x1 := Chart1.Series[21].XValue[0];
y1 := Chart1.Series[21].YValue[0];
x2 := Chart1.Series[21].XValue[NumPht-1];
y2 := Chart1.Series[21].YValue[NumPht-1];
//-----------------------------------------
cx1 := Chart1.Series[21].CalcXPos(0);
cy1 := Chart1.Series[21].CalcYPos(0);
cx2 := Chart1.Series[21].CalcXPos(NumPht-1);
cy2 := Chart1.Series[21].CalcYPos(NumPht-1);
//---------------------------------------------
setLength(pts_2d,2);
//-----------------------
pts_2d[0].ID := '0';
pts_2d[0].used := true;
pts_2d[0].X[1] := cx1;
pts_2d[0].X[2] := x1;
pts_2d[0].Y[1] := cy1;
pts_2d[0].Y[2] := y1;
//-----------------------
pts_2d[1].ID := '1';
pts_2d[1].used := true;
pts_2d[1].X[1] := cx2;
pts_2d[1].X[2] := x2;
pts_2d[1].Y[1] := cy2;
pts_2d[1].Y[2] := y2;
//------------------------
Trans2D := TcoordTrans2D.Create(1,2,'C',pts_2d);
Trans2D.solve;
coef_a := trans2D.params[0];
coef_b := trans2D.params[1];
coef_c := trans2D.params[2];
coef_d := trans2D.params[3];
end;

Posted: Tue Jan 16, 2007 2:10 am
by Pep
Hi Matt,

have you tried to add an "Abort" after the ShowMessage has been called ?

Code: Select all

procedure TForm1.Chart1DblClick(Sender: TObject);
begin
  //....
  showmessage('message..');
  Abort;
end;