[comp.sys.handhelds] HP28/48 HAM Progs and MERCATOR PROJECTION Progs

jdg@hpqtdla.sqf.hp.com (James Gentles) (11/23/90)

Of interest to RADIO HAMS and CARTOGRAPHERS with HP28/48 calculators.
The following  details the contents of my  HP28 ham radio  directory. 
Read on if you are interested. Anyone  out there  got any other stuff  
for ham applications of the HP28/48 please post or email.
73
James
---------------------------------------------------------------------
      I have no professional connection with Hewlett-Packard's 
    calculator operations other than as a user of their products.
---------------------------------------------------------------------
Opinions expressed are my own, and are not intended to be an official
              statement by Hewlett-Packard Company
---------------------------------------------------------------------
Name:         James Gentles   GM4WZP
Organization: Hewlett-Packard  Queensferry Telecomunications Division
Email:        jdg@hpqtdla.hpsqf.hp.com                         hp-sdd 
Address:      Station Road, South Queensferry, West Lothian, Scotland
---------------------------------------------------------------------

This file contains a collection of HP28 programs used for translation
between different co-ordinate systems, calculating Great Circle Distances
and bearings, and calculating Radio Horizons. The programs may also be
of use to anyone interested in Transverse Mercator Projection Calculations.

The co-ordinate systems that can be translated between are:
      *	Latitude and Longitude (the fundamental measure of global position).
      *	The QRA Locator square system where the world is divided into
	a number of sections, each 2.5 mins latitude and 5 mins longitude.
      * The Great Britain National Grid reference System, which defines
	any point in Great Britain to within 100 metres.
      * The Irish National Grid reference System, which defines any point in
	Ireland (North and South) to within 100 metres.
Note:	These National Grid systems are used by Amateurs in the UK and Eire 
	to define a stations position to within a 10Km square. These are
	collected for a Worked all Britain (WAB) award.

Although these National Grid Systems are peculiar to the British Isles, they
use a mapping scheme called "Transverse Mercator Projection". These programs
could be used for translation between Latitude and longitude and ANY mapping
system that uses this projection by altering the constants used to define
the projection. These are contained in a list. The programs are written
specially for the British and Irish Grids, and their Grid Numbering scheme.
This means that 100Km squares are given grid letters, rather than numbers.
This extra level of complexity could easily be removed. The raw numbers from
the projection are more accurate than the 100 metres. It may even be possible
to use the formulae for "Mercator Projection" by simply swapping the Latitude
and Longitude entries. "Mercator Projection" is one of the projections commonly
used to show the whole world in atlases. It's main disadvantage for 'whole
world' maps is the distortion near the poles, making Antartica appear much
larger than it should be. For small parts of the globe (e.g. the UK) this
projection provides a very accurate model however.

Finally in this introduction a brief description of the UK national grid.
The grid system allows a map to contain a regular grid for reference and
distance calculations over short distances. However, because the map is a
projection of the surface of a shape approximating to an oblate spheroid
onto a plane (or cylindrical shaped) piece of paper then these grid lines
have a very complex relationship to latitude and longitude. The origin of
the grid is off the SW corner of England, and there are 4 main squares,
each 500Km on all sides. The square nearest the origin is called S (South?),
and covers most of England. The square north of that is N (North?) and covers
mostly Scotland. The square north of that again is H (?) and covers the most
northerly islands of Scotland. Finally the eastern extremity of England just
pokes into square T to the east of square S. These letters appear to be named
arbitrarily. Each of these 500Km squares is divided into 25 100Km squares as
follows:
			A	B	C	D	E

			F	G	H	J	K

			L	M	N	O	P

			Q	R	S	T	U

			V	W	X	Y	Z

So for example I live at "NT119779" to the nearest 100metres. The full
reference from datum for this is Eastings 311900, Northings 677900.
Note program XX6-> is used to do this translation.

The Irish grid only covers one of the above described 500Km squares, so
it is identical to the British system except the leading N, S, H or T is
not required.

There now follows a description of each of the objects listed at the end. 



QRA Locator Square Translator: The following procedures translate between 
the worldwide QRA (or ANB or Maidenhead, whatever its called) locator
system used by Radio Amateurs.

->QRA   Takes Latitude from stack level 2, and Longitude from level 1
        and returns a string with the Locator. South and West are
        negative. The input should be in DD.MMSS format. The input is
        tested to ensure that it is +-90 and +-180 respectively. For
        example, take QTH ->QRA gives "IO85HX" for my locator.

