/* ------------------------------------------------------------------
 *
 * hf2rad.c
 *
 * copyright 1998 Mark J. Stock
 *
 * v0.0 1998-07-27	initial version
 * v0.1 1998-07-27	added ocean level import and export
 *
 * The object of hftorad is to be a tool for converting heightfield
 * data, in the form of a raw or binary PGM file, to a radiance-
 * readable format.
 *
 * ------------------------------------------------------------------ */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "const.h"

/*
 * All 2D arrays are indexed from top left corner, 1st index
 * is row number, 2nd index is column
 */

/* Important sizes */
int inheight;			/* input height */
int inwidth;			/* input width */

/* The input array, values between -32k and 32k */
unsigned short int in[MAX_SIZE][MAX_SIZE];

void Usage(char [80],int);

main(int argc, char *argv[]) {

   /* initialize variables */
   int i,j;
   double x_min,y_min,xpos,ypos,zpos;
   char progname[80];			/* name of executable */
   char infile[80];			/* name of the input PGM heightfield file */
   char outfile[80];			/* name of the output Radiance files (root) */
   char rfilename[80];			/* name of output file */
   char dfilename[80];			/* name of output file */
   FILE *rfp;				/* .rad file pointer, contains gensurf command */
   FILE *dfp;				/* .dat file pointer, contains raw data */
   double scale = 30.0;			/* scale, meters per pixel in PGM, width and height */
   double vscale = 1.0;			/* scale, meters per increment, pixel intensity, vertical */
   double outheight;			/* output height */
   double outwidth;			/* output width */
   int use_vscale = 0;			/* scale the elevations? 0==no, 1==yes */
   double ocean_level = 0.0;		/* what it says. */
   int use_ocean = 0;			/* shift elevations to ocean level is zero? 0==no, 1==yes */

   /*
    * Parse the command-line options
    */
   (void) strcpy(progname,argv[0]);
   if (argc < 4) (void) Usage(progname,0);
   for (i=1; i<argc; i++) {
      if (strncmp(argv[i], "-help", 2) == 0)
         (void) Usage(progname,0);
      else if (strncmp(argv[i], "-infile", 2) == 0)
         (void) strcpy(infile,argv[++i]); 
      else if (strncmp(argv[i], "-outfile", 3) == 0)
         (void) strcpy(outfile,argv[++i]); 
      else if (strncmp(argv[i], "-scale", 2) == 0)
         scale = atof(argv[++i]);
      else if (strncmp(argv[i], "-vertical", 2) == 0) {
         vscale = atof(argv[++i]);
         use_vscale = 1; }
      else if (strncmp(argv[i], "-ocean", 3) == 0) {
         ocean_level = atof(argv[++i]);
         use_ocean = 1; }
      else
         (void) Usage(progname,0);
   }


   /*
    * Read in heightfield
    */

   (void) read_pgm_ushort(infile,in);


   /*
    * Act on user inputs and info from read
    */

   outheight = (inheight-1)*scale;
   outwidth = (inwidth-1)*scale;
   /* center the stuff around 0,0 */
   y_min = outheight/2.0;
   x_min = -outwidth/2.0;


   /*
    * Write output
    */

   /* Write .dat file */
   sprintf(dfilename,"%s.dat",outfile);
   dfp = fopen(dfilename,"w");
   if (dfp==NULL) {
      fprintf(stderr,"Could not open output data file %s\n",dfilename);
      exit(0);
   }
   for (i=0; i<inheight; i++) {
      ypos = -1.0*i*scale + y_min;
      for (j=0; j<inwidth; j++) {
         /* find elevation of output pixel location */
         xpos = j*scale + x_min;
         zpos = (double) in[i][j];
         if (use_ocean) zpos = zpos - ocean_level;
         if (use_vscale) zpos = zpos*vscale;
         fprintf(dfp,"%lf %lf %lf\n",xpos,ypos,zpos);
      }
   }
   fclose(dfp);

   /* Write .rad file */
   sprintf(rfilename,"%s.rad",outfile);
   rfp = fopen(rfilename,"w");
   if (rfp==NULL) {
      fprintf(stderr,"Could not open output Radiance file %s\n",rfilename);
      exit(0);
   }
   fprintf(rfp,"#Radiance input file for heightfield\n\n");
   fprintf(rfp,"void colorpict image_pat\n13 red green blue groundimage.pic picture.cal pic_u pic_v\n");
   fprintf(rfp,"\t-s %lf -t %lf %lf 0.0\n0\n0\n",outwidth+scale,x_min-scale/2.0,-1*y_min-scale/2.0);
   fprintf(rfp,"\nimage_pat plastic ground_mat\n0\n0\n5  1.0  1.0  1.0  0.0  0.05\n");
   fprintf(rfp,"\n!gensurf ground_mat gm %s %s %s %d %d\n",
            dfilename, dfilename, dfilename, inwidth-1, inheight-1);
   if (use_ocean) {
      fprintf(rfp,"\nocean_mat polygon ocean_surf\n0 0 12\n");
      fprintf(rfp,"%lf %lf 0.0\n",x_min,ypos);
      fprintf(rfp,"%lf %lf 0.0\n",xpos,ypos);
      fprintf(rfp,"%lf %lf 0.0\n",xpos,y_min);
      fprintf(rfp,"%lf %lf 0.0\n",x_min,y_min);
   }
   fclose(rfp);


   /*
    * Write output statistics and quit
    */
   (void) write_finish();
}


void Usage(char progname[80],int status) {

   /* Usage for hf2rad */
   static char **cpp, *help_message[] =
   {
       "where options include:",
       "  -help          writes this help information",
       " ",
       "  -infile name   name of input PGM file, binary or raw",
       "  -out name      root of output text files, name.rad and name.dat",
       "  -ocean val     set ocean level at val, and shift all elevations",
       "                 so ocean level is at 0, occurs before vscale",
       "  -scale val     rescale the horizontal dimension by this multiple",
       "                 essentially, val is the linear length per pixel",
       "  -vscale val    rescale the elevation by this multiple",
       "                 val here is the elevation per unit of intensity",
       " ",
       "Options may be abbreviated to an unambiguous length.",
       NULL
   };

   fprintf(stderr, "usage:\n  %s [-options ...]\n\n", progname);
   for (cpp = help_message; *cpp; cpp++)
      fprintf(stderr, "%s\n", *cpp);
   exit(status);
}
