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.PolyconicLLtoCartes
ian (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
//must match CartesianToPolyconicLL procedure
//ScaleMultiplier * r = 215 to work 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.Handl
e, MM_ISOTROPIC);
SetWindowExtEx(MCECanvas.H
andle, 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(ClientR
ect);
//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.