I noticed in the Navigator text for Joseph Becker (in the Demo.ahn file), the latitude - expressed as a decimal degrees - is incorrect (30' is always 0.5 degrees). In the Places Management dialog, the number is correct (if I remember), but displays wrongly in the Navigator. I am assuming the problem lies with the conversions between decimal degrees and degrees-minutes-seconds. Actually, from decimal degrees to DMS is not as simple as it appears on the surface.
I have a small Pascal test file (following) which demonstrates the routines necessary. I hope the code is simple enough to follow.
Also, in the Navigator the location is displayed as decimal degrees. I think that method is not commonly used anywhere - decimal degrees are used in computation only (as a rule).
Code: Alles auswählen
Program conversiontest;
VAR
{Note: functions require numeric values, string -> numeric may be required,
as well as numeric -> string for display, depending on your usage}
{variables for testing. Using globals for clarity}
deg : extended ; {decimal degrees}
d : longint ; {degrees - could be negative for negative angles}
m : longint ; {minutes}
s : extended ; {seconds - might be fractions of a second, hence extended}
{------------------------------}
PROCEDURE dms2deg ; {convert degrees-minutes-seconds to decimal degrees}
VAR
isneg : boolean ;
temp : longint ;
BEGIN
IF d < 0
THEN isneg := true
ELSE isneg := false ; {save sign}
temp := abs (d) ;
deg := temp+((m+(s/60))/60) ;
IF isneg
THEN deg := -deg
END ; {dms2deg}
{------------------------------}
PROCEDURE deg2dms ; {convert decimal degrees to degrees-minutes-seconds}
{A bit trickier, due to "rollover" during conversion, i.e. if result yields
60 seconds, that is actually 1 minute + 0 seconds!}
VAR
temp : extended ; {MUCH easier to work in seconds!}
absdeg : extended ; {absolute value of input}
isneg : boolean ;
BEGIN
IF (deg < 0)
THEN isneg := true
ELSE isneg := false ;{save sign}
absdeg := abs (deg) ; {only work with positive angles}
d := trunc (absdeg) ; {get degrees}
temp := absdeg * 3600 ; {convert absolute value to seconds}
temp := temp - (d * 3600) ; {remainder, in seconds}
{Note: d is longint, else * 3600 could cause 'rollover' in 16-bit integer}
m := trunc (temp/60) ; {get minutes}
s := temp - (m * 60) ; {get remainder, in seconds and decimal seconds}
IF isneg
THEN d := -d ; {might be negative}
END ; {deg2dms}
{------------------------------}
BEGIN {Lets test it out!}
d := 63 ; {assign test data}
m := 59 ; {CANNOT be negative in the real world}
s := 55.125 ; {CANNOT be negative in the real world}
dms2deg ;
write ('D:',d,' ','M:',m,' ','S:',s:0:3) ; {seconds to 3 decimals}
writeln (' -> DEG:',deg:0:8) ; {decimal degrees - 8 decimals}
writeln ;
deg2dms ; {just use answer from previous conversion}
write ('DEG:',deg:0:8) ;
writeln (' -> D:',d,' ','M:',m,' ','S:',s:0:3) ; {seconds to 3 decimals}
END.
Code: Alles auswählen
Program conversiontest1;
VAR
{Note: functions require numeric values; normal conversions to/from strings
may be required, depending on your usage. This approach is a little
more 'modern', since it uses FUNCTIONS/PROCEDURES with parameters
passed, rather than global variables. Also, the FRAC function is used
to bypass a step or two. The routines also work for negative angles,
as did the first routine ("conversiontest").}
{variables for testing}
deg : extended ; {decimal degrees}
d : longint ; {degrees - could be negative for negative angles}
m : longint ; {minutes}
s : extended ; {seconds - might be fractions of a second, hence extended}
{------------------------------}
FUNCTION dms2deg (_d,_m:longint; _s:extended): extended ; {DMS to dec. deg}
{Convert degrees-minutes-seconds to decimal_degrees. Always work with
positive input.}
VAR
isneg : boolean ;
temp : longint ;
decdeg : extended ;
BEGIN
IF _d < 0
THEN isneg := true
ELSE isneg := false ; {save sign}
temp := abs (_d) ;
decdeg := temp+((_m+(_s/60))/60) ;
IF isneg
THEN dms2deg := -decdeg {make negative}
ELSE dms2deg := decdeg
END ; {dms2deg}
{------------------------------}
PROCEDURE deg2dms (_deg:extended; VAR _d,_m:longint; VAR _s:extended) ;
{Convert decimal_degrees to degrees-minutes-seconds. Always work with
positive input.}
VAR
isneg : boolean ;
absdeg : extended ; {absolute value of input}
temp : extended ; {remainders}
BEGIN
IF (_deg < 0)
THEN isneg := true
ELSE isneg := false ; {save sign}
absdeg := abs (_deg) ; {only work with positive angles}
_d := trunc (absdeg) ; {get degrees}
temp := frac (absdeg) * 60 ; {remainder = decimal_minutes}
_m := trunc (temp) ; {get minutes}
_s := frac (temp) * 60 ; {get seconds}
IF isneg
THEN _d := -d ; {return negative sign}
END ; {deg2dms}
{------------------------------}
BEGIN {Lets test it out!}
d := 63 ; {assign test data}
m := 59 ; {CANNOT be negative in the real world}
s := 55.125 ; {CANNOT be negative in the real world}
deg := dms2deg (d,m,s) ;
write ('D:',d,' ','M:',m,' ','S:',s:0:3) ; {seconds to 3 decimals}
writeln (' -> DEG:',deg:0:8) ; {decimal degrees - 8 decimals}
writeln ;
{Lets make SURE the routine works, by zeroing the output first}
d := 0 ; m := 0 ; s := 0 ;
{Then calculate d/m/s from "scratch"}
deg2dms (deg,d,m,s) ; {just use answer from previous conversion}
write ('DEG:',deg:0:8) ;
writeln (' -> D:',d,' ','M:',m,' ','S:',s:0:3) {seconds to 3 decimals}
END.
- Mathemagician (Ruhestand professionellen Landvermesser)
P.S. In my career, we ALWAYS used Hewlett-Packard calculators and computers. Mostly (in the old days!) they had proprietary CPUs, working in BCD (binary coded decimal). NO rounding errors!