📄 gdchart.c
字号:
/* GDCHART 0.94b GDCHART.C 18 APR 1999 *//* vi:set tabstop=4 */#include <includes.h>#include <limits.h>#include <math.h>#include <stdarg.h>#define GDC_INCL#define GDC_LIB#define GDC_VARS#include "gdc.h"#include "gdchart.h"#ifndef M_PI#define M_PI 3.14159265358979323846 /* pi */#define M_PI_2 1.57079632679489661923 /* pi/2 */#endif#ifdef _WIN32#ifdef HAVE__ALLOCA# define alloca(x) _alloca(x)# define USE_ALLOCA#endif /* _alloca */#endif /* _WIN32 */#ifdef HAVE_ALLOCA#define USE_ALLOCA#endif/* two dimensional interger/float array acess */#ifdef USE_ALLOCA# define I(x,y) [(x) * num_points + (y)]#else# define I(x,y) [x][y] /* unix standard method */#endif#ifndef MAXINT# define MAXINT INT_MAX#endif /* * MkLinux defines MAXSHORT as SHORT_MAX, but does not * define SHORT_MAX. However, it defines a SHRT_MAX */#ifndef SHORT_MAX#ifdef SHRT_MAX#define SHORT_MAX SHRT_MAX#endif#endif#define HIGHSET 0#define LOWSET 1#define CLOSESET 2/* scaled translation onto graph */#define PX( x ) (int)( xorig + (setno*xdepth_3D) + (x)*xscl )#define PY( y ) (int)( yorig - (setno*ydepth_3D) + (y)*yscl )#define PV( y ) (int)( vyorig - (setno*ydepth_3D) + (y)*vyscl )#define SET_RECT( gdp, x1, x2, y1, y2 ) gdp[0].x = gdp[3].x = x1, \ gdp[0].y = gdp[1].y = y1, \ gdp[1].x = gdp[2].x = x2, \ gdp[2].y = gdp[3].y = y2#ifdef THUMB_VALS/* ------------------------------------------------------------------- * draw an arrow at (x,y)-upper left in arrwclr to the size of SmallFont * could, with just a little difficulty, be made to accept a font siz * ------------------------------------------------------------------- */voidsmallarrow( gdImagePtr im, int x, int y, char up, int arrwclr ){ gdImageLine( im, x+2, y, x+2, y+GDC_fontc[GDC_SMALL].h, arrwclr ); gdImageLine( im, x+3, y, x+3, y+GDC_fontc[GDC_SMALL].h, arrwclr ); if( up ) /* oo */ { /* uoou */ gdImageSetPixel( im, x, y+2, arrwclr ); /* uuoouu */ gdImageSetPixel( im, x+1, y+2, arrwclr ); /* oo */ gdImageSetPixel( im, x+4, y+2, arrwclr ); /* oo */ gdImageSetPixel( im, x+5, y+2, arrwclr ); /* oo */ gdImageSetPixel( im, x+1, y+1, arrwclr ); /* oo */ gdImageSetPixel( im, x+4, y+1, arrwclr ); /* oo */ } /* oo */ else /* ddoodd */ { /* dood */ gdImageSetPixel( im, x, y+(GDC_fontc[GDC_SMALL].h-2), arrwclr ); /* oo */ gdImageSetPixel( im, x+1, y+(GDC_fontc[GDC_SMALL].h-2), arrwclr ); gdImageSetPixel( im, x+4, y+(GDC_fontc[GDC_SMALL].h-2), arrwclr ); gdImageSetPixel( im, x+5, y+(GDC_fontc[GDC_SMALL].h-2), arrwclr ); gdImageSetPixel( im, x+1, y+(GDC_fontc[GDC_SMALL].h-1), arrwclr ); gdImageSetPixel( im, x+4, y+(GDC_fontc[GDC_SMALL].h-1), arrwclr ); }}#endif#define SET_3D_POLY( gdp, x1, x2, y1, y2, xoff, yoff ) \ gdp[0].x = x1, gdp[0].y = y1, \ gdp[1].x = x1+(xoff), gdp[1].y = y1-yoff, \ gdp[2].x = x2+(xoff), gdp[2].y = y2-yoff, \ gdp[3].x = x2, gdp[3].y = y2/* ------------------------------------------------------------------------- *//* vals in pixels *//* ref is front plane *//* allows for intersecting 3D lines *//* (also used for single 3D lines >:-Q */struct YS { int y1; int y2; float slope; int lnclr; int shclr; };static int qcmpr( const void *a, const void *b ) { if( ((struct YS*)a)->y2 < ((struct YS*)b)->y2 ) return 1; if( ((struct YS*)a)->y2 > ((struct YS*)b)->y2 ) return -1; return 0; }voiddraw_3d_line( gdImagePtr im, int y0, int x1, int x2, int y1[], int y2[], int xdepth, int ydepth, int num_sets, int clr[], int clrshd[] ){#define F(x,i) (int)( (float)((x)-x1)*slope[i]+(float)y1[i] ) float depth_slope = xdepth==0? MAXFLOAT: (float)ydepth/(float)xdepth; float #if defined(USE_ALLOCA) || defined(HAVE_ALLOCA) *slope = (float*)alloca (num_sets * sizeof (float));#else slope[num_sets];#endif /* USE_ALLOCA */ int i; int x; gdPoint#ifdef USE_ALLOCA *poly = (gdPoint*)alloca (4 * sizeof (gdPoint));#else poly[4];#endif /* USE_ALLOCA */ struct YS#ifdef USE_ALLOCA *ypts = (struct YS*)alloca (num_sets * sizeof (struct YS));#else ypts[num_sets];#endif /* USE_ALLOCA */ for( i=0; i<num_sets; ++i ) { /* lnclr[i] = clr[i]; shclr[i] = clrshd[i];*/ slope[i] = x2==x1? MAXFLOAT: (float)(y2[i]-y1[i])/(float)(x2-x1); } for( x=x1+1; x<=x2; ++x ) { for( i=0; i<num_sets; ++i ) /* load set of points */ { ypts[i].y1 = F(x-1,i); ypts[i].y2 = F(x,i); ypts[i].lnclr = clr[i]; ypts[i].shclr = clrshd[i]; ypts[i].slope = slope[i]; } /* sorted "lowest" first */ qsort( ypts, num_sets, sizeof(struct YS), qcmpr ); /* put out in that order */ for( i=0; i<num_sets; ++i ) { /* top */ SET_3D_POLY( poly, x-1, x, ypts[i].y1, ypts[i].y2, xdepth, ydepth ); gdImageFilledPolygon( im, poly, 4, /* depth_slope ever < 0 ? */ -ypts[i].slope>depth_slope? ypts[i].shclr: ypts[i].lnclr ); if( x == x1+1 ) /* edging */ gdImageLine( im, x-1, ypts[i].y2, x-1+xdepth, ypts[i].y2-ydepth, -ypts[i].slope<=depth_slope? ypts[i].shclr: ypts[i].lnclr ); } }}/* ------------------------------------------------------------------------- *//* vals in pixels *//* ref is front plane */voiddraw_3d_area( gdImagePtr im, int x1, int x2, int y0, /* drawn from 0 */ int y1, int y2, int xdepth, int ydepth, int clr, int clrshd ){ gdPoint poly[4]; int y_intercept = 0; /* if xdepth || ydepth */ if( xdepth || ydepth ) { float line_slope = x2==x1? MAXFLOAT: (float)-(y2-y1) / (float)(x2-x1); float depth_slope = xdepth==0? MAXFLOAT: (float)ydepth/(float)xdepth; y_intercept = (y1 > y0 && y2 < y0) || /* line crosses y0 */ (y1 < y0 && y2 > y0)? (int)((1.0/ABS(line_slope))*(float)(ABS(y1-y0)))+x1: 0; /* never */ /* edging along*/ gdImageLine( im, x1+xdepth, y0-ydepth, x2+xdepth, y0-ydepth, clrshd ); SET_3D_POLY( poly, x1, x2, y1, y2, xdepth, ydepth ); /* top */ gdImageFilledPolygon( im, poly, 4, line_slope>depth_slope? clrshd: clr ); SET_3D_POLY( poly, x1, x2, y0, y0, xdepth, ydepth+1 ); /* along y axis */ gdImageFilledPolygon( im, poly, 4, clr ); SET_3D_POLY( poly, x2, x2, y0, y2, xdepth, ydepth ); /* side */ gdImageFilledPolygon( im, poly, 4, clrshd ); if( y_intercept ) gdImageLine( im, y_intercept, y0, y_intercept+xdepth, y0-ydepth, clrshd );/* edging */ gdImageLine( im, x1, y0, x1+xdepth, y0-ydepth, clrshd ); /* edging */ gdImageLine( im, x2, y0, x2+xdepth, y0-ydepth, clrshd ); /* edging */ /* SET_3D_POLY( poly, x2, x2, y0, y2, xdepth, ydepth ); gdImageFilledPolygon( im, poly, 4, clrshd ); */ gdImageLine( im, x1, y1, x1+xdepth, y1-ydepth, clrshd ); /* edging */ gdImageLine( im, x2, y2, x2+xdepth, y2-ydepth, clrshd ); /* edging */ } if( y1 == y2 ) /* bar rect */ SET_RECT( poly, x1, x2, y0, y1 ); /* front */ else { poly[0].x = x1; poly[0].y = y0; poly[1].x = x2; poly[1].y = y0; poly[2].x = x2; poly[2].y = y2; poly[3].x = x1; poly[3].y = y1; } gdImageFilledPolygon( im, poly, 4, clr ); gdImageLine( im, x1, y0, x2, y0, clrshd ); /* edging along y0 */ if( (xdepth || ydepth) && /* front edging only on 3D */ (y1<y0 || y2<y0) ) /* and only above y0 */ { if( y1 > y0 && y2 < y0 ) /* line crosses from below y0 */ gdImageLine( im, y_intercept, y0, x2, y2, clrshd ); else if( y1 < y0 && y2 > y0 ) /* line crosses from above y0 */ gdImageLine( im, x1, y1, y_intercept, y0, clrshd ); else /* completely above */ gdImageLine( im, x1, y1, x2, y2, clrshd ); }}/* ------------------------------------------------------------------------- *//* vals in pixels *//* ref is front plane */voiddraw_3d_bar( gdImagePtr im, int x1, int x2, int y0, int yhigh, int xdepth, int ydepth, int clr, int clrshd ){#define SET_3D_BAR( gdp, x1, x2, y1, y2, xoff, yoff ) \ gdp[0].x = x1, gdp[0].y = y1, \ gdp[1].x = x1+(xoff), gdp[1].y = y1-yoff, \ gdp[2].x = x2+(xoff), gdp[2].y = y2-yoff, \ gdp[3].x = x2, gdp[3].y = y2 gdPoint poly[4]; int usd = MIN( y0, yhigh ); /* up-side-down bars */ if( xdepth || ydepth ) { if( y0 != yhigh ) /* 0 height? */ { SET_3D_BAR( poly, x2, x2, y0, yhigh, xdepth, ydepth ); /* side */ gdImageFilledPolygon( im, poly, 4, clrshd ); } SET_3D_BAR( poly, x1, x2, usd, usd, xdepth, ydepth ); /* top */ gdImageFilledPolygon( im, poly, 4, clr ); } SET_RECT( poly, x1, x2, y0, yhigh ); /* front */ gdImageFilledPolygon( im, poly, 4, clr ); if( xdepth || ydepth ) gdImageLine( im, x1, usd, x2, usd, clrshd );}/* ------------------------------------------------------------------------- */struct BS { float y1; float y2; int clr; int shclr; };static int barcmpr( const void *a, const void *b ) { if( ((struct BS*)a)->y2 < ((struct BS*)b)->y2 ) return -1; if( ((struct BS*)a)->y2 > ((struct BS*)b)->y2 ) return 1; return 0; }/* ------------------------------------------------------------------------- *//* little/no error checking 0: ok, -ret: error no graph output ret: error graph out watch out for # params and array sizes==num_points*/intout_graph( short GIFWIDTH, /* no check for a gif that's too small to fit */ short GIFHEIGHT, /* needed info (labels, etc), could core dump */ FILE *gif_fptr, /* open file pointer (gif out) */ GDC_CHART_T type, int num_points, /* points along x axis (even iterval) */ /* all arrays dependant on this */ char *xlbl[], /* array of xlabels */ int num_sets, ... ){ va_list ap; int i, j; int graphwidth; int grapheight; gdImagePtr im; gdImagePtr bg_img = NULL; float xorig, yorig, vyorig = 0.0; float yscl = 0.0; float vyscl = 0.0; float xscl = 0.0; float vhighest = -MAXFLOAT; float vlowest = MAXFLOAT; float highest = -MAXFLOAT; float lowest = MAXFLOAT; char do_vol = ( type == GDC_COMBO_HLC_BAR || /* aka: combo */ type == GDC_COMBO_HLC_AREA || type == GDC_COMBO_LINE_BAR || type == GDC_COMBO_LINE_AREA || type == GDC_3DCOMBO_HLC_BAR || type == GDC_3DCOMBO_HLC_AREA|| type == GDC_3DCOMBO_LINE_BAR|| type == GDC_3DCOMBO_LINE_AREA ); char threeD = ( type == GDC_3DAREA || type == GDC_3DLINE || type == GDC_3DBAR || type == GDC_3DHILOCLOSE || type == GDC_3DCOMBO_HLC_BAR || type == GDC_3DCOMBO_HLC_AREA|| type == GDC_3DCOMBO_LINE_BAR|| type == GDC_3DCOMBO_LINE_AREA ); char num_hlc_sets = ( type == GDC_COMBO_HLC_BAR || type == GDC_COMBO_HLC_AREA || type == GDC_3DCOMBO_HLC_BAR || type == GDC_3DCOMBO_HLC_AREA|| type == GDC_3DHILOCLOSE || type == GDC_HILOCLOSE )? num_sets: 0; char do_bar = ( type == GDC_3DBAR || /* offset X objects to leave */ type == GDC_BAR ); /* room at X(0) and X(n) */ /* i.e., not up against Y axes*/ char do_ylbl_fractions = /* %f format not given, or*/ ( !GDC_ylabel_fmt || /* format doesn't have a %,g,e,E,f or F*/ strlen(GDC_ylabel_fmt) == strcspn(GDC_ylabel_fmt,"%geEfF") ); float ylbl_interval = 0.0; int num_lf_xlbls = 0; int xdepth_3Dtotal = 0; int ydepth_3Dtotal = 0; int xdepth_3D = 0; /* affects PX()*/ int ydepth_3D = 0; /* affects PY() and PV()*/ int hlf_barwdth = 0; /* half bar widths*/ int hlf_hlccapwdth = 0; /* half cap widths for HLC_I_CAP and DIAMOND*/ int annote_len = 0, annote_hgt = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -