/* ***********************************************************************
 * *                                                                     *
 * *  Function to convert a PBM, PGM or PPM (ASCII or Raw) file to       *
 * *   an IRIS USER product                                              *
 * *                                                                     *
 * ***********************************************************************
 * File: utils/pipes_in/PBMSatToIris.C
 *
 *                      COPYRIGHT (c) 2002, 2003  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */

/* This program is a pipe which takes aPBM, PGM or PPM (ASCII or Raw) file
 * and converts it into an IRIS USER product containing that data.
 *
 * NOTE: Make sure in the setup utility under Input, that PBMSatToIris
 * Command line syntax is set to Pathnames.
 *
 *
 * Note if you are modifying this program, and wish to insert a diagnostic
 * printf, be sure to write it to the error output.
 */

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

#include "sigtypes.h"
#include "projection.h"
#include "headers.h"
#include "product.h"

#include "dsp_lib.h"
#include "fileformats_lib.h"
#include "himath_lib.h"
#include "misc_lib.h"
#include "user_lib.h"


struct command_line
{
  char  sInFile[FILENAME_SIZE];
  char  sInPath[PATHNAME_SIZE];
  char  sOutPath[PATHNAME_SIZE];
};

/* This holds information to customize the convertor */
struct projection_summary8
{
  FLT8  fRMax;                  /* Range from center to right side of screen */
  BIN4  iRadarLat;              /* Latitude of the radar */
  BIN4  iRadarLon;              /* Longitude */
  BIN4  iCenterLat;             /* Latitude of center of product */
  BIN4  iCenterLon;             /* Longitude */
  BIN4  iReferenceLat;          /* Latitude of reference point */
  BIN4  iReferenceLon;          /* Longitude */
  SINT4 iXSize, iYSize;         /* Sizes in pixels */
  SINT4 iXScale, iYScale;       /* Scales in cm/pixel */
  SINT4 iXRadPos, iYRadPos;     /* Radar positions in 1/1000 of pixels */
  UINT1 iType;                  /* Type of projection */
  UINT1 lRotate180;             /* Rotate image by 180 degrees */
  char  ipad_end[6];
};

struct convert_config
{
  UINT1  lLogToFile;
  UINT1  lLogToTerm;
  UINT1  lVerbose;              /* Log more details */
  FILE   *iLogFile;             /* Open file descriptor to log file */
  char   sIngSitename[16];      /* Ingest sitename to use, space padded */
  struct projection_summary8 Projection;
};
struct convert_config CSetup_c;

/* Local function prototypes
 */
static void  ProcessCommandLine (int iArgc, char *sArgv[], 
  struct command_line *pCommand_a ); 
static void  Usage( void );
static void  LoadSetup(struct convert_config *pCSetup_a );
static UINT2 ProcessConfigLine(char *sline_a,struct convert_config *pCSetup_a );
static void ConvertPBMToIris(struct command_line *cmd_a, struct projection_summary8 *pProjSum_a);
static void RotateImage180
( PICINFO *pPinfo_a );
static void  Lprintf(const char *sString_a);
static void FillProjectionNumbers(struct projection_summary8 *pProj_a );

#define MAX_LINELENGTH (120)
/* ===============================================================
 * Main program starts here.
 */