QRA->   Takes a string from the stack level 1 and returns the Latitude
        in level 2 and Longitude in level 1 of the square center. This
        is the inverse of ->QRA. The output is in DD.MMSS. Some error
        trapping is done on the input, but it is not foolproof. 

Transverse Mercator Projection Routines, to change to Latitude and Longitude,
all Latitude and longitude numbers are entered, and returned in DD.MMSSsss
format unless otherwise stated.

->NGR	Lat and Long to National Grid Reference (Great Britain). Put
	Latitude on stack (north is +ve), then Longitude on stack
	(east is +ve), returns a string of format "NT119779". The bottom
	left corner of the 100m square defined.

NGR->	National Grid to Lat and Long. The inverse of ->NGR. Returns the
	Lat and Long of the centre of the 100m square defined.

->IGR	Lat and Long to Irish Grid Reference. Put Latitude on stack 
	(north is +ve), then Longitude on stack (east is +ve), returns 
	a string of format "T119779". The bottom left corner of the 100m 
	square defined.

IGR->	Irish Grid to Lat and Long. The inverse of ->IGR. Returns the
	Lat and Long of the centre of the 100m square defined.

->XX6	Used by ->NGR and ->IGR to translate eastings and northings in metres
	to a national grid reference, e.g. 311900 677900 become "NT119799"
	If the coordinates do not fall into one of the 4 500Km squares a "#"
	is returned in the first character of the string.

XX6->	Performs the inverse process of ->XX6.

->TMP	Performs the Transverse Mercator Projection. On entry the stack should
	contain Lat, Long (both in radians), then all the constants in list 
	AIRY or IRISH depending on what projection is being used. The routine 
	returns eastings and northings on the stack in metres.

TMP->	Performs the inverse Transverse Mercator Projection. On entry the 
	stack should contain eastings, northings, then all the constants in 
	list AIRY or IRISH depending on what projection is being used. The 
	routine returns Latitude and longitude on the stack in radians.

VRH2	Used by ->TMP and TMP-> routines

AOM	Used by ->TMP and TMP-> routines

PHI	Used by ->TMP and TMP-> routines

ABNE	Used by ->TMP and TMP-> routines

PAD0	Used by ->XX6 routine

AIRY	List of constants used by TMP routines for Great Britain. See following
	listing of object for comments on what individual elements are.

IRISH	List of constants used by TMP routines for Ireland. See following
	listing of object for comments on what individual elements are.


Great Circle Distance & Bearings: Calculates the distance between your
station and the remote station, also gives beam heading required.

GCIR    Takes the output of QRA-> (Lat and Long) and uses the Lat and 
        Long in QTH to compute the great circle distance and bearing 
        from QTH to the stack Lat and Long. The distance is returned
        in Level 2, in Km. The bearing, in DD.MMSS from north (+E,-W) 
        is returned in Level 1. This program assumes the earth is a
        perfect sphere ( we all know this is an approximation as the 
        earth is actually flat :-). This program uses the PRESERVE
        routine given in the manual to ensure degrees mode is used.
      
QTH     Must contain the two numbers << Lat,Long >> representing your
        stations position, in degrees, minnutes and seconds.

ERAD    Must contain the equatorial radius of the earth. I use:
        6378.888
        which is in Kilometers, thus the answer to GCIR is in Km,
        you can use UNITS to change this constant if you wish.

Radio Horizon: Calculates the flat-band line of sight communication
distance at VHF.

HORIZ   Returns the distance between a point on the earth and the
        VHF radio 'horizon' given the height above sea level. The
        height is taken from level 1, and the distance returned in 
        level 1, both will be in the same units as ERAD. e.g. For
        914m ASL enter 0.914 to give an answer of 124.68 Km. Note
        this is NOT the same as the line of sight horizon, as it
        includes a correction of SQRT(4/3) to allow for tropospheric
        bending.

LOFS    Line of Sight. Same as HORIZ but does not take into account
        any bending, can be used for frequencies above VHF or light.




The Procedures:


->QRA   Checksum BC9E
<< HMS-> 180 + SWAP HMS-> 90 + -> lo la
   << IF lo 0 < lo 360 > la 0 < la 180 > OR OR OR
      THEN la 90 - lo 180 - "Lat/Long out of range" 1 DISP
           2 WAIT ABORT
      END
      lo 20 / IP 65 + CHR
      la 10 / IP 65 + CHR
      lo 20 / FP 10 * IP 48 + CHR
      la 10 / FP 10 * IP 48 + CHR
      lo 2 / FP 24 * IP 65 + CHR
      la  FP 24 * IP 65 + CHR
   >> + + + + +
