// sh01.c
//
// compile with:       cc -o sh01 sh01.c -lgd -lpng -lm
//
// uses the libgd library.  for documentation see the file:
//   /usr/share/doc/gd-*/index.html  
//   or the website:   http://www.libgd.org/reference
//  
// you will need truetype fonts.  if you don't have them, you can
// copy ../fonts/truetype/.. from openoffice.org to /usr/share/
// libgd origin at upper left

#include "gd.h"
#include "math.h"
#include "string.h"
#include <stdio.h>
#include <stdlib.h>

#define  PNGFMT      "sh01.png"

#define  X0          300          // start of deploy

#define  Y0          300      
#define  S0L0        20
#define  S1L0        20
#define  SFX0         0
#define  SX0         10
#define  SD0         20

#define  Y1          580
#define  S0L1        15
#define  S1L1        25
#define  SFX1         5
#define  SX1         10
#define  SD1         30

#define  Y2          860
#define  S0L2        10
#define  S1L2        30
#define  SFX2        10
#define  SX2         10
#define  SD2         40

#define  Y3          1140
#define  S0L3        10
#define  S1L3        30
#define  SFX3        40
#define  SX3         50
#define  SD3        120

#define  SH          100          // height of shell
#define  SHNUM       20
#define  SHTHICK     9
#define  SHEDGE      1

#define  XSIZE       2560         // display window in pixels
#define  YSIZE       1280

#define  PI          3.14159265358979324
#define  D2R         (PI/180.0)
#define  R2D         (180.0/PI)
#define  FNT         "DejaVuMonoSans"

// draw a shell =============================================================

void  tshell( gdImagePtr im, int xl, int yc, int l, int col) {
   // xl  == left side of the shell
   // yc  == center of the shell
   // l   == length of the shell from center
   // col == shell color

   double hh = (double) SH;
   double ll = (double) l;
   double  r = 0.5*( ll + hh*hh/ll ) ;
   double an = R2D*asin( hh / r );
   int    ri = (int) r ;
   int    ex = xl + l + SHTHICK/2 - ri ;

   // printf( "%5d%5d%5d%8d%5d%12.3f\n", xl, yc, l,  ri, ex, an );

   gdImageSetThickness( im, SHTHICK );
   gdImageArc(  im, ex, yc, 2*ri, 2*ri, 360-an, 360+an, col );
   // gdImageSetThickness( im, SHEDGE  );
   // gdImageLine( im, xl, yc+SH-SHTHICK, xl, yc-SH, col );
}

// draw a stack of shells ===================================================

void  tstack( gdImagePtr im, int ycl, int s0l, int s1l, int sfx,
             int sx, int sd, int col0, int col1, int col2, int col3 ) {

   // printf( "\n%8d%8d%8d%12d%8d\n", ycl, s0l, s1l, sx, sd );

   int i ;
   for( i = SHNUM-1 ; i >= 0 ; i-- ) {
      tshell( im, i*sd+X0+sfx+sx, ycl, s1l, col1) ;
      tshell( im, i*sd+X0+sfx   , ycl, s0l, col0) ;
   }

   // base
   for( i = -3 ; i < 0 ; i++ ) {
      tshell( im, i*SHTHICK+X0, ycl, S0L0, col2) ;
   }
   gdImageFilledRectangle( im, X0-30, ycl-SH, X0-10, ycl+SH, col2 );
   gdImageFilledRectangle( im, X0-80, ycl-SH, X0-30, ycl+SH, col3 );
   gdImageFilledRectangle( im, X0-170, ycl-SH, X0-80, ycl+SH, col2 );
   gdImageFilledArc( im, X0-270, ycl, 250, 100, 270, 450, col2, gdArc );
}

// ==========================================================================

int main() {

   FILE     *pngout              ; // file handle for png output frame
   char     labstring[80]        ; // used for labelling
   int      fs                   ; // large font size

   gdImagePtr im = gdImageCreateTrueColor(XSIZE, YSIZE );

   // allocate standard colors
   int black = gdImageColorAllocate(im,   0,   0,   0);
   int white = gdImageColorAllocate(im, 255, 255, 255);
   int sun1  = gdImageColorAllocate(im,  51,  51, 102);
   int red   = gdImageColorAllocate(im, 255,   0,   0);
   int green = gdImageColorAllocate(im,   0, 255,   0);
   int dgreen= gdImageColorAllocate(im,   0, 128,   0);
   int blue  = gdImageColorAllocate(im,   0,   0, 255);
   int gray  = gdImageColorAllocate(im, 128, 128, 128);
   int dgray = gdImageColorAllocate(im,  48,  48,  48);
   int yelo  = gdImageColorAllocate(im, 230, 230, 100);
   int trans = gdImageColorAllocate(im,   1,   1,   1);

   // white background 
   gdImageFilledRectangle( im, 0, 0, XSIZE-1, YSIZE-1, white );
   
   tstack( im, Y0, S0L0, S1L0, SFX0, SX0, SD0, green, blue, gray, yelo ) ;
   tstack( im, Y1, S0L1, S1L1, SFX0, SX1, SD1, green, blue, gray, yelo ) ;
   tstack( im, Y2, S0L2, S1L2, SFX2, SX2, SD2, green, blue, gray, yelo ) ;
   tstack( im, Y3, S0L3, S1L3, SFX3, SX3, SD3, green, blue, gray, yelo ) ;

   fs= 80 ;
   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE-23*fs, 120,                 // x, y
      "Belleville Spring Deployment" ); // text
   
   fs= 64 ;
   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE-19*fs, 320,                 // x, y
      "Two thinsat curvatures,"      ); // text

   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE-19*fs, 440,                 // x, y
      "  compressed together,"       ); // text

   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE-19*fs, 560,                 // x, y
      "   create spring force"       ); // text

   fs= 50 ;
   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE/2-10*fs, 300,               // x, y
      "Solid Stack"                  ); // text

   gdImageStringFT( im, NULL,           // imagespace, bounding box
      black , FNT, fs, 0.0,             // color, font, fontsize, angle
      XSIZE/2-10*fs, 380,               // x, y
      "For Launch"                   ); // text


   // output the frame ------------------------------------------------------

   pngout = fopen( PNGFMT, "wb");
   gdImagePngEx( im, pngout, 1 );
   gdImageDestroy(im);
   fclose(pngout);
}
