/*===========================================================================
  Copyright (C) 1993-2009 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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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  module PLVEC
.AUTHOR      R.M. van Hees IPG-ESO Garching
.KEYWORDS    plot software, graphics, bulk data fame
.LANGUAGE    C
.PURPOSE     Vector plotting routine for two dimensional data
.COMMENTS    holds PLVEC and PLVECI
.ENVIRONment MIDAS and AGL
             #include <agl.h>           Prototypes for AGL application programs
             #include <midas_def.h>     Prototypes for MIDAS interfaces
             #include <plot_def.h>      Symbols used by the PLT interfaces

.VERSION     1.1     10-Sep-1993   FORTRAN --> ANSI-C    RvH

090422		last modif
------------------------------------------------------------*/
/*
 * Define _POSIX_SOURCE to indicate
 * that this is a POSIX program
 */
#define  _POSIX_SOURCE 1

/*
 * definition of the used functions in this module
 */
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <midas_def.h>

/*
 * define some macros and constants
 */
#include <plot_def.h>

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTIFIER  PLVEC
.PURPOSE     Vector plotting routine for two dimensional data
     input:    float  *p_imgA  pointer to data of frame with intensities
               float  *p_imgB  pointer to data of frame with pos. angles
               float  *image   image size in pixel coordinates
               float  *area    image size in world coordinates
               double *step    distance between pixels in world units
               float  scar     scale of vector [units/mm]
               float  *ranp    range in intensity and position angle range
               int    head     head: 1) the vector get an arrow
                                     0) only a line
.COMMENTS    makes a vector field with vector (R,Phi) from (X,Y)
             Phi in degrees
             Magnitude is EXPAND * 1/30 range in X / mean length
----------------------------------------------------*/
#ifdef __STDC__
      void PLVEC( float *p_imgA, float *p_imgB, float *image, float *area, 
                  double *step, float scar, float *ranp, int head)
#else
      void PLVEC( p_imgA, p_imgB, image, area, step, scar, ranp, head )
      int    head;
      float  *p_imgA, *p_imgB, *image, *area, scar, *ranp;
      double *step;
