Source file geodat.icn
############################################################################
#
#	File:     geodat.icn
#
#	Subject:  Procedures for geodetic datum conversion
#
#	Authors:  William S. Evans and Gregg M. Townsend
#
#	Date:     July 31, 2000
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#	These procedures provide "projections" that convert among geodetic
#	datums, which relate locations on the earth's surface to longitude
#	and latitude coordinates.  As measurement techniques improve,
#	newer datums typically give slightly different values from older
#	ones.  The values returned here are used with the project()
#	procedure of cartog.icn.
#
#	geodat(s1, s2) defines a geodetic datum conversion.
#	molodensky() performs an algorithmic datum conversion.
#	nadcon(s1, s2) uses data files for more precise conversion.
#
#	ellipsoid(s) return the parameters of the named ellipsoid.
#
############################################################################
#
#	geodat(f, t) returns a projection from longitude and latitude
#	in datum f to longitude and latitude in datum t.
#	f and t are strings.  If f and t equal "NAD83", "NAD27",
#	"HARN", or "HPGN", geodat returns a nadcon projection.
#	Failing that, geodat returns a molodensky projection.
#
#	The input to the projection is a list of signed numeric values,
#	angles measured in degrees, with each pair representing one
#	location; longitude precedes latitude.  The output is a list
#	with the same form and length as the input list.
#
############################################################################
#
#	nadcon(f, t) returns a projection from longitude and latitude
#	in datum f to longitude and latitude in datum t.  The strings
#	f and t must each be one of "NAD83", "NAD27", "HARN", or "HPGN".
#	The projection uses our implementation of the National Oceanic
#	and Atmospheric Administration's (NOAA's) North American Datum
#	Conversion Utility (NADCON); for more information, see
#	    http://www.ngs.noaa.gov/TOOLS/Nadcon/Nadcon.html
#
#	nadcon() requires data grid (.loa and .laa) files, which must be
#	found in the current directory or along the space-separated path
#	given by the environment variable DPATH.  These files can be
#	downloaded from:
#	    http://www.cs.arizona.edu/icon/ftp/data/nadcon/
#	    ftp://ftp.cs.arizona.edu/icon/data/nadcon/
#
#	The projection's input and output are lists of signed numbers.
#	Output is properly rounded and so may not agree exactly with
#	the equivalent NOAA programs.
#
############################################################################
#
#	molodensky(dx, dy, dz, ain, fin, aout, fout) returns a projection
#	from input longitude and latitude to output longitude and latitude.
#	The projection uses the standard Molodensky transformation.
#	The input datum is specified by an ellipsoid with parameters
#	ain, the equatorial radius in metres, and fin, the flattening;
#	and by three shift values dx, dy, and dz.  The output datum is
#	specified by an ellipsoid with parameters aout and fout.
#
#	If dz is null, then dx and dy are interpreted as the names of
#	an input and output datum.  The names are the ID codes
#	specified in NIMA TR 8350.2.
#
#	The projection's input and output are lists of signed numbers.
#
############################################################################
#
#	ellipsoid(s) return a list [a, 1/f] containing the defining
#	parameters of the standard ellipsoid model named s;  a is the
#	equatorial radius and 1/f is the flattening factor.  Names are
#	listed in the code; the default is "WGS84".
#
############################################################################
#
#	Ellipsoid and datum parameters are from:
#		
#		Department of Defense World Geodetic System 1984
#		National Imagery and Mapping Agency
#		Technical Report TR8350.2
#		Third Edition, Amendment 1 (3 January 2000)
#		ftp://ftp.nima.mil/pub/gg/tr8350.2/
#
############################################################################
#
#   Links: cartog, io
#
############################################################################



link cartog
link io



#  Procedures and globals named with a "gdt_" prefix are 
#  not intended for access outside this file.

global gdt_datum_ptab		# table of gdt_datum_rec's, keyed by code



###################### Geodat Conversion #################################

procedure geodat(f, t)		#: define geodetic conversion
   return nadcon(f, t) | molodensky(f, t) | fail
end



###################### NADCON Conversion #################################

record gdt_nadcon(		# nadcon conversion record
   proj,			# projection procedure
   inv,				# invert myself
   grids			# list of gdt_nadcon_grid records to search
   )

record gdt_nadcon_grid(		# information about a .loa and .laa file
   name,			# name of file
   offset,			# offset in file to start of grid data
   termLen,			# number of chars in line termination (1 or 2)
   nc, nr, nz,			# number of rows, columns in file (nz = ??) 
   xmin, xmax, dx,		# dimension of coverage
   ymin, ymax, dy,		#
   angle			# ??
   )

procedure nadcon(f, t)		#: define NAD data conversion
   local d, ft

   ft := (gdt_nadcon_datum(f) || "-" || gdt_nadcon_datum(t)) | fail
   d := gdt_nadcon()
   d.inv := gdt_nadcon_inv
   case ft of {
      "NAD27-NAD83"|"NAD83-NAD27":
         # more specific grids should precede less specific ones
         d.grids := gdt_nadcon_initGrids(
            ["hawaii","prvi","stlrnc", "stgeorge","stpaul","alaska","conus"])
      "NAD83-HPGN"|"HPGN-NAD83":
         d.grids := gdt_nadcon_initGrids(
            ["alhpgn","azhpgn","cnhpgn","cohpgn","cshpgn","emhpgn","ethpgn",
               "flhpgn","gahpgn","hihpgn","inhpgn","kshpgn","kyhpgn","lahpgn",
               "mdhpgn","mehpgn","mihpgn","mshpgn","nbhpgn","ndhpgn","nehpgn",
               "nmhpgn","nvhpgn","nyhpgn","ohhpgn","okhpgn","pvhpgn","sdhpgn",
               "tnhpgn","uthpgn","vahpgn","wihpgn","wmhpgn","wohpgn","wthpgn",
               "wvhpgn","wyhpgn"])
      "NAD27-HPGN":
         return compose(nadcon("NAD27", "NAD83"), nadcon("NAD83", "HPGN"))
      "HPGN-NAD27":
         return compose(nadcon("HPGN", "NAD83"), nadcon("NAD83", "NAD27"))
      default:				# identity conversion
         d.grids := []
      }
   case ft of {
      "NAD27-NAD83"|"NAD83-HPGN":	d.proj := gdt_nadcon_fwd
      "NAD83-NAD27"|"HPGN-NAD83":	d.proj := gdt_nadcon_bck
      default:				d.proj := gdt_identity
      }
   return d