int main(int iArgc, char *sArgv[])
{
  struct command_line cmd;

  setlocale( LC_ALL, "" ) ;

  /* Process the command line arguments */
  ProcessCommandLine( iArgc, sArgv, &cmd );

  /* Process the setup file,if any.  */
  LoadSetup(&CSetup_c);

  /* Open the logging file, if any */
  if (CSetup_c.lLogToFile)
    {
      char *sptr;
      char sLogPath[PATHNAME_SIZE];
      sptr = getenv( "IRIS_LOG" );
      if (sptr)
	{
	  strncpy( sLogPath, sptr, PATHNAME_SIZE-20 );
	  sLogPath[PATHNAME_SIZE-20] = 0;
	}
      else
	strcpy( sLogPath, "/tmp/" );
      strcat( sLogPath, "PBMSatToIris.log" );
      CSetup_c.iLogFile = fopen( sLogPath, "w" );
      if (NULL == CSetup_c.iLogFile)
	{
	  fprintf( stderr, "Can not open log file: '%s'\n", sLogPath );
	  exit(EXIT_FAILURE);
	}
    }

  /* Starting here we can use the Lprintf function */
  if (CSetup_c.lVerbose)
     Lprintf( "Verbose Logging On.\n");

  /* Now check for missing data in the command line */
  if (cmd.sInPath[0]==0)
  {
    Lprintf("ERROR: missing -ip command line option\n" );
    exit(EXIT_FAILURE);
  }
  if (cmd.sOutPath[0]==0)
  {
    Lprintf("ERROR: missing -op command line option\n" );
    exit(EXIT_FAILURE);
  }
    
  /* Read in the header */
  ConvertPBMToIris(&cmd, &CSetup_c.Projection);
}
static void ConvertPBMToIris(struct command_line *cmd_a, struct projection_summary8 *pProjSum_a)
{
  FILE   *fp;
  char   *sptr;
  char   sname[16];
  struct full_time_spec Time;
  struct product_hdr prod_hdr;
  PICINFO pinfo;

  if (FILE_FORMAT_TYPE_PBM == GetPictureType(cmd_a->sInPath))
    ReadPBM(cmd_a->sInPath, &pinfo);
  else
  {
    Lprintf("ERROR: Unknown picture type\n" );
    exit(EXIT_FAILURE);
  }

  if (CSetup_c.lVerbose)
    {
      char sString[FILENAME_SIZE+50];
      sprintf( sString, "Processing file: %s\n", cmd_a->sInFile );
      Lprintf( sString );
    }

  /*********************************
  ** Fill in the Projection Numbers 
  **********************************/
  pProjSum_a->iXSize = pinfo.w;
  pProjSum_a->iYSize = pinfo.h;
  FillProjectionNumbers(pProjSum_a);

  /*********************************
  ** Setup the product header 
  **********************************/
  strncpy(sname, cmd_a->sInFile, 16);

  sname[15] = '\0';
  if ((sptr = strrchr(sname, '.')) != NULL) *sptr = '\0';

  STR_UPPER(sname, 16);
  GetTimeFull( &Time, TIME_FLG_GMT );
  HeaderFromScratch( &prod_hdr, &Time, CSetup_c.sIngSitename,
                     CSetup_c.sIngSitename, sname );

  prod_hdr.pcf.iptype    = PROD_USER;
  prod_hdr.pcf.ixscale   = pProjSum_a->iXScale;
  prod_hdr.pcf.iyscale   = pProjSum_a->iYScale;
  prod_hdr.pcf.izscale   = 0;
  prod_hdr.pcf.ixsize    = pProjSum_a->iXSize;
  prod_hdr.pcf.iysize    = pProjSum_a->iYSize;
  prod_hdr.pcf.izsize    = 1;
  prod_hdr.pcf.ixrad     = pProjSum_a->iXRadPos;
  prod_hdr.pcf.iyrad     = pProjSum_a->iYRadPos;
  prod_hdr.pcf.izrad     = 0;

  prod_hdr.pcf.idata_out = DB_USER;
  prod_hdr.pcf.idata_in  = DB_USER;
  
  prod_hdr.pcf.iprojection_type = pProjSum_a->iType;
  prod_hdr.pcf.colors.iflags = (COLOR_SCALE_TOP_SAT | COLOR_SCALE_BOT_SAT);
  prod_hdr.pcf.colors.istart = 160;
  prod_hdr.pcf.colors.istep  = 160;
  prod_hdr.pcf.colors.icolcnt = 16;
  prod_hdr.pcf.colors.iset_and_scale = 0x0104;


  prod_hdr.end.ilat_center = pProjSum_a->iCenterLat;
  prod_hdr.end.ilon_center = pProjSum_a->iCenterLon;

  prod_hdr.end.ilat_ref = pProjSum_a->iReferenceLat;
  prod_hdr.end.ilon_ref = pProjSum_a->iReferenceLon;

  prod_hdr.hdr.ibytes = PRODUCT_HDR_SIZE + 
     (prod_hdr.pcf.ixsize*prod_hdr.pcf.iysize);

  /* Rotate the image */
  if (pProjSum_a->lRotate180) RotateImage180( &pinfo );

  fp = fopen(cmd_a->sOutPath, "w");
  if (fp)
    {
      int iy;
      fwrite( &prod_hdr, sizeof(struct product_hdr), 1, fp );
      // Need to flip the Y axis
      for (iy = (prod_hdr.pcf.iysize - 1); iy >= 0; iy--)
	fwrite(&pinfo.pic[iy * prod_hdr.pcf.ixsize], prod_hdr.pcf.ixsize, 1, fp );
      fclose(fp);
    }
  else
    {
      Lprintf("ERROR: Can't open output file\n");
      exit(EXIT_FAILURE);
    }
  
  if (CSetup_c.lVerbose)
    {
      char   sLog[200];
      sprintf( sLog, "Wrote %d bytes\n", prod_hdr.hdr.ibytes);
      Lprintf( sLog);
    }
}