>>


QRA->   Checksum 9DE4
<< 
   << "Not valid QRA" 1 DISP 1 WAIT >> -> 'er'
      <<
      DUP IF TYPE 2 <> THEN er EVAL ABORT END
      DUP IF SIZE 6 <> THEN er EVAL ABORT END
      -> q
         << 1 6 FOR i q i DUP SUB NUM 65 - NEXT
         -> a b c d e f 
           << 'b*10+(d+17)+f/24+1/48-90' EVAL ->HMS
           'a*20+(c+17)*2+e/12+1/24-180' EVAL ->HMS
         >>
      >>
   >>
>>


->NGR 	Checksum 7F70
<< HMS-> D->R SWAP HMS-> D->R       Change to degrees decimal then radians
   AIRY LIST-> DROP  		Put constants for Airy projection on stack 
   ->TMP 			Transverse Mercator Proj returns E&N in meters
   ->XX6			Translate to grid letters and 100metre accy
>>

 
NGR-> 	Checksum 9E92
<< XX6-> 			Translate grid letters to full coords
   AIRY LIST-> DROP 		Put constants for Airy projection on stack
   TMP-> 			Transverse Mercator to Lat Long convertion
   SWAP R->D ->HMS SWAP		Translate to deg/min/seconds
   R->D ->HMS 
>>

 
->IGR 	Checksum 6E58
<< HMS-> D->R SWAP HMS-> 	Same as ->NGR but since Irish grid is only 500Km
  D->R IRISH LIST-> DROP 	square then initial grid letter ("S") can be
  ->TMP ->XX6 2 8 SUB		ignored so is stripped off.
>>

 
IGR-> 	Checksum F77C
<< "S" SWAP + XX6-> IRISH 	Same as NGR-> but to use same XX6-> routine the
  LIST-> DROP TMP-> SWAP 	"S" suffix is added to the grid ref before
  R->D ->HMS SWAP R->D ->HMS 	parsing by XX6->, so its output is correct
>>

 
->XX6 	Checksum 4FB1 
<< 100 / IP SWAP 100 / IP 
-> n e 				Throw away accuracy better than 100m
  << e 5000 / IP n 5000 / IP 
   -> es ns			Find what 500Km square to be used
    <<
      IF es 0 ==		For eastings 0 to 500000
      THEN
        IF ns 2 ==		Northings 1000000 to 1500000 square H
        THEN "H"
        ELSE
          IF ns 1 ==		Northings  500000 to 1000000 square N
          THEN "N"
          ELSE
            IF ns 0 ==		Northings       0 to  500000 square S
            THEN "S"
            ELSE "#"		ELSE illigal square denoted by #
            END
          END
        END
      ELSE
        IF ns 0 == es 1 == AND	for eastings 500000 to 1000000 and
        THEN "T"		Northings 0 to 500000 square T
        ELSE "#"		ELSE illigal square denoted by #
        END
      END e 1000 / IP 5 MOD 	Now find letter within square by first numbering
      1 + 4 n 1000 		squares top left to bottom right. 
      / IP 5 MOD - -> el nl
      << nl 5 * el + DUP	So numbers are 0 to 24
        IF 8 <=			Skip the number 8
        THEN 1 -		So numbers are 0 to 7 then 9 thru 25
        END 65 + CHR +		puch grid character A to H then J thru Z
      >> e 1000 MOD
      << STD
      >> NFMT PAD0 n 1000 MOD
      << STD
      >> NFMT PAD0 + +		Build into reference e.g. NJ123456 using PAD0
    >>				to fill in leading 0's in the strings.
  >>