end

procedure gdt_nadcon_fwd(p, L)
   local i, a

   a := []
   every i := 1 to *L by 2 do {
      gdt_nadcon_fwdPoint(p, a, L[i], L[i+1]) | fail
      }
   return a
end

procedure gdt_nadcon_bck(p, L)
   local i, a
    
   a := []
   every i := 1 to *L by 2 do {
      gdt_nadcon_bckPoint(p, a, L[i], L[i+1]) | fail
      }
   return a
end

procedure gdt_identity(p, L)
   return L
end

procedure gdt_nadcon_inv(p)
   local q

   q := copy(p)
   case p.proj of {
      gdt_nadcon_bck :	q.proj := gdt_nadcon_fwd
      gdt_nadcon_fwd :	q.proj := gdt_nadcon_bck
      gdt_identity :	q.proj := gdt_identity
      }
   return q
end

procedure gdt_nadcon_datum(x)
   case x of {
      "NAD27":		return "NAD27"
      "NAD83":		return "NAD83"
      "HARN" | "HPGN":	return "HPGN"
      }
end


procedure gdt_nadcon_initGrids(names)
   local grids, latf, lonf, a1, a2, b1, b2, g

   grids := []
   every name := !names do {
      close(\lonf)
      close(\latf)

      g := gdt_nadcon_grid()
      g.name := name

      lonf := dopen(name || ".loa") | &null
      latf := dopen(name || ".laa") | &null

      if /lonf | /latf then next		# filename unreadable

      a1 := read(lonf) | &null
      a2 := read(lonf) | &null
      b1 := read(latf) | &null
      b2 := read(latf) | &null
      if /a1 | /a2 | /b1 | /b2 | a1 ~== b1 | a2 ~== b2 then {
         write(&errout, g.name, " incompatible or corrupt files.")
         next
         }
      g.offset := where(lonf)

      if g.offset = 141 then
         g.termLen := 2
      else
         g.termLen := 1
      a2 ? {
         g.nc := integer(move(4))
         g.nr := integer(move(4))
         g.nz := integer(move(4))
         g.xmin := real(move(12))
         g.dx := real(move(12))
         g.xmax := g.xmin + (g.nc - 1) * g.dx
         g.ymin := real(move(12))
         g.dy := real(move(12))
         g.ymax := g.ymin + (g.nr - 1) * g.dy
         g.angle := real(move(12))
         put(grids, g)
         }
      }
   close(\lonf)
   close(\latf)

   if *grids = 0 then {
      write(&errout, "No valid NADCON conversion files found.")
      fail
      }
   return grids
end

procedure gdt_nadcon_findGrid(grids, xpt, ypt)
   local g

   every g := !grids do {
      if (g.xmin < xpt < g.xmax & g.ymin < ypt < g.ymax) then return g
      }
   fail
end

procedure gdt_nadcon_box(f, g, xcol, yrow)
# This procedure is very sensitive to the format of the .loa & .laa
# files.  In particular, it assumes:
#	1) each line contains 6 numbers (except, possibly, the
#	   last line of a row, which contains (nc % 6) numbers,
#	2) each number is 12 chars long,
   local charsPerRow, pos, t1, t2, t3, t4

   charsPerRow := (72 + g.termLen) * integer(g.nc / 6)
   if (g.nc % 6) > 0 then
      charsPerRow +:= g.termLen + 12 * (g.nc % 6)

   pos := g.offset + charsPerRow * (yrow - 1) +
      (72 + g.termLen) * integer((xcol - 1) / 6) + 12 * ((xcol - 1) % 6)

   seek(f, pos)
   t1 := reads(f, 12)
   if (xcol % 6 = 0) then reads(f, g.termLen)	# line termination
   t3 := reads(f, 12)
   seek(f, pos + 12 * g.nc + g.termLen * ceil(g.nc / 6.0))
   t2 := reads(f, 12)
   if (xcol % 6 = 0) then reads(f, g.termLen)	# line termination
   t4 := reads(f, 12)

   return [real(t1), real(t2), real(t3), real(t4)]
end


procedure gdt_nadcon_fwdPoint(p, a, xpt, ypt)
   local g, latf, lonf, xgrid, ygrid, xcol, yrow, t, dlas, dlos

   if not(g := gdt_nadcon_findGrid(p.grids, xpt, ypt)) then {
      runerr(205, [xpt, ypt])		# point not in available areas
      fail
      }
   lonf := dopen(g.name || ".loa")
   latf := dopen(g.name || ".laa")

   xgrid := (xpt - g.xmin) / g.dx + 1.0
   ygrid := (ypt - g.ymin) / g.dy + 1.0
   xcol := integer(xgrid)
   yrow := integer(ygrid)

   t := gdt_nadcon_box(lonf, g, xcol, yrow)
   dlos := t[1] + (t[3]-t[1]) * (xgrid-xcol) + (t[2]-t[1]) * (ygrid-yrow) +
         (t[4]-t[3]-t[2]+t[1]) * (xgrid-xcol) * (ygrid-yrow)
    
   t := gdt_nadcon_box(latf, g, xcol, yrow)
   dlas := t[1] + (t[3]-t[1]) * (xgrid-xcol) + (t[2]-t[1]) * (ygrid-yrow) +
         (t[4]-t[3]-t[2]+t[1]) * (xgrid-xcol) * (ygrid-yrow)
    
   close(lonf)
   close(latf)

   # Why is the range specified in +east and the correction in +west?
   put(a, xpt - dlos / 3600.0, ypt + dlas / 3600.0)
   return
end

$define CTG_NADCON_SMALL 0.000000001	# close enough for NADCON inverse

procedure gdt_nadcon_bckPoint(p, a, xpt, ypt)
   local xguess, yguess, b, i, dx, dy

   xguess := xpt
   yguess := ypt
   b := []
   every i:= 1 to 10 do {
      gdt_nadcon_fwdPoint(p, b, xguess, yguess) | fail
      dx := xpt - get(b)
      dy := ypt - get(b)
      if abs(dx) > CTG_NADCON_SMALL then xguess +:= dx
      if abs(dy) > CTG_NADCON_SMALL then yguess +:= dy
      if abs(dx) <= CTG_NADCON_SMALL & abs(dy) <= CTG_NADCON_SMALL then {
         put(a, xguess, yguess)
         return
         }
      }
   write(&errout, "Maximum iterations exceeded!!")
   fail
