/*===========================================================================
  Copyright (C) 1994-2011 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTIFIER  DRAW
.LANGUAGE    C
.AUTHOR      K. Banse, ESO Garching
.KEYWORDS    ImageDisplay, cursor
.PURPOSE     a) use cursor rectangle to get the position of the two cursors 
                on the ImageDisplay and draw the desired figure into the 
                overlay channel
             b) plot contents of a 1-dim frame as y-coords into DeAnza
.ALGORITHM   a) exit by pressing ENTER with both cursors off.
             b) a frame is scaled in x and z, the scaled image is
                then plotted into a 512*512 byte memory board of DeAnza
.INPUT/OUTPUT
  the following keys are used:

  MYACT/C/1/2			= RE, for rectangle
				= CI, for circle
				= EL, for ellips
				= SL, for slit
				= AR, for arrow
				= LI, for straight line
				= CR, for cross
				= AN, for interactively defined lines 
                                      (DRAW/ANY)
				= FI  for executing an ASCII file containing
				      DRAW/.. commands
				= XI, for drawing an image

  P1/C/1/100			specs for input
				= name for table (a)
				= CURSOR for interactive input (b)
				= coord_string for fixed position (c)
  P2/C/1/1		 	= F for frame related coords (a,c)
				= S for screen coords. (a,c)
				for (b) only S applicable
  INPUTR/R/1/3			(1) rotation angle
  				(2) start angle - only for Circle, Ellips
  				(3) end angle - in degrees from 0 to 360
				    0 degrees is along positive x-axis, 
				    increasing counter clockwise
  P3/C/1/3			drawing option
				(1:1) = F, if shape should be filled
				      or N if not, for RE,CI,EL,SL
				(1:2) = RU,RD,LU,LD (right-up,right-down,...)
				direction of arrow, for AR
				(1:3) = size of cross arms in screen pixels
				for CR
  DAZHOLD/I/1/1		        cursor no., 0, 1 or 2

 ---------------------------------------------------------
  
  for DRAW/IMAGE (XI)

  IN_A/C/1/60			data frame to be loaded
  DAZHOLD/I/3/1		        split mode, = 0 for single image
					    = 1 for 3/4 images
  DAZIN/I/1/1			scaling factor
				used, if DEFAULT(1:1) = 'N'
  DEFAULT/C/1/5		        default flags
  				(1) = 'Y', take scaling of image from
					   descr. DISPLAY_DATA(1,2)
				    = 'N', take scaling from key DAZIN
  				(2) = 'N', take x-center and yline
					   from key INPUTC
  				(3) = 'Y', take cuts of image from
					   descr. CUTS(1,2)
				    = 'N', take cuts of image from INPUTR(1,2)
				(5) = 'Y', overplot on existing image
				      else, clear channel first
				(6) = 'N', use fixpixel
  INPUTI/I/1/2			if DEFAULT(6:6).NE.'Y',
				(1,2) frame,screen pixel of fixpoint
  INPUTR/R/1/6			(1,2) cuts if DEFAULT(3) = 'N'
				(3) = highest possible value for y-pixels
				(4) = offset in y on display, in [0,QMSZY-1]
				(5) = intensity in [0,255]
  				(6) optional angle

.VERSION     1.00       940620  converted from DRAW.FOR    R.M.van Hees

 110519		last modif
------------------------------------------------------------*/

/* Define _POSIX_SOURCE to indicate that this is a POSIX program */

#define  _POSIX_SOURCE 1


#include <string.h>
#include <stdio.h>
#include <math.h>
#include <midas_def.h>
#include <idinumd.h>
#include <proto_II.h>

#ifndef TRUE
#define TRUE            1
#define FALSE           0
#endif

#ifndef MYABS
#define MYABS(a)      ((a)>0)?(a):(-(a))
#endif

#ifndef PI
#define PI		3.14159265358979325e0
#endif
#define DEG2RAD		(PI / 180.0)

#define NSHAPE		9
#define MXFIG		5000

extern int tstcolor();

/*

*/

int main()

