program co_trans; { Koordinatentransformation }

const
   {$I b:math_con }

   OBLIQUITY = 0.4092062; { Schiefe der Ekliptik }

type
   ZEIT = record
             stunde:0..23;
             minute,sekunde:0..59;
          end;

   DATUM = record
              jahr:integer;
              monat:1..12;
              tag:1..31;
           end;

   JUL = record
            ganz:long_integer;
            fract:real;
         end;

var c:char;

   {$I b:math_sub }

procedure juldat(var julian:JUL; gregorian:DATUM; uhrzeit:ZEIT;
                 flag:boolean);
external;

procedure sidtime(var sternzeit:ZEIT; julian:JUL);
external;

procedure etoa(var ra,de:real; l,b,obl:real);
external;

procedure atoe(var l,b:real; ra,de,obl:real);
external;

procedure htoa(var ra,de:real; az,h,phi:real);
external;

procedure atoh(var az,h:real; ra,de,phi:real);
external;

procedure ttog(var ra,de,r:real; rat,det,rt,rab,deb:real);
external;

procedure gtot(var rat,det,rt:real; ra,de,r,rab,deb:real);
external;

procedure time(var uhr:ZEIT; winkel:real);
begin
   winkel := deg(winkel) / 15.0;
   uhr.stunde := trunc(winkel); winkel := winkel - uhr.stunde;
   winkel := winkel * 60.0;
   uhr.minute := trunc(winkel); winkel := winkel - uhr.minute;
   winkel := winkel * 60.0;
   uhr.sekunde := trunc(winkel)
end;

{ ekliptikal -> aequatorial }
procedure ea;
var ra,de,l,b:real;
    rat:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT ECLIPTICAL COORDINATES INTO EQUATORIAL COORDINATES >');
   writeln;
   write('> Ecliptical longitude: '); readln(l);
   write('> Ecliptical latitude : '); readln(b);
   writeln;
   etoa(ra,de,rad(l),rad(b),OBLIQUITY);
   time(rat, ra);
   writeln('  Right ascension: ',rat.stunde:2,rat.minute:3,rat.sekunde:3);
   writeln('  Declination    : ',deg(de):10:5);
   read(c)
end;

{ aequatorial -> ekliptikal }
procedure ae;
var ra,de,l,b:real;
    rat:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT EQUATORIAL COORDINATES INTO ECLIPTICAL COORDINATES >');
   writeln;
   write('> Right ascension: hour  : '); readln(rat.stunde);
   write('>                  minute: '); readln(rat.minute);
   write('>                  second: '); readln(rat.sekunde);
   write('> Declination    : '); readln(de);
   writeln;
   ra := 15.0 * (rat.stunde + rat.minute / 60.0 + rat.sekunde / 3600.0);
   atoe(l,b,rad(ra),rad(de),OBLIQUITY);
   writeln('  Ecliptical longitude: ',deg(l):10:5);
   writeln('  Ecliptical latitude : ',deg(b):10:5);
   readln(c)
end;

{ Geographische Daten eingeben }
procedure geoin(var lmst,phi:real);
var flag:boolean;
    l:real;
    ut:ZEIT;
    date:DATUM;
    jd:JUL;
    c:char;
begin
   write('> Date: year : '); readln(date.jahr);
   write('>       month: '); readln(date.monat);
   write('>       day  : '); readln(date.tag);
   write('> UT:  hour  : '); readln(ut.stunde);
   write('>      minute: '); readln(ut.minute);
   write('>      second: '); readln(ut.sekunde);
   write('> Gregorian calendar (y/n): '); read(c);
   writeln;
   if c = 'n' then flag := false else flag := true;
   write('> Longitude: '); readln(l);
   write('> Latitude : '); readln(phi);
   juldat(jd,date,ut,flag);
   sidtime(ut,jd);
   lmst := 15.0 * (ut.stunde + ut.minute / 60.0 + ut.stunde / 3600.0) - l
end;