end



################# Standard Molodensky Datum Transformation ##################
# See NIMA TR 8350.2
#
# ************************ WARNING ******************************************
# NIMA TR 8350.2 contains Molodensky parameters to convert
# from an arbitrary datum to WGS84.  To convert from datum A to datum B,
# I call molodensky(Ax-Bx,Ay-By,Az-Bz,Aa,Af,Ba,Bf) where Ax,Ay,Az are the
# shift to convert A to WGS84; Bx,By,Bz are the shift to convert B to WGS84;
# Aa,Af,Ba,Bf are the ellipsoid parameters.
# ************************ WARNING ******************************************
#
# TODO:
#	1) Add special conversion for North and South pole
#	2) Add Multiple Regression Equations
#	3) Add special WGS72 to WGS84 conversion
#
record gdt_molo(
   proj,		# projection procedure (always gdt_molo_proj)
   inv,			# invert myself (always gdt_molo_inv)
   dx, dy, dz,		# x,y,z differences (output - input)
   ain, fin,		# input ellipsoid specs
   aout, fout		# output ellipsoid specs
   )

procedure molodensky(dx,dy,dz,ain,fin,aout,fout) #: define geodetic conversion
   local p, a, din, ein, dout, eout

   if /dx | /dy then fail
   if /dz then {
      din := gdt_datum_params(dx) | fail
      ein := ellipsoid(din.eps) | fail
      dout := gdt_datum_params(dy) | fail
      eout := ellipsoid(dout.eps) | fail
      a := []
      put(a, din.dx - dout.dx, din.dy - dout.dy, din.dz - dout.dz)
      put(a, ein[1], ein[2], eout[1], eout[2])
      return molodensky ! a
      }
   p := gdt_molo()
   p.proj := gdt_molo_proj
   p.inv := gdt_molo_inv
   p.dx := dx
   p.dy := dy
   p.dz := dz
   p.ain := ain
   p.fin := fin
   p.aout := aout
   p.fout := fout
   return p
end

procedure gdt_molo_proj(p, L)
   local e2, slam, clam, sphi, cphi, Rm, Rn, dlam, dphi
   local i, bbya, da, df, lam, phi, lllist

   da := p.aout - p.ain
   df := p.fout - p.fin
   e2 := p.fin * (2 - p.fin)
   bbya := 1. - p.fin
   lllist := []
   every i := 1 to *L by 2 do {
      lam := dtor(L[i])
      slam := sin(lam)
      clam := cos(lam)
      phi := dtor(L[i+1])
      sphi := sin(phi)
      cphi := cos(phi)
      Rm := p.ain * (1 - e2) / (1 - e2 * sphi ^ 2) ^ (1.5)
      Rn := p.ain / sqrt(1 - e2 * sphi ^ 2)
      dlam := (-p.dx * slam + p.dy * clam) / (Rn * cphi)
      dphi := (-p.dx * sphi * clam - p.dy * sphi * slam + p.dz * cphi +
               da * (Rn * e2 * sphi * cphi) / p.ain +
               df * (Rm / bbya + Rn * bbya) * sphi * cphi) / Rm
      put(lllist, rtod(lam + dlam), rtod(phi + dphi))
      }
   return lllist
end

procedure gdt_molo_inv(p)
   local q

   q := gdt_molo()
   q.proj := gdt_molo_proj
   q.inv := gdt_molo_inv
   q.dx := -p.dx
   q.dy := -p.dy
   q.dz := -p.dz
   q.ain := p.aout
   q.fin := p.fout
   q.aout := p.ain
   q.fout := p.fin
   return q
end



###################### Ellipsoid Parameters #################################

procedure ellipsoid(name)	#: return [a, 1/f] for named ellipsoid
   local f, line, w, i

   /name := "WGS84"
   return case name of {
      "Airy 1830"|"Airy"|"AA":			[6377563.396, 1 / 299.3249646]
      "Australian National"|"AN":		[6378160.0, 1 / 298.25]
      "Bessel 1841"|"BR":			[6377397.155, 1 / 299.1528128]
      "Bessel 1841 (Namibia)"|"BN":		[6377483.865, 1 / 299.1528128]
      "Clarke 1866"|"Clarke66"|"NAD27"|"CC":	[6378206.4, 1 / 294.9786982]
      "Clarke 1880"|"CD":			[6378249.145, 1 / 293.465]
      "Everest 1830"|"Everest"|"EA":		[6377276.345, 1 / 300.8017]
      "Everest 1948"|"Modified Everest"|"EE":	[6377304.063, 1 / 300.8017]
      "Everest 1956"|"EC":			[6377301.243, 1 / 300.8017]
      "Everest 1969"|"ED":			[6377295.664, 1 / 300.8017]
      "Everest (Pakistan)"|"EF":		[6377309.613, 1 / 300.8017]
      "Everest (Sabah & Sarawak)"|"EB":		[6377298.556, 1 / 300.8017]
      "Fischer 1960":				[6378166.0, 1 / 298.3]
      "Fischer 1968":				[6378150.0, 1 / 298.3]
      "GRS67":					[6378160.0, 1 / 298.247167427]
      "GRS80"|"NAD83"|"RF":			[6378137.0, 1 / 298.257222101]
      "Hayford":				[6378388.0, 1 / 297.0]
      "Helmert 1906"|"HE":			[6378200.0, 1 / 298.3]
      "Hough"|"HO":				[6378270.0, 1 / 297.0]
      "Indonesian 1974"|"ID":			[6378160.0, 1 / 298.247]
      "International 1924"|"IN":		[6378388.0, 1 / 297.0]
      "Krassovsky 1940"|"KA":			[6378245.0, 1 / 298.3]
      "Modified Airy"|"AM":			[6377340.189, 1 / 299.3249646]
      "Modified Fischer 1960"|"FA":		[6378155.0, 1 / 298.3]
      "South American 1969"|"SA":		[6378160.0, 1 / 298.25]
      "WGS 1960"|"WGS 60"|"WGS60"|"W60"|"WA":	[6378165.0, 1 / 298.3]
      "WGS 1966"|"WGS 66"|"WGS66"|"W66"|"WB":	[6378145.0, 1 / 298.25]
      "WGS 1972"|"WGS 72"|"WGS72"|"W72"|"WD":	[6378135.0, 1 / 298.26]
      "WGS 1984"|"WGS 84"|"WGS84"|"W84"|"WE":	[6378137.0, 1 / 298.257223563]
      default: runerr(207, name)
      }