{
register int nn;
int    actvals, intens, knul, length, ncurs, nmal, npnts, stat, unit;
int    input_fl, rota_fl, shape_fl, coord[4], dazhld[13];
int    fid, begin, m;
int    xfig[2*MXFIG], yfig[2*MXFIG];

float  rdum, rotang, arcs[2], rbuff[4], cpos[4];

double ca, sa;
double ddum;

char   ref[2], dropt[4], shape[7], keynm[16], cbuff[102], frame[102], 
       table[102], output[82];
char   *err_qual = "DRAW: unknown qualifier...",
       *usr_curs = "Give a second position, using the cursor";
static char *shapes[NSHAPE] = { "RE","CI","EL","SL","AR","LI","CR","AN","XI" };
static int   shpcur[NSHAPE] = { 2, 2, 2, 2, 2, 2, 0, 0, 0 };

enum shapeflags { RE, CI, EL, SL, AR, LI, CR, AN, XI };
enum inputflags { KEYW, FIXP, TABL, CURS };





(void) SCSPRO("DRAW");

for (nn=0; nn<4; nn++)
   {
   cpos[nn] = 0.0;
   coord[nn] = 0;
   }

arcs[0] = arcs[1] = 0.0;
ca = sa = 0.0;

/* Attach ImageDisplay + get info about displayed image */

DCOPEN(1);
(void) SCKRDI("AUX_MODE",9,1,&actvals,&nmal,&unit,&knul);
if (nmal == 1) CONCHA_C(QDSPNO,QOVCH,1,0);


/* Get split mode + addresses + memories per pixel */

(void) SCKRDI("DAZHOLD",1,13,&actvals,dazhld,&unit,&knul);
if (dazhld[12] == QIMCH)
   (void) Cdazscr(QDSPNO,QOVCH,&SCROLX,&SCROLY);


/* get shape of region */

(void) SCKGETC("MYACT",1,2,&actvals,shape);
CGN_UPSTR(shape);

fid = -1;
if (shape[0] == 'F')
   {		/* DRAW in a loop reading the commands from an ASCII file */
   (void) SCKGETC("DRAWCOLOR",1,80,&actvals,table);
   fid = osaopen(table,0);
   if (fid < 0) 
      {
      sprintf(output,"Could not open file: %s",table);
      SCETER(11,table);
      }
   }



file_loop:
if (fid > -1)
   {
   nn = osaread(fid,output,80);
   if (nn <0)
      {
      (void) osaclose(fid);
      goto end_of_it;
      }
   begin = 0;
   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);
   if ((length < 2) || (cbuff[0] == '!')) goto file_loop;
   m = CGN_INDEXC(cbuff,'/') + 1;
   if (m < 2) goto file_loop;

   CGN_UPSTR(cbuff);
   shape[0] = cbuff[m++];
   shape[1] = cbuff[m];

   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);	/* 1. param */
   if (length < 1) goto file_loop;
   
   if (shape[0] == 'W')			/* DRAW/WAIT */
      {
      m = CGN_CNVT(cbuff,2,1,&length,rbuff,&ddum);
      if (m < 1) rbuff[0] = 1.;		/* default to 1 sec */
      length = CGN_NINT(rbuff[0]*1000.);	/* units are millisecs */
      OSY_SLEEP(length,0);
      goto file_loop;
      }

   cbuff[length++] = ' ';
   cbuff[length++] = '\0';
   (void) SCKWRC("P1",1,cbuff,1,length,&unit);
   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);	/* 2. param */
   if (length < 1) goto file_loop;
   
   cbuff[length++] = ' ';
   cbuff[length++] = '\0';
   (void) SCKWRC("P2",1,cbuff,1,length,&unit);
   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);	/* 3. param */
   if (length < 1) goto file_loop;
   
   cbuff[length++] = ' ';
   cbuff[length++] = '\0';
   (void) SCKWRC("P3",1,cbuff,1,length,&unit);
   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);	/* 4. param */
   if (length < 1) goto file_loop;
   
   rbuff[0] = 0.; rbuff[1] = rbuff[2] = -1.0;

   m = CGN_INDEXC(cbuff,',');
   if (m > 0)
      {
      m = CGN_CNVT(&cbuff[m+1],2,1,&unit,rbuff,&ddum);
      cbuff[m++] = ' ';
      cbuff[m++] = '\0';
      (void) SCKWRC("DRAWCOLOR",1,cbuff,1,m,&unit);
      }
   else
      {
      cbuff[length++] = ' ';
      cbuff[length++] = '\0';
      (void) SCKWRC("DRAWCOLOR",1,cbuff,1,length,&unit);
      }
  
   length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);  /* skip 5. param */
   if (length > 0) 
      {
      length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);  /* 6. param */
      if (length > 0) 
         {
         cbuff[1] = ' ';
         (void) SCKWRC("P6",1,cbuff,1,2,&unit);
         }

      length = CGN_EXTRSS(output,nn,' ',&begin,cbuff,80);  /* 7. param */
      if (length > 0) 
         m = CGN_CNVT(cbuff,2,2,&unit,&rbuff[1],&ddum);
      }

   (void) SCKWRR("INPUTR",rbuff,1,3,&unit);
   }
         
