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
Calculate terrain XY coordinates from mouse click on TChart
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
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.
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.
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
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;
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;
Hi Matt,
have you tried to add an "Abort" after the ShowMessage has been called ?
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;
Pep Jorge
http://support.steema.com
http://support.steema.com