#endif
{
register int ii, jj;

int   nx, ny;
float arrow, deltx, delty, phi, x, y, xstart, ystart, xvn, yvn, 
      arrmm[PLDIM2], dval[PLDIM2], frmmm[PLDIM2], val,
      psi[PLDIM2], xvu[PLDIM2], yvu[PLDIM2], clpl[4], wndl[4];

double deg2rad = PI / 180.0;

nx = (int) fabs( image[1] - image[0] ) + 1;
ny = (int) fabs( image[3] - image[2] ) + 1; 

if ( step[0] < 0.0 )
   xstart = MYMAX( area[0], area[1] );
else
   xstart = MYMIN( area[0], area[1] );

if ( step[1] < 0.0 )
   ystart = MYMAX( area[2], area[3] );
else
   ystart = MYMIN( area[2], area[3] );
deltx = (float) step[0];
delty = (float) step[1];

(void) AG_RGET( "devd", dval );
(void) AG_RGET( "clpl", clpl );
(void) AG_RGET( "wndl", wndl );
frmmm[0] = 10 * dval[0] * ( clpl[1] - clpl[0] );
frmmm[1] = 10 * dval[1] * ( clpl[3] - clpl[2] );

y = ystart;
for ( ii = 0; ii < ny; ii++ )
    { x = xstart;
      for ( jj = 0; jj < nx; jj++ )
          { val   = *p_imgA++;
            phi   = fmod(*p_imgB++,360.0);
            if ((val >= ranp[0] && val <= ranp[1]) &&
                (phi >= ranp[2] && phi <= ranp[3])) 
               { AG_VU2N( x, y, &xvn, &yvn );
                 AG_WDEF( 0.0, frmmm[0], 0.0, frmmm[1] );
                 AG_VN2U( xvn, yvn, xvu, yvu );
                 arrmm[0] = (float) ((fabs(val)/scar) * sin( deg2rad * phi ));
                 arrmm[1] = (float) ((fabs(val)/scar) * cos( deg2rad * phi));
                 xvu[1] = xvu[0] - arrmm[0];
                 yvu[1] = yvu[0] + arrmm[1];
                 AG_GPLL( xvu, yvu, 2 );

                 if ( head )
                    { xvu[0] = xvu[1];
                      yvu[0] = yvu[1]; 
                      arrow = 1.0;
                      if (phi >= 0.0 || phi < 90.0) 
                         { psi[0] = phi - 30.0;
                           psi[1] = 60.0 - phi;
                           xvu[1] = xvu[0] + arrow*sin(deg2rad * psi[0]);
                           yvu[1] = yvu[0] - arrow*cos(deg2rad * psi[0]);
                           AG_GPLL( xvu, yvu, 2 );
                           xvu[1] = xvu[0] + arrow*cos(deg2rad * psi[1]);
                           yvu[1] = yvu[0] - arrow*sin(deg2rad * psi[1]);
                           AG_GPLL( xvu, yvu, 2 );
                         }
                      else if (phi >= 90.0 || phi < 180)
                         { psi[0] = phi - 120.0;
                           psi[1] = 150.0 - phi;
                           xvu[1] = xvu[0] + arrow*cos(deg2rad * psi[0]);
                           yvu[1] = yvu[0] + arrow*sin(deg2rad * psi[0]);
                           AG_GPLL( xvu, yvu, 2 );
                           xvu[1] = xvu[0] + arrow*sin(deg2rad * psi[1]);
                           yvu[1] = yvu[0] + arrow*cos(deg2rad * psi[1]);
                           AG_GPLL( xvu, yvu, 2 );
                         }
                      else if (phi >= 180.0 || phi < 270)
                         { psi[0] = phi - 210.0;
                           psi[1] = 240.0 - phi;
                           xvu[1] = xvu[0] - arrow*sin(deg2rad * psi[0]);
                           yvu[1] = yvu[0] + arrow*cos(deg2rad * psi[0]);
                           AG_GPLL( xvu, yvu, 2 );
                           xvu[1] = xvu[0] - arrow*cos(deg2rad * psi[1]);
                           yvu[1] = yvu[0] + arrow*sin(deg2rad * psi[1]);
                           AG_GPLL( xvu, yvu, 2 );
                         }
                      else if (phi >= 270.0 || phi <= 360)
                         { psi[0] = phi - 300.0;
                           psi[1] = 330.0 - phi;
                           xvu[1] = xvu[0] - arrow*sin(deg2rad * psi[0]);
                           yvu[1] = yvu[0] - arrow*cos(deg2rad * psi[0]);
                           AG_GPLL( xvu, yvu, 2 );
                           xvu[1] = xvu[0] - arrow*cos(deg2rad * psi[1]);
                           yvu[1] = yvu[0] - arrow*sin(deg2rad * psi[1]);
                           AG_GPLL( xvu, yvu, 2 );
                         }
                   }
                AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] );
               }
            x += deltx;
          }
      y += delty;
    }
return;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTIFIER  PLVECI
.PURPOSE     produce plot information for a two-dimensional contour plot
     input:  int   plmode    plot mode, see PMODE in PLISTAT
             char  *nameA    name of first data frame
             char  *identA   ascii identifier of first frame
             char  *nameB    name of second data frame 
             char  *identB   ascii identifier of second frame
             float  scar     scale of vector [units/mm]
             float  *ranp    position angle range
----------------------------------------------------*/
#ifdef __STDC__
      void PLVECI( int plmode, char *nameA, char *identA, 
                   char *nameB, char *identB, float scar, float *ranp )
#else
     void PLVECI( plmode, nameA, identA, nameB, identB, scar, ranp )
     char  *nameA, *identA, *nameB, *identB;
     int   plmode;
     float scar, *ranp; 