nn = 0;
while ((nn < NSHAPE) && (strncmp(shape,shapes[nn],2) != 0)) nn++;
if (nn == NSHAPE)  SCETER(1,err_qual);                          /* EXIT */

ncurs = shpcur[nn];
shape_fl = nn;


/* Get intensity and rotation option (+ eventual start/stop angles) */

(void) SCKGETC("DRAWCOLOR",1,4,&actvals,table);
intens = tstcolor(table);

(void) SCKRDR("INPUTR",1,3,&actvals,rbuff,&unit,&knul);
rotang = rbuff[0];
rota_fl = (MYABS(rotang) > 0.01) ? TRUE : FALSE;
if (rota_fl)
   {
   ca = cos( DEG2RAD * rotang );
   sa = sin( DEG2RAD * rotang );
   }


arcs[0] = -1.0;
if ((shape_fl > 0) && (shape_fl < 3))		/* for circle, ellips */
   {
   if (rbuff[1] < 0) 
      arcs[0] = -1.0;
   else
      {
      arcs[0] = rbuff[1];
      if (rbuff[2] < 0) 
         arcs[1] = 360.0;
      else
         arcs[1] = rbuff[2];
      }
   }

          
if (shape_fl == 8)			/* draw/image */
   DRAW_IMA();

else if (shape_fl == 7)			/* draw/any */
   DRAW_ANY(intens);


/* Set the drawing option - filled or not, 
                          - right-up, -down, left-up, -down,
                          - size of cross arms */                       
