Attachment 'echr11.c'

Download

   1 // echr11.c
   2 // compile:  gcc -o echr11 echr11.c -lgd -lpng -lm
   3 #define  NAME  "echr11"
   4 
   5 // A NiOH2 WO3 electrochrome
   6 
   7 #define RATE    6  
   8 #define HVEL    12.0             // Ion velocity
   9 #define ITILT   0.15
  10 
  11 #define NPICS   100              // 
  12 #define FNT    "DejaVuMonoSans"
  13 #define FSZ     25               // this scales the font and the whole drawing
  14 #define XSIZE   1024
  15 #define YSIZE   768
  16 #define WIDE    ( 2*FSZ)
  17 #define TALL    (22*FSZ)
  18 #define LTALL   (18*FSZ)
  19 #define XCENT   (20*FSZ)
  20 #define YCENT   (15*FSZ)
  21 #define XCC     (XCENT)
  22 #define XM4     (XCENT-4*WIDE)   // front surface front glass
  23 #define XM3     (XCENT-3*WIDE)   // front of NIOH
  24 #define XM2     (XCENT-2*WIDE)   // back of NIOH
  25 #define XM1     (XCENT-1*WIDE)   // front of WO3
  26 #define XP1     (XCENT+1*WIDE)   // back surface mirror
  27 #define XL1     (XCENT+2*WIDE)   // label box left
  28 #define XL4     (XSIZE-1*WIDE)   // label box right
  29 #define XL2     ((XL1+XL4)/2 -9 )//
  30 #define XL3     ((XL1+XL4)/2 +9 )//
  31 #define YL1     (YCENT- 6*FSZ)   // label box 1 top
  32 #define YL2     (YCENT- 3*FSZ)   // label box 1 bottom
  33 #define YL3     (YCENT+ 3*FSZ)   // label box 2 top
  34 #define YL4     (YCENT+ 6*FSZ)   // label box 2 bottom
  35 #define XCCH    (XCC-HVEL)       // stopping zone for ions
  36 #define XM3H    (XM3+HVEL)       // stopping zone for ions
  37 
  38 #define  ASIZE  2 
  39 
  40 #include <gd.h>
  41 #include <math.h>
  42 #include <string.h>
  43 #include <stdlib.h>
  44 #include <sys/stat.h>
  45 #include <sys/types.h>
  46 
  47 #define PI 3.14159265359
  48 #define DEG2RAD(x) ((x)*PI/180.)
  49 
  50 // ----------------------------------------------------
  51 char     rmmkdir[200] ;
  52 char     pngfmt[ 200] ;
  53 char     png2swf[200] ;
  54 int      rate = RATE          ; // swf frame rate
  55 double   ffrac                ; // frame fraction
  56 int      sign                 ; // sign of battery
  57 int      active               ; // changing state
  58 
  59 gdImagePtr im;
  60 
  61 int      ytop= YCENT - TALL/2 ;
  62 int      yltop=YCENT -LTALL/2 ;
  63 int      ybot= YCENT + TALL/2 ;
  64 int      ylbot=YCENT +LTALL/2 ;
  65 int      deltay = (int)( ((double)ITILT)*((double)XCENT) ) ;
  66 int      brown, dblue, lblue  ;
  67 int      black, white, gray   ;
  68 int      red,   lred          ;
  69 int      green, lgreen, sun1  ;
  70 int      backgr, dgray, trans ;
  71 int      light[256]           ; // Yellow color range
  72 int      light1               ;
  73 double   pi2                  ; //  
  74 double   nioh[1000][1000]     ; // NIOH2 cell state
  75 double   wo3[1000][1000]      ; // WO3 cell state
  76 int      hyd[1000]            ; // hydrogen atom position
  77 
  78 //======================================================================
  79 
  80 //----------------------------------------
  81 void atom_init() {
  82    int  x, y  ;
  83    for( y=ytop ; y<= ybot ; y += ASIZE ) {
  84       for( x = 0 ; x < WIDE ; x += ASIZE ) {
  85          nioh[x][y]=drand48() ;
  86          wo3[x][y] =drand48() ;
  87       }
  88       hyd[y] = XCC ;
  89 }  }
  90 
  91 //----------------------------------------
  92 void frame_init() {
  93    im     = gdImageCreateTrueColor(XSIZE, YSIZE);
  94 
  95    white  = gdImageColorAllocate (im, 255, 255, 255);
  96    black  = gdImageColorAllocate (im,   0,   0,   0);
  97    gray   = gdImageColorAllocate (im, 127, 127, 127);
  98    dgray  = gdImageColorAllocate (im,  64,  64,  64);
  99    red    = gdImageColorAllocate (im, 255,   0,   0);
 100    green  = gdImageColorAllocate (im,   0, 255,   0);
 101    lred   = gdImageColorAllocate (im, 255, 224, 224);
 102    lgreen = gdImageColorAllocate (im, 224, 255, 224);
 103    backgr = gdImageColorAllocate (im,   0,  51, 102);
 104    trans  = gdImageColorAllocate (im,   1,   1,   1);
 105    brown  = gdImageColorAllocate (im,  60,  40,   0);
 106    dblue  = gdImageColorAllocate (im,   0,   0, 100);
 107    lblue  = gdImageColorAllocate (im, 200, 210, 255);
 108 }
 109 
 110 //----------------------------------------
 111 void light_init() {
 112    int i          ;
 113    int rx, gx, bx ;
 114    double di      ;
 115 
 116    for( i=0 ; i < 256 ; i++ ) {
 117       di        = (double) i                             ;
 118       int rx    = (double)(                         di ) ;
 119       int gx    = (double)(  51.0 + (204.0/256.0) * di ) ;
 120       int bx    = (double)( 102.0 - (102.0/256.0) * di ) ;
 121 
 122       // printf( "%3d%4d%4d%4d\n", i, rx, gx, bx );
 123 
 124       light[i] = gdImageColorAllocate( im, rx, gx, bx ) ;
 125    }
 126    sun1   = light[0] ;
 127    light1 = light[255] ;
 128 }  
 129 
 130 //----------------------------------------
 131 void draw_background() {
 132    gdImageFilledRectangle( im, 0, 0, XSIZE-1, YSIZE-1, backgr );
 133 }
 134 
 135 //----------------------------------------
 136 void draw_light() {
 137 
 138    int    light01  = light[ 127 ] ;
 139 
 140    // gamma is funny, so this corrects additive light
 141    int    light02  = light[ ((int)(127.0 * (1.0+0.3*sqrt(ffrac)))) ] ;
 142    int    light03  = light[ ((int)(127.0 *      ffrac ))     ] ;
 143    int    light04  = light[ ((int)(127.0 * (1.0-ffrac)))     ] ;
 144 
 145    gdPoint  alight[8] ;
 146 
 147    // incoming triangle
 148    alight[0].x = 0              ;
 149    alight[0].y = yltop - deltay ;
 150    alight[1].x = 0              ;
 151    alight[1].y = yltop + deltay ;
 152    alight[2].x = XCENT          ;
 153    alight[2].y = yltop          ;
 154    gdImageFilledPolygon( im , alight, 3 , light01 ) ;
 155 
 156    // reflected addition 
 157    alight[0].x = 0              ;
 158    alight[0].y = yltop + deltay ;
 159    alight[1].x = 0              ;
 160    alight[1].y = ylbot - deltay ;
 161    alight[2].x = XCENT          ;
 162    alight[2].y = ylbot          ;
 163    alight[3].x = XCENT          ;
 164    alight[3].y = yltop          ;
 165    gdImageFilledPolygon( im , alight, 4 , light02 ) ;
 166 
 167    // reflected triangle
 168    alight[0].x = 0              ;
 169    alight[0].y = ylbot + deltay ;
 170    alight[1].x = 0              ;
 171    alight[1].y = ylbot - deltay ;
 172    alight[2].x = XCENT          ;
 173    alight[2].y = ylbot          ;
 174    gdImageFilledPolygon( im , alight, 3 , light03 ) ;
 175 }
 176 
 177 //----------------------------------------
 178 void draw_sun() {
 179    gdImageFilledRectangle( im, 0, yltop-deltay, 10, ylbot-deltay , light1 );
 180 }
 181 
 182 //----------------------------------------
 183 void draw_atoms() {
 184    int  x, y ;
 185    double  hvd = -HVEL * (double) sign;
 186    for( y=ytop ; y< ybot ; y += ASIZE ) {
 187       
 188       if( (y/ASIZE)%3 != 0 ) {
 189 	 x = hyd[y] + (int)( hvd * drand48() ) ;
 190 	 if( ( x > XM3 ) && ( x < XCC  ) ) { hyd[y] = x ; }
 191          else                              { x = hyd[y] ; }
 192          if( active == 1 ) {
 193             gdImageFilledRectangle( im,  x, y,  x+ASIZE, y+ASIZE, lblue );
 194          }
 195      }  
 196       for( x = 0 ; x < WIDE ; x += ASIZE ) {
 197          if( (y/ASIZE)%3 == 0 ) {
 198             int xd = XM2 + x;
 199             gdImageFilledRectangle( im, xd, y, xd+ASIZE, y+ASIZE, gray );
 200          } 
 201          if( nioh[x][y] > ffrac ) {
 202             int xn = XM3 + x;
 203 	    gdImageFilledRectangle( im, xn, y, xn+ASIZE, y+ASIZE, brown );
 204          }
 205          if( wo3[x][y]  > ffrac ) {
 206             int xw = XM1 + x;
 207             gdImageFilledRectangle( im, xw, y, xw+ASIZE, y+ASIZE, dblue );
 208 }  }  }  }
 209 
 210 //----------------------------------------
 211 void draw_frame() {
 212  
 213    int ffx, fx1, fx2, ffy, fww, fw2, xcc ;
 214    int yb1, yb2, yb3, yb4, yb5      ;
 215    int xb0, xb1, xb2, xb3, xb4, xb5 ;
 216    int xc0, xc1, xc2, xc3, xc4, xc5 ;
 217    int yc1, yc2           ;
 218 
 219    ffx = (int)      FSZ   ;
 220    fx1 = (int) (0.7*FSZ)  ; 
 221    fx2 = (int) (0.5*FSZ)  ;
 222    ffy = (int) (0.7*FSZ)  ;
 223    fww = (int)    (WIDE)  ; 
 224    fw2 = (int)  (WIDE/2)  ; 
 225 
 226    // battery coordinates
 227 
 228    yb1 = ybot +     ffy   ;
 229    yb2 = ybot + 2 * ffy   ;
 230    yb3 = ybot + 3 * ffy   ;  // center
 231    yb4 = ybot + 4 * ffy   ;
 232    yb5 = ybot + 5 * ffy   ;
 233  
 234    xb0 = XCC  - 7*fw2     ;
 235    xb1 = XM2              ;
 236    xb2 = xb1  +       fx2 ;
 237    xb3 = xb2  +       fx2 ;
 238    xb4 = xb3  +       fx2 ;
 239    xb5 = XCC  + fw2       ;
 240 
 241    xc0 = XCC  - 5*fww     ;  
 242    xc1 = xc0  + ffx       ;
 243    xc2 = xc1  + ffx       ;
 244    xc3 = XCC  + 2*fww     ;
 245    xc4 = xc3  - ffx       ;
 246    xc5 = xc4  - ffx       ;
 247    yc1 = yb3  - ffx       ;
 248    yc2 = yb3  + ffx       ;
 249 
 250    gdImageSetThickness( im, 3 );
 251 
 252    gdImageRectangle( im,       XM3, ytop, XM2, ybot, brown ); // NIOH
 253    gdImageRectangle( im,       XM1, ytop, XCC, ybot, dblue ); // WO3
 254    gdImageRectangle( im,       XM4, ytop, XM3, ybot, white ); //front glass
 255    gdImageFilledRectangle( im, XCC, ytop, XP1, ybot, white ); //back reflector
 256 
 257    // battery
 258  
 259    gdImageLine(      im,     xb0, ybot,       xb0,  yb3, white );
 260    gdImageLine(      im,     xb0,  yb3,       xb1,  yb3, white );
 261    gdImageLine(      im,     xb1,  yb1,       xb1,  yb5, white );
 262    gdImageLine(      im,     xb2,  yb2,       xb2,  yb4, white );
 263    gdImageLine(      im,     xb3,  yb1,       xb3,  yb5, white );
 264    gdImageLine(      im,     xb4,  yb2,       xb4,  yb4, white );
 265    gdImageLine(      im,     xb5,  yb3,       xb4,  yb3, white );
 266    gdImageLine(      im,     xb5, ybot,       xb5,  yb3, white );
 267 
 268    // draw plusminus 
 269 
 270    gdImageSetThickness( im, 7 );
 271 
 272    if(      sign == -1 ) {
 273       gdImageLine(   im,     xc0, yb3,        xc2,  yb3, red   );
 274       gdImageLine(   im,     xc1, yc1,        xc1,  yc2, red   );
 275       gdImageLine(   im,     xc3, yb3,        xc5,  yb3, green );
 276    }
 277    else if( sign ==  1 ) {
 278       gdImageLine(   im,     xc0, yb3,        xc2,  yb3, green );
 279       gdImageLine(   im,     xc4, yc1,        xc4,  yc2, red   );
 280       gdImageLine(   im,     xc3, yb3,        xc5,  yb3, red   );
 281    }
 282 }
 283 
 284 // draw arrow  -------------------------------------------------------------
 285 
 286 void arrow( int x0, int y0, int x1, int y1, int color ) {
 287    gdPoint ap[3] ;
 288    double asize = (double) FSZ ;
 289    double ang   = atan2( y0-y1 , x0-x1 );
 290 
 291    ap[0].x = x0;
 292    ap[0].y = y0;
 293    ap[1].x = x0+(int)( asize*(     -cos(ang) - 0.5*sin(ang) ));
 294    ap[1].y = y0+(int)( asize*(  0.5*cos(ang) -     sin(ang) ));
 295    ap[2].x = x0+(int)( asize*(     -cos(ang) + 0.5*sin(ang) ));
 296    ap[2].y = y0+(int)( asize*( -0.5*cos(ang) -     sin(ang) ));
 297 
 298    gdImageLine( im, x0, y0, x1, y1, color ) ;
 299    gdImageFilledPolygon( im, ap, 3, color ) ;
 300 }
 301 
 302 //----------------------------------------
 303 void draw_labels() {
 304 
 305    // boxes with material labels
 306    gdImageFilledRectangle(im, XL1, YL1, XL2, YL2, brown ) ;// NIOH Label
 307    gdImageFilledRectangle(im, XL3, YL1, XL4, YL2, dblue ) ;// WO3  Label
 308    gdImageSetThickness(im, 5 );
 309    gdImageRectangle(im, XL1, YL3, XL2, YL4, brown ) ;// NIOH Label
 310    gdImageRectangle(im, XL3, YL3, XL4, YL4, dblue ) ;// WO3  Label
 311    gdImageStringFT( im, NULL,  white, FNT, FSZ, 0.0,
 312                     XL1, YL4-FSZ, " Ni(OH)₂     WO₃ " ) ;
 313    gdImageStringFT( im, NULL,  white, FNT, FSZ, 0.0,
 314                     XL1, YL2-FSZ, "  NIOOH     H+WO₃" ) ;
 315 
 316    int xl1 = (XL1+XL2)/2 ;
 317    int xl2 = (XL3+XL4)/2 ;
 318    int yl1 = YL2 + 20 ;
 319    int yl2 = YL3 - 20 ;
 320    int xh  = (XL2+XL3)/2 - 2*FSZ ;
 321    int yh  = (YL2+YL3)/2 - 4 ;
 322 
 323    int lpr1 = (int)(201.0-200.0*ffrac) ;
 324    int lpr2 = (int)(  1.0+250.0*ffrac) ;
 325 
 326    gdImageStringFT( im, NULL, light[lpr1], FNT, FSZ, 0.0,
 327             XL1-FSZ, YL1-3*FSZ, "4.6μPa Light Pressure" );
 328    gdImageStringFT( im, NULL, light[lpr2], FNT, FSZ, 0.0,
 329             XL1-FSZ, YL4+4*FSZ, "7.8μPa Light Pressure" );
 330 
 331    if(      sign == -1 ) {
 332       if( active == 1 ) {
 333          arrow( xl1, yl1, xl1, yl2,  white );
 334          arrow( xl2, yl1, xl2, yl2,  white );
 335          arrow( xl2-15, yl1, xl1+15, yl2,  lblue );
 336          gdImageStringFT( im, NULL, lblue, FNT, 1.5*FSZ, 0.0, xh, yh, "H+" );
 337       }
 338       gdImageStringFT( im, NULL, red  , FNT, FSZ, 0.0,
 339                        XL1, YL1-9 , "  Anode " );
 340       gdImageStringFT( im, NULL, green, FNT, FSZ, 0.0,
 341                        XL3, YL1-9 , " Cathode" );
 342    }
 343    else if( sign ==  1 ) {
 344       if( active == 1 ) {
 345          arrow( xl1, yl2, xl1, yl1,  white );
 346          arrow( xl2, yl2, xl2, yl1,  white );
 347          arrow( xl1+15, yl2, xl2-15, yl1,  lblue );
 348          gdImageStringFT( im, NULL, lblue, FNT, 1.5*FSZ, 0.0, xh, yh, "H+" );
 349       }
 350       gdImageStringFT( im, NULL, green, FNT, FSZ, 0.0,
 351                        XL1, YL4+FSZ+9 , " Cathode" );
 352       gdImageStringFT( im, NULL, red  , FNT, FSZ, 0.0,
 353                        XL3, YL4+FSZ+9 , "  Anode " );
 354    }
 355 
 356    // title
 357    gdImageStringFT( im, NULL,  white, FNT, 1.5*FSZ, 0.0,       // TITLE
 358                         (int)(2.0*FSZ), (int)(2.0*FSZ),
 359                        " Electrochromic Light Shutter" );
 360 }
 361       
 362 //=====================================================================
 363 
 364 int main () {
 365    FILE   *pngout              ;
 366    char   comment[80]          ;
 367    char   dirname[80]          ;
 368    char   framename[80]        ;
 369    int    frame                ; // frame count
 370    int    npics                ; // last frame count
 371    int    i                    ; 
 372    pi2    = 8.0*atan(1.0)      ; // pi
 373    npics  = (double)NPICS      ;
 374 
 375    sprintf( rmmkdir, "rm -rf %sdir ; mkdir %sdir", NAME, NAME );
 376 
 377    system( rmmkdir )           ; // make directory
 378    atom_init()                 ; // set up atom points
 379  
 380    for( frame = 0 ; frame <= npics ; frame++ ) {
 381 
 382       // sinusoidal fraction variation
 383       double frang = pi2*((double)frame)/((double)npics );
 384       double offs  = acos(5.0/6.0) ;
 385    
 386       ffrac = 0.6*(0.8333-cos( frang ) );
 387       if(           ffrac < 0.0 )   { ffrac=0.0 ; active=0 ; }
 388       else if(      ffrac > 1.0 )   { ffrac=1.0 ; active=0 ; }
 389       else                          {             active=1 ; }
 390 
 391       if( sin( frang-offs ) > 0.0 ) { sign =  1 ; }
 392       else                          { sign = -1 ; }
 393 
 394       printf( "%04d/%04d\r", frame, npics );   fflush( stdout );
 395 
 396       frame_init()             ; // set up colors
 397       light_init()             ;
 398 
 399       draw_background()        ; // draw sunw background
 400       draw_light()             ; // draw light
 401       draw_sun()               ; // draw sun
 402       draw_atoms()             ; // draw atoms
 403       draw_frame()             ; // draw frame and battery
 404       draw_labels()            ; // draw title and reaction labels
 405 
 406       sprintf( framename, "%sdir/a%04d.png", NAME , frame );
 407       pngout = fopen ( framename , "wb");
 408       gdImagePngEx( im, pngout, 1 );
 409       gdImageDestroy (im);
 410       fclose (pngout);
 411    } // end of frame loop
 412 
 413    sprintf( png2swf, "png2swf -o %s.swf -r%3d %sdir/*.png", NAME, rate, NAME );
 414    system(  png2swf );
 415 }  

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2013-05-06 18:32:09, 13.7 KB) [[attachment:echr11.c]]
  • [get | view] (2013-05-06 18:32:32, 3394.2 KB) [[attachment:echr11.swf]]
 All files | Selected Files: delete move to page

You are not allowed to attach a file to this page.