/*===========================================================================
  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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   GETPROJ
.AUTHOR      R.M. van Hees IPG-ESO Garching
.KEYWORDS    perspective plots
.LANGUAGE    C
.PURPOSE     project three dimensional data to two dimensions
     input:    float *wcfram     : frame values of resp. X, Y and Z axis 
                                       (amin, amax, abig & asmall)
               float *angle      : projection angles:
                                       altitude =  0: edge-on 
                                                = 90: face-on
                                       azimuth  =  0: x-axis horizontaly
                                                = 90: y-axis horizontaly
                                       (rotation counter clockwise)
               float scales[2]   : scale: scaling factor of the z component,
                                       offset: offset of the plot in units of 
                                       the third axis
               int   nval        : number of datapoints
               struct Odata *data: 3-D data (x,y,z) in world coord.
    output:    struct Pdata *proj: projected data (x,y) in viewport coord.
                                       (see AGL manual)

.COMMENTS    none

.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.3     26-Mar-1994   removed initatialisation, RvH
             1.2     30-Nov-1993   2-D & 3-D data is passed with structs, RvH
             1.1     10-Sep-1993   Creation  R.M. van Hees

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

/*
 * declaration of the used functions
 */
#include <stdio.h>
#include <math.h>

#include <midas_def.h>

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

#define ANG_EPS		1e-3

/*
 * here start the code of the function
 */
void GETPROJ( wcfram, angle, scales, nval, data, proj )
int    nval;
float  *wcfram, *angle, *scales;
struct Odata  *data;
struct Pdata  *proj;

{              
register int   ii;

int     tproj;
float   wndl[4];
double  alt, azi, dx, dy, dz, xmin, ymin, zmin, xrange, yrange, zrange,
        scale_X, scale_Y, proj_x, proj_y, proj_z, x_off, y_off;
               
/*
 * constants
 */
double halfpi  = 0.5 * PI,
       twopi   = 2.0 * PI,
       deg2rad = PI / 180.0;

/*
 * initialize the length and minimum value of the axes
 */
xmin   = *(wcfram + FOR_X);
xrange = *(wcfram + FOR_X + 1) - *(wcfram + FOR_X);
ymin   = *(wcfram + FOR_Y);
yrange = *(wcfram + FOR_Y + 1) - *(wcfram + FOR_Y);
zmin   = *(wcfram + FOR_Z);
zrange = *(wcfram + FOR_Z + 1) - *(wcfram + FOR_Z);

/*
 * initialize the projection angles, 
 *   and get rid of those special angles which may cause difficulties
 */
if ( fabs( angle[0] ) < ANG_EPS ) 
   alt = deg2rad * ( angle[0] + ANG_EPS );
else
   alt = deg2rad * angle[0];

if ( fmod( angle[1], 45.0 ) < ANG_EPS ) 
   azi = - deg2rad * ( angle[1] + ANG_EPS ) + halfpi;
else
   azi = -deg2rad * angle[1] + halfpi;
azi -= twopi * floor( azi / twopi );
if ( azi < 0.0 ) azi += twopi;

if ( azi < halfpi )
   tproj = 1;
else if ( azi < PI )
   tproj = 2;
else if ( azi < PI + halfpi )
   tproj = 3;
else
   tproj = 4;
/*
 * set the projection values
 */
proj_x = sin( alt ) * sin( azi );
proj_y = sin( alt ) * cos( azi );
proj_z = cos( alt );

/*
 * get device dimensions in "AGL-window" coordinates
 */
(void) AG_RGET( "wndl", wndl );

/*
 * determine the scale of the plot in X and Y
 */ 
scale_X = 0.8 * (wndl[1] - wndl[0]) / ( fabs(proj_x) + fabs(proj_y) );
scale_Y = 0.9 * (wndl[3] - wndl[2]) / ( fabs(proj_y) + fabs(proj_x) + proj_z );

/*
 * determine offset (in X and Y direction) and scale (Y direction) of the plot
 */
proj_z *= *scales;
x_off = wndl[0] + 0.00 * (wndl[1] - wndl[0]);
y_off = wndl[2] + 0.05 * (wndl[3] - wndl[2]);

/*
 * do the projection
 */
switch ( tproj )
   { case 1:
         for ( ii = 0; ii < nval; ii++ )
             { dx = ( data->xx - xmin )/ xrange;
               dy = ( data->yy - ymin )/ yrange;
               dz = ( data++->zz + scales[1] - zmin )/ zrange;
               proj->px   = x_off + scale_X * (   dx  * proj_x + 
                                               (1-dy) * proj_y );
               proj++->py = y_off + scale_Y * (   dy  * proj_x +
                                                  dx  * proj_y +
                                                  dz  * proj_z  );
             }
         break;
     case 2:
         for ( ii = 0; ii < nval; ii++ )
             { dx = ( data->xx - xmin )/ xrange;
               dy = ( data->yy - ymin )/ yrange;
               dz = ( data++->zz + scales[1] - zmin )/ zrange;
               proj->px   = x_off + scale_X * (   dx  * proj_x - 
                                                  dy  * proj_y );
               proj++->py = y_off + scale_Y * ((dx-1) * proj_y +
                                                  dy  * proj_x +
                                                  dz  * proj_z  );
             }
         break;
     case 3:
         for ( ii = 0; ii < nval; ii++ )
             { dx = ( data->xx - xmin )/ xrange;
               dy = ( data->yy - ymin )/ yrange;
               dz = ( data++->zz + scales[1] - zmin )/ zrange;
               proj->px   = x_off + scale_X * ((dx-1) * proj_x - 
                                                  dy  * proj_y );
               proj++->py = y_off + scale_Y * ((dy-1) * proj_x +
                                               (dx-1) * proj_y +
                                                  dz  * proj_z  );
             }
         break;
     case 4:
         for ( ii = 0; ii < nval; ii++ )
             { dx = ( data->xx - xmin )/ xrange;
               dy = ( data->yy - ymin )/ yrange;
               dz = ( data++->zz + scales[1] - zmin )/ zrange;
               proj->px   = x_off + scale_X * ((dx-1) * proj_x + 
                                               (1-dy) * proj_y );
               proj++->py = y_off + scale_Y * (   dx  * proj_y +
                                               (dy-1) * proj_x +
                                                  dz  * proj_z  );
             }
         break;
   }
}