#if 0
/* ======================================================================
 * Function to rotate the image
 */
static void RotateImage
( PICINFO *pPinfo_a,
  FLT8     fRotateAngle_a )
{
  SINT4 iSize, iXNew, iYNew, iXOld, iYOld;
  UINT1 *pNewImage;
  FLT8 fXCenter, fYCenter;
  /* Skip rotation if zero */
  if (fRotateAngle_a==0.0) return;

  iSize = pPinfo_a->w * pPinfo_a->h;

  pNewImage = (UINT1*)malloc( iSize );
  if (!pNewImage) return;

  /* Initialize to area not scanned */
  memset( pNewImage, DV_NOSCAN1, iSize );

  fXCenter = (((FLT8)pPinfo_a->w)-1.0)/2.0;
  fYCenter = (((FLT8)pPinfo_a->h)-1.0)/2.0;
  /* Loop through all the pixels */
  for (iXNew=0; iXNew<pPinfo_a->w; iXNew++)
    {
      FLT8 fXNew;
      fXNew = ((FLT8)iXNew) - fXCenter;
      for (iYNew=0; iYNew<pPinfo_a->h; iYNew++)
	{
	  FLT8 fYNew, fRange, fAngle, fYOld, fXOld;
	  /* Convert location to polar from the center */
	  /* Note that integer values are defined to be the centers of the pixels */
	  fYNew = ((FLT8)iYNew) - fYCenter;

	  fRange = sqrt( fXNew*fXNew + fYNew*fYNew );
	  if ((fXNew==0.0) && (fYNew==0.0) )
	    fAngle = 0.0;
	  else
	    fAngle = atan2( fXNew, fYNew );

	  /* Rotate the angle */
	  fAngle += fRotateAngle_a;

	  /* Convert polar to location */
	  fXOld = fRange * sin( fAngle );
	  fYOld = fRange * cos( fAngle );
	  iXOld = NINT( fXOld + fXCenter );
	  iYOld = NINT( fYOld + fYCenter );

	  /* Conditionally copy the pixel */
	  if ((iXOld>=0)&&(iXOld<pPinfo_a->w)&&(iYOld>=0)&&(iYOld<pPinfo_a->h))
	    {
	      pNewImage[iXNew + (iYNew*pPinfo_a->w)] =
		pPinfo_a->pic[iXOld + (iYOld*pPinfo_a->w)];
	    }
	}
    }
  /* Copy image into input */
  memcpy( pPinfo_a->pic, pNewImage, iSize );

  free(pNewImage);
}
#endif

/* ======================================================================
 * Function to rotate the image by 180 degrees.
 */