#endif
{
int    actvals;
float  one, ssize, tsize, x1, x2, y1, y2, xt, yt, yh;
float  mnmx[2], scale[2], xl[3], yl[3], clpl[4], image[4], wndl[4];
char   buff[81];

/*
 * Only for plot mode is 2
 */
if ( plmode != 2 ) return;

/*
 * get the symbol and character dimensions, from the MIDAS keywords
 */
PCKRDR( "SSIZE", 1, &actvals, &ssize );
PCKRDR( "TSIZE", 1, &actvals, &tsize );

/*
 * if the symbol size or the text size is not equal to 1, set it to 1
 * and call PCTSET to get the proper sizes for the MIDAS layout
 */
if ( ssize != 1.0 || tsize != 1.0 )
   { one = 1.0;
     PCKWRR( "SSIZE", 1, &one );
     PCKWRR( "TSIZE", 1, &one );
   }
PCTSET();

AG_SSET( "norm");
AG_SSET( "linx");
AG_SSET( "liny");
(void) AG_RGET( "clpl", clpl );
(void) AG_RGET( "wndl", wndl );
x1 = clpl[1] + 0.01;
x2 = 1.0;
y1 = 0.0;
y2 = clpl[3];
AG_CDEF( x1, x2, y1, y2);
AG_WDEF( 0.0, 1.0, 0.0, 1.0 );

/*
 * plot MIDAS logo
 */
PLLOGI( &xt, &yt );

/* 
 * set character height
 */
AG_SSET( "sydi=0.75;chdi=0.75,0.75" );
AG_TGET( "M", xl, yl );
yh = 2.0 * yl[1];

/*
 * plot user name
 */
PLUSER( buff );
AG_GTXT( xt, yt, buff, 1 );

/*
 * name of first frame
 */
yt -= 2*yh;
if ( strlen( nameA ) > (size_t) 12 )
   { AG_GTXT( xt, yt, "Frame A:", 1 );
     yt -= yh;
     AG_GTXT( xt, yt, nameA, 1 ); 
   }
else
   { (void) sprintf( buff, "Frame A: %s", nameA );
     AG_GTXT( xt, yt, buff, 1 );
   }
/*
 * identification
 */
if ( strlen( identA ) > (size_t) 0 )
   { yt -= yh;
     AG_GTXT( xt, yt, "Identification A:", 1 );
     yt -= yh;
     AG_GTXT( xt, yt, identA, 1 );
   }
/*
 * name of second frame
 */
yt -= 2 * yh;
if ( strlen( nameB ) > (size_t) 12 )
   { AG_GTXT( xt, yt, "Frame B:", 1 );
     yt -= yh;
     AG_GTXT( xt, yt, nameB, 1 ); 
   }
else
   { (void) sprintf( buff, "Frame B: %s", nameB );
     AG_GTXT( xt, yt, buff, 1 );
   }
/*
 * identification
 */
if ( strlen( identB ) > (size_t) 0 )
   { yt -= yh;
     AG_GTXT( xt, yt, "Identification B:", 1 );
     yt -= yh;
     AG_GTXT( xt, yt, identB, 1 );
   }
/*
 * area
 */
PCKRDR( "PIXEL", 4, &actvals, image );
yt -= 2*yh;
AG_GTXT( xt, yt, "Area:", 1 );
yt -= yh;
(void) sprintf( buff, "X: %.0f to %.0f", image[0], image[1] );
AG_GTXT( xt, yt, buff, 1 );
yt -= yh;
(void) sprintf( buff, "Y: %.0f to %.0f", image[2], image[3] );
AG_GTXT( xt, yt, buff, 1 );
/*
 * scales
 */
PCKRDR( "SCALES", 2, &actvals, scale );
yt -= 2*yh;
AG_GTXT( xt, yt, "Scales:", 1 );
yt -= yh;
(void) sprintf( buff, "X: %-.6g", scale[0] );
AG_GTXT( xt, yt, buff, 1 );
yt -= yh;
(void) sprintf( buff, "Y: %-.6g", scale[1] );
AG_GTXT( xt, yt, buff, 1 );
yt -= yh;
(void) sprintf( buff, "I: %-.6g", scar );
AG_GTXT( xt, yt, buff, 1 );
/*
 * minimum and maximum
 */
PCKRDR( "ZWNDL", 2, &actvals, mnmx );
yt -= 2*yh;
(void) sprintf( buff, "Min: %-.3g ", mnmx[0] );
AG_GTXT( xt, yt, buff, 1 );
yt -= yh;
(void) sprintf( buff, "Max: %-.3g ", mnmx[1] );
AG_GTXT( xt, yt, buff, 1 );

/*
 * position angle range
 */
yt -= 2*yh;
AG_GTXT( xt, yt, "Position angles:", 1 );
yt -= yh;
(void) sprintf( buff, "%-.3g %s %-.3g", ranp[2], "-- ", ranp[3] );
AG_GTXT( xt, yt, buff, 1 );

yt -= 2.*yh;
PLDATI( &xt, &yt );

/*
 * back to standard sizes
 */
AG_CDEF( clpl[0], clpl[1], clpl[2], clpl[3] );
AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] );

/*
 * back to standard sizes
 */
AG_CDEF( clpl[0], clpl[1], clpl[2], clpl[3] );
AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] );

/*
 * reset if necessary the symbol and text size
 */
if ( ssize != 1.0 || tsize != 1.0 )
   { PCKWRR( "SSIZE", 1, &ssize );
     PCKWRR( "TSIZE", 1, &tsize );
     PCTSET();
   }
return;
}