>>

 
XX6-> 	Checksum E0D1
<< -> str
  << str 3 5 SUB str 6 8 SUB 	Split incloming string up e.g. N J 123 456
  str NUM str 2 					       f s  e   n
  2 SUB NUM 66 - DUP		letters are translated to numbers and s is
    IF 7 <			connditioned to be contiguous top right to
    THEN 1 +			bottom left 0 to 24
    END -> e n f s
    <<
      IF f 72 ==		IF H square msdigit should be
      THEN 0 2
      ELSE
        IF f 78 ==		IF N square msdigit should be
        THEN 0 1
        ELSE
          IF f 83 ==		IF S square msdigit should be
          THEN 0 0
          ELSE
            IF f 84 ==		IF T square msdigit should be
            THEN 1 0
            ELSE "XX Error" 
                 1 DISP HALT
            END
          END
        END
      END -> e1 n1		pass the msdigits of easting and northing
      << s 5 MOD 4 s 5 / IP 5 
        MOD - -> e2 n2
        << e STR-> e1 5000 
        * e2 1000 * +
         + 100 * 50 + n STR-> 
        n1 5000 * n2 
        1000 * + + 100 * 50 +
        >>			Recombine elements into full N&E adding 50meters
      >>			to both to place them at square centre
    >>
  >>
>>

 
->TMP 	Checksum 8523
<<					Reference Transverse Mercator Projection
  << RAD -> l k a b k0 l0 n0 e0 f0	Constants, Formulae and Methods
    << l l0 - k k0 - k k0 + -> p k3 k4	Ordnance Survey Information March 1983
      << a b f0 ABNE -> a1 b1 n1 e2
        << n1 k3 k4 b1 AOM a1 e2 k VRH2 -> 
        m v r h2
          << l l0 - -> p
            << m n0 + 				Formula I
            k SIN k COS v 2 / * * 			II
            'v/24*SIN(k)*COS(k )^3*	
             (5-TAN(k)^2+9*h2)' ->NUM 			III
            'v/720*SIN(k)*COS(k)^5*(61-
             58*TAN(k)^2+TAN(k)^4)' ->NUM 		IIIA
            p 6 ^ * SWAP p 4 ^ 			COMPUTE NORTHINGS
            * + SWAP p SQ * + + 
            k COS v * 				Formula IV
            'v/6* COS(k)^3*(v/r-TAN(k)^2)' ->NUM 	V
            'v/120*COS (k)^5*(5-18*TAN(k)^2+
             TAN(k)^4+14*h2-58*TAN(k)^2*h2)' ->NUM	VI
            p 5 ^ * SWAP p 3 ^ * + SWAP p * 	COMPUTE EASTINGS
            + e0 + SWAP
            >>
          >>
        >>
      >>
    >>
  >> PRESERVE					RETURN TO ORIGINAL STATUS
>>

 
TMP-> 	Checksum 1541
<<					Reference Transverse Mercator Projection
  << RAD -> e n a b k0 l0 n0 e0 f0	Constants, Formulae and Methods
    << e e0 - -> y1			Ordnance Survey Information March 1983
      << a b f0 ABNE -> a1 b1 n1 e2
        << n n0 n1 k0 a1 b1 PHI -> k k3 
        k4
          << a1 e2 k VRH2 -> v r h2
            << k TAN 2 r v * * / 		Formula VII
            'TAN(k) / (24*r*v^3)*(5+3*
             TAN(k)^2+h2-9*TAN(k)^2*h2)' ->NUM  	VIII
            'TAN(k)/( 720*r*v^5)*(61+90* 
             TAN(k)^2+45*TAN(k)^4 )' ->NUM		IX
            y1 6 ^ * SWAP y1 4 ^ * 		CALCULATE LATITUDE
            SWAP - SWAP y1 SQ * + k SWAP - 
            k COS v * INV 			Formula X
            '1/(COS(k)*6*v^3)*(v 
             /r+2*TAN(k)^2)' ->NUM 			XI
            '1/(COS(k)*120*v^5)*(5+28*
             TAN(k)^2+24* TAN(k)^4)' ->NUM 		XII
            '1/( COS(k)*5040*v^7)
            *(61 +662*TAN(k)^2+1320* TAN(k)
            ^4+720*TAN(k)^ 6)' ->NUM 			XIIA
            y1 7 ^ * SWAP y1 5 ^ *     		CALCULATE LONGITUDE
            SWAP - SWAP y1 3 ^ * + SWAP y1 
            * SWAP - l0 +
            >>
          >>
        >>
      >>
    >>
  >> PRESERVE
>>

 
VRH2 	Checksum F951
<< -> a1 e2 k
  << 'a1/SQRT(1-e2*SIN(k )^2)' ->NUM DUP 
  '(1- e2)/(1-e2*SIN(k)^2)' ->NUM * DUP2 
  / 1 -
  >>
