/*
 * ppmice.c:
 *
 * Copyright (c) 2002 James McKenzie <james@fishsoup.dhs.org>,
 * All rights reserved.
 *
 */

static char rcsid[] = "$Id: toview.c,v 1.10 2002/08/24 13:45:45 root Exp $";

/*
 * $Log: toview.c,v $
 * Revision 1.10  2002/08/24 13:45:45  root
 * #
 *
 * Revision 1.9  2002/08/24 13:38:11  root
 * #
 *
 * Revision 1.8  2002/08/23 18:51:25  root
 * #
 *
 * Revision 1.7  2002/08/23 17:03:58  root
 * #
 *
 * Revision 1.6  2002/08/23 13:42:28  root
 * #
 *
 * Revision 1.5  2002/08/23 08:35:04  root
 * #
 *
 * Revision 1.4  2002/08/21 23:02:37  root
 * #
 *
 * Revision 1.3  2002/08/21 21:22:44  root
 * #
 *
 * Revision 1.2  2002/08/21 16:04:15  root
 * #
 *
 * Revision 1.1  2002/08/21 16:04:07  root
 * #
 *
 * Revision 1.1  2002/08/21 12:07:29  root
 * #
 *
 * Revision 1.2  2002/08/21 09:40:55  root
 * #
 *
 */

/*  ppmpc.c

    Project Earth image in Mollweide projection to rectangular
    Mercator bitmap.

    Based on the projection code from the GCTPc package, developed
    by the EROS Data Center.  GCTPc is available from the following
    FTP sites:

	ftp://edcftp.cr.usgs.gov/pub/software/gctpc/gctpc.tar.Z
	ftp://charon.er.usgs.gov/pub/S.gctpc.tar.Z

*/

#include <math.h>
#include "ppm.h"

#define EPSLN	1.0e-10

#include "size.h"

#define PSIZE 1024
#define PWIDTH (PSIZE)
#define PHEIGHT (PSIZE)


#define Sin sin
#define Cos cos
#define ArcCos acos
#define Sqrt sqrt
#define mp (m->p)
#define mp2 (m->p2)
#define mcphi (m->cphi)
#define msphi (m->sphi)

typedef struct
{
  double p;
  double p2;
  double r;
  double s;
  double x;
  double y;
  double lat;
  double lon;
  double op;
}
Gvp;
typedef struct
{
  double lambda;
  double cphi, sphi;
}
Grt;
int
gvp (Gvp * m, double x, double y, double *lat, double *lon)
{
  double rho, rho2, rho4;
  double l1, l2, r1, r2;
  double q, s;

  x -= m->x;
  y -= m->y;
  x = x * m->s;
  q = y * m->s;

  y = x;
  x = -q;

  *lon = -atan2 (y, x);

  rho2 = (y * y) + (x * x);
  rho = sqrt (rho2);
  rho4 = rho2 * rho2;
  s = (rho2 - 2. * mp * rho2 + mp2 * rho2 + rho4 - mp2 * rho4);

  if (s < 0)
    return 0;
  l1 =
    ArcCos ((-(mp * rho) + mp2 * rho - Sqrt (s)) /
            (1. - 2. * mp + mp2 + rho2));


  r1 = ((-1. + mp) * Cos (l1)) / (mp - Sin (l1));
  *lat = l1;
  if (r1 < 0)
    return 0;
  return 1;

}

grt (Grt * m, double lat, double lon, double *ao, double *oo)
{
  double a, b;
  a = mcphi * Cos (lat) * Cos (lon) - msphi * Sin (lat);
  b = Cos (lat) * Sin (lon);


  *ao = atan2 (msphi * Cos (lat) * Cos (lon) +
               mcphi * Sin (lat), Sqrt ((a * a) + (b * b))) * (180.0 / M_PI);


  *oo = (atan2 (Cos (lat) * Sin (lon),
                mcphi * Cos (lat) * Cos (lon) -
                msphi * Sin (lat))) * (180.0 / M_PI);

  (*oo) += m->lambda;
  while ((*oo) > 180.0)
    (*oo) -= 360.0;
  while ((*oo) < -180.0)
    (*oo) += 360.0;

}

init_gvp (Gvp * m, double p)
{
  double lat, rho;

  m->p = p;

  m->r = (PSIZE / 2);
  m->x = (PSIZE / 2);
  m->y = (PSIZE / 2);


  lat = asin (1.0 / p);
  rho = (p - 1.0) * cos (lat) / (p - sin (lat));


  m->r *= 0.9 / rho;

  m->s = 1.0 / m->r;
  m->p2 = (m->p) * (m->p);

  m->op = 1.0 / m->p;
}



init_grt (Grt * m, double phi, double lambda)
{

  m->cphi = cos ((90 - phi) * (M_PI / 180.0));
  m->sphi = sin ((90 - phi) * (M_PI / 180.0));
  m->lambda = lambda + 180.0;

}


int
main (argc, argv)
     int argc;
     char *argv[];
{
  FILE *ifp, *afp = NULL;

  pixel **ipixels, **opixels;
  pixval maxval;

  Gvp m;
  Grt g;
  int x, y;
  int w, h;

  int argn;
  char *usage =
    "[-dim <num>] [-red <num>] [-green <num>] [-blue <num>] [pbmfile]";


  ppm_init (&argc, argv);

  argn = 1;

  while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
    {
      pm_usage (usage);
      ++argn;
    }

  init_gvp (&m, atof (argv[4]));

  ifp = pm_openr (argv[1]);
  ipixels = ppm_readppm (ifp, &w, &h, &maxval);
  pm_close (ifp);

  init_grt (&g, atof (argv[2]), atof (argv[3]));

  opixels = ppm_allocarray (PWIDTH, PHEIGHT);
  maxval = 255;



  for (y = 0; y < PHEIGHT; ++y)
    {
      for (x = 0; x < PWIDTH; ++x)
        {
#if 0
          double lat =
            90.0 * ((double) ((OHEIGHT / 2) - y)) / ((double) (OHEIGHT / 2));
          double lon =
            180.0 * ((double) (x - (OWIDTH / 2))) / ((double) (OWIDTH / 2));
#endif
          double lat, lon, a, b;
          int ix, iy;
          if (gvp (&m, (double) x, (double) y, &a, &b))
            {


              //fprintf(stderr,"%.3f %.3f %.3f %.3f\n",(double) x,(double) y,lat,lon);

              grt (&g, a, b, &lat, &lon);

              lat = (90.0 - lat) / 180.0;
              iy = (int) ((lat * (double) OHEIGHT) + .5);
              lon = (lon + 180.0) / 360.0;
              ix = (int) ((lon * (double) OWIDTH) + .5);

              if (ix < 0)
                ix = 0;
              if (iy < 0)
                iy = 0;
              if (ix >= w)
                ix = w - 1;
              if (iy >= h)
                iy = h - 1;

              // fprintf(stderr,"  %d %d\n",ix,iy);
              opixels[y][x] = ipixels[iy][ix];

            }
          else
            {
              PPM_ASSIGN (opixels[y][x], 0, 0, 0);
            }
        }
    }


  ppm_writeppm (stdout, opixels, PWIDTH, PHEIGHT, maxval, 0);
  pm_close (stdout);
  exit (0);
}
