/*->c.sat */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>
#include <locale.h>
#include <math.h>


#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.wimpt"
#include "h.bbc"
#include "h.akbd"
#include "h.werr"
#include "h.flex"

#include "h.DrawLevel0"


#include "h.wos"
#include "h.ram"
#include "h.file"
#include "h.main"
#include "h.DrawLib"
#include "h.pic"
#include "h.mym"
#include "h.key"

#include "h.pan"
#include "h.data"



#define SQR(a) ((a)*(a))


const int      R5 = 3432;    /* {earth radius in NM} */

#define  PI   3.14159265

#define DEG_TO_RAD  (PI / 180.0)

#define MIN_TO_RAD  (DEG_TO_RAD / 60.0)

#define DRAWPERNM   256


#define MINHT 0


point next_point;
point last_point;




int    H0=15000;   /*  {Satellite altitude in nautical miles} */


int SAT_LAT=20;    /*  {Satellite latitude in degrees} */
int SAT_LON=20;    /*  {Satellite longitude in degrees} */

int S0;         /*  {Distance from the satellite to the horizon} */

int LAT;        /*  {Unprojected latitude in radians} */
int LON;        /*  {Unprojected longitude in radians} */




int PROJ_LAT;   /*  {Projected latitude in radians} */
int PROJ_LON;   /*  {Projected longitude in radians} */

int G0;         /*  {Largest distance from satellite coords at} */
                   /*  {which points will be plotted.  i.e. the }  */
                   /*  {maximum projected LAT/LON distance in NM}  */



int  SINL1;   
int  COSL1;
int  SINL2;
int  COSL2;
int  SINL1SINL2;
int  SINL1COSL2;


int S1ADJUST;
int S2ADJUST;
int S3ADJUST;
int visible;




int tval[5401];       /* value of TSHIFT * cos(angle) in mins */



#define TSHIFT 16384


void inittable(void)
{
 int i;
 for(i=0;i<=5400;i++) tval[i]=(int)(TSHIFT*cos(MIN_TO_RAD*i));
}



int tcos(int mins)
{
 int minus;

 /* dprintf(0,"tcos mins=%d",mins); */

 if(mins<0) mins=-mins;
 minus=0;

 if(mins>=(5400*4)) mins=mins % (5400*4);

 if(mins>5400 && mins<=(5400*2))
 {
  minus=1;
  mins=5400*2-mins;
 }
 else
 if(mins>(2*5400) && mins<=(5400*3))
 {
  minus=1;
  mins=mins-5400*2;
 }
 else
 if(mins>(3*5400) && mins<(5400*4))
 {
  mins=5400*4-mins;
 }

/* dprintf(0,"tcos x"); */

 return(minus?-tval[mins]:tval[mins]);
}



int tsin(int mins)
{
 int minus;


/* dprintf(0,"tsin mins=%d",mins); */

 if(mins<0)
 {
  mins=-mins;
  minus=1;
 }
 else
  minus=0;


 if(mins>=(5400*4)) mins=mins%(5400*4);

 if(mins>5400 && mins<=(5400*2))
 {
  mins=5400*2-mins;
 }
 else
 if(mins>(2*5400) && mins<=(5400*3))
 {
  minus=!minus;
  mins=mins-5400*2;
 }
 else
 if(mins>(3*5400) && mins<(5400*4))
 {
  minus=!minus;
  mins=5400*4-mins;
 }

/* dprintf(0,"tsin x"); */

 return(minus?-tval[5400-mins]:tval[5400-mins]);
}






void compute_constants(void)
{
 int L1;
 int L2;

 L1=SAT_LAT*60;
 L2=SAT_LON*60;

 S0=(int)sqrt(H0 * (2*R5 + H0));  /* {Compute distance from satellite} */
                             /* {to horizon} */
 /* {Compute distance from horizon to line from the satellite to the} */
 /* {the center of the earth} */

 G0=(R5*((int)sqrt(SQR(R5+H0) - SQR(R5))))/(R5+H0);


 SINL1 = tsin(L1);            /*  {Compute static values used by the} */
 COSL1 = tcos(L1);            /*  {SCALE_COORDS procedure} */
 SINL2 = tsin(L2);
 COSL2 = tcos(L2);
 SINL1SINL2 = (SINL1 * SINL2)/TSHIFT;
 SINL1COSL2 = (SINL1 * COSL2)/TSHIFT;
 S1ADJUST = ((((R5+H0) * COSL1)/TSHIFT)*SINL2)/TSHIFT;
 S2ADJUST = ((((R5+H0) * COSL1)/TSHIFT)*COSL2)/TSHIFT;
 S3ADJUST = ((R5+H0) * SINL1)/TSHIFT;
}







