G'day,
Sorry for bumping an old post, but this seems the most appropriate location.
Many thanks for this library. Honestly, I couldn't have solved some issues on this job without it. My use is with the WGS84 unit. I'm not a surveyor, but in my industry we use Eastings, Northings extensively. I've been tasked with sending a device a GPS signal, so I needed to convert from EN to LatLon (cause I only know GPS commands that contain Lat Lon).
I've got everything working, and the conversion in WGS84 checks out against empirical data. So chances are, my question here is about convention.
I've noticed two oddities when using WGS84.pas.
1. In the comments for WGS84.pas, UTM.X is Easting, and UTM.Y is northing. And that makes sense. In my code though, I only get everything working if I use UTM.Y as Easting and UTM.X and northing.
2. Northing is coming out with a negative sign. Sure, I'm in the southern hemisphere, so this kind of makes sense. Except I've never seen negative northings in use in any field (I work in subsea oil and gas). And there's already a UTM.southernhemi boolean which I thought would take care of this.
My question is: Am I using WGS84.pas incorrectly, and I misunderstanding survey coordinates?, or is there an issue in WGS84.pas?In the test code that follows, I ask the user to enter a Lat Lon. This is then used to determine the UTM Zone (UTM.Fuseau) and determine if we're in the SouthernHemisphere.
I then convert this LAt Lon to Easting, Northing, and display that in my UI
I then convert back to Lat Lon (as a test) and display that.
I have a support unit (GSPSupport.pas) really so I can simplify code elsewhere by using a singleton for TWGS84.
Here's relevant snippets of my code:
MainForm
InitialiseGPS(edtLatitude.Value, edtLongitude.Value);
LatLonToEN(edtLatitude.Value, edtLongitude.Value, dEast{%H-}, dNor{%H-});
ENToLatLon(dEast, dNor, dLat{%H-}, dLon{%H-});
memGPS.Lines.Add('Original Lat:%.6f, Long:%.6f', [edtLatitude.Value, edtLongitude.Value]);
memGPS.Lines.Add('E:%.2f, N:%.2f', [dEast, dNor]);
memGPS.Lines.Add('Converted Lat:%.6f, Long:%.6f', [dLat, dLon]);
GPSSupport.pas
Var
FWGS84: TWGS84;
FFuseau: Integer;
FSouthernHemi: Boolean;
Function GetWGS88: TWGS84;
Begin
If Not Assigned(FWGS84) Then
FWGS84 := TWGS84.Create;
Result := FWGS84;
End;
Procedure InitialiseGPS(ALat, ALon: Double);
Begin
FFuseau := floor((ALon + 180) / 6) + 1;
FSouthernHemi := (ALat < 0);
End;
Procedure LatLonToEN(ALat, ALon: Double; Var AEast, ANorth: Double);
Var
oLatLon: TrecLatLon;
oUTM: TrecUTM;
oWGS84: TWGS84;
Begin
oLatLon.Lat := ALat;
oLatLon.Lon := ALon;
oWGS84 := GetWGS88;
oWGS84.WGS84ToUTM(oLatLon, oUTM{%H-});
AEast := oUTM.Y;
ANorth := oUTM.X;
End;
Procedure ENToLatLon(AEast, ANorth: Double; Var ALat, ALon: Double);
Var
oLatLon: TrecLatLon;
oUTM: TrecUTM;
oWGS84: TWGS84;
Begin
If FFuseau = -1 Then
Raise Exception.Create('Fuseau (UTM Zone) not defined. Call InitialiseGPS first.');
oUTM.X := ANorth;
oUTM.Y := AEast;
oUTM.southhemi := FSouthernHemi;
oUTM.fuseau := FFuseau;
oWGS84 := GetWGS88;
oWGS84.UTMToWGS84(oUTM, oLatLon{%H-});
ALat := oLatLon.Lat;
ALon := oLatLon.Lon;
End;
Initialization
FWGS84 := nil;
FFuseau := -1;
FSouthernHemi := True;
Finalization
FreeAndNil(FWGS84);
And finally, here's the output from the above:
Original Lat:-19.809287, Long:114.608388
E:249468.54, N:-7807850.06
Converted Lat:-19.809287, Long:114.608388
I haven't checked if the Easting/Northing is mm accurate, I only need accuracy to metre. Other than the minus sign, the E N checks out.
As you'll see, in Procedures ENToLatLon & LatLontoEN I had to switch X & Y around for Easting & Northing