end



###################### Datum Parameters #################################


record gdt_datum_rec(
   region,		# major region of datum (e.g. "Africa")
   name,		# datum code name
   area,		# area of datum (e.g. "Cameroon")
   eps,			# ellipsoid specification (e.g. "CD")
   dx, dy, dz,		# x,y,z differences from WGS84
   ex, ey, ez		# x,y,z maximum error in converted point (unused)
   )


procedure gdt_datum_params(codename)
   initial gdt_datum_init()
   return \gdt_datum_ptab[codename] | runerr(207, codename)
end


procedure gdt_datum_add(key, fields[])
   return gdt_datum_ptab[key] := gdt_datum_rec ! fields
end


procedure gdt_datum_init()
   gdt_datum_ptab := table()

$define add gdt_datum_add

# ----------------- AFRICA --------------------------------
add("ADI-M", "Africa",
"Adindan","mean Ethiopia & Sudan","CD",	-166,-15,204, 5,5,3
)
add("ADI-E", "Africa",
"Adindan","Burkina Faso","CD",		-118,-14,218, 25,25,25
)
add("ADI-F", "Africa",
"Adindan","Cameroon","CD",		-134,-2,210, 25,25,25
)
add("ADI-A", "Africa",
"Adindan","Ethiopia","CD",		-165,-11,206, 3,3,3
)
add("ADI-C", "Africa",
"Adindan","Mali","CD",			-123,-20,220, 25,25,25
)
add("ADI-D", "Africa",
"Adindan","Senegal","CD",		-128,-18,224, 25,25,25
)
add("ADI-B", "Africa",
"Adindan","Sudan","CD",			-161,-14,205, 3,5,3
)
add("AFG", "Africa",
"Afgooye","Somalia","KA",		-43,-163,45, 25,25,25
)
add("ARF-M", "Africa",
"Arc 1950","mean","CD",			-143,-90,-294, 20,33,20
)
add("ARF-A", "Africa",
"Arc 1950","Botswana","CD",		-138,-105,-289, 3,5,3
)
add("ARF-H", "Africa",
"Arc 1950","Burundi","CD",		-153,-5,-292, 20,20,20
)
add("ARF-B", "Africa",
"Arc 1950","Lesotho","CD",		-125,-108,-295, 3,3,8
)
add("ARF-C", "Africa",
"Arc 1950","Malawi","CD",		-161,-73,-317, 9,24,8
)
add("ARF-D", "Africa",
"Arc 1950","Swaziland","CD",		-134,-105,-295, 15,15,15
)
add("ARF-E", "Africa",
"Arc 1950","Zaire","CD",		-169,-19,-278, 25,25,25
)
add("ARF-F", "Africa",
"Arc 1950","Zambia","CD",		-147,-74,-283, 21,21,27
)
add("ARF-G", "Africa",
"Arc 1950","Zimbabwe","CD",		-142,-96,-293, 5,8,11
)
add("ARS-M", "Africa",
"Arc 1960","mean Kenya & Tanzania","CD",-160,-6,-302, 20,20,20
)
add("ARS-A", "Africa",
"Arc 1960","Kenya","CD",		-157,-2,-299, 4,3,3
)
add("ARS-B", "Africa",
"Arc 1960","Tanzania","CD",		-175,-23,-303, 6,9,10
)
add("PHA", "Africa",
"Ayabelle Lighthouse","Djibouti","CD",	-79,-129,145, 25,25,25
)
add("BID", "Africa",
"Bissau","Guinea-Bissau","IN",		-173,253,27, 25,25,25
)
add("CAP", "Africa",
"Cape","South Africa","CD",		-136,-108,-292, 3,6,6
)
add("CGE", "Africa",
"Carthage","Tunisia","CD",		-263,6,431, 6,9,8
)
add("DAL", "Africa",
"Dabola","Guinea","CD",			-83,37,124, 15,15,15
)
add("EUR-F", "Africa",
"European 1950","Egypt","IN",		-130,-117,-151, 6,8,8
)
add("EUR-T", "Africa",
"European 1950","Tunisia","IN",		-112,-77,-145, 25,25,25
)
add("LEH", "Africa",
"Leigon","Ghana","CD",			-130,29,364, 2,3,2
)
add("LIB", "Africa",
"Liberia 1964","Liberia","CD",		-90,40,88, 15,15,15
)
add("MAS", "Africa",
"Massawa","Eritrea (Ethiopia)","BR",	639,405,60, 25,25,25
)
add("MER", "Africa",
"Merchich","Morocco","CD",		31,146,47, 5,3,3
)
add("MIN-A", "Africa",
"Minna","Cameroon","CD",		-81,-84,115, 25,25,25
)
add("MIN-B", "Africa",
"Minna","Nigeria","CD",			-92,-93,122, 3,6,5
)
add("MPO", "Africa",
"M'Poraloko","Gabon","CD",		-74,-130,42, 25,25,25
)
add("NSD", "Africa",
"North Sahara 1959","Algeria","CD",	-186,-93,310, 25,25,25
)
add("OEG", "Africa",
"Old Egyptian 1907","Egypt","HE",		-130,110,-13, 3,6,8
)
add("PTB", "Africa",
"Point 58","mean Burkina Faso & Niger","CD",-106,-129,165, 25,25,25
)
add("PTN", "Africa",
"Pointe Noire 1948","Congo","CD",		-148,51,-291, 25,25,25
)
add("SCK", "Africa",
"Schwarzeck","Namibia","BN",		616,97,-251, 20,20,20
)
add("SRL", "Africa",
"Sierra Leone 1960","Sierra Leone","CD",	-88,4,101, 15,15,15
)
add("VOR", "Africa",
"Voirol 1960","Algeria","CD",		-123,-206,219, 25,25,25
)

