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

static char rcsid[] =
  "$Id: ppmweather.c,v 1.5 2002/08/23 08:35:08 root Exp $";

/*
 * $Log: ppmweather.c,v $
 * Revision 1.5  2002/08/23 08:35:08  root
 * #
 *
 * Revision 1.4  2002/08/23 08:35:04  root
 * #
 *
 * Revision 1.3  2002/08/21 16:04:15  root
 * #
 *
 * Revision 1.2  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
 * #
 *
 */

/*  ppmmolw.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"


typedef struct
{
  double lon;
  double scale;
  double x;
  double y;
}
Molw;

double
get_theta (Molw * m, double lat)
{
  double theta, dtheta;

  int tries = 0;

  lat *= M_PI / 180.0;

  theta = lat;

  lat = M_PI * sin (lat);

  do
    {
      if ((tries++) > 100)
        break;
      dtheta =
        ((2 * theta) + sin (2 * theta) - lat) / (2 + 2 * cos (2 * theta));
      theta -= dtheta;

    }
  while (fabs (dtheta) > EPSLN);

  return theta;
}


int
molw (Molw * m, double theta, double lat, double lon, double *x, double *y)
{

  lat *= M_PI / 180.0;

  lon -= m->lon;

  while (lon < -180.0)
    lon += 180.0;
  while (lon > 180.0)
    lon -= 180.0;

  lon *= M_PI / 180.0;
  *x = (m->x) +
    ((m->scale) * (lon - (m->lon)) * cos (theta) * (2.0 * M_SQRT2 / M_PI));

  *y = (m->y) - ((m->scale) * M_SQRT2 * sin (theta));

}

init_molw (Molw * m)
{
  int y = 174;
  int lx = 8;
  int rx = 629;


  m->x = 0.5 * (double) (lx + rx);
  m->y = (double) y;

  m->scale = (double) (rx - lx);
  m->scale = m->scale / (4 * M_SQRT2);
  m->lon = 0;

}


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

  pixel **ipixels, **opixels;
  pixval maxval, amaxval, r, g, b, lr, lg, lb;

  Molw m;
  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;
    }

  if (argn != argc)
    {
      ifp = pm_openr (argv[argn]);
      ++argn;
    }
  else
    ifp = stdin;

  if (argn != argc)
    pm_usage (usage);


  init_molw (&m);

  ipixels = ppm_readppm (ifp, &w, &h, &maxval);
  pm_close (ifp);

  opixels = ppm_allocarray (OWIDTH, OHEIGHT);
  maxval = 255;

  for (y = 0; y < OHEIGHT; ++y)
    {
      double lat =
        90.0 * ((double) ((OHEIGHT / 2) - y)) / ((double) (OHEIGHT / 2));
      double theta = get_theta (&m, lat);

      for (x = 0; x < OWIDTH; ++x)
        {
          double lon =
            180.0 * ((double) (x - (OWIDTH / 2))) / ((double) (OWIDTH / 2));
          double mx, my;
          int ix, iy;

          molw (&m, theta, lat, lon, &mx, &my);



          ix = (int) (mx + .5);
          iy = (int) (my + .5);
          if (ix < 0)
            ix = 0;
          if (iy < 0)
            iy = 0;
          if (ix >= w)
            ix = w - 1;
          if (iy >= h)
            iy = h - 1;

          r = PPM_GETR (ipixels[iy][ix]);
          g = PPM_GETG (ipixels[iy][ix]);
          b = PPM_GETB (ipixels[iy][ix]);

          if ((r != g) || (g != b))
            {
              r = lr;
              g = lg;
              b = lb;
            }
          else
            {
              lr = r;
              lg = g;
              lb = b;
            }


          if ((r == 255) || (r < 2))
            r = g = b = 114;
// if ((lat>80.0) || (lat<-80.0)) r=g=b=255;


          PPM_ASSIGN (opixels[y][x], r, g, b);

        }
    }


  ppm_writeppm (stdout, opixels, OWIDTH, OHEIGHT, maxval, 0);
  pm_close (stdout);
  exit (0);
}