void scale_coords(void)
{
 int    R5CLAT;
 int    S1;
 int    S2;
 int    S3;
 double S;


 R5CLAT=(R5*tcos(LAT))/TSHIFT;

 S1 = (R5CLAT * tsin(LON))/TSHIFT- S1ADJUST;
 S2 = (R5CLAT * tcos(LON))/TSHIFT - S2ADJUST;
 S3 = (R5 * tsin(LAT))/TSHIFT- S3ADJUST;

 S  =          (((double)S1)*((double)S1) + 
                ((double)S2)*((double)S2) + 
                ((double)S3)*((double)S3));

 visible=S<=( ((double)S0)*((double)S0) );

 PROJ_LAT = - (S1*SINL1SINL2)/TSHIFT
            - (S2*SINL1COSL2)/TSHIFT 
            + (S3*COSL1)/TSHIFT;

 PROJ_LON = (S1*COSL2)/TSHIFT - (S2*SINL2)/TSHIFT; 
}







void draw_grid(void)
{
 int i;
 int j;
 int first;

 veccircle(drxcentre,drycentre,(int)(G0*DRAWPERNM),&drawdiag);

 if(selection & MGRID)
 {
  for(i=-5;i<=5;i++)
  {
   first=1;
   LAT = (i * 15) * 60;

   for(j=0;j<=120;j++)
   {
    LON = (j * 3) * 60;
    scale_coords();
    if(visible)
    {
     if(first)
     {
      vecmove(PROJ_LON*DRAWPERNM+drxcentre,
              PROJ_LAT*DRAWPERNM+drycentre,&drawdiag);
      first=0;
     }
     else
      vecdraw(PROJ_LON*DRAWPERNM+drxcentre,
              PROJ_LAT*DRAWPERNM+drycentre,&drawdiag);
    }
    else first=1;

   }
  }


  for(i=0;i<=23;i++)
  {
   first=1;

   LON = (i * 15) * 60;
   for(j=-29;j<=29;j++)
   {
    LAT = (j * 3) * 60;
    scale_coords();
    if(visible)
    {
     if(first)
     {
      vecmove(PROJ_LON*DRAWPERNM+drxcentre,
              PROJ_LAT*DRAWPERNM+drycentre,&drawdiag);
      first=0;
     }
     else
      vecdraw(PROJ_LON*DRAWPERNM+drxcentre,
              PROJ_LAT*DRAWPERNM+drycentre,&drawdiag);
    }
    else first=1;

   }
  }
 }
}





/* plot a single data set using mercator */


void sdataset(int line,int fill)
{
 point p;
 point p2;
 int   mlon;
 int   mlat;
 int   pending;

 /* pending == 0 waiting for a good move */
 /* pending == 1 got a move in p2,  now want draw */
 /* pending == 2 drawing */

 veclinecolour(line,&drawdiag);
 vecfillcolour(fill,&drawdiag);

 pending=0;

 while(getpoint(&p))
 {
  if(p.type>=1000 || pending==0)
  {
   closediag(&drawdiag);
   p2=p;

   LAT=p2.y;
   LON=p2.x;

   scale_coords();
   if(visible) pending=1;
   else        pending=0;

   mlon=PROJ_LON;
   mlat=PROJ_LAT;
  }
  else
  {
   if(p.type>=detail)
   {
    LAT=p.y;
    LON=p.x;

    scale_coords();
    if(visible)
    {
     if(pending==1)
     {
      vecmove(mlon*DRAWPERNM+drxcentre,mlat*DRAWPERNM+drycentre,
                                                                &drawdiag);
      pending=2;
     }
 
     if(abs(p2.x-p.x)>10800)
     {
      if(p2.x>0) p.x+=2*10800;
      else       p.x-=2*10800;
     }

     vecdraw(PROJ_LON*DRAWPERNM+drxcentre,PROJ_LAT*DRAWPERNM+drycentre,
                                                                &drawdiag);

     p2=p;
    }
    else pending=0;
   }
  }
 }
}