else
   {
   (void) SCKGETC("P3",1,3,&actvals,dropt);
   CGN_UPSTR(dropt);

/* shape[0,1] = shape of figure
   shape[2] = F(ill) or N(ofill) (for figures which can be filled)
   shape[2] = direction for arrows
   shape[3] = '3' or '4' for circle options (center+radius or rectangle) */

   switch (shape_fl)
      {
      case RE:
      case EL: 
      case SL:
         shape[2] = dropt[0];
         break;
      case CI:
         shape[3] = '4';
         shape[2] = dropt[0];
         rota_fl = FALSE;
         break;
      case AR: 
      case LI:
         if ( strncmp( dropt, "RD", 2 ) == 0 )
            shape[2] = '2';
         else if ( strncmp( dropt, "LU", 2 ) == 0 )
            shape[2] = '3';
         else if ( strncmp( dropt, "LD", 2 ) == 0 )
            shape[2] = '4';
         else
            shape[2] = '1';
         break;
      case CR:
         if ( CGN_CNVT(dropt,1,1,&length,&rdum,&ddum) <= 0 )
            length = 9;
         break;
      default:
         SCETER(2,err_qual);
         break;
      }


   /* Get input option: via Keyword, Cursor, Table or Fixed coordinates */

   (void) strcpy(ref,"S");
   (void) SCKGETC("P6",1,1,&actvals,frame);
   if ( *frame == 'k' || *frame == 'K' )
      {						/* input from keyword */
      (void) SCKGETC("P1",1,15,&actvals,keynm);
      input_fl = KEYW;
      }
   else
      {						/* input explicitely */
      (void) SCKGETC("P1",1,100,&actvals,frame);
      CGN_UPCOPY(cbuff,frame,100);

      if (strncmp(cbuff,"CURSOR",6) == 0)
         input_fl = CURS;			/* center chosen via cursor */
      else
         {
         (void) SCKGETC("P2",1,1,&actvals,ref);	/* get coord. ref. */
         if (*ref == 'f') 
            *ref = 'F';                       /* use frame (world) coords */
         else if (*ref == 'p')
            *ref = 'P';                       /* use pixel values */

         nmal = CGN_INDEXC(cbuff,',');
         if (nmal <= 0)
            {
            CGN_FRAME(frame,3,table,0);
            input_fl = TABL;
            if (*ref == '+') *ref = 'F';	/* default for table input */
            }
         else
            input_fl = FIXP;

         if ((*ref == 'F') || (*ref == 'P'))
            {					/* get displayed frame */
            CGN_FRAME("*",1,frame,0);
            nmal = CGN_INDEXC(frame,' ');
            if (nmal > 0) frame[nmal] = '\0';		/* truncate name */
            }
         else
            {
            (void) strcpy(ref,"S");
            if (input_fl == TABL)
               (void) SCTDIS("Warning: REF_FLAG = `S' ...",0);
            }
         }
      }

   stat = nmal = 0;
   while (stat == 0)
      {
      switch (input_fl)
         {
         case KEYW:
            stat = KEYW_INP(keynm,ncurs,cpos);
            break;
         case FIXP:
            FIXP_INP(shape,ref,cbuff,frame,ncurs,cpos);
            break;
         case TABL:
            {
            int   aux_flag;
            static int nr;

            stat = TABL_INP(table,frame,ref,shape,&aux_flag,cpos,rbuff);
            if (stat == -1)                     /* pixel conversion error */
               {
               stat = 0;                /* reset, so we continue */
               break;
               } 

            if (stat == -1) break;		/* pixel conversion error */

            if (aux_flag > 0)
               {
               if (aux_flag >= 10)
                  {				/* we also got rotation angle */
                  if (shape_fl != CI) 
                     {
                     rotang = rbuff[1];
                     rota_fl = (MYABS(rotang) > 0.01) ? TRUE : FALSE;
                     if (rota_fl)
                        {
                        ca = cos( DEG2RAD * rotang );
                        sa = sin( DEG2RAD * rotang );
                        }
                     }
                  aux_flag -= 10;
                  }
               if (aux_flag == 1)		/* we also got color */
                  intens = CGN_NINT(rbuff[0]);
               }

            if (stat == 0)
               {
               if ( !rota_fl && (shape_fl == LI))
                  {
                  if ( nr == 0 )
                     {
                     xfig[0] = CGN_NINT( cpos[0] );
                     yfig[0] = CGN_NINT( cpos[1] );
                     xfig[1] = CGN_NINT( cpos[2] );
                     yfig[1] = CGN_NINT( cpos[3] );
                     nr++;
                     }
                  else
                     {
                     if ( (CGN_NINT(*cpos) == xfig[nr])
                          && 
                          (CGN_NINT(cpos[1]) == yfig[nr]) )
                        {
                        xfig[++nr] = CGN_NINT( *cpos );
                        yfig[nr]   = CGN_NINT( cpos[1] );
                        }
                     else
                        {
                        (void) IIGPLY_C(QDSPNO,QOVCH,xfig,yfig,nr+1,intens,1);
                        nr = 0;
                        }
                     }
                  }
               }
            else
               {
               if (nr++ > 0)
                  {
                  (void) IIGPLY_C(QDSPNO,QOVCH,xfig,yfig,nr,intens,1);
                  }
               }

            break;
            }
         case CURS:
            stat = CURS_INP(shape,&ncurs,cpos);
            break;
         default:
            SCETER(3,"DRAW: unknown input...");
            break;
         }

      if (stat == 0)
         {
         nmal++;
         if (shape_fl ==  CR)                    /* handle CROSS */
            {
            if ((input_fl == CURS) && (ncurs == 2))     
               {
               coord[0] = (cpos[0]+ cpos[2]) * 0.5;
               coord[1] = (cpos[1]+ cpos[3]) * 0.5;
               coord[2] = CGN_NINT( 0.5 * (cpos[3] + cpos[2] -
                                                      coord[1] - *coord ));
               cpos[0] = coord[0];
               cpos[1] = coord[1];
               cpos[2] = coord[2];
               }
            else
               cpos[2] = length;
            goto build_graph;
            }

         /* all other shapes need 2 or more cursor inputs */

         if (input_fl == CURS)
            {
            if (ncurs == 0)
               {
               int xyA[5], xyB[5], statA, statB;

               (void) SCTDIS( usr_curs,99);
               Ccursin( QDSPNO,1,ncurs,xyA,&statA,xyB,&statB);
               cpos[2] = xyA[0];
               cpos[3] = xyA[1];

               if (shape_fl == CI) 
                  {
                  rbuff[0] = cpos[0] - cpos[2];
                  rbuff[1] = cpos[1] - cpos[3];
                  cpos[2] = (float) sqrt((double)((rbuff[0]*rbuff[0]) +
                                                 (rbuff[1]*rbuff[1])));
                  }
               }
            if (shape_fl == CI)	
               {
               if (IDINUM == 11)
                  shape[3] = '3';		/* use center + radius */
               else
                  shape[3] = '4';		/* use a rectangle */
               }
            }

build_graph:
         coord[0] = CGN_NINT(cpos[0]);
         coord[1] = CGN_NINT(cpos[1]);
         coord[2] = CGN_NINT(cpos[2]);
         coord[3] = CGN_NINT(cpos[3]);

         if ((shape_fl == CI) && (shape[3] == '4'))
            {		/* for circles within rectangles we have to work */
            coord[0] = CGN_NINT((cpos[0]+cpos[2])/2);
            coord[1] = CGN_NINT((cpos[1]+cpos[3])/2);
            cpos[2] = MYABS(cpos[0] - coord[0]);
            cpos[3] = MYABS(cpos[1] - coord[1]);
            coord[2] = CGN_NINT((cpos[2] + cpos[3])/2);
            }


         /* now build the desired shape */

         m = 2 * MXFIG;
         buildgra(shape,coord,arcs,xfig,yfig,m,&npnts);

         if (rota_fl)			/* test, if rotation desired */
            {
            double centx, centy, xx, yy;

            if (ncurs == 0)
               {
               centx = cpos[0];
               centy = cpos[1];
               }
            else
               {
               centx = (cpos[0] + cpos[2]) * 0.5;
               centy = (cpos[1] + cpos[3]) * 0.5;
               }
            for ( nn = 0; nn < npnts; nn++ )
               {
               xx = ca * (xfig[nn]-centx) - sa * (yfig[nn]-centy);
               yy = sa * (xfig[nn]-centx) + ca * (yfig[nn]-centy);
               xfig[nn] = CGN_NINT( centx - xx );
               yfig[nn] = CGN_NINT( centy - yy );
               }
            }


         /* finally draw shape */

         (void) IIGPLY_C(QDSPNO,QOVCH,xfig,yfig,npnts,intens,1);
         }

      if ( input_fl == FIXP ) stat = 1;         /* only one position */
      }                                   /* closing of the while-loop */


   /* save no. of coords. entered */

   (void) SCKWRI("OUTPUTI",&nmal,1,1,&unit);
   if ( input_fl == CURS )     
      {
      (void) strcpy( output, " " ); 
      (void) SCTDIS( output, 0 );
      }
   else if ( input_fl == TABL )     
      {
      (void) sprintf( output, "%-d table rows processed...", nmal );
      (void) SCTDIS( output, 0 );
      }
   }
if (fid > -1) goto file_loop;


end_of_it:
DCCLOS( QDSPNO );
Crefrovr();

return SCSEPI();
}