static void RotateImage180
( PICINFO *pPinfo_a )
{
  SINT4 iSize, iXNew, iYNew, iXOld, iYOld;
  UINT1 *pNewImage;

  iSize = pPinfo_a->w * pPinfo_a->h;

  pNewImage = (UINT1*)malloc( iSize );
  if (!pNewImage) return;

  /* Loop through all the pixels */
  for (iXNew=0; iXNew<pPinfo_a->w; iXNew++)
    {
      iXOld = pPinfo_a->w - iXNew;
      for (iYNew=0; iYNew<pPinfo_a->h; iYNew++)
	{
	  iYOld = pPinfo_a->h - iYNew;
	  pNewImage[iXNew + (iYNew*pPinfo_a->w)] = pPinfo_a->pic[iXOld + (iYOld*pPinfo_a->w)];
	}
    }
  /* Copy image into input */
  memcpy( pPinfo_a->pic, pNewImage, iSize );

  free(pNewImage);
}

/* ======================================================================
 * Function to process the command line arguments.
 */
static void ProcessCommandLine
(int iArgc_a, char *sArgv_a[],  struct command_line *pCommand_a )
{
  int iArg;
  memset( pCommand_a, 0, sizeof(*pCommand_a) );

  /* Parse command line options
  */
  for( iArg=1 ; iArg<iArgc_a ; iArg++ )
    {
      const char *sArg = sArgv_a[iArg];
      /* fprintf( stderr, "Processing %d: '%s'\n", iArg, sArg ); */

      if (0 == strncmp( sArg, "-h", 2 ))
        {
          Usage();
        }
      else if (0 == strncmp( sArg, "-if:", 4 ))
        {
          strncpy( pCommand_a->sInFile, &sArg[4], FILENAME_SIZE-1 );
        }
      else if (0 == strncmp( sArg, "-ip:", 4 ))
        {
          strncpy( pCommand_a->sInPath, &sArg[4], PATHNAME_SIZE-1 );
        }
      else if (0 == strncmp( sArg, "-op:", 4 ))
        {
          strncpy( pCommand_a->sOutPath, &sArg[4], PATHNAME_SIZE-1 );
        }
    }
}
/* ==================================================
 */
static void Usage( void )
{
  fprintf( stderr, "Options: -help\n" );
  fprintf( stderr, "         (all other arguments ignored)\n" );
  exit(EXIT_FAILURE) ;
}

/* ============================================================
 * Function to load the convert setup from a configuration file.
 */
static void LoadSetup( struct convert_config *pCSetup_a )
{
  char sPath[PATHNAME_SIZE];
  char sline[81], *sptr;
  FILE* stream;
  SINT4 iline;
  UINT2 lerror;

  /* Initialize the data to the default values */
  memset( pCSetup_a, 0, sizeof(*pCSetup_a) );
  spacify_ncpy( pCSetup_a->sIngSitename, "UNKNOWN", 16 );
  /* Default location is 0 0 latlon, AED, max range=100 km */
  pCSetup_a->Projection.fRMax = 100.0;
  pCSetup_a->Projection.iType = MAPROJ_AZIMUTHAL;
  
  /* Generate the file name and open the file */
  sptr = getenv( "IRIS_CONFIG" );
  if (NULL == sptr) 
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_CONFIG" );
      exit(EXIT_FAILURE);
    }

  strncpy( sPath, sptr, 140 );
  strcat( sPath, "PBMSatToIris.conf" );
  stream = fopen( sPath, "r" );

  /* Don't worry about a missing config file */
  if (NULL == stream) return;

  /* now loop through the file reading and parsing lines */
  iline = 1;
  sptr = fgets( sline, 81, stream );
  while (NULL != sptr)
    {
      lerror = ProcessConfigLine( sptr, pCSetup_a );
      if (lerror) fprintf( stderr, "Syntax error on config file line %d\n", iline );
      iline +=1;
      sptr = fgets( sline, 81, stream );
    }

  fclose( stream );
  return;
}