# ----------------- ASIA --------------------------------
add("AIN-A", "Asia",
"Ain el Abd 1970","Bahrain","IN",	-150,-250,-1, 25,25,25
)
add("AIN-B", "Asia",
"Ain el Abd 1970","Saudi Arabia","IN",	-143,-236,7, 10,10,10
)
add("BAT", "Asia",
"Djakarta (Batavia)","Sumatra (Indonesia)","BR",-377,681,-50, 3,3,3
)
add("EUR-H", "Asia",
"European 1950","Iran","IN",		-117,-132,-164, 9,12,11
)
add("HKD", "Asia",
"Hong Kong 1963","Hong Kong","IN",	-156,-271,-189, 25,25,25
)
add("HTN", "Asia",
"Hu-Tzu-Shan","Taiwan","IN",		-637,-549,-203, 15,15,15
)
add("IND-B", "Asia",
"Indian","Bangladesh","EA",		282,726,254, 10,8,12
)
add("IND-I", "Asia",
"Indian","India & Nepal","EC",		295,736,257, 12,10,15
)
add("INF-A", "Asia",
"Indian 1954","Thailand","EA",		217,823,299, 15,6,12
)
add("ING-A", "Asia",
"Indian 1960","Vietnam (near 16N)","EA",198,881,317, 25,25,25
)
add("ING-B", "Asia",
"Indian 1960","Con Son Island (Vietnam)","EA",182,915,344, 25,25,25
)
add("INH-A", "Asia",
"Indian 1975","Thailand","EA",		209,818,290, 12,10,12
)
add("INH-A1", "Asia",
"Indian 1975","Thailand","EA",		210,814,289, 3,2,3
)
add("IDN", "Asia",
"Indonesian 1974","Indonesia","ID",	-24,-15,5, 25,25,25
)
add("KAN", "Asia",
"Kandawala","Sri Lanka","EA",		-97,787,86, 20,20,20
)
add("KEA", "Asia",
"Kertau 1948","West Malaysia & Singapore","EE",-11,851,5, 10,8,6
)
add("KGS", "Asia",
"Korean Geodetic System 1995","South Korea","WE",0,0,0, 1,1,1
)
add("NAH-A", "Asia",
"Nahrwan","Masirah Island (Oman)","CD",	-247,-148,369, 25,25,25
)
add("NAH-B", "Asia",
"Nahrwan","United Arab Emirates","CD",	-249,-156,381, 25,25,25
)
add("NAH-C", "Asia",
"Nahrwan","Saudi Arabia","CD",		-243,-192,477, 20,20,20
)
add("FAH", "Asia",
"Oman","Oman","CD",			-346,-1,224, 3,3,9
)
add("QAT", "Asia",
"Qatar National","Qatar","IN",		-128,-283,22, 20,20,20
)
add("SOA", "Asia",
"South Asia","Singapore","FA",		7,-10,-26, 25,25,25
)
add("TIL", "Asia",
"Timbalai 1948","Brunei & East Malaysia (Sarawak & Sabah)","EB",
					-679,669,-48, 10,10,12
)
add("TOY-M", "Asia",
"Tokyo","mean","BR",			-148,507,685, 20,5,20
)
add("TOY-A", "Asia",
"Tokyo","Japan","BR",			-148,507,685, 8,5,8
)
add("TOY-C", "Asia",
"Tokyo","Okinawa","BR",			-158,507,676, 20,5,20
)
add("TOY-B", "Asia",
"Tokyo","South Korea","BR",		-146,507,687, 8,5,8
)
add("TOY-B1", "Asia",
"Tokyo","South Korea","BR",		-147,506,687, 2,2,2
)

# ----------------- AUSTRALIA --------------------------------
add("AUA", "Australia",
"Australian Geodetic 1966","Australia & Tasmania","AN",-133,-48,148, 3,3,3
)
add("AUG", "Australia",
"Australian Geodetic 1984","Australia & Tasmania","AN",-134,-48,149, 2,2,2
)

# ----------------- EUROPE --------------------------------
add("EST", "Europe",
"Co-ordinate System 1937 of Estonia","Estonia","BN",374,150,588, 2,3,3
)
add("EUR-M", "Europe",
"European 1950","mean","IN",		-87,-98,-121, 3,8,5
)
add("EUR-A", "Europe",
"European 1950","mean Western Europe","IN",-87,-96,-120, 3,3,3
)
add("EUR-E", "Europe",
"European 1950","Cyprus","IN",		-104,-101,-140, 15,15,15
)
add("EUR-G", "Europe",
"European 1950","England & Channel Islands & Scotland & Shetland Islands","IN",
					-86,-96,-120, 3,3,3
)
add("EUR-K", "Europe",
"European 1950","England & Ireland & Scotland & Shetland Islands","IN",
					-86,-96,-120, 3,3,3
)
add("EUR-B", "Europe",
"European 1950","Greece","IN",		-84,-95,-130, 25,25,25
)
add("EUR-I", "Europe",
"European 1950","Sardinia (Italy)","IN",-97,-103,-120, 25,25,25
)
add("EUR-J", "Europe",
"European 1950","Sicily (Italy)","IN",	-97,-88,-135, 20,20,20
)
add("EUR-L", "Europe",
"European 1950","Malta","IN",		-107,-88,-149, 25,25,25
)
add("EUR-C", "Europe",
"European 1950","Norway & Finland","IN",-87,-95,-120, 3,5,3
)
add("EUR-D", "Europe",
"European 1950","Portugal & Spain","IN",-84,-107,-120, 5,6,3
)
add("EUS", "Europe",
"European 1979","mean","IN",		-86,-98,-119, 3,3,3
)
add("HJO", "Europe",
"Hjorsey 1955","Iceland","IN",		-73,46,-86, 3,3,6
)
add("IRL", "Europe",
"Ireland 1965","Ireland","AM",		506,-122,611, 3,3,3
)
add("OGB-M", "Europe",
"Ordnance Survey Great Britain 1936","mean","AA",375,-111,431, 10,10,15
)
add("OGB-A", "Europe",
"Ordnance Survey Great Britain 1936","England","AA",371,-112,434, 5,5,6
)
add("OGB-B", "Europe",
"Ordnance Survey Great Britain 1936","England & Isle of Man & Wales","AA",
					371,-111,434, 10,10,15
)
add("OGB-C", "Europe",
"Ordnance Survey Great Britain 1936","Scotland & Shetland Islands","AA",
					384,-111,425, 10,10,10
)
add("OGB-D", "Europe",
"Ordnance Survey Great Britain 1936","Wales","AA",370,-108,434, 20,20,20
)
add("MOD", "Europe",
"Rome 1940","Sardinia","IN",		-225,-65,9, 25,25,25
)
add("SPK-A", "Europe",
"S-42 (Pulkovo 1942)","Hungary","KA",	28,-121,-77, 2,2,2
)
add("SPK-B", "Europe",
"S-42 (Pulkovo 1942)","Poland","KA",	23,-124,-82, 4,2,4
)
add("SPK-C", "Europe",
"S-42 (Pulkovo 1942)","Czechoslavakia","KA",26,-121,-78, 3,3,2
)
add("SPK-D", "Europe",
"S-42 (Pulkovo 1942)","Latvia","KA",	24,-124,-82, 2,2,2
)
add("SPK-E", "Europe",
"S-42 (Pulkovo 1942)","Kazakhstan","KA",15,-130,-84, 25,25,25
)
add("SPK-F", "Europe",
"S-42 (Pulkovo 1942)","Albania","KA",	24,-130,-92, 3,3,3
)
add("SPK-G", "Europe",
"S-42 (Pulkovo 1942)","Romania","KA",	28,-121,-77, 3,5,3
)
add("CCD", "Europe",
"S-JTSK","Czechoslavakia (Prior 1 Jan 1993)","BR",589,76,480, 4,2,3
)

