Attachment 'gs11.c'

Download

   1 // gs11.c
   2 // gcc -o gs11 gs11.c -lgd -lpng -lm
   3 #define  NAME   "gs11"
   4 
   5 #define  V      10         // tesselation size ,  1002 elements
   6 
   7 // NM sets the array sizes - a smarter person would use a malloc()
   8 #define  NM          580   // max tesselation size, 3,600,002 elements
   9 #define  XSIZE       480   // Y screen size (0=left, 1023=right)
  10 #define  YSIZE       540   // Y screen size (0=top,  599=bottom)
  11 #define  Y0CENT       30   // Y center of small top image
  12 #define  Y1CENT      100   // Y center of small front image
  13 #define  YTCENT      240   // Y center of time text
  14 #define  X0CENT      300   // X center top images
  15 #define  X1CENT      400   // X center top images
  16 #define  YBCENT      350   // Y center of big bottom image
  17 #define  XBCENT      240   // X center of big bottom image
  18 #define  SIZE          6   // size of spot
  19 #define  SPACE       160   // scaling of big drawing
  20 
  21 // note - these are applied to the display, not the stored
  22 // geodesic sphere display, which is always scaled to unity
  23 
  24 #define  XEXP        1.2   // expand array in x (orbital) direction
  25 #define  YEXP        1.0   // expand array in y (NS)      direction
  26 #define  ZEXP        0.2   // expand array in z (radial)  direction
  27 
  28 // turn the array just a bit, so objects in back are visible past those
  29 // in front
  30 #define  XZROTATE   0.01
  31 
  32 #define  ASKEW       2.0   // apogee skew 
  33 
  34 #define  NPICS       240   // number of images in animation
  35 #define  RATE         10   // images per second
  36 #define  ESIZE        80   // diameter of earth disk
  37 #define  ORBSIZE      80   // radius of orbit
  38 #define  ZFACTR      0.2   // scaling for items in back
  39 #define  ASCALE       12   // earth orbiting arrow scale
  40 #define  OSCALE    0.125   // earth orbiting scale
  41 #define  CMID      155.0   // midrange color in daylight
  42 #define  CSCALE    100.0   // color scaling to distance
  43 #define  CDIM       0.25   // dimming factor for eclipse
  44 
  45 #define  FNT        "DejaVuMonoSans"
  46 #define  FSZ          20
  47 
  48 #define  SPEEDUP     (14400.0*RATE/NPICS)
  49 
  50 // --------------------------------------------------------------
  51 // How toroidal orbits work.
  52 //
  53 // An elliptical orbit is faster than a similar circular orbit at
  54 // perigee, and slower at apogee.   If the delta between circular
  55 // and elliptical is ZEXP ( == e R ) then an array element halfway
  56 // between perigee and apogee in an elliptical orbit is displaced
  57 // 2 * ZEXP ahead of its circular neighbor.  We need enough ZEXP
  58 // to keep perigee and apogee objects from colliding, and also to
  59 // provide a reasonably large surface facing forwards or backwards
  60 // in orbit at the 6AM and 6PM positions of the orbit.
  61 // 
  62 // We need enough YEXP (North/South) size to make a reasonable 
  63 // large disk for radio and solar capture.   We need enough XEXP
  64 // to make radio disk, and capture the sun at the noon position.
  65 //
  66 // You can fiddle with the relative values of XEXP, YEXP, and ZEXP
  67 // to see how it shapes the array.  We probably want something a
  68 // little flattened in ZEXP to reduce relative skew. 
  69 //
  70 // This program will arbitrarily draw "right hand" toroidal orbits;
  71 // If your thumb is the orbital direction, the orbits will turn
  72 // in the direction of your fingers.  Viewing from just outside the
  73 // orbit, looking at the center of the earth, the orbit will evolve
  74 // like so:
  75 
  76 //  angle   Z (radius)             Y(NS)      X orbit
  77 //    0°    -ZEXP inside,perigee   0          0
  78 //   90°    0                      YEXP top   +2*ZEXP skew forward
  79 //  180°    +ZEXP outside,apogee   0          0
  80 //  270°    0                      YEXP bot   -2*ZEXP skew backward
  81 
  82 // --------------------------------------------------------------
  83 // How to draw a geodesic sphere - tesselated icosahedron
  84 //
  85 // make a big array of normalized array points
  86 // for a geodesic sphere radius 1 
  87 //   class 1 icosahedral base
  88 //   V up to whole bunches, possibly millions of points
  89 //   number of vertexes is 10*V^2 + 2
  90 //     
  91 //  12 vertices
  92 //  20 faces
  93 //  30 edges
  94 // 
  95 //  Procedure:
  96 //  (1) define the 12 vertices 
  97 //  (3) define the 30 edges in terms of 2 vertices each (by index)
  98 //  (2) define the 20 faces in terms of 3 vertices each (by index)
  99 //
 100 //  see http://en.wikipedia.org/wiki/Icosahedron
 101 //
 102 //            -1       +1
 103 //  axes:   x left  to  right
 104 //          y down  to  up
 105 //          z back  to  front
 106 //
 107 //  φ = (1 + √5) / 2 is the golden ratio
 108 //               x   y   z
 109 //  0, 1, 2, 3  (±1, ±φ, 0)  
 110 //  4, 5, 6, 7  (0, ±1, ±φ)   
 111 //  8, 9,10,11  (±φ, 0, ±1) 
 112 //
 113 //  The radius is sqrt( 1 + φ^2 )
 114 //  we will normalize that to one, later, and rotate so that 
 115 //  there are vertices top and bottom
 116 
 117 #include  <gd.h>
 118 #include  <math.h>
 119 #include  <stdio.h>
 120 #include  <stdlib.h>
 121 
 122 typedef struct { int a, b, c;    } Index3 ;
 123 typedef struct { int a, b;       } Index2 ;
 124 typedef struct { double x,y,z;   } Point  ;
 125 
 126 #define  SZ     ( 10*(NM+2)*NM )  // max array size (divis by 4)
 127 
 128 Point    vertex[SZ] ;             // array to vertices of max array
 129 double     xdis[SZ], ydis[SZ], zdis[SZ], wdis[SZ] ;
 130 int         col[SZ] ;
 131 Index3   colrgb[SZ] ;
 132 
 133 #define  RMMKDIR    "rm -rf %sdir ; mkdir %sdir"
 134 #define  PNGFMT     "%sdir/a%05d.png"
 135 #define  PNG2SWF    "png2swf -o %s.swf -r %d %sdir/*.png" 
 136 
 137 // --------------------------------------------------------------------
 138 // this array is used to generate the icosahedron main vertices
 139 // 2 is φ ,  1 is 1, 0 is 0
 140 
 141 // point 0 is at the left, and 2, 4, 6, 8, and 10 are clockwise around it
 142 // point 1 is at the right, and 3, 5, 7, 9, and 11 are clockwise around it
 143 // 0 is opposite 1, 2 is opposite 3, 4 is opposite 5, etc.
 144 
 145 static Index3 vertABC[12] = {
 146                { 2, 1, 0},   //  0 left point after rotation
 147                {-2,-1, 0},   //  1 right point after rotation
 148                { 2,-1, 0},   //  2
 149                {-2, 1, 0},   //  3
 150                { 1, 0, 2},   //  4
 151                {-1, 0,-2},   //  5
 152                { 0, 2, 1},   //  6
 153                { 0,-2,-1},   //  7
 154 	       { 0, 2,-1},   //  8
 155                { 0,-2, 1},   //  9
 156                { 1, 0,-2},   // 10
 157                {-1, 0, 2},   // 11
 158 };
 159 
 160 // --------------------------------------------------------------------
 161 // this array is used to generate the 30 edges, between the numbered 
 162 // vertices in vertABC
 163 
 164 static Index2 edge[30] = {
 165                {  0,  2 },
 166                {  0,  4 },
 167                {  0,  6 },
 168                {  0,  8 },
 169                {  0, 10 },
 170                {  1,  3 },
 171                {  1,  5 },
 172                {  1,  7 },
 173                {  1,  9 },
 174                {  1, 11 },
 175                {  2,  4 },
 176                {  2,  7 },
 177                {  2,  9 },
 178                {  2, 10 },
 179                {  3,  5 },
 180                {  3,  6 },
 181                {  3,  8 },
 182                {  3, 11 },
 183                {  4,  6 },
 184                {  4,  9 },
 185                {  4, 11 },
 186                {  5,  7 },
 187                {  5,  8 },
 188                {  5, 10 },
 189                {  6,  8 },
 190                {  6, 11 },
 191                {  7,  9 },
 192                {  7, 10 },
 193                {  8, 10 },
 194 	       {  9, 11 },
 195 };
 196 
 197 // --------------------------------------------------------------------
 198 // this array is used to generate the 20 faces, between the numbered
 199 // vertices in vertABC
 200 
 201 static Index3 face[20] = {
 202                {  0,  2,  4 },
 203                {  0,  4,  6 },
 204                {  0,  6,  8 },
 205                {  0,  8, 10 },
 206                {  0, 10,  2 },
 207                {  1,  3,  5 },
 208                {  1,  5,  7 },
 209                {  1,  7,  9 },
 210                {  1,  9, 11 },
 211                {  1, 11,  3 },
 212                {  2,  7, 10 },
 213                {  5,  7, 10 },
 214                {  5,  8, 10 },
 215                {  5,  8,  3 },
 216                {  6,  8,  3 },
 217                {  6, 11,  3 },
 218 	       {  6, 11,  4 },
 219                {  9, 11,  4 },
 220                {  9,  2,  4 },
 221                {  9,  2,  7 },
 222 };
 223 
 224 // --------------------------------------------------------------------
 225 
 226 double  psi   ; 
 227 double  znorm ;
 228 
 229 int     sun1, white, red, green, blue     ; //  color indexes 
 230 int     dred, gray, trans, lgray, cyan    ;
 231 int     dgray, yellow, magenta, black     ; 
 232 int     dcyan                             ;
 233 
 234 double  xsize   = (double)   XSIZE        ; // screen width
 235 double  ysize   = (double)   YSIZE        ; // screen width
 236 double  xcenter = (double) ( XSIZE / 2 )  ; // half screen width
 237 int     ex      = (int) (1.5*ORBSIZE)     ; // drawn earth center x
 238 int     ey      = (int) (1.3*ORBSIZE)     ; // drawn earth center y
 239 int     re      = ESIZE / 2               ; // drawn earth radius 
 240 int     nvert                             ; // vertices in geosphere
 241 
 242 double     pi2  = 6.2831853070795864      ;
 243 gdImagePtr im                             ; // Declare the image
 244 FILE       *pngout                        ; // Declare output file
 245 
 246 // =============================================================
 247 
 248 int  normalize( Point *a ) {
 249    double len = sqrt( a->x*a->x + a->y*a->y + a->z*a->z );
 250    if( len == 0.0 ) {
 251       fprintf(stderr, "Normalize error%12.3f%12.3f%12.3f\n", a->x, a->y,a->z );
 252       return 1 ;
 253    }
 254    a->x /= len ;
 255    a->y /= len ;
 256    a->z /= len ;
 257    // printf( "N %12.3f%12.3f%12.3f%12.3f\n",a->x, a->y, a->z, len );
 258    return  0  ;
 259 } 
 260 
 261 // -------------------------------------------------------------
 262 
 263 double   val( int type ) {
 264    switch( type ) {
 265       case -2 :  return -psi ;
 266       case -1 :  return -1.0 ;
 267       case  0 :  return  0.0 ;
 268       case  1 :  return  1.0 ;
 269       case  2 :  return  psi ;
 270    }
 271    return 0.0 ;
 272 }
 273 
 274 // -------------------------------------------------------------
 275 
 276 void colorstart() {
 277    int    cp, cq,  ix, of ;
 278    white   =gdImageColorAllocate( im, 255, 255, 255);
 279    black   =gdImageColorAllocate( im,   0,   0,   0);
 280    gray    =gdImageColorAllocate( im, 128, 128, 128);
 281    dgray   =gdImageColorAllocate( im,  96,  96,  96);
 282    lgray   =gdImageColorAllocate( im, 192, 192, 192);
 283    cyan    =gdImageColorAllocate( im,   0, 192, 192);
 284    dcyan   =gdImageColorAllocate( im,   0,  48,  48);
 285    red     =gdImageColorAllocate( im, 255,   0,   0);
 286    dred    =gdImageColorAllocate( im, 128,   0,   0);
 287    yellow  =gdImageColorAllocate( im, 255, 255,   0);
 288    green   =gdImageColorAllocate( im,   0, 255,   0);
 289    blue    =gdImageColorAllocate( im,   0,   0, 255);
 290    magenta =gdImageColorAllocate( im, 192,   0, 192);
 291    trans   =gdImageColorAllocate( im,   1,   1,   1);
 292 
 293    for( ix = 0 ; ix < nvert ; ix++ ) {
 294      int ir = colrgb[ix].a ;
 295      int ig = colrgb[ix].b ;
 296      int ib = colrgb[ix].c ;
 297      col[ix]       = gdImageColorAllocate( im, ir   , ig   , ib   );
 298      col[ix+nvert] = gdImageColorAllocate( im, ir/4 , ig/4 , ib/4 );
 299    }
 300 }
 301 
 302 // draw arrowhead (either degrees or radians ) -----------------------------
 303 
 304 void arrowhead( double xp, double yp, double asize,
 305                 double deg, double rad, int color ) {
 306    double angl = rad+pi2*deg/360.0 ;
 307    gdPoint arrow[3] ;
 308 
 309    arrow[0].x = (int)(xp);
 310    arrow[0].y = (int)(yp);
 311    arrow[1].x = (int)(xp+asize*(    -cos(angl)-0.5*sin(angl)));
 312    arrow[1].y = (int)(yp+asize*( 0.5*cos(angl)-    sin(angl)));
 313    arrow[2].x = (int)(xp+asize*(    -cos(angl)+0.5*sin(angl)));
 314    arrow[2].y = (int)(yp+asize*(-0.5*cos(angl)-    sin(angl)));
 315    gdImageFilledPolygon( im, arrow, 3, color );
 316 }
 317 
 318 // draw arrow  -------------------------------------------------------------
 319 
 320 void arrow( double x0, double y0, double x1, double y1, int color ) {
 321    double  asize = 0.02*(x1-x0) ;
 322 
 323    gdImageLine( im, (int)x0, (int)y0, (int)x1, (int)y1, color ) ;
 324    arrowhead( x1, y1, ASCALE, 0.0, 0.0, color ) ;
 325 }
 326 
 327 // draw rotating earth and orbiting body and side arrow  -------------
 328 
 329 void earth( double ang ) {
 330    double  x,  y  ;
 331    double  xs, ys ;
 332    int  x0, y0 ;
 333 	   int  x1, y1 ;
 334    double  an0 ;
 335    int ie    ;
 336    int orbit = 2*ORBSIZE ;
 337 
 338    gdImageFilledArc(im, ex, ey, ESIZE, ESIZE,   0, 360, dcyan, gdArc);
 339    gdImageFilledArc(im, ex, ey, ESIZE, ESIZE,  90, 270,  cyan, gdArc);
 340    gdImageArc(      im, ex, ey, orbit, orbit,  30, 330, white );
 341    gdImageArc(      im, ex, ey, orbit, orbit, 330,  30, dgray );
 342 
 343    // draw longitude lines  ( 6 = 180/30 degrees )
 344    for( ie = 0 ; ie < 6 ; ie ++ ) {
 345       an0 = (ang/6.0) + pi2*( (double)ie) / 12.0 ;
 346       x0  = ex - (int)( ((double)re) * cos(an0) );
 347       x1  = ex + (int)( ((double)re) * cos(an0) );
 348       y0  = ey + (int)( ((double)re) * sin(an0) );
 349       y1  = ey - (int)( ((double)re) * sin(an0) );
 350       gdImageLine( im, x0, y0, x1, y1, black );
 351    }
 352 
 353    // draw latitude lines
 354    for( ie = 1 ; ie < 3 ; ie++ ) {
 355       an0 = pi2*( (double) ie ) / 12.0 ;
 356       x0  = (int)( 2.0 * ((double)re) * cos(an0) );
 357       gdImageArc( im, ex, ey, x0, x0, 0, 360, black );
 358    }
 359    
 360    // draw arrowhead to show side point of view
 361    x= -( ORBSIZE + ASCALE ) ;
 362    y=  0.0 ;
 363    xs = x*cos(ang)+y*sin(ang) + (double) ex ;
 364    ys = y*cos(ang)-x*sin(ang) + (double) ey ;
 365  
 366    arrowhead( xs, ys, ASCALE,  0.0, -ang, white );
 367 }
 368 
 369 // =============================================================
 370 
 371 int main() {
 372    double  angle ;
 373    int     frame ;
 374    char    pngfilename[64];
 375    char    command[128];
 376 
 377    double  test   ;   // depth testing
 378    int     ox, oy ;
 379    int     s0     ;
 380 
 381    double  xu, yu ;
 382    int     xi, yi ;
 383    int     icol   ;
 384    double  deg    ; 
 385 
 386    int     i      ;
 387    double  dv = (double) V ;
 388    
 389    psi   = 0.5 * ( 1.0 + sqrt(5.0) ) ;
 390    znorm = sqrt( psi*psi + 1.0 ) ;
 391 
 392    sprintf( command, RMMKDIR, NAME, NAME );
 393    system( command );
 394 
 395    // COMPUTE THE ICOSAHEDRON -------------------------------------------
 396    // we will generate the icosahedron, then interpolate the edge points
 397    // and face points between them.   These will then be normalized to
 398    // radius 1
 399 
 400    // compute 12 vertices ------------------------- 
 401 
 402    for( nvert = 0 ; nvert < 12 ; nvert++ ) {
 403       double xtemp = val( vertABC[nvert].a );
 404       double ytemp = val( vertABC[nvert].b );
 405       double ztemp = val( vertABC[nvert].c );
 406       
 407       // rotate so x value of 0th vertex is max
 408       double xr = psi*xtemp + ytemp ;
 409       double yr = psi*ytemp - xtemp ;
 410       double zr = znorm*ztemp       ;
 411       double sxz = XZROTATE         ;
 412       double cxz = sqrt( 1.0-sxz*sxz );
 413 
 414       // rotate x to z (radial) directions, y (NS) remains same
 415       vertex[nvert].x = cxz * xr - sxz * zr ;
 416       vertex[nvert].y = yr                  ;
 417       vertex[nvert].z = cxz * zr + sxz * xr ;
 418    }
 419    // nvert is now 12
 420 
 421    // compute 30 edges ---------------------------
 422    //  using two points on the icosahedron, in the edge table
 423 
 424    for( i = 0 ; i < 30 ; i++ ) {
 425       Point va = vertex[ edge[i].a ] ;   // find icosahedron points
 426       Point vb = vertex[ edge[i].b ] ;   // find icosahedron points
 427       double da ;
 428 
 429       for( da = 1.0 ; da < dv ; da++ ) {
 430          double db = dv-da ;
 431          vertex[ nvert ].x = da*va.x + db*vb.x ;
 432          vertex[ nvert ].y = da*va.y + db*vb.y ;
 433          vertex[ nvert ].z = da*va.z + db*vb.z ;
 434          nvert++ ;   // add more vertices
 435    }  }
 436 
 437    // number of new edge points = 30*(V-1)
 438    // nvert is now 30*V - 18
 439 
 440    // compute 20 faces ---------------------------
 441    //  using three points on the icosahedron, in the face table
 442 
 443    for( i = 0 ; i < 20 ; i++ ) {
 444       Point va = vertex[ face[i].a ] ;   // find icosahedron points
 445       Point vb = vertex[ face[i].b ] ;   // find icosahedron points
 446       Point vc = vertex[ face[i].c ] ;   // find icosahedron points
 447       double da, db ;
 448 
 449       for( da = 1.0 ; da < dv ; da++ ) {
 450          for( db = 1.0 ; db < ( dv-da) ; db++ ) {
 451             double dc = dv-(da+db);
 452             vertex[ nvert ].x = da*va.x + db*vb.x + dc*vc.x ;
 453             vertex[ nvert ].y = da*va.y + db*vb.y + dc*vc.y ;
 454             vertex[ nvert ].z = da*va.z + db*vb.z + dc*vc.z ;
 455             nvert++ ;   // add more vertices
 456    }  }  }
 457 
 458    // number of new face points = 10*V^2 - 30*V + 20
 459    // nvert is now 10*V^2 + 2
 460 
 461    // color -----------------------------------------------
 462    // first we normalize each vertex point to radius 1.  Then
 463    // we will choose vertex color based on position in the base array
 464 
 465    for( i = 0 ; i < nvert ; i++ ) {
 466       normalize( &vertex[i] );
 467       colrgb[i].a = (int) ( CMID + CSCALE*vertex[i].x ) ;
 468       colrgb[i].b = (int) ( CMID + CSCALE*vertex[i].y ) ;
 469       colrgb[i].c = (int) ( CMID + CSCALE*vertex[i].z ) ;
 470    }
 471 
 472    // ICOSAHEDRON COMPUTED --------------------------------------------
 473    // graphics loop ---------------------------------------------------
 474 
 475    for( frame = 1 ; frame <= NPICS ; frame++ ) {
 476       im = gdImageCreateTrueColor(XSIZE, YSIZE );
 477       sprintf( command,  PNGFMT, NAME, frame );
 478       pngout = fopen( command, "wb");
 479 
 480       angle = (frame+0.001) * pi2 / ((double) NPICS ) ;
 481       colorstart() ;
 482       earth(angle) ;
 483 
 484       //  labels -----------------------------------------------------------
 485 
 486       gdImageStringFT( im, NULL,                       // imagespace, bounding
 487                        white, FNT, FSZ,                // color, font, fontsize
 488                        0.0, X1CENT, Y0CENT+FSZ/2,      // angle, x, y
 489                        "Top" );                        // the text
 490 
 491       gdImageStringFT( im, NULL,                       // imagespace, bounding
 492                        white, FNT, FSZ,                // color, font, fontsize
 493                     0.0, X1CENT-3*FSZ/2, Y1CENT+FSZ/2, // angle, x, y
 494                        "Front" );                      // the text
 495 
 496       gdImageStringFT( im, NULL,                       // imagespace, bounding
 497                        white, FNT, 2*FSZ,              // color, font, fontsize
 498                      0.0, X1CENT-3*FSZ, YSIZE-FSZ,     // angle, x, y
 499                        "Side" );                       // the text
 500 
 501       //  time code -------------------------------------------------------
 502  
 503       double time0 = ( 4.0 * (double) frame ) / ( (double) NPICS ) ;
 504       char   timestring[64] ;
 505 
 506       int hour = (int) time0 ;
 507       int min  = (int) ( 0.1 +  60.0*( time0 - (double) hour));
 508 
 509       sprintf( timestring, " %1dh%3dm", hour, min );
 510 
 511       gdImageStringFT( im, NULL,                       // imagespace, bounding 
 512                        white, FNT, FSZ,                // color, font, fontsize
 513                        0.0, 0, YTCENT,                 // angle, x, y
 514                        timestring );                   // y, the text 
 515 
 516 
 517       //  direction arrows ------------------------------------------------
 518           // large side view, small top view, small side view
 519 
 520      gdImageSetThickness( im, 3 );
 521 
 522       arrow( 0, YBCENT, 2*XBCENT, YBCENT, gray ); // large side view
 523       arrow( X0CENT-80, Y0CENT, X0CENT+80, Y0CENT, gray ); // top arrow
 524 
 525       //  compute element locations in X, Y, Z --------------------------
 526       //  this is where we skew and distort the array.    The Z scaling
 527       //  becomes the x distance skew.  The orbit of each element can be
 528       //  elliptical in Y (north-south)  versus Z (radial), while the X
 529       //  distance (along the orbit) gets the skew 
 530 
 531       double zm = SPACE * ZEXP ;   // radial
 532       double ym = SPACE * YEXP ;
 533       double xm = SPACE * XEXP ;
 534       double xt = SPACE * ( 1.0 + ASKEW * ZEXP ) ; // range of x values
 535       double as = ASKEW * zm/ym ;
 536       double dtest = (257.0/1024.0) ;
 537       double test0 = (-1025.0/1024.0);
 538       double test1 = ( 1025.0/1024.0);
 539       double zfactr = ZFACTR/zm ;
 540 
 541       // offsets from large side view to screen
 542       int lsxo = XBCENT ;
 543       int lsyo = YBCENT ;
 544 
 545       // compute the points of the rotated, scaled, and skewed array
 546       for( i=0 ; i < nvert ; i++ ) {
 547          zdis[i] = zm*(cos(angle)*vertex[i].z+sin(angle)*vertex[i].y ) ;
 548          ydis[i] = ym*(cos(angle)*vertex[i].y-sin(angle)*vertex[i].z ) ;
 549          xdis[i] = xm*vertex[i].x            + as*ydis[i] ;
 550       }
 551 
 552 
 553       //  layer from back, so that bigger points in front overlap smaller
 554       //  points in back.   This will make a large loop
 555       for( test = test0; test < test1 ; test += dtest ) {
 556 
 557          // compute display slices
 558          double z0 =  test*zm ;
 559          double z1 = dtest*zm + z0 ;
 560          double y0 =  test*ym ;
 561          double y1 = dtest*ym + y0 ;
 562          double x0 =  test*xt ;
 563          double x1 = dtest*xt + x0 ;
 564  
 565          /*
 566          printf( "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
 567                   test, x0,   x1,   y0,   y1,   z0,   z1 );
 568          */
 569 
 570          // step through all the vertices multiple times
 571          for( i=0 ; i < nvert; i++ ) {
 572 
 573             //  draw view from top (Z+) --------------------------------------
 574 
 575             if( ( ydis[i] >= y0 ) && ( ydis[i] < y1 ) ) {
 576 
 577                // small top view
 578 
 579 	       ox = X0CENT + (int) ( 0.25*xdis[i] );
 580                oy = Y0CENT + (int) ( 0.25*zdis[i] );
 581                gdImageSetPixel( im, ox, oy, col[i] );
 582 
 583                // orbiting tiny top view
 584 
 585                xu = 3.0 -ORBSIZE - OSCALE * zdis[i] ;
 586                yu =                OSCALE * xdis[i] ; 
 587 
 588                xi = ex + (int)( xu*cos(angle)+yu*sin(angle)) ;
 589                yi = ey + (int)( yu*cos(angle)-xu*sin(angle)) ;
 590 
 591                if(  ( xi <   ex      ) 
 592                   ||( yi < ( ey-re ) )
 593                   ||( yi > ( ey+re ) ) ) icol = col[      i] ;
 594                else                      icol = col[nvert+i] ; //shadow
 595 
 596                gdImageSetPixel( im, xi, yi, icol );
 597             }
 598 
 599             // side views ---------------------------------------------
 600 
 601             if( ( zdis[i] >= z0 ) && ( zdis[i] < z1 ) ) {
 602 
 603                // BIG side view 
 604                ox = XBCENT + (int) (  xdis[i] );
 605                oy = YBCENT + (int) ( -ydis[i] );
 606 
 607                s0 = (int) (     SIZE * (1.00 + zfactr * zdis[i] ) ) ;
 608                gdImageFilledArc(im, ox, oy, s0, s0, 0, 360, col[i], gdArc);
 609             }
 610 
 611             // small front view - apogee to left, closer ---------------
 612 
 613             if( ( xdis[i] >= x0 ) && ( xdis[i] < x1 ) ) {
 614                ox = X0CENT + (int) (  0.25*zdis[i] );
 615                oy = Y1CENT + (int) ( -0.25*ydis[i] );
 616                gdImageSetPixel( im, ox, oy, col[i] );
 617             }
 618          }
 619       }
 620 
 621       /* Output the frame in PNG format. */
 622       gdImagePngEx( im, pngout, 1 );
 623       gdImageDestroy(im);
 624       fclose(pngout);
 625    }
 626 
 627    sprintf( command, PNG2SWF, NAME, RATE, NAME );
 628    system( command );
 629    return 0 ;
 630 }

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-02 00:38:42, 21.9 KB) [[attachment:gs11.c]]
  • [get | view] (2021-01-20 01:53:50, 2183.2 KB) [[attachment:gs11.mpg]]
  • [get | view] (2021-05-20 04:53:19, 5877.2 KB) [[attachment:gs11.png]]
  • [get | view] (2013-05-02 00:39:17, 6982.8 KB) [[attachment:gs11.swf]]
  • [get | view] (2013-05-02 02:22:26, 45.0 KB) [[attachment:gs110100.png]]
  • [get | view] (2021-01-31 01:30:33, 2410.2 KB) [[attachment:gs12.mp4]]
  • [get | view] (2021-01-31 01:43:26, 5166.9 KB) [[attachment:gs12.ogg]]
  • [get | view] (2013-06-07 17:42:30, 6475.5 KB) [[attachment:ss_paper.pdf]]
 All files | Selected Files: delete move to page

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