gdcpie.cpp

Go to the documentation of this file.
00001 /* GDCHART 0.94b  GDC_PIE.C  12 Nov 1998 */
00002 
00003 #include <stdio.h>
00004 #include <values.h>
00005 #include <math.h>
00006 
00007 #define GDC_INCL
00008 #define GDC_LIB
00009 #include "gdc.h"
00010 #include "gdcpie.h"
00011 
00012 #include <string.h>
00013 #include <stdlib.h>
00014 
00015 /*
00016 
00017 unsigned long           GDCPIE_BGColor                  DEFAULTO( 0x000000L );  
00018 unsigned long           GDCPIE_PlotColor                DEFAULTO( 0xC0C0C0L );  
00019 unsigned long           GDCPIE_LineColor                DEFAULTO( GDC_DFLTCOLOR );
00020 unsigned long           GDCPIE_EdgeColor                DEFAULTO( GDC_NOCOLOR ); 
00021 
00022 char                            GDCPIE_other_threshold  DEFAULTO( -1 );
00023 unsigned short          GDCPIE_3d_angle                 DEFAULTO( 45 );                 
00024 unsigned short          GDCPIE_3d_depth                 DEFAULTO( 10 );                 
00025 char                            *GDCPIE_title                   DEFAULTO( NULL );               
00026 enum GDC_font_size      GDCPIE_title_size               DEFAULTO( GDC_MEDBOLD );
00027 enum GDC_font_size      GDCPIE_label_size               DEFAULTO( GDC_SMALL );
00028 int                                     GDCPIE_label_dist               DEFAULTO( 1+8/2 );              
00029 unsigned char           GDCPIE_label_line               DEFAULTO( FALSE );              
00030 
00031 int                                     *GDCPIE_explode                 DEFAULTO( (int*)NULL ); 
00032                                                                                                                         
00033 unsigned long           *GDCPIE_Color                   DEFAULTO( (unsigned long*)NULL );
00034 unsigned char           *GDCPIE_missing                 DEFAULTO( (unsigned char*)NULL );       
00035 
00036 GDCPIE_PCT_TYPE         GDCPIE_percent_labels   DEFAULTO( GDCPIE_PCT_NONE );
00037 
00038 */
00039 /* rem circle:  x = rcos(@), y = rsin(@)        */
00040 
00041 extern struct   GDC_FONT_T      GDC_fontc[];
00042 
00043 #define SET_RECT( gdp, x1, x2, y1, y2 ) gdp[0].x = gdp[3].x = x1,       \
00044                                                                                 gdp[0].y = gdp[1].y = y1,       \
00045                                                                                 gdp[1].x = gdp[2].x = x2,       \
00046                                                                                 gdp[2].y = gdp[3].y = y2
00047 
00048 #define PX( x )                         ( cx + (int)( ((float)rad)*sin(pscl*(double)(x)) ) )            /* expects a val */
00049 #define PY( x )                         ( cy - (int)( ((float)rad)*cos(pscl*(double)(x)) ) )            /* expects a val */
00050 
00051 #define CX( i,d )               ( cx                +   \
00052                                                   (d? xdepth_3D: 0) +   \
00053                                                   (int)( (double)(GDCPIE_explode?GDCPIE_explode[(i)]:0) * sin((double)(slice_angle[0][i])) ) )
00054 #define CY( i,d )               ( cy                -   \
00055                                                   (d? ydepth_3D: 0) -   \
00056                                                   (int)( (double)(GDCPIE_explode?GDCPIE_explode[(i)]:0) * cos((double)(slice_angle[0][i])) ) )
00057 /* expect slice number:     i (index into slice_angle array) *\ 
00058  *   and position on slice: f (0: slice middle,              *
00059  *                             1: leading (clockwise),       *
00060  *                             2: trailing edge)             *
00061  *   and 3D depth:          d (0: do depth,                  *
00062  *                             1: no depth adjustment)       *
00063 \* adjusts for explosion                                     */
00064 #define IX( i,f,d )             ( CX(i,d) + (int)( (double)rad * sin((double)(slice_angle[f][i])) ) )
00065 #define IY( i,f,d )             ( CY(i,d) - (int)( (double)rad * cos((double)(slice_angle[f][i])) ) )
00066 /* same as above except o is angle */
00067 #define OX( i,o,d )             ( CX(i,d) + (int)( (double)rad * sin((double)(o)) ) )
00068 #define OY( i,o,d )             ( CY(i,d) - (int)( (double)rad * cos((double)(o)) ) )
00069 
00070 #define TO_INT_DEG(o)           (int)rint( (double)((o)/(2.0*M_PI)*360.0) )
00071 #define TO_INT_DEG_FLOOR(o)     (int)floor( (double)((o)/(2.0*M_PI)*360.0) )
00072 #define TO_INT_DEG_CEIL(o)      (int)ceil( (double)((o)/(2.0*M_PI)*360.0) )
00073 #define TO_RAD(o)                       ( (o)/360.0*(2.0*M_PI) )
00074                                                                                                                                                                         /* assume !> 4*PI */
00075 #define MOD_2PI(o)                      ( (o)>=(2.0*M_PI)? ((o)-(2.0*M_PI)): (((o)<0)? ((o)+(2.0*M_PI)): (o)) )
00076 #define MOD_360(o)                      ( (o)>=360? (o)-360: (o) )                                                              /* assume !> 720 */ 
00077 
00078 struct tmp_slice_t { int        i;                                      // original index
00079                                          char   hidden;                         // 'behind' top [3D] pie
00080                                          float  angle;                          // radian 
00081                                          float  slice; };                       // radian
00082 static float                            pie_3D_rad;                     // user requested 3D angle in radians
00083 
00084 // degrees (radians) between angle a, and depth angle
00085 // 1&2, so comparisons can be done.
00086 #define RAD_DIST1( a )          ( (dist_foo1=ABS(((a>-.00001&&a<.00001)?0.00001:a)-pie_3D_rad)), ((dist_foo1>M_PI)? ABS(dist_foo1-2.0*M_PI): dist_foo1) )
00087 #define RAD_DIST2( a )          ( (dist_foo2=ABS(((a>-.00001&&a<.00001)?0.00001:a)-pie_3D_rad)), ((dist_foo2>M_PI)? ABS(dist_foo2-2.0*M_PI): dist_foo2) )
00088 static float                            dist_foo1, dist_foo2;
00089 
00090 /* ------------------------------------------------------- *\ 
00091  * oof!  cleaner way???
00092  * order by angle opposite (180) of depth angle
00093  * comparing across 0-360 line
00094 \* ------------------------------------------------------- */
00095 //static int ocmpr( struct tmp_slice_t *a, struct tmp_slice_t *b )
00096 static int ocmpr( const void *a1, const void *b1 )
00097 {
00098          struct tmp_slice_t *a = (tmp_slice_t *)a1;
00099          struct tmp_slice_t *b = (tmp_slice_t *)b1;
00100         if( RAD_DIST1(a->angle) < RAD_DIST2(b->angle) )
00101                 return 1;
00102         if( RAD_DIST1(a->angle) > RAD_DIST2(b->angle) )
00103                 return -1;
00104 
00105         /* a tie (will happen between each slice) */
00106         /* are we within pie_3D_rad */
00107         if( (a->angle < pie_3D_rad) && (pie_3D_rad < a->slice) ||
00108                 (a->slice < pie_3D_rad) && (pie_3D_rad < a->angle) )
00109                 return 1;
00110         if( (b->slice < pie_3D_rad) && (pie_3D_rad < b->angle) ||
00111                 (b->angle < pie_3D_rad) && (pie_3D_rad < b->slice) )
00112                 return -1;
00113 
00114         /* let slice angle decide */
00115         if( RAD_DIST1(a->slice) < RAD_DIST2(b->slice) )
00116                 return 1;
00117         if( RAD_DIST1(a->slice) > RAD_DIST2(b->slice) )
00118                 return -1;
00119 
00120         return 0;
00121 }
00122 
00123 /* ======================================================= *\ 
00124  * PIE
00125  * 
00126  * Notes:
00127  *  always drawn from 12:00 position clockwise
00128  *  'missing' slices don't get labels
00129  *  sum(val[0], ... val[num_points-1]) is assumed to be 100%
00130 \* ======================================================= */
00131 void
00132 pie_gif( short                  GIFWIDTH,
00133                  short                  GIFHEIGHT,
00134                  FILE                   *gif_fptr,                      /* open file pointer */
00135                  GDCPIE_TYPE    type,
00136                  int                    num_points,
00137                  char                   **lbl,                          /* data labels */
00138                  float                  *val )                          /* data */
00139 {
00140 #ifndef WIN32
00141         int                     i;
00142 
00143         gdImagePtr      im;
00144         int                     BGColor,
00145                                 LineColor,
00146                                 PlotColor,
00147                                 EdgeColor,
00148                                 EdgeColorShd,
00149                                 SliceColor[num_points],
00150                                 SliceColorShd[num_points];
00151 
00152         float           rad = 0.0;                                      // radius
00153         float           tot_val = 0.0;
00154         float           pscl;
00155         int                     cx,                                                     // affects PX()
00156                                 cy;                                                     // affects PY()
00157                                                                 /* ~ 1% for a size of 100 pixs */
00158                                                                 /* label sizes will more dictate thos */
00159         float           min_grphable = ( GDCPIE_other_threshold < 0?
00160                                                                   100.0/(float)MIN(GIFWIDTH,GIFHEIGHT):
00161                                                                   (float)GDCPIE_other_threshold )/100.0;
00162         short           num_slices1 = 0,
00163                                 num_slices2 = 0;
00164         char            any_too_small = FALSE;
00165         char            others[num_points];
00166         float           slice_angle[3][num_points];     // must be used with others[]
00167         char            threeD = ( type == GDC_3DPIE );
00168 
00169         int                     xdepth_3D      = 0,                     // affects PX()
00170                                 ydepth_3D      = 0;                     // affects PY()
00171         int                     do3Dx = 0,                                      // reserved for macro use
00172                                 do3Dy = 0;
00173 
00174 //      GDCPIE_3d_angle = MOD_360(90-GDCPIE_3d_angle+360);
00175         pie_3D_rad = TO_RAD( GDCPIE_3d_angle );
00176 
00177         xdepth_3D      = threeD? (int)( cos((double)MOD_2PI(M_PI_2-pie_3D_rad+2.0*M_PI)) * GDCPIE_3d_depth ): 0;
00178         ydepth_3D      = threeD? (int)( sin((double)MOD_2PI(M_PI_2-pie_3D_rad+2.0*M_PI)) * GDCPIE_3d_depth ): 0;
00179 //      xdepth_3D      = threeD? (int)( cos(pie_3D_rad) * GDCPIE_3d_depth ): 0;
00180 //      ydepth_3D      = threeD? (int)( sin(pie_3D_rad) * GDCPIE_3d_depth ): 0;
00181 
00182         load_font_conversions();
00183 
00184         /* ----- get total value ----- */
00185         for( i=0; i<num_points; ++i )
00186                 tot_val += val[i];
00187 
00188         /* ----- pie sizing ----- */
00189         /* ----- make width room for labels, depth, etc.: ----- */
00190         /* ----- determine pie's radius ----- */
00191         {
00192         int             title_hgt  = GDCPIE_title? 1                    /*  title? horizontal text line */
00193                                                                            + GDC_fontc[GDCPIE_title_size].h
00194                                                                                 * (int)cnt_nl( GDCPIE_title, (int*)NULL )
00195                                                                            + 2:
00196                                                                            0;
00197         float   last = 0.0;
00198         float   label_explode_limit = 0.0;
00199         int             cheight,
00200                         cwidth;
00201 
00202         // maximum: no labels, explosions
00203         // gotta start somewhere
00204         rad = (float)MIN( GIFWIDTH/2-(1+ABS(xdepth_3D)), GIFHEIGHT/2-(1+ABS(ydepth_3D))-title_hgt );
00205 
00206         /* ok fix center, i.e., no floating re labels, explosion, etc. */
00207         cx = GIFWIDTH/2 /* - xdepth_3D */ ;
00208         cy = (GIFHEIGHT-title_hgt)/2 + title_hgt /* + ydepth_3D */ ;
00209 
00210         cheight = (GIFHEIGHT- title_hgt)/2 /* - ydepth_3D */ ;
00211         cwidth  = cx;
00212 
00213         /* walk around pie. determine spacing to edge */
00214         for( i=0; i<num_points; ++i )
00215                 {
00216                 float   thos_pct = val[i]/tot_val;                                              /* should never be > 100% */
00217                 float   thos = thos_pct*(2.0*M_PI);                                             /* pie-portion */
00218                 if( (thos_pct > min_grphable) ||                                                /* too small */
00219                         (!GDCPIE_missing || !GDCPIE_missing[i]) )                       /* still want angles */
00220                         {
00221                         int thos_explode = GDCPIE_explode? GDCPIE_explode[i]: 0;
00222                         double  thos_sin;
00223                         double  thos_cos;
00224                         slice_angle[0][i] = thos/2.0+last;                              /* mid-point on full pie */
00225                         slice_angle[1][i] = last;                                               /* 1st on full pie */
00226                         slice_angle[2][i] = thos+last;                                  /* 2nd on full pie */
00227                         thos_sin        = sin( (double)slice_angle[0][i] );
00228                         thos_cos        = cos( (double)slice_angle[0][i] );
00229 
00230                         if( !GDCPIE_missing || !(GDCPIE_missing[i]) )
00231                                 {
00232                                 short   lbl_wdth,
00233                                                 lbl_hgt;
00234                                 float   thos_y_explode_limit,
00235                                                 thos_x_explode_limit;
00236 
00237                                 /* start slice label height, width     */
00238                                 /*  accounting for PCT placement, font */
00239                                 if( lbl && lbl[i] )
00240                                         {
00241                                         char    foo[1+4+1+1];                                   /* XPG2 compatibility */
00242                                         int             pct_len;
00243                                         int             lbl_len = 0;
00244                                         lbl_hgt = ( cnt_nl(lbl[i], &lbl_len) + (GDCPIE_percent_labels == GDCPIE_PCT_ABOVE ||
00245                                                                                                                         GDCPIE_percent_labels == GDCPIE_PCT_BELOW? 1: 0) )
00246                                                           * (GDC_fontc[GDCPIE_label_size].h+1);
00247                                         sprintf( foo,
00248                                                          (GDCPIE_percent_labels==GDCPIE_PCT_LEFT ||
00249                                                           GDCPIE_percent_labels==GDCPIE_PCT_RIGHT) &&
00250                                                          lbl[i]? "(%.0f%%)":
00251                                                                          "%.0f%%",
00252                                                         thos_pct * 100.0 );
00253                                         pct_len = GDCPIE_percent_labels == GDCPIE_PCT_NONE? 0: strlen(foo);
00254                                         lbl_wdth = ( GDCPIE_percent_labels == GDCPIE_PCT_RIGHT ||
00255                                                                  GDCPIE_percent_labels == GDCPIE_PCT_LEFT? lbl_len+1+pct_len:
00256                                                                                                                                                    MAX(lbl_len,pct_len) )
00257                                                            * GDC_fontc[GDCPIE_label_size].w;
00258                                         }
00259                                 else
00260                                         lbl_wdth = lbl_hgt = 0;
00261                                 /* end label height, width */
00262                                 
00263                                 /* diamiter limited by thos piont's: explosion, label                 */
00264                                 /* (radius to box @ slice_angle) - (explode) - (projected label size) */
00265                                 /* radius constraint due to labels */
00266                                 thos_y_explode_limit = (float)thos_cos==0.0? MAXFLOAT:
00267                                                                                 (       (float)( (double)cheight/ABS(thos_cos) ) - 
00268                                                                                         (float)( thos_explode + (lbl[i]? GDCPIE_label_dist: 0) ) -
00269                                                                                         (float)( lbl_hgt/2 ) / (float)ABS(thos_cos)     );
00270                                 thos_x_explode_limit = (float)thos_sin==0.0? MAXFLOAT:
00271                                                                                 (       (float)( (double)cwidth/ABS(thos_sin) ) - 
00272                                                                                         (float)( thos_explode + (lbl[i]? GDCPIE_label_dist: 0) ) -
00273                                                                                         (float)( lbl_wdth ) / (float)ABS(thos_sin)      );
00274 
00275                                 rad = MIN( rad, thos_y_explode_limit );
00276                                 rad = MIN( rad, thos_x_explode_limit );
00277 
00278                                 // ok at thos radius (which is most likely larger than final)
00279                                 // adjust for inter-label spacing
00280 //                              if( lbl[i] && *lbl[i] )
00281 //                                      {
00282 //                                      char which_edge = slice_angle[0][i] > M_PI? +1: -1;             // which semi
00283 //                                      last_label_yedge = cheight - (int)( (rad +                              // top or bottom of label
00284 //                                                                                                              (float)(thos_explode +
00285 //                                                                                                              (float)GDCPIE_label_dist)) * (float)thos_cos ) +
00286 //                                                                                           ( (GDC_fontc[GDCPIE_label_size].h+1)/2 +
00287 //                                                                                                      GDC_label_spacing )*which_edge;
00288 //                                      }
00289 
00290                                 /* radius constriant due to exploded depth */
00291                                 /* at each edge of the slice, and the middle */
00292                                 /* thos is really stupid */
00293                                 /*  thos section uses a different algorithm then above, but does the same thing */
00294                                 /*  could be combined, but each is ugly enough! */
00295 // PROTECT /0
00296                                 if( threeD )
00297                                         {
00298                                         short   j;
00299                                         int             thos_y_explode_pos;
00300                                         int             thos_x_explode_pos;
00301 
00302                                         // first N E S W (actually no need for N)
00303                                         if( (slice_angle[1][i] < M_PI_2 && M_PI_2 < slice_angle[2][i]) &&                               // E
00304                                                 (thos_x_explode_pos=OX(i,M_PI_2,1)) > cx+cwidth )
00305                                                 rad -= (float)ABS( (double)(1+thos_x_explode_pos-(cx+cwidth))/sin(M_PI_2) );
00306                                         if( (slice_angle[1][i] < 3.0*M_PI_2 && 3.0*M_PI_2 < slice_angle[2][i]) &&               // W
00307                                                 (thos_x_explode_pos=OX(i,3.0*M_PI_2,1)) < cx-cwidth )
00308                                                 rad -= (float)ABS( (double)(thos_x_explode_pos-(cx+cwidth))/sin(3.0*M_PI_2) );
00309                                         if( (slice_angle[1][i] < M_PI && M_PI < slice_angle[2][i]) &&                                   // S
00310                                                 (thos_y_explode_pos=OY(i,M_PI,1)) > cy+cheight )
00311                                                 rad -= (float)ABS( (double)(1+thos_y_explode_pos-(cy+cheight))/cos(M_PI) );
00312 
00313                                         for( j=0; j<3; ++j )
00314                                                 {
00315                                                 thos_y_explode_pos = IY(i,j,1);
00316                                                 if( thos_y_explode_pos < cy-cheight )
00317                                                         rad -= (float)ABS( (double)((cy-cheight)-thos_y_explode_pos)/cos((double)slice_angle[j][i]) );
00318                                                 if( thos_y_explode_pos > cy+cheight )
00319                                                         rad -= (float)ABS( (double)(1+thos_y_explode_pos-(cy+cheight))/cos((double)slice_angle[j][i]) );
00320 
00321                                                 thos_x_explode_pos = IX(i,j,1);
00322                                                 if( thos_x_explode_pos < cx-cwidth )
00323                                                         rad -= (float)ABS( (double)((cx-cwidth)-thos_x_explode_pos)/sin((double)slice_angle[j][i]) );
00324                                                 if( thos_x_explode_pos > cx+cwidth )
00325                                                         rad -= (float)ABS( (double)(1+thos_x_explode_pos-(cx+cwidth))/sin((double)slice_angle[j][i]) );
00326                                                 }
00327                                         }
00328                                 }
00329                         others[i] = FALSE;
00330                         }
00331                 else
00332                         {
00333                         others[i] = TRUE;
00334                         slice_angle[0][i] = -MAXFLOAT;
00335                         }
00336                 last += thos;
00337                 }
00338         }
00339 
00340         /* ----- go ahead and start the GIF ----- */
00341         im = gdImageCreate( GIFWIDTH, GIFHEIGHT );
00342 
00343         /* --- allocate the requested colors --- */
00344         BGColor   = clrallocate( im, GDCPIE_BGColor );
00345         LineColor = clrallocate( im, GDCPIE_LineColor );
00346         PlotColor = clrallocate( im, GDCPIE_PlotColor );
00347         if( GDCPIE_EdgeColor != GDC_NOCOLOR )
00348          {
00349          EdgeColor = clrallocate( im, GDCPIE_EdgeColor );
00350          if( threeD )
00351           EdgeColorShd = clrshdallocate( im, GDCPIE_EdgeColor );
00352          }
00353 
00354         /* --- set color for each slice --- */
00355         for( i=0; i<num_points; ++i )
00356                 if( GDCPIE_Color )
00357                         {
00358                         unsigned long   slc_clr = GDCPIE_Color[i];
00359 
00360                         SliceColor[i]     = clrallocate( im, slc_clr );
00361                         if( threeD )
00362                          SliceColorShd[i] = clrshdallocate( im, slc_clr );
00363                         }
00364                 else
00365                         {
00366                         SliceColor[i]     = PlotColor;
00367                         if( threeD )
00368                          SliceColorShd[i] = clrshdallocate( im, GDCPIE_PlotColor );
00369                         }
00370 
00371         pscl = (2.0*M_PI)/tot_val;
00372         
00373         /* ----- calc: smallest a slice can be ----- */
00374         /* 1/2 circum / num slices per side. */
00375         /*              determined by number of labels that'll fit (height) */
00376         /* scale to user values */
00377         /* ( M_PI / (GIFHEIGHT / (SFONTHGT+1)) ) */
00378 //      min_grphable = tot_val /
00379 //                                 ( 2.0 * (float)GIFHEIGHT / (float)(SFONTHGT+1+TFONTHGT+2) );
00380 
00381 
00382         if( threeD )
00383                 {
00384                 /* draw background shaded pie */
00385                 {
00386                 float   rad1 = rad;
00387                 for( i=0; i<num_points; ++i )
00388                         if( !(others[i]) &&
00389                                 (!GDCPIE_missing || !GDCPIE_missing[i]) )
00390                                 {
00391                                 float   rad = rad1;
00392 
00393                                 gdImageLine( im, CX(i,1), CY(i,1), IX(i,1,1), IY(i,1,1), SliceColorShd[i] );
00394                                 gdImageLine( im, CX(i,1), CY(i,1), IX(i,2,1), IY(i,2,1), SliceColorShd[i] );
00395 
00396                                 gdImageArc( im, CX(i,1), CY(i,1),
00397                                                                 rad*2, rad*2,
00398                                                                 TO_INT_DEG_FLOOR(slice_angle[1][i])+270,
00399                                                                 TO_INT_DEG_CEIL(slice_angle[2][i])+270,
00400                                                                 SliceColorShd[i] );
00401                                 rad1 = rad;
00402                                 rad *= 3.0/4.0;
00403                                 gdImageFillToBorder( im, IX(i,0,1), IY(i,0,1), SliceColorShd[i], SliceColorShd[i] );
00404                                 rad = rad1;
00405                                 if( GDCPIE_EdgeColor != GDC_NOCOLOR )
00406                                         {
00407                                         gdImageLine( im, CX(i,1), CY(i,1), IX(i,1,1), IY(i,1,1), EdgeColorShd );
00408                                         gdImageLine( im, CX(i,1), CY(i,1), IX(i,2,1), IY(i,2,1), EdgeColorShd );
00409                                         gdImageArc( im, CX(i,1), CY(i,1), 
00410                                                                         rad*2, rad*2,
00411                                                                         TO_INT_DEG(slice_angle[1][i])+270, TO_INT_DEG(slice_angle[2][i])+270,
00412                                                                         EdgeColorShd);
00413                                         }
00414                                 }
00415                 }
00416                 /* fill in connection to foreground pie */
00417                 /* thos is where we earn our keep */
00418                 {
00419                 struct tmp_slice_t      tmp_slice[2*num_points+2];
00420                 int                                     t,
00421                                                         num_slice_angles = 0;
00422 
00423                 for( i=0; i<num_points; ++i )
00424                         if( !GDCPIE_missing || !GDCPIE_missing[i] )
00425                                 {
00426                                 if( RAD_DIST1(slice_angle[1][i]) < RAD_DIST2(slice_angle[0][i]) )
00427                                         tmp_slice[num_slice_angles].hidden = FALSE;
00428                                 else
00429                                         tmp_slice[num_slice_angles].hidden = TRUE;
00430                                 tmp_slice[num_slice_angles].i       = i;
00431                                 tmp_slice[num_slice_angles].slice   = slice_angle[0][i];
00432                                 tmp_slice[num_slice_angles++].angle = slice_angle[1][i];
00433                                 if( RAD_DIST1(slice_angle[2][i]) < RAD_DIST2(slice_angle[0][i]) )
00434                                         tmp_slice[num_slice_angles].hidden = FALSE;
00435                                 else
00436                                         tmp_slice[num_slice_angles].hidden = TRUE;
00437                                 tmp_slice[num_slice_angles].i       = i;
00438                                 tmp_slice[num_slice_angles].slice   = slice_angle[0][i];
00439                                 tmp_slice[num_slice_angles++].angle = slice_angle[2][i];
00440                                 // identify which 2 slices (i) have a tangent parallel to depth angle 
00441                                 if( slice_angle[1][i]<MOD_2PI(pie_3D_rad+M_PI_2) && slice_angle[2][i]>MOD_2PI(pie_3D_rad+M_PI_2) )
00442                                         {
00443                                         tmp_slice[num_slice_angles].i       = i;
00444                                         tmp_slice[num_slice_angles].hidden  = FALSE;
00445                                         tmp_slice[num_slice_angles].slice   = slice_angle[0][i];
00446                                         tmp_slice[num_slice_angles++].angle = MOD_2PI( pie_3D_rad+M_PI_2 );
00447                                         }
00448                                 if( slice_angle[1][i]<MOD_2PI(pie_3D_rad+3.0*M_PI_2) && slice_angle[2][i]>MOD_2PI(pie_3D_rad+3.0*M_PI_2) )
00449                                         {
00450                                         tmp_slice[num_slice_angles].i       = i;
00451                                         tmp_slice[num_slice_angles].hidden  = FALSE;
00452                                         tmp_slice[num_slice_angles].slice   = slice_angle[0][i];
00453                                         tmp_slice[num_slice_angles++].angle = MOD_2PI( pie_3D_rad+3.0*M_PI_2 );
00454                                         }
00455                                 }
00456 
00457                 qsort( (void *)tmp_slice, num_slice_angles, sizeof(struct tmp_slice_t), ocmpr );
00458                 for( t=0; t<num_slice_angles; ++t )
00459                         {
00460                         gdPoint gdp[4];
00461 
00462                         i = tmp_slice[t].i;
00463 
00464                         gdp[0].x  = CX(i,0);                                    gdp[0].y = CY(i,0);
00465                         gdp[1].x  = CX(i,1);                                    gdp[1].y = CY(i,1);
00466                         gdp[2].x  = OX(i,tmp_slice[t].angle,1); gdp[2].y = OY(i,tmp_slice[t].angle,1);
00467                         gdp[3].x  = OX(i,tmp_slice[t].angle,0); gdp[3].y = OY(i,tmp_slice[t].angle,0);
00468 
00469                         if( !(tmp_slice[t].hidden) )
00470                                 gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] );
00471                         else
00472                                 {
00473                                 rad -= 2.0;                                                                             /* no peeking */
00474                                 gdp[0].x  = OX(i,slice_angle[0][i],0);  gdp[0].y = OY(i,slice_angle[0][i],0);
00475                                 gdp[1].x  = OX(i,slice_angle[0][i],1);  gdp[1].y = OY(i,slice_angle[0][i],1);
00476                                 rad += 2.0;
00477                                 gdp[2].x  = OX(i,slice_angle[1][i],1);  gdp[2].y = OY(i,slice_angle[1][i],1);
00478                                 gdp[3].x  = OX(i,slice_angle[1][i],0);  gdp[3].y = OY(i,slice_angle[1][i],0);
00479                                 gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] );
00480                                 gdp[2].x  = OX(i,slice_angle[2][i],1);  gdp[2].y = OY(i,slice_angle[2][i],1);
00481                                 gdp[3].x  = OX(i,slice_angle[2][i],0);  gdp[3].y = OY(i,slice_angle[2][i],0);
00482                                 gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] );
00483                                 }
00484                                 
00485 
00486                         if( GDCPIE_EdgeColor != GDC_NOCOLOR )
00487                                 {
00488                                 gdImageLine( im, CX(i,0), CY(i,0), CX(i,1), CY(i,1), EdgeColorShd );
00489                                 gdImageLine( im, OX(i,tmp_slice[t].angle,0), OY(i,tmp_slice[t].angle,0),
00490                                                                  OX(i,tmp_slice[t].angle,1), OY(i,tmp_slice[t].angle,1),
00491                                                          EdgeColorShd );
00492                                 }
00493                         }
00494                 }
00495                 }
00496 
00497 
00498         /* ----- pie face ----- */
00499         {
00500         // float        last = 0.0;
00501         float   rad1 = rad;
00502         for( i=0; i<num_points; ++i )
00503                 if( !others[i] &&
00504                         (!GDCPIE_missing || !GDCPIE_missing[i]) )
00505                         {
00506                         float   rad = rad1;
00507 
00508                         // last += val[i];
00509                         // EXPLODE_CX_CY( slice_angle[0][i], i );
00510                         gdImageLine( im, CX(i,0), CY(i,0), IX(i,1,0), IY(i,1,0), SliceColor[i] );
00511                         gdImageLine( im, CX(i,0), CY(i,0), IX(i,2,0), IY(i,2,0), SliceColor[i] );
00512 
00513                         gdImageArc( im, CX(i,0), CY(i,0), 
00514                                                         (int)rad*2, (int)rad*2,
00515                                                         TO_INT_DEG_FLOOR(slice_angle[1][i])+270,
00516                                                         TO_INT_DEG_CEIL(slice_angle[2][i])+270,
00517                                                         SliceColor[i] );
00518                         rad1 = rad;
00519                         rad *= 3.0/4.0;
00520                         gdImageFillToBorder( im, IX(i,0,0), IY(i,0,0), SliceColor[i], SliceColor[i] );
00521                         /* catch missed pixels on narrow slices */
00522                         gdImageLine( im, CX(i,0), CY(i,0), IX(i,0,0), IY(i,0,0), SliceColor[i] );
00523                         rad = rad1;
00524                         if( GDCPIE_EdgeColor != GDC_NOCOLOR )
00525                                 {
00526                                 gdImageLine( im, CX(i,0), CY(i,0), IX(i,1,0), IY(i,1,0), EdgeColor );
00527                                 gdImageLine( im, CX(i,0), CY(i,0), IX(i,2,0), IY(i,2,0), EdgeColor );
00528 
00529                                 gdImageArc( im, CX(i,0), CY(i,0), 
00530                                                                 rad*2, rad*2,
00531                                                                 TO_INT_DEG(slice_angle[1][i])+270, TO_INT_DEG(slice_angle[2][i])+270,
00532                                                                 EdgeColor );
00533                                 }
00534                         }
00535         }
00536 
00537         if( GDCPIE_title )
00538                 {
00539                 int     title_len;
00540 
00541                 cnt_nl( GDCPIE_title, &title_len );
00542                 GDCImageStringNL( im,
00543                                                   &GDC_fontc[GDCPIE_title_size],
00544                                                   (GIFWIDTH-title_len*GDC_fontc[GDCPIE_title_size].w)/2,
00545                                                   1,
00546                                                   GDCPIE_title,
00547                                                   LineColor,
00548                                                   GDC_JUSTIFY_CENTER );
00549                 }
00550 
00551         /* labels */
00552         if( lbl )
00553                 {
00554                 float   liner = rad;
00555 
00556                 rad += GDCPIE_label_dist;
00557                 for( i=0; i<num_points; ++i )
00558                         {
00559                         if( !others[i] &&
00560                                 (!GDCPIE_missing || !GDCPIE_missing[i]) )
00561                                 {
00562                                 char    pct_str[1+4+1+1];
00563                                 int             pct_wdth;
00564                                 int             lbl_wdth;
00565                                 short   num_nl = cnt_nl( lbl[i], &lbl_wdth );
00566                                 int             lblx,  pctx,
00567                                                 lbly,  pcty,
00568                                                 linex, liney;
00569 
00570                                 lbl_wdth *= GDC_fontc[GDCPIE_label_size].w;
00571                                 sprintf( pct_str,
00572                                                  (GDCPIE_percent_labels==GDCPIE_PCT_LEFT ||
00573                                                   GDCPIE_percent_labels==GDCPIE_PCT_RIGHT) &&
00574                                                  lbl[i]? "(%.0f%%)":
00575                                                                  "%.0f%%",
00576                                                 (val[i]/tot_val) * 100.0 );
00577                                 pct_wdth = GDCPIE_percent_labels == GDCPIE_PCT_NONE?
00578                                                         0:
00579                                                         strlen(pct_str) * GDC_fontc[GDCPIE_label_size].w;
00580 
00581                                 lbly = (liney = IY(i,0,0))-( num_nl * (1+GDC_fontc[GDCPIE_label_size].h) ) / 2;
00582                                 lblx = pctx = linex = IX(i,0,0);
00583 
00584                                 if( slice_angle[0][i] > M_PI )                                                          /* which semicircle */
00585                                         {
00586                                         lblx -= lbl_wdth;
00587                                         pctx = lblx;
00588                                         ++linex;
00589                                         }
00590                                 else
00591                                         --linex;
00592 
00593                                 switch( GDCPIE_percent_labels )
00594                                         {
00595                                         case GDCPIE_PCT_LEFT:   if( slice_angle[0][i] > M_PI )
00596                                                                                                 pctx -= lbl_wdth-1;
00597                                                                                         else
00598                                                                                                 lblx += pct_wdth+1;
00599                                                                                         pcty = IY(i,0,0) - ( 1+GDC_fontc[GDCPIE_label_size].h ) / 2;
00600                                                                                         break;
00601                                         case GDCPIE_PCT_RIGHT:  if( slice_angle[0][i] > M_PI )
00602                                                                                                 lblx -= pct_wdth-1;
00603                                                                                         else
00604                                                                                                 pctx += lbl_wdth+1;
00605                                                                                         pcty = IY(i,0,0) - ( 1+GDC_fontc[GDCPIE_label_size].h ) / 2;
00606                                                                                         break;
00607                                         case GDCPIE_PCT_ABOVE:  lbly += (1+GDC_fontc[GDCPIE_label_size].h) / 2;
00608                                                                                         pcty = lbly - (GDC_fontc[GDCPIE_label_size].h);
00609                                                                                         break;
00610                                         case GDCPIE_PCT_BELOW:  lbly -= (1+GDC_fontc[GDCPIE_label_size].h) / 2;
00611                                                                                         pcty = lbly + (GDC_fontc[GDCPIE_label_size].h) * num_nl;
00612                                                                                         break;
00613                                         case GDCPIE_PCT_NONE:
00614                                         default:
00615                                         break;
00616                                         }
00617 
00618                                 if( GDCPIE_percent_labels != GDCPIE_PCT_NONE )
00619                                         gdImageString( im,
00620                                                                    GDC_fontc[GDCPIE_label_size].f,
00621                                                                    slice_angle[0][i] <= M_PI? pctx:
00622                                                                                                                           pctx+lbl_wdth-pct_wdth,
00623                                                                    pcty,
00624                                                                    (unsigned char *)pct_str,
00625                                                                    LineColor );
00626                                 if( lbl[i] )
00627                                         GDCImageStringNL( im,
00628                                                                           &GDC_fontc[GDCPIE_label_size],
00629                                                                           lblx,
00630                                                                           lbly,
00631                                                                           lbl[i],
00632                                                                           LineColor,
00633                                                                           slice_angle[0][i] <= M_PI? GDC_JUSTIFY_LEFT:
00634                                                                                                                                  GDC_JUSTIFY_RIGHT );
00635                                 if( GDCPIE_label_line )
00636                                         {
00637                                         float   rad = liner;
00638                                         gdImageLine( im, linex, liney, IX(i,0,0), IY(i,0,0), LineColor );
00639                                         }
00640                                 }
00641                         }
00642                 rad -= GDCPIE_label_dist;
00643                 }
00644 
00645         gdImageGif(im, gif_fptr);
00646 
00647         gdImageDestroy(im);
00648         return;
00649 #endif
00650 }
00651 
00652 
00653 void hola() {
00654 fprintf(stderr,"hola");
00655 }// end hola;

Generated on Sat Dec 15 00:00:57 2007 for BulmaGes by  doxygen 1.5.1