|
1
16th October 22:54
External User
|
LAT/LON to X/Y and back
I don't know if this is the right place to post this problem or not....but
hre goes...
I have a 1024 x 1024 form with nothing on it. I have the code below in it
that takes some LAT and LON coordinates and converts them to screen
coordinates and draws them on the screen with the LAT/LON and the screen
coordinates in text. This all works very nicely. The problem I am having
is trying to figure out how to go in the opposite direction. In other
words, if I click on the form I want to be able to show the LAT/LON in the
form caption. Can anyone figure out how to do this and provides me with a
working example?
While we are at it I welcome any comments that might help me improve on the
code I already have here. I know I shouldn't but for the sake of getting
this to work I have all of the coordinates hard coded in this example.
*** I got the math to do this from Wolfram Research Resource Library based
on reasearch by J.P Snyder USGS Pro Paper 1395
Map Projections -- A Working Manual. I only wish I was smart enough to have
come up with them myself =)
Thanks for any and all assistance.
Rich
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Math, StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function ValidateLon(VAR Lon:Extended): Boolean;
procedure ValidateLat(VAR Lat:Extended);
procedure PolyconicLLtoCartesian(Lat, Lon: Extended;
VAR CartX, CartY:
integer);
end;
var
Form1: TForm1;
origin_X, origin_Y :integer;
MCECanvas:TCanvas;
MCELatitude :Extended = 30.407; //Default Latitude for Center
MCELongitude :Extended = -88.921; //Default Longitude for Center
//the shifts required to make the key location in the middle of the
screen
//also used to track user offsets
LatShift : Extended = 0.0;
LonShift : Extended = 0.0;
ScaleExpansion : Integer = 2; //shown in submenu area EXP=
ScaleMultiplier : Double = 100.0; //used to expand map to correct size
implementation
{$R *.dfm}
(************************************************* *****************************)
(* This function makes sure the Longitude is within the range of
*)
(* 180.0 to -18.0 and returns true if the Longitude sent was OK to start
with *)
(* If it has to adjust the Longitude, it will return false.
*)
(************************************************* *****************************)
function TForm1.ValidateLon(VAR Lon:Extended): Boolean;
begin
Result := True; //default is a valid Lon
while (Lon > 180.0) do //make sure Lon is a valid number
begin
Lon := Lon - 360.0;
Result := False; //return of false means it was invalid
end;
while (Lon < -180.0) do
begin
Lon := Lon + 360.0;
Result := False;
end;
end;
(************************************************* *****************************)
procedure TForm1.ValidateLat(VAR Lat:Extended);
begin
while (Lat > 90.0) do
Lat := Abs(Lat - 180.0);
while (Lat < -90.0) do
Lat := -(Lat + 180.0);
end;
(************************************************* *****************************)
(* Receives latitude and logitude and uses them as polyconic coordinate
*)
(* values and returns X,Y scaled to Cartesian coodinate system with the
*)
(* lesson location longitude centered.
*)
(************************************************* *****************************)
procedure TForm1.PolyconicLLtoCartesian (Lat, Lon: Extended;VAR CartX,
CartY: integer);
const
PrevLonIsValid : Boolean = True;
var
r : Extended;
CotanLat, LonSinLat : Extended;
NextLonIsValid : Boolean;
begin
r := 58.0; //arbitrary scaler to make it look right
//spin the world to make current location's longitude
// in the center of the screen. DO NOT shift latitude like this since it
// is to scale only at the center longitude in this type projection.
Lon := Lon - LonShift;
//if Lon is a valid number ValidateLon returns true
NextLonIsValid := ValidateLon(Lon);
//check to see if the previous and next numbers cross 180 degrees from the
//central meridian
//save info for next time
// These evil calculations are brought to you by Wolfram Research Resource
// Library based on reasearch by J.P Snyder USGS Pro Paper 1395
// Map Projections -- A Working Manual
//pre-calculate to make CartX, CartY formula easier
LonSinLat := Lon * Sin(DegToRad(Lat));
//don't send a 0 to Cotan function
if ((Lat > 0.0) OR (Lat < 0.0)) then
begin
CotanLat := Cotan(DegToRad(Lat));
CartX := Round(ScaleMultiplier * (r * CotanLat *
Sin(DegToRad(LonSinLat))));
end
else
begin
CotanLat:= 0.000001;
CartX := Round(ScaleMultiplier * (r * DegToRad(Lon)));
end;
CartY := Round(ScaleMultiplier * (r * (DegToRad(Lat - LatShift) +
(CotanLat * (1.0 - Cos(DegToRad(LonSinLat)))))));
end;
(************************************************* *****************************)
procedure TForm1.FormCreate(Sender: TObject);
begin
MCECanvas := TCanvas.Create;
//get the handle for the Tod frame
MCECanvas.Handle := GetDC(Handle);
origin_X := (Width div 2);
origin_Y := (Height div 2);
//Logical units are mapped to arbitrary units with equally scaled axes
SetMapMode(MCECanvas.Handle, MM_ISOTROPIC);
SetWindowExtEx(MCECanvas.Handle, Width, Height, nil);
//the negative Frame.Height causes positive y to be up
SetViewportExtEx(MCECanvas.Handle, Width, -Height, nil);
//set the origin in middle of frame
SetViewportOrgEx(MCECanvas.Handle, origin_X, origin_Y, nil);
MCECanvas.Brush.Style := bsClear;//bsSolid; //bsClear to see behind text
MCECanvas.Brush.Color := clBlack; //color behind TextOut
MCECanvas.Font.Name := 'System';
MCECanvas.Font.Color := clBlack;
MCECanvas.Pen.Color := clBlack;
MCECanvas.Pen.Style := psSolid;
MCECanvas.Pen.Width := 2;
LatShift := MCELatitude;
LonShift := MCELongitude;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
Here : TPoint;
MyLat, MyLon : extended;
IntLatLon : TPoint;
mid : TPoint;
begin
//Clear off the canvas
MCECanvas.Brush := Brush;
MCECanvas.FillRect(ClientRect);
//get the target's lat/lon and convert to Cartesian coords
PolyconicLLtoCartesian(30.407, -88.921, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '30.407 : -88.921');
PolyconicLLtoCartesian(34.682, -88.921, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '34.682 : -88.921');
PolyconicLLtoCartesian(34.58, -94.086, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '34.58 : -94.086');
PolyconicLLtoCartesian(34.58, -83.757, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '34.58 : -83.757');
PolyconicLLtoCartesian(26.128, -88.922, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '26.128 : -88.922');
PolyconicLLtoCartesian(26.043, -93.655, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '26.043 : -93.655');
PolyconicLLtoCartesian(26.043, -84.188, Here.x, Here.y);
MCECanvas.Ellipse(Here.X, Here.Y, Here.X + 10, Here.Y + 10);
mid.x := (Here.x + 5);
mid.y := (Here.y + 5);
MCECanvas.Font.Color := clRed;
MCECanvas.TextOut(Here.x + 10, Here.y + 10, IntToStr(mid.X) + ':' +
IntToStr(mid.Y));
MCECanvas.Font.Color := clBlue;
MCECanvas.TextOut(Here.x - 40, Here.y - 10, '26.043 : -84.188');
MCECanvas.Brush.Color := clRed;
MCECanvas.Ellipse(0, 0, 10, 10);
end;
procedure TForm1.FormClick(Sender: TObject);
begin
//need to show the Lat and Lon of the loacation where the mouse was
clicked
end;
end.
|