# ----------------- NORTH AMERICA --------------------------------
add("CAC", "North America",
"Cape Canaveral","mean Bahamas & Florida","CC",-2,151,181, 3,3,3
)
gdt_datum_ptab["NAD27"] :=
add("NAS-C", "North America",
"North American 1927","mean CONUS","CC",-8,160,176, 5,5,6
)
add("NAS-B", "North America",
"North American 1927","mean West CONUS","CC",-8,159,175, 5,3,3
)
add("NAS-A", "North America",
"North American 1927","mean East CONUS","CC",-9,161,179, 5,5,8
)
add("NAS-D", "North America",
"North American 1927","Alaska (minus Aleutian Islands)","CC",
					-5,135,172, 5,9,5
)
add("NAS-V", "North America",
"North American 1927","Aleutian Islands East of 180W","CC",
					-2,152,149, 6,8,10
)
add("NAS-W", "North America",
"North American 1927","Aleutian Islands West of 180W","CC",
					2,204,105, 10,10,10
)
add("NAS-Q", "North America",
"North American 1927","Bahamas (minus San Salvador Island)","CC",
					-4,154,178, 5,3,5
)
add("NAS-R", "North America",
"North American 1927","San Salvador Island","CC",1,140,165, 25,25,25
)
add("NAS-E", "North America",
"North American 1927","mean Canada","CC",-10,158,187, 15,11,6
)
add("NAS-F", "North America",
"North American 1927","Albert & British Columbia (Canada)","CC",
					-7,162,188, 8,8,6
)
add("NAS-G", "North America",
"North American 1927","Eastern Canada","CC",-22,160,190, 6,6,3
)
add("NAS-H", "North America",
"North American 1927","Manitoba & Ontario (Canada)","CC",-9,157,184, 9,5,5
)
add("NAS-I", "North America",
"North American 1927","Northwest Territories & Saskatchewan (Canada)","CC",
					4,159,188, 5,5,3
)
add("NAS-J", "North America",
"North American 1927","Yukon (Canada)","CC",-7,139,181, 5,8,3
)
add("NAS-O", "North America",
"North American 1927","Canal Zone","CC",0,125,201, 20,20,20
)
add("NAS-P", "North America",
"North American 1927","mean Caribbean","CC",-3,142,183, 3,9,12
)
add("NAS-N", "North America",
"North American 1927","mean Central America","CC",0,125,194, 8,3,5
)
add("NAS-T", "North America",
"North American 1927","Cuba","CC",	-9,152,178, 25,25,25
)
add("NAS-U", "North America",
"North American 1927","Greenland (Hayes Peninsula)","CC",11,114,195, 25,25,25
)
add("NAS-L", "North America",
"North American 1927","Mexico","CC",	-12,130,190, 8,6,6
)
add("NAR-A", "North America",
"North American 1983","Alaska (minus Aleutian Islands)","RF",0,0,0, 2,2,2
)
add("NAR-E", "North America",
"North American 1983","Aleutian Islands","RF",-2,0,4, 5,2,5
)
add("NAR-B", "North America",
"North American 1983","Canada","RF",	0,0,0, 2,2,2
)
gdt_datum_ptab["NAD83"] :=
add("NAR-C", "North America",
"North American 1983","CONUS","RF",	0,0,0, 2,2,2
)
add("NAR-H", "North America",
"North American 1983","Hawaii","RF",	1,1,-1, 2,2,2
)
add("NAR-D", "North America",
"North American 1983","Mexico & Central America","RF",0,0,0, 2,2,2
)

# ----------------- SOUTH AMERICA --------------------------------
add("BOO", "South America",
"Bogota Observatory","Colombia","IN",	307,304,-318, 6,5,6
)
add("CAI", "South America",
"Campo Inchauspe 1969","Argentina","IN",-148,136,90, 5,5,5
)
add("CHU", "South America",
"Chua Astro","Paraguay","IN",		-134,229,-29, 6,9,5
)
add("COA", "South America",
"Corrego Alegre","Brazil","IN",		-206,172,-6, 5,3,5
)
add("PRP-M", "South America",
"Provisional South American 1956","mean","IN",-288,175,-376, 17,27,27
)
add("PRP-A", "South America",
"Provisional South American 1956","Bolivia","IN",-270,188,-388, 5,11,14
)
add("PRP-B", "South America",
"Provisional South American 1956","Northern Chile","IN",
					-270,183,-390, 25,25,25
)
add("PRP-C", "South America",
"Provisional South American 1956","Southern Chile","IN",
					-305,243,-442, 20,20,20
)
add("PRP-D", "South America",
"Provisional South American 1956","Colombia","IN",-282,169,-371, 15,15,15
)
add("PRP-E", "South America",
"Provisional South American 1956","Ecuador","IN",-278,171,-367, 3,5,3
)
add("PRP-F", "South America",
"Provisional South American 1956","Guyana","IN",-298,159,-369, 6,14,5
)
add("PRP-G", "South America",
"Provisional South American 1956","Peru","IN",-279,175,-379, 6,8,12
)
add("PRP-H", "South America",
"Provisional South American 1956","Venezuela","IN",-295,173,-371, 9,14,15
)
add("HIT", "South America",
"Provisional South Chilean 1963","Southern Chile","IN",16,196,93, 25,25,25
)
add("SAN-M", "South America",
"South American 1969","mean","SA",	-57,1,-41, 15,6,9
)
add("SAN-A", "South America",
"South American 1969","Argentina","SA",	-62,-1,-37, 5,5,5
)
add("SAN-B", "South America",
"South American 1969","Bolivia","SA",	-61,2,-48, 15,15,15
)
add("SAN-C", "South America",
"South American 1969","Brazil","SA",	-60,-2,-41, 3,5,5
)
add("SAN-D", "South America",
"South American 1969","Chile","SA",	-75,-1,-44, 15,8,11
)
add("SAN-E", "South America",
"South American 1969","Colombia","SA",	-44,6,-36, 6,6,5
)
add("SAN-F", "South America",
"South American 1969","Ecuador (minus Galapagos Islands)","SA",
					-48,3,-44, 3,3,3
)
add("SAN-J", "South America",
"South American 1969","Baltra & Galapagos Islands (Ecuador)","SA",
					-47,26,-42, 25,25,25
)
add("SAN-G", "South America",
"South American 1969","Guyana","SA",	-53,3,-47, 9,5,5
)
add("SAN-H", "South America",
"South American 1969","Paraguay","SA",	-61,2,-33, 15,15,15
)
add("SAN-I", "South America",
"South American 1969","Peru","SA",	-58,0,-44, 5,5,5
)
add("SAN-K", "South America",
"South American 1969","Trinidad & Tobago","SA",-45,12,-33, 25,25,25
)
add("SAN-L", "South America",
"South American 1969","Venezuela","SA",	-45,8,-33, 3,6,3
)
add("SIR", "South America",
"South American Geocentric Reference System (SIRGAS)","South America","RF",
					0,0,0, 1,1,1
)
add("ZAN", "South America",
"Zanderij","Suriname","IN",		-265,120,-358, 5,5,8
)