>>
 
 
AOM 	Checksum 447F			Compute Developed Meridion Arc m
<< -> n1 k3 k4 b1			stack variables to local variables
  << '(1+n1+5/4*n1^2+ 5/4*
   n1^3)*k3' ->NUM 
  '(3*n1+3*n1^2+21/8*n1^3)*
   SIN(k3)*COS(k4)' ->NUM 
  '(15/8*n1^2+15/ 8*n1^3)*
   SIN(2*k3)*COS(2*k4)' ->NUM 
  '35/ 24*n1^3*SIN(3*k3)*
   COS(3*k4)' ->NUM 
  - + - b1 *
  >>					on exit m is on stack
>>

 
PHI 	Checksum DF6C			Iteratively Calculate Latitude k
<< -> n n0 n1 k0 a1 b1			stack variables to local variables
  << '(n-n0)/a1+k0' ->NUM 0 0		First approximation to Latitude
    DO DROP2 DUP DUP k0 - SWAP 
      k0 + -> k k3 k4
      << n1 k3 k4 b1 AOM -> m		re-compute arc of meridian
        << n n0 - m - DUP
          IF .001 <			
          THEN k k3 k4
          ELSE 'k+(n -n0-m)/a1' 	re-calculate phi
               ->NUM k3 k4
          END
        >>
      >> 4 ROLL
    UNTIL .001 <			UNTIL error is less than .001
    END					returns k k3 k4 on stack
  >>
>>

 
ABNE 	Checksum 6926
<< -> a b f0				Stack variables to local variables
  << a f0 * b f0 * -> a1 b1		Scale Major & Minor axes by f0
    << a1 b1 DUP2 - a1 b1 + / 		calculate n from scaled axes
    a1 SQ b1 SQ - a1 SQ /		calculate e^2 (e2) from scaled axes
    >>
  >>					returns a1 b1 n e2 on stack
>>

 
PAD0 	Checksum 91D6
<<					Takes string from stack and
  WHILE 				while it is shorter than 3 characters
    DUP SIZE 3 <
  REPEAT 
    "0" SWAP +				add a leading "0"
  END
>>

 
AIRY 	Checksum 51C5      	Constants defining Transverse Mercator 
				Projection for Airy Spheroid
{ 6377563.396			Major semi-axis m
6356256.91			Minor semi-axis m
.855211333477	  	        True Origin 49 deg N              for
-3.490658E-2 			             2 deg W	      GREAT BRITAIN
-100000 			False Origin in m E of true origin
400000 						m N of true origin
.9996012717 }			Scale factor on Central meridian Fo

 
IRISH 	Checksum 2E20 		Constants defining Transverse Mercator 
				Projection for Airy Spheroid
{ 6377563.396			Major semi-axis m
6356256.91			Minor semi-axis m
.933751149817			True Origin 53.5 deg N		  for
-.139626340159			             8   deg W	        IRELAND 
250000 				False Origin in m E of true origin
200000 						m N of true origin
1.000035 }			Scale factor on Central meridian Fo
 

GCIR   Checksum AA31
       << 
          << DEG HMS-> SWAP HMS-> QTH HMS-> SWAP HMS-> 
             4 ROLLD ROT -
             DUP IF 180 > THEN 360 - END
             DUP IF -180 < THEN 360 + END
             IF DUP 0 == THEN .000001 + END   ! ensures we dont divide by 0
             -> lah laa dif
             << 'ACOS(SIN(lah)*SIN(laa)+COS(lah)*COS(laa)*COS(dif))' ->NUM
                DUP 180 / pi * ERAD * ->NUM SWAP -> dis
                << 'ACOS((SIN(laa)-SIN(lah)*COS(dis))/(COS(lah)*SIN(dis)))'
                   ->NUM
                >>
                IF dif 0 > THEN NEG END ->HMS ! correction for E or W of N
             >>
          >> PRESERVE
       >> 


HORIZ  Checksum 6E8B
       << ERAD * 8 * 3 / SQRT
       >>


LOFS   Chechsum D7E9
       << ERAD * 2 * SQRT
       >>


ERAD   6378.388


QTH    << 55.5910  -3.244 >>            Must be in DD.MMSSsss format, Lat,Long

 
SYMBOL KEY:
 
SQRT  131:-Square_root_symbol 
pi  135:-Symbolic_constant 
<=  137:-Less_than_&_equal_to 
<>  139:-Not_equal_to 
->  141:-Right_hand_arrow 
<<  146:-Start_program_construct 
>>  147:-End_program_construct *