{ aequatorial -> horizontal }
procedure ah;
var de,lmst,t,phi,h,az:real;
    ra:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT EQUATORIAL COORDINATES INTO HORIZONTAL COORDINATES >');
   writeln;
   geoin(lmst,phi);
   write('> Right ascension: hour  : '); readln(ra.stunde);
   write('>                  minute: '); readln(ra.minute);
   write('>                  second: '); readln(ra.sekunde);
   write('> Declination    : '); readln(de);
   writeln;
   t := lmst - (ra.stunde + ra.minute / 60.0 + ra.sekunde / 3600.0) * 15.0;
   t := pi2mod(rad(t));
   atoh(az,h,t,rad(de),rad(phi));
   writeln('  Azimut: ',deg(az):10:5);
   writeln('  Height: ',deg(h):10:5);
   read(c)
end;

{ horizontal -> aequatorial }
procedure ha;
var de,lmst,t,phi,h,az:real;
    ra:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT HORIZONTAL COORDINATES INTO EQUATORIAL COORDINATES >');
   writeln;
   geoin(lmst,phi);
   write('> Azimut: '); readln(az);
   write('> Height: '); readln(h);
   writeln;
   htoa(t,de,rad(az),rad(h),rad(phi));
   t := pi2mod(rad(lmst) - t);
   time(ra,t);
   writeln('  Right ascension: ',ra.stunde:2,ra.minute:3, ra.sekunde:3);
   writeln('  Declination    : ',deg(de):10:5);
   read(c)
end;

{ topographisch -> geozentrisch }
procedure tg;
var ra,dego,rg,rat1,det,rt,lmst,phi:real;
    rat,rag:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT TOPOCENTRIC EQUTORIAL INTO GEOCENTRIC EQUATORIAL >');
   writeln;
   geoin(lmst,phi);
   write('> Right ascension:   hour: '); readln(rat.stunde);
   write('>                  minute: '); readln(rat.minute);
   write('>                  second: '); readln(rat.sekunde);
   write('> Declination    : '); readln(det);
   write('> Distance AU    : '); readln(rt);
   writeln;
   rat1 := 15 * (rat.stunde + rat.minute * 60.0 + rat.sekunde * 3600.0);
   ttog(ra,dego,rg,rad(rat1),rad(det),rt,rad(lmst),rad(phi));
   time(rag,ra);
   writeln('Geocentric coordinates:');
   writeln('  Right ascension: ',rag.stunde:2,rag.minute:3,rag.sekunde:3);
   writeln('  Declination    : ',deg(dego):10:5);
   writeln('  Distance       : ',rg);
   read(c)
end;

{ geozentrisch -> topozentrisch }
procedure gt;
var ra,dego,rg,rat1,det,rt,lmst,phi:real;
    rat,rag:ZEIT;
    c:char;
begin
   write(chr(27),'E');
   writeln('< CONVERT GEOCENTRIC EQUTORIAL INTO TOPOCENTRIC EQUATORIAL >');
   writeln;
   geoin(lmst,phi);
   write('> Right ascension:   hour: '); readln(rag.stunde);
   write('>                  minute: '); readln(rag.minute);
   write('>                  second: '); readln(rag.sekunde);
   write('> Declination    : '); readln(dego);
   write('> Distance AU    : '); readln(rg);
   writeln;
   ra := 15 * (rag.stunde + rag.minute * 60.0 + rag.sekunde * 3600.0);
   gtot(rat1,det,rt,rad(ra),rad(dego),rg,rad(lmst),rad(phi));
   time(rat,rat1);
   writeln('Topocentric coordinates:');
   writeln('  Right ascension: ',rat.stunde:2,rat.minute:3,rat.sekunde:3);
   writeln('  Declination    : ',deg(det):10:5);
   writeln('  Distance       : ',rt);
   read(c)
end;

begin
   repeat
      write(chr(27),'E');
      writeln('< CONVERSION BETWEEN DIFFERENT COORDINATE-SYSTEMS >');
      writeln;
      writeln('  select conversion:');
      writeln;
      writeln('  a) ecliptical             --> geozentric equatorial');
      writeln('  b) geozentric equatorial  --> ecliptical');
      writeln;
      writeln('  c) horizontal             --> topozentric equatorial');
      writeln('  d) topozentric equatorial --> horizontal');
      writeln;
      writeln('  e) geozentric equatorial  --> topozentric equatorial');
      writeln('  f) topozentric equatorial --> geozentric equatorial');
      writeln;
      writeln('  x) exit');
      read(c);
      case c of
         'a':ea;
         'b':ae;
         'c':ha;
         'd':ah;
         'e':gt;
         'f':tg;
      end;
   until c = 'x';
   writeln
end.