# ----------------- ATLANTIC OCEAN --------------------------------
add("AIA", "Atlantic Ocean",
"Antigua Island Astro 1943","Antigua & Leeward Islands","CD",
					-270,13,62, 25,25,25
)
add("ASC", "Atlantic Ocean",
"Ascension Island 1958","Ascension Island","IN",-205,107,53, 25,25,25
)
add("SHB", "Atlantic Ocean",
"Astro DOS 71/4","St Helena Island","IN",-320,550,-494, 25,25,25
)
add("BER", "Atlantic Ocean",
"Bermuda 1957","Bermuda","CC",		-73,213,296, 20,20,20
)
add("DID", "Atlantic Ocean",
"Deception Island","Deception Island & Antarctica","CD",260,12,-147, 20,20,20
)
add("FOT", "Atlantic Ocean",
"Fort Thomas 1955","Nevis & St. Kitts & Leeward Islands","CD",
					-7,215,225, 25,25,25
)
add("GRA", "Atlantic Ocean",
"Graciosa Base SW 1948",
"Faial & Graciosa & Pico & Sao Jorge & Terceira Islands (Azores)","IN",
					-104,167,-38, 3,3,3
)
add("ISG", "Atlantic Ocean",
"ISTS 061 Astro 1968","South Georgia Island","IN",-794,119,-298, 25,25,25
)
add("LCF", "Atlantic Ocean",
"L. C. 5 Astro 1961","Cayman Brac Island","CC",42,124,147, 25,25,25
)
add("ASM", "Atlantic Ocean",
"Montserrat Island Astro 1958","Montserrat & Leeward Islands","CD",
					174,359,365, 25,25,25
)
add("NAP", "Atlantic Ocean",
"Naparima BWI","Trinidad & Tobago","IN",-10,375,165, 15,15,15
)
add("FLO", "Atlantic Ocean",
"Observatorio Meteorologico 1939","Corvo & Flores Islands (Azores)","IN",
					-425,-169,81, 20,20,20
)
add("PLN", "Atlantic Ocean",
"Pico de las Nieves","Canary Islands","IN",-307,-92,127, 25,25,25
)
add("POS", "Atlantic Ocean",
"Porto Santo 1936","Porto Santo & Madeira Islands","IN",-499,-249,314, 25,25,25
)
add("PUR", "Atlantic Ocean",
"Puerto Rico","Puerto Rico & Virgin Islands","CC",11,72,-101, 3,3,3
)
add("QUO", "Atlantic Ocean",
"Qornoq","South Greenland","IN",	164,138,-189, 25,25,32
)
add("SAO", "Atlantic Ocean",
"Sao Braz","Sao Miguel & Santa Maria Islands","IN",-203,141,53, 25,25,25
)
add("SAP", "Atlantic Ocean",
"Sapper Hill 1943","East Falkland Island","IN",-355,21,72, 1,1,1
)
add("SGM", "Atlantic Ocean",
"Selvagem Grande 1938","Salvage Islands","IN",-289,-124,60, 25,25,25
)
add("TDC", "Atlantic Ocean",
"Tristan Astro 1968","Tristan da Cunha","IN",-632,438,-609, 25,25,25
)

# ----------------- INDIAN OCEAN --------------------------------
add("ANO", "Indian Ocean",
"Anna 1 Astro 1965","Cocos Islands","AN",-491,-22,435, 25,25,25
)
add("GAA", "Indian Ocean",
"Gan 1970","Republic of Maldives","IN",	-133,-321,50, 25,25,25
)
add("IST", "Indian Ocean",
"ISTS 073 Astro 1969","Diego Garcia","IN",208,-435,-229, 25,25,25
)
add("KEG", "Indian Ocean",
"Kerguelen Island 1949","Kerguelen Island","IN",145,-187,103, 25,25,25
)
add("MIK", "Indian Ocean",
"Mahe 1971","Mahe Island","CD",		41,-220,-134, 25,25,25
)
add("REU", "Indian Ocean",
"Reunion","Mascarene Islands","IN",	94,-948,-1262, 25,25,25
)

