Ahnenblattportal Forum Index
 •Portal  •Imprint  •Forum  •Search  •Profile  •Log in to check your private messages  •Log in   •Register  

 v2.93 BUG! - Places: angle conversion is flawed [FIXED ±]

Post new topicReply to topic
Author Message
Mathemagician




Gender:
Age: 67
Joined: 14 Dec 2014
Posts: 51
Topics: 16
Location: West Coast of Canada


canada.gif

PostPosted: 12.02.2016, 00:53    v2.93 BUG! - Places: angle conversion is flawed [FIXED ±]  Reply with quoteBack to top

Dirk,

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).

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.


Here's a better way to do the same think (above is quite "klunky"):

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.


Followup: I had a closer look at the value displayed in the Navigator's data box (for Joseph Becker)- the latitude is displayed as 51.516666 (for 51°30'). Converting back to DMS yields 51°30'60"! This is a classic rounding error in computers. I'm guessing the conversion routines currently use the INT function to grab the degrees or minutes, etc., but INT returns a real (from a real). All reals are encoded using base 2 techniques and are subject to tiny rounding errors - using INT (working with reals again) can produce a false result. For example, somewhere in your routine, the code may take the INT of 30.99999.... and returns 31, since the source is subject to error and the INT contributes to that error by again working in base 2 reals. I recommend having a look at my second routine - it should be fairly "bullet-proof", at least until the 5th (or higher) decimal place of seconds. The latitude and longitude can be stored internally as EXTENDED reals (10 bytes, less handling) then converted back to DMS when needed; there shouldn't be a problem with that. By the way, I tried deleting the Dortmund latitude in Places Management, then re-entering it - seemed to convert OK. But why does Places display (on opening the file) 51.5, but the Navigator box displays 51.56666?

- 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!

_________________
Allen T.
British Columbia, Canada

"Little did I know how little I knew..."


Last edited by Mathemagician on 21.02.2016, 17:41; edited 2 times in total

OfflineView user's profileSend private messageSend e-mailVisit poster's website    
DirkB
Administrator



Gender:
Age: 51
Joined: 20 Jan 2006
Posts: 745
Topics: 85
Location: Hamburg


germany.gif

PostPosted: 13.02.2016, 12:58    (No subject)  Reply with quoteBack to top

Dear Allen,

this problem will be fixed in the next version.

- Dirk

OfflineView user's profileSend private messageVisit poster's website    
Mathemagician




Gender:
Age: 67
Joined: 14 Dec 2014
Posts: 51
Topics: 16
Location: West Coast of Canada


canada.gif

PostPosted: 13.02.2016, 18:04    (No subject)  Reply with quoteBack to top

Dirk,

Great! I think this type of rounding error would probably come back, but only with certain values. No doubt the logic you have used is correct (works in Places Management, at least), but the INT routine (at least with Delphi/Pascal) is troublesome.

_________________
Allen T.
British Columbia, Canada

"Little did I know how little I knew..."

OfflineView user's profileSend private messageSend e-mailVisit poster's website    
Mathemagician




Gender:
Age: 67
Joined: 14 Dec 2014
Posts: 51
Topics: 16
Location: West Coast of Canada


canada.gif

PostPosted: 21.02.2016, 17:51    (No subject)  Reply with quoteBack to top

Dirk,

Excellent! The Delphi computations are undoubtedly now correct for DEC -> DMS (ver. 2.94), but there is a small glitch in the display of the result. Seconds are being displayed to 0.1", but are being truncated, rather than rounded (to the nearest 1/10 of a second). For example, 49.12355278 gets displayed as 49° 7' 24.7", but it is actually calculated as 24.79" (should display as 24.8"). Yes, I know this is being fussy - it translates to only about 3m "on the ground"!

_________________
Allen T.
British Columbia, Canada

"Little did I know how little I knew..."

OfflineView user's profileSend private messageSend e-mailVisit poster's website    
Display posts from previous:      
Post new topicReply to topic


 Jump to:   




Show permissions


Board Security

Powered by Orion based on phpBB © 2001, 2002 phpBB Group
CBACK Orion Style based on FI Theme
All times are GMT + 2 Hours



[ Page generation time: 0.0876s (PHP: 87% - SQL: 13%) | SQL queries: 28 | GZIP enabled | Debug on ]