/* ===============================================================
 * Process one line from the configuration file.  Returns nonzero if there
 * is a syntax error.
 *
 * The config can contain the following commands.  All blank lines and
 * lines beginning with "#" are ignored.  Commands can be in any order.
 * Commands take effect in the order received.  For example, syntax errors
 * before the LOG command will not be logged.
 *
 * LOG           <FILE TERM BOTH NONE>
 * SITENAME      <name>
 * VERBOSE
 *
 */
static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a )
{
  char *stokens[9], *sptr;
  UINT4 icount, ioffset;
  
  ioffset = 0;
  icount  = 0;
  /* Process up to 9 tokens, stop when the line is exhausted. */
  while (icount<9) 
    {
      stokens[icount] = sigtok( sline_a, &ioffset );
      if (NULL == stokens[icount])
	break;
      else
	icount++;
    }
  
  /* Blank lines are allowed and skipped */
  if (icount == 0) return FALSE;
  
  /* Skip commented lines */
  if (stokens[0][0] == '#') return FALSE;


  /* See if the line contains the CENTER_LATLON command */
  if ( 0 == strcmp( "CENTER_LATLON", stokens[0] ) )
    {
      FLT8 fLatitude, fLongitude;
      if ( icount < 3 ) return TRUE;
      
      fLatitude = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLongitude = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatitude  <  -90.0 ) return TRUE;
      if (fLatitude  >   90.0 ) return TRUE;
      if (fLongitude < -180.0 ) return TRUE;
      if (fLongitude >  180.0 ) return TRUE;

      pConfig_a->Projection.iCenterLat = iBin4FromFDeg(fLatitude);
      pConfig_a->Projection.iCenterLon = iBin4FromFDeg(fLongitude);
      return FALSE;
    }

  /* See if the line contains the LOG file command */
  if ( 0 == strcmp( "LOG", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if      ( 0 == strcmp( "BOTH", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "FILE", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=FALSE;}
      else if ( 0 == strcmp( "TERM", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "NONE", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=FALSE;}
      else
	return TRUE;
      return FALSE;
    }

  /* See if the line contains the MAX_RANGE command */
  if ( 0 == strcmp( "MAX_RANGE", stokens[0] ) )
    {
      FLT8 fRMax;
      if ( icount < 2 ) return TRUE;
      
      fRMax = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      if (fRMax <     1.0 ) return TRUE;
      if (fRMax > 10000.0 ) return TRUE;

      pConfig_a->Projection.fRMax = fRMax;
      return FALSE;
    }

  /* See if the line contains the PROJECTION file command */
  if ( 0 == strcmp( "PROJECTION", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;

      pConfig_a->Projection.iType = iProjectionFromName16( stokens[1] );
      if (pConfig_a->Projection.iType >= MAPROJ_COUNT ) return TRUE;
      return FALSE;      
    }

  /* See if the line contains the RADAR_LATLON command */
  if ( 0 == strcmp( "RADAR_LATLON", stokens[0] ) )
    {
      FLT8 fLatitude, fLongitude;
      if ( icount < 3 ) return TRUE;
      
      fLatitude = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLongitude = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatitude  <  -90.0 ) return TRUE;
      if (fLatitude  >   90.0 ) return TRUE;
      if (fLongitude < -180.0 ) return TRUE;
      if (fLongitude >  180.0 ) return TRUE;

      pConfig_a->Projection.iRadarLat = iBin4FromFDeg(fLatitude);
      pConfig_a->Projection.iRadarLon = iBin4FromFDeg(fLongitude);
      return FALSE;
    }

  /* See if the line contains the ROTATE command */
  if ( 0 == strcmp( "ROTATE180", stokens[0] ) )
    {
      pConfig_a->Projection.lRotate180 = TRUE;
      return FALSE;
    }

  /* See if the line contains the SITENAME command */
  if ( 0 == strcmp( "SITENAME", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      spacify_ncpy( pConfig_a->sIngSitename, stokens[1], 16 );
      return FALSE;
    }
  
  
  if ( 0 == strcmp( "VERBOSE", stokens[0] ) )
    {
      pConfig_a->lVerbose = TRUE;
      return FALSE;
    }

  /* Unrecognized lines will generate a syntax error */
  return TRUE;
}

/* ===========================================
 * Print string to log and terminal, if desired.
 */
static void Lprintf
( const char *sString_a )
{
  if (CSetup_c.lLogToTerm) fputs( sString_a, stderr );
  if (CSetup_c.lLogToFile)
    {
      fputs( sString_a, CSetup_c.iLogFile );
      fflush( CSetup_c.iLogFile );
    }
}


/* ===============================================
 * Fill in the radar position in pixels*1000, etc., from other information
 * in the setup file.
 */
static void FillProjectionNumbers
( struct projection_summary8 *pProj_a )
{ 
  MESSAGE istatus;
  struct mpj_projection8 mpj;
  struct mpj_region8     region;
  FLT8  fypix_org; 

  /* As a default, set reference to center */
  pProj_a->iReferenceLat = pProj_a->iCenterLat;
  pProj_a->iReferenceLon = pProj_a->iCenterLon;

  /* Initialize outputs in case of an error return
   */
  pProj_a->iXRadPos = 0;
  pProj_a->iYRadPos = 0;
  pProj_a->iXScale = 100000;
  pProj_a->iYScale = 100000;

  mpj.iprojection_type = pProj_a->iType;
  mpj.Ref.fLat         = fRadianFromBin4( pProj_a->iReferenceLat );
  mpj.Ref.fLon         = fRadianFromBin4( pProj_a->iReferenceLon );

  region.Loc1.fLat = fRadianFromBin4( pProj_a->iCenterLat );
  region.Loc1.fLon = fRadianFromBin4( pProj_a->iCenterLon );
  region.fde  = pProj_a->fRMax;
  region.fdn  = pProj_a->fRMax;
  region.fxpix = (FLT8)pProj_a->iXSize;
  fypix_org = (FLT8)pProj_a->iYSize;
  istatus = mpj_pin_region( &mpj, &region, MPJ_LOC1|MPJ_FDE|MPJ_FDN );
  if (istatus != SS_NORMAL)
    {
      sig_signal( istatus );
      return;
    }

  /* Now rescale to product the correct Y-size. It may be correct already
  ** for some AED projections
  */
  if ((fabs(region.fypix - fypix_org)) > .5)
  {
    FLT8 fratio;
    fratio = fypix_org/region.fxpix;
    istatus = mpj_rescale_region(&mpj, &region, MPJ_LOC1|MPJ_FDE, fratio);
    if (istatus != SS_NORMAL)
    {
      sig_signal( istatus );
      return;
    }
   
  }
  

  /* Fill in the final X & Y sizes and scales
   */
  pProj_a->iXSize  = NINT( region.fxpix );
  pProj_a->iYSize  = NINT( region.fypix );
  pProj_a->iXScale = NINT( 200000.0*region.fde/region.fxpix);
  pProj_a->iYScale = NINT( 200000.0*region.fdn/region.fypix);
  
  /* Fill in the radar location in fractional pixels within the
   * data array.  If pointer is NULL, then use the center.
   */
  {
    struct latlon8 RadarEarth;
    struct XYPoint8 Pix; UINT1 lValid;
    RadarEarth.fLat = fRadianFromBin4( pProj_a->iRadarLat ) ;
    RadarEarth.fLon = fRadianFromBin4( pProj_a->iRadarLon ) ;
    
    mpj_earth_to_pixel( &mpj, &region, &RadarEarth, &Pix, &lValid ) ;
    
    pProj_a->iXRadPos = NINT( 1000.0 * Pix.fX ) ;
    pProj_a->iYRadPos = NINT( 1000.0 * Pix.fY ) ;
  }
  return;
}