void scity(int textcol,int bcol)
{
 city p;
 char text[64];

 vectextcolour(textcol,-1,&drawdiag);
 vectextsize(textsize,textsize,&drawdiag);
 veclinecolour(bcol,&drawdiag);
 vecfillcolour(bcol,&drawdiag);

 while(getcity(&p))
 {
  if(p.type>=detail)
  {
   LAT=p.y;
   LON=p.x;

   scale_coords();

   if(visible)
   {
    if(showname || showstate || showcountry)
    {
     text[0]=0;
     if(showname)    strcat(text,p.name);
     if(showstate)   strcat(text,p.state);
     if(showcountry) strcat(text,p.country);

     if(strlen(text))
     {
      vecstring(PROJ_LON*DRAWPERNM+drxcentre,
               PROJ_LAT*DRAWPERNM+drycentre,text,&drawdiag);

      if(showbullet)
      veccircle(PROJ_LON*DRAWPERNM+drxcentre,
               PROJ_LAT*DRAWPERNM+drycentre,bulletsize,&drawdiag);
     }
    }
    else
    if(showbullet)
    veccircle(PROJ_LON*DRAWPERNM+drxcentre,
               PROJ_LAT*DRAWPERNM+drycentre,bulletsize,&drawdiag);
   }
  }
 }
}








/*
  SAT_LAT  satellite latitude <-90.0 thru 90.0> 
  SAT_LON  satellite longitude <-180.0 thru 180.0>
  H0       satellite altitude in NM <1.0 thru 30000.0> 
*/




void drawsat(void)
{
 int i;


 compute_constants();

 for(i=0;i<=CITY;i++)
 {
  if(selection & (1<<i))
  {
   if(opendataset(i))
   {
    if(i<CITY) sdataset(linecolour[i],fillcolour[i]);
    else       scity(linecolour[CITY],linecolour[BULLET]);
    closedataset();
   }
  }
 }


 veclinecolour(linecolour[GRID],&drawdiag);
 vecfillcolour(fillcolour[GRID],&drawdiag);

 draw_grid();
}




void satset(void)
{
 compute_constants();

 drwidth =(int)(2*G0*DRAWPERNM);
 drheight=(int)(2*G0*DRAWPERNM);

 drxcentre=drwidth/2;
 drycentre=drheight/2;

 oswidth=(drwidth*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);
 osheight=(drheight*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);

 oswidth=oswidth>>8;
 osheight=osheight>>8;
}




void satsizeicon(void)
{
 int tlat;
 int tlon;
 int height;

 int tlat2;
 int tlon2;
 int height2;

 if(sscanf(iconaddr(whandle[SATSIZE],6),"%d",&tlat)!=1)    tlat=SAT_LAT;
 if(sscanf(iconaddr(whandle[SATSIZE],11),"%d",&tlon)!=1)   tlon=SAT_LON;
 if(sscanf(iconaddr(whandle[SATSIZE],14),"%d",&height)!=1) height=H0;


 tlat2=tlat;
 tlon2=tlon;
 height2=height;


 switch(icon)
 {
  case 10:                                 /* down/up on Lat */
          if(tlon>-180) tlon--;
          break;

  case 12:
          if(tlon<180) tlon++;
          break;

  case  1:                                 /* down/up on Lon */
          if(tlat>-90) tlat--;
          break;

  case 16:
          if(tlat<90) tlat++;
          break;

  case 13:            /* down/up on ht. */
          if(height>(MINHT+100)) height-=100;
          break;

  case 15:
          if(height<30000) height+=100;
          break;

  case  5:                                 /* default */
          height=15000;
          tlon=tlat=0;
          break;

  case  4:            /* OK */
          if(tlon<-180)    tlon=-180;
          if(tlon>180)     tlon=180;
          if(tlat>90)      tlat=90;
          if(tlat<-90)     tlat=-90;
          if(height<MINHT) height=MINHT;
          if(height>30000) height=30000;

          SAT_LON=tlon;
          SAT_LAT=tlat;
          H0=height;

          if(buttons==0x4) zapmenu();
          break;


  case  3:            /* window */
          break;

 }


 if(tlon!=tlon2)     writeiconf(whandle[SATSIZE],11,"%d",tlon);
 if(tlat!=tlat2)     writeiconf(whandle[SATSIZE],6,"%d",tlat);
 if(height!=height2) writeiconf(whandle[SATSIZE],14,"%d",height);
}



              /* N L R D U */

static char mapiclst[3][5]=
{
          6,          0,           0,          11,           14,
         11,          0,           0,          14,            6,
         14,          0,           0,           6,           11
};





void satsizekey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               zapmenu();
               break;

       case CR:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<11;j++) if(mapiclst[j][0]==icon) break;
               cicon=mapiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[SATSIZE],cicon);
               break;

    default:return;
 }
 *key=-1;
}














void satsetupbox(void)
{
 writeiconf(whandle[SATSIZE],6,"%d",SAT_LAT);
 writeiconf(whandle[SATSIZE],11,"%d",SAT_LON);
 writeiconf(whandle[SATSIZE],14,"%d",H0);



}