# ----------------- PACIFIC OCEAN --------------------------------
add("AMA", "Pacific Ocean",
"American Samoa 1962","American Samoa Islands","CC",-115,118,426, 25,25,25
)
add("ATF", "Pacific Ocean",
"Astro Beacon E 1945","Iwo Jima","IN",	145,75,-272, 25,25,25
)
add("TRN", "Pacific Ocean",
"Astro Tern Island (FRIG) 1961","Tern Island","IN",114,-116,-333, 25,25,25
)
add("ASQ", "Pacific Ocean",
"Astronomical Station 1952","Marcus Island","IN",124,-234,-25, 25,25,25
)
add("IBE", "Pacific Ocean",
"Bellevue (IGN)","Efate & Erromango Islands","IN",-127,-769,472, 20,20,20
)
add("CAO", "Pacific Ocean",
"Canton Astro 1966","Phoenix Islands","IN",298,-304,-375, 15,15,15
)
add("CHI", "Pacific Ocean",
"Chatham Island Astro 1971","Chatham Island (New Zealand)","IN",
					175,-38,113, 15,15,15
)
add("GIZ", "Pacific Ocean",
"DOS 1968","Gizo Island (New Georgia Islands)","IN",230,-199,-752, 25,25,25
)
add("EAS", "Pacific Ocean",
"Easter Island 1967","Easter Island","IN",211,147,111, 25,25,25
)
add("GEO", "Pacific Ocean",
"Geodetic Datum 1949","New Zealand","IN",84,-22,209, 5,3,5
)
add("GUA", "Pacific Ocean",
"Guam 1963","Guam","CC",		-100,-248,259, 3,3,3
)
add("DOB", "Pacific Ocean",
"GUX 1 Astro","Guadalcanal Island","IN",252,-209,-751, 25,25,25
)
add("JOH", "Pacific Ocean",
"Johnston Island 1961","Johnston Island","IN",189,-79,-202, 25,25,25
)
add("KUS", "Pacific Ocean",
"Kusaie Astro 1951","Caroline Islands & Fed. States of Micronesia","IN",
					647,1777,-1124, 25,25,25
)
add("LUZ-A", "Pacific Ocean",
"Luzon","Philippines (minus Mindanao Island)","CC",-133,-77,-51, 8,11,9
)
add("LUZ-B", "Pacific Ocean",
"Luzon","Mindanao Island (Philippines)","CC",-133,-79,-72, 25,25,25
)
add("MID", "Pacific Ocean",
"Midway Astro 1961","Midway Islands","IN",912,-58,1227, 25,25,25
)
add("OHA-M", "Pacific Ocean",
"Old Hawaiian","mean","CC",		61,-285,-181, 25,20,20
)
add("OHA-A", "Pacific Ocean",
"Old Hawaiian","Hawaii","CC",		89,-279,-183, 25,25,25
)
add("OHA-B", "Pacific Ocean",
"Old Hawaiian","Kauai","CC",		45,-290,-172, 20,20,20
)
add("OHA-C", "Pacific Ocean",
"Old Hawaiian","Maui","CC",		65,-290,-190, 25,25,25
)
add("OHA-D", "Pacific Ocean",
"Old Hawaiian","Oahu","CC",		58,-283,-182, 10,6,6
)
add("OHI-M", "Pacific Ocean",
"Old Hawaiian Int","mean","IN",		201,-228,-346, 25,20,20
)
add("OHI-A", "Pacific Ocean",
"Old Hawaiian Int","Hawaii","IN",	229,-222,-348, 25,25,25
)
add("OHI-B", "Pacific Ocean",
"Old Hawaiian Int","Kauai","IN",	185,-233,-337, 20,20,20
)
add("OHI-C", "Pacific Ocean",
"Old Hawaiian Int","Maui","IN",		205,-233,-355, 25,25,25
)
add("OHI-D", "Pacific Ocean",
"Old Hawaiian Int","Oahu","IN",		198,-226,-347, 10,6,6
)
add("PIT", "Pacific Ocean",
"Pitcairn Astro 1967","Pitcairn Island","IN",185,165,42, 25,25,25
)
add("SAE", "Pacific Ocean",
"Santo (DOS) 1965","Espirito Santo Island","IN",170,42,84, 25,25,25
)
add("MVS", "Pacific Ocean",
"Viti Levu 1916","Viti Levu Island (Fiji Islands)","CD",51,391,-36, 25,25,25
)
add("ENW", "Pacific Ocean",
"Wake-Eniwetok 1960","Marshall Islands","HO",102,52,-38, 3,3,3
)
add("WAK", "Pacific Ocean",
"Wake Island Astro 1952","Wake Atoll","IN",276,-57,149, 25,25,25
)

# ----------------- WORLD-WIDE DATUM ----------------------------
gdt_datum_ptab["WGS66"] :=
add("W66", "World-wide Datum",
"WGS 1966","Global Definition I","WB",	0,0,0, 0,0,0
)
gdt_datum_ptab["WGS72"] :=
add("W72", "World-wide Datum",
"WGS 1972","Global Definition I","WD",	0,0,0, 3,3,3
)
gdt_datum_ptab["WGS84"] :=
add("W84", "World-wide Datum",
"WGS 1984","Global Definition II","WE",	0,0,0, 0,0,0
)

# ----------------- MISC. NON-SATELLITE DERIVED ----------------------------
# Error bounds of zero mean unknown error.
add("BUR", "Misc. Non-satellite derived",
"Bukit Rimpah","Bangka & Belitung Islands (Indonesia)","BR",-384,664,-48, 0,0,0
)
add("CAZ", "Misc. Non-satellite derived",
"Camp Area Astro","Camp McMurdo Area (Antarctica)","IN",-104,-129,239, 0,0,0
)
add("EUR-S", "Misc. Non-satellite derived",
"European 1950","mean Near East","IN",	-103,-106,-141, 0,0,0
)
add("GSE", "Misc. Non-satellite derived",
"Gunung Segara","Kalimantan (Indonesia)","BR",-403,684,41, 0,0,0
)
add("HEN", "Misc. Non-satellite derived",
"Herat North","Afghanistan","IN",	-333,-222,114, 0,0,0
)
add("HER", "Misc. Non-satellite derived",
"Hermannskogel",
"Yugoslavia (Prior to 1990) Slovenia & Croatia & Bosnia & Herzegovina & Serbia",
"BN",					682,-203,480, 0,0,0
)
add("IND-P", "Misc. Non-satellite derived",
"Indian","Pakistan","EF",		283,682,231, 0,0,0
)
add("PUK", "Misc. Non-satellite derived",
"Pulkovo 1942","Russia","KA",		28,-130,-95, 0,0,0
)
add("TAN", "Misc. Non-satellite derived",
"Tananarive Observatory 1925","Madagascar","IN",-189,-242,-91, 0,0,0
)
add("VOI", "Misc. Non-satellite derived",
"Voirol 1874","Tunisia & Algeria","CD",	-73,-247,227,0,0,0
)
add("YAC", "Misc. Non-satellite derived",
"Yacare","Uruguay","IN",		-155,171,37, 0,0,0
)
return
end

This page produced by UniDoc on 2021/04/15 @ 23:59:44.