From: <hez...@us...> - 2009-08-04 01:39:05
|
Revision: 10206 http://plplot.svn.sourceforge.net/plplot/?rev=10206&view=rev Author: hezekiahcarty Date: 2009-08-04 01:38:53 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Add support for custom axis labels Modified Paths: -------------- trunk/doc/docbook/src/api.xml trunk/include/plplot.h trunk/include/plstrm.h trunk/src/plbox.c trunk/src/plvpor.c Modified: trunk/doc/docbook/src/api.xml =================================================================== --- trunk/doc/docbook/src/api.xml 2009-08-03 20:32:05 UTC (rev 10205) +++ trunk/doc/docbook/src/api.xml 2009-08-04 01:38:53 UTC (rev 10206) @@ -11887,6 +11887,64 @@ </sect1> + <sect1 id="plslabelfunc" renderas="sect3"> + <title> + <function>plslabelfunc</function>: Assign a function to use for generating custom axis labels + </title> + + <para> + <funcsynopsis> + <funcprototype> + <funcdef> + <function>plslabelfunc</function> + </funcdef> + <paramdef><parameter>label_func</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </para> + + <para> + This function allows a user to provide their own function to provide + axis label text. The user function is given the numeric value for a + point on an axis and returns a string label to correspond with that + value. + </para> + + <variablelist> + <varlistentry> + <term> + <parameter>label_func</parameter> + (<literal>void (*) (PLINT, PLFLT, const char *, void *)</literal>, input) + </term> + <listitem> + <para> + This is the custom label function. In order to reset to the + default labeling, set this to <literal>NULL</literal>. The + <literal>const char*</literal> argument should be set to point to + the appropriate label text. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>label_data</parameter> + (<literal>void *</literal>, input) + </term> + <listitem> + <para> + This parameter may be used to pass data to the label_func + function. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + This function is used in examples 1 and 19. + </para> + + </sect1> + <sect1 id="plsmaj" renderas="sect3"> <title> <function>plsmaj</function>: Set length of major ticks Modified: trunk/include/plplot.h =================================================================== --- trunk/include/plplot.h 2009-08-03 20:32:05 UTC (rev 10205) +++ trunk/include/plplot.h 2009-08-04 01:38:53 UTC (rev 10206) @@ -253,6 +253,11 @@ #define PLSWIN_DEVICE 1 /* device coordinates */ #define PLSWIN_WORLD 2 /* world coordinates */ +/* Axis label tags */ +#define PL_X_AXIS 1 /* The x-axis */ +#define PL_Y_AXIS 2 /* The y-axis */ +#define PL_Z_AXIS 3 /* The z-axis */ + /* PLplot Option table & support constants */ /* Option-specific settings */ @@ -451,6 +456,11 @@ #define PLESC_DOUBLEBUFFERING_DISABLE 2 #define PLESC_DOUBLEBUFFERING_QUERY 3 +typedef struct { + PLFLT exp_label_disp; + PLFLT exp_label_pos; + PLFLT exp_label_just; +} PLLabelDefaults; /*--------------------------------------------------------------------------*\ * BRAINDEAD-ness @@ -518,6 +528,7 @@ #define plbop c_plbop #define plbox c_plbox #define plbox3 c_plbox3 +#define plslabelfunc c_plslabelfunc #define plcalc_world c_plcalc_world #define plarc c_plarc #define plclear c_plclear @@ -768,6 +779,11 @@ const char *yopt, const char *ylabel, PLFLT ytick, PLINT nsuby, const char *zopt, const char *zlabel, PLFLT ztick, PLINT nsubz); +/* Setup a user-provided custom labeling function */ +PLDLLIMPEXP void +c_plslabelfunc(void (*label_func)(PLINT, PLFLT, const char *, PLPointer), + PLPointer label_data); + /* Calculate world coordinates and subpage from relative device coordinates. */ PLDLLIMPEXP void Modified: trunk/include/plstrm.h =================================================================== --- trunk/include/plstrm.h 2009-08-03 20:32:05 UTC (rev 10205) +++ trunk/include/plstrm.h 2009-08-04 01:38:53 UTC (rev 10206) @@ -656,6 +656,8 @@ PLINT xdigmax, ydigmax, zdigmax; PLINT xdigits, ydigits, zdigits; char *timefmt; + void (*label_func)(PLINT, PLFLT, const char *, PLPointer); + PLPointer label_data; /* Variables governing physical coordinate system */ Modified: trunk/src/plbox.c =================================================================== --- trunk/src/plbox.c 2009-08-03 20:32:05 UTC (rev 10205) +++ trunk/src/plbox.c 2009-08-04 01:38:53 UTC (rev 10206) @@ -37,7 +37,7 @@ /* Static function prototypes */ static void -plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1, +plxybx(const char *opt, const char *label, PLINT axis, PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2, PLFLT vmin, PLFLT vmax, PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits); @@ -55,7 +55,7 @@ PLFLT wy2, PLFLT disp, PLFLT pos, PLFLT just, const char *text); static void -plform(PLFLT value, PLINT scale, PLINT prec, char *result, PLINT len, PLINT ll, PLINT lf); +plform(PLINT axis, PLFLT value, PLINT scale, PLINT prec, char *result, PLINT len, PLBOOL ll, PLBOOL lf, PLBOOL lo); static void grid_box(const char *xopt, PLFLT xtick1, PLINT nxsub1, @@ -102,6 +102,7 @@ * l: Logarithmic axes, major ticks at decades, minor ticks at units * n: Write numeric label at conventional location * m: Write numeric label at unconventional location + * o: Label text is generated by a user-defined function * t: Draw major tick marks * s: Draw minor tick marks * v: (for Y only) Label vertically @@ -520,7 +521,7 @@ ty = plP_w3wcy(xmin, ymin, zmin); ux = plP_w3wcx(xmax, ymin, zmin); uy = plP_w3wcy(xmax, ymin, zmin); - plxybx(xopt, xlabel, tx, ty, ux, uy, + plxybx(xopt, xlabel, PL_X_AXIS, tx, ty, ux, uy, xmin, xmax, xtick, nsubx, 0, &xdigits); dx = ux - tx; @@ -532,7 +533,7 @@ ty = plP_w3wcy(xmin, ymax, zmin); ux = plP_w3wcx(xmin, ymin, zmin); uy = plP_w3wcy(xmin, ymin, zmin); - plxybx(yopt, ylabel, tx, ty, ux, uy, + plxybx(yopt, ylabel, PL_Y_AXIS, tx, ty, ux, uy, ymax, ymin, ytick, nsuby, ln, &ydigits); dx = ux - tx; @@ -548,7 +549,7 @@ ty = plP_w3wcy(xmin, ymax, zmin); ux = plP_w3wcx(xmin, ymin, zmin); uy = plP_w3wcy(xmin, ymin, zmin); - plxybx(yopt, ylabel, tx, ty, ux, uy, + plxybx(yopt, ylabel, PL_Y_AXIS, tx, ty, ux, uy, ymax, ymin, ytick, nsuby, 0, &ydigits); dx = ux - tx; @@ -560,7 +561,7 @@ ty = plP_w3wcy(xmax, ymax, zmin); ux = plP_w3wcx(xmin, ymax, zmin); uy = plP_w3wcy(xmin, ymax, zmin); - plxybx(xopt, xlabel, tx, ty, ux, uy, + plxybx(xopt, xlabel, PL_X_AXIS, tx, ty, ux, uy, xmax, xmin, xtick, nsubx, ln, &xdigits); dx = ux - tx; @@ -576,7 +577,7 @@ ty = plP_w3wcy(xmax, ymax, zmin); ux = plP_w3wcx(xmin, ymax, zmin); uy = plP_w3wcy(xmin, ymax, zmin); - plxybx(xopt, xlabel, tx, ty, ux, uy, + plxybx(xopt, xlabel, PL_X_AXIS, tx, ty, ux, uy, xmax, xmin, xtick, nsubx, 0, &xdigits); dx = ux - tx; @@ -588,7 +589,7 @@ ty = plP_w3wcy(xmax, ymin, zmin); ux = plP_w3wcx(xmax, ymax, zmin); uy = plP_w3wcy(xmax, ymax, zmin); - plxybx(yopt, ylabel, tx, ty, ux, uy, + plxybx(yopt, ylabel, PL_Y_AXIS, tx, ty, ux, uy, ymin, ymax, ytick, nsuby, ln, &ydigits); dx = ux - tx; @@ -604,7 +605,7 @@ ty = plP_w3wcy(xmax, ymin, zmin); ux = plP_w3wcx(xmax, ymax, zmin); uy = plP_w3wcy(xmax, ymax, zmin); - plxybx(yopt, ylabel, tx, ty, ux, uy, + plxybx(yopt, ylabel, PL_X_AXIS, tx, ty, ux, uy, ymin, ymax, ytick, nsuby, 0, &ydigits); dx = ux - tx; @@ -616,7 +617,7 @@ ty = plP_w3wcy(xmin, ymin, zmin); ux = plP_w3wcx(xmax, ymin, zmin); uy = plP_w3wcy(xmax, ymin, zmin); - plxybx(xopt, xlabel, tx, ty, ux, uy, + plxybx(xopt, xlabel, PL_X_AXIS, tx, ty, ux, uy, xmin, xmax, xtick, nsubx, ln, &xdigits); dx = ux - tx; @@ -649,18 +650,19 @@ * i: Inverts tick marks (i.e. drawn downwards) * l: Logarithmic axes, major ticks at decades, minor ticks at units * n: Write numeric label + * o: Use custom label function * t: Draw major tick marks * s: Draw minor tick marks * u: Write label on line \*--------------------------------------------------------------------------*/ static void -plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1, +plxybx(const char *opt, const char *label, PLINT axis, PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2, PLFLT vmin_in, PLFLT vmax_in, PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits) { static char string[STRING_LEN]; - PLINT lb, ld, lf, li, ll, ln, ls, lt, lu; + PLINT lb, ld, lf, li, ll, ln, ls, lt, lu, lo; PLINT major, minor, mode, prec, scale; PLINT i, i1, i2, i3, i4; PLINT nsub1; @@ -692,6 +694,7 @@ ls = plP_stsearch(opt, 's'); lt = plP_stsearch(opt, 't'); lu = plP_stsearch(opt, 'u'); + lo = plP_stsearch(opt, 'o'); if (lu) plxytx(wx1, wy1, wx2, wy2, 3.2, 0.5, 0.5, label); @@ -776,7 +779,7 @@ tp = tick1 * (1. + floor(vmin / tick1)); for (tn = tp; BETW(tn, vmin, vmax); tn += tick1) { if(BETW(tn, vmin+tcrit, vmax-tcrit)) { - plform(tn, scale, prec, string, STRING_LEN, ll, lf); + plform(axis, tn, scale, prec, string, STRING_LEN, ll, lf, lo); pos = (vmax_in > vmin_in)? (tn - vmin) / (vmax - vmin): (vmax - tn) / (vmax - vmin); @@ -784,7 +787,7 @@ } } *digits = 2; - if (!ll && mode) { + if (!ll && !lo && mode) { snprintf(string, STRING_LEN, "(x10#u%d#d)", (int) scale); plxytx(wx1, wy1, wx2, wy2, height, 1.0, 0.5, string); } @@ -859,6 +862,7 @@ * l: Logarithmic axes, major ticks at decades, minor ticks at units * m: Write numeric label on right axis * n: Write numeric label on left axis + * o: Use custom label function * s: Draw minor tick marks * t: Draw major tick marks * u: Writes left-hand label @@ -871,7 +875,7 @@ PLFLT tick, PLINT nsub, PLINT *digits) { static char string[STRING_LEN]; - PLINT lb, lc, ld, lf, li, ll, lm, ln, ls, lt, lu, lv; + PLINT lb, lc, ld, lf, li, ll, lm, ln, ls, lt, lu, lv, lo; PLINT i, mode, prec, scale; PLINT nsub1, lstring; PLFLT pos, tn, tp, temp, height, tick1; @@ -903,6 +907,7 @@ lt = plP_stsearch(opt, 't'); lu = plP_stsearch(opt, 'u'); lv = plP_stsearch(opt, 'v'); + lo = plP_stsearch(opt, 'o'); if (lu && !right) plztx("h", dx, dy, wx, wy1, wy2, 5.0, 0.5, 0.5, label); @@ -992,7 +997,7 @@ *digits = 0; tp = tick1 * floor(vmin / tick1); for (tn = tp + tick1; BETW(tn, vmin, vmax); tn += tick1) { - plform(tn, scale, prec, string, STRING_LEN, ll, lf); + plform(PL_Z_AXIS, tn, scale, prec, string, STRING_LEN, ll, lf, lo); pos = (vmax_in > vmin_in)? (tn - vmin) / (vmax - vmin): (vmax - tn) / (vmax - vmin); @@ -1005,7 +1010,7 @@ lstring = strlen(string); *digits = MAX(*digits, lstring); } - if (!ll && mode) { + if (!ll && !lo && mode) { snprintf(string, STRING_LEN, "(x10#u%d#d)", (int) scale); pos = 1.15; height = 0.5; @@ -1196,11 +1201,11 @@ label_box(const char *xopt, PLFLT xtick1, const char *yopt, PLFLT ytick1) { static char string[STRING_LEN]; - PLBOOL ldx, lfx, lix, llx, lmx, lnx, ltx; - PLBOOL ldy, lfy, liy, lly, lmy, lny, lty, lvy; + PLBOOL ldx, lfx, lix, llx, lmx, lnx, ltx, lox; + PLBOOL ldy, lfy, liy, lly, lmy, lny, lty, lvy, loy; PLFLT vpwxmi, vpwxma, vpwymi, vpwyma; PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax; - PLFLT pos, tn, tp, offset, height; + PLFLT pos, tn, tp, offset, height, just; PLFLT factor, tstart; const char *timefmt; @@ -1213,6 +1218,7 @@ lmx = plP_stsearch(xopt, 'm'); lnx = plP_stsearch(xopt, 'n'); ltx = plP_stsearch(xopt, 't'); + lox = plP_stsearch(xopt, 'o'); ldy = plP_stsearch(yopt, 'd'); lfy = plP_stsearch(yopt, 'f'); @@ -1222,6 +1228,7 @@ lny = plP_stsearch(yopt, 'n'); lty = plP_stsearch(yopt, 't'); lvy = plP_stsearch(yopt, 'v'); + loy = plP_stsearch(yopt, 'o'); plP_xgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax); /* n.b. large change; vpwxmi always numerically less than vpwxma, and @@ -1251,7 +1258,7 @@ strfqsas(string, STRING_LEN, timefmt, (double) tn, plsc->qsasconfig); } else { - plform(tn, xscale, xprec, string, STRING_LEN, llx, lfx); + plform(PL_X_AXIS, tn, xscale, xprec, string, STRING_LEN, llx, lfx, lox); } height = lix ? 1.75 : 1.5; pos = (vpwxmax > vpwxmin)? @@ -1267,14 +1274,24 @@ /* Write separate exponential label if mode = 1. */ - if (!llx && !ldx && xmode) { - pos = 1.0; - height = 3.2; + if (!llx && !ldx && !lox && xmode) { + /* Assume label data is for placement of exponents if no custom + label function is provided. */ + if (plsc->label_data) { + height = ((PLLabelDefaults *)plsc->label_data)->exp_label_disp; + pos = ((PLLabelDefaults *)plsc->label_data)->exp_label_pos; + just = ((PLLabelDefaults *)plsc->label_data)->exp_label_just; + } + else { + height = 3.2; + pos = 1.0; + just = 0.5; + } snprintf(string, STRING_LEN, "(x10#u%d#d)", (int) xscale); if (lnx) - plmtex("b", height, pos, 0.5, string); + plmtex("b", height, pos, just, string); if (lmx) - plmtex("t", height, pos, 0.5, string); + plmtex("t", height, pos, just, string); } } @@ -1298,7 +1315,7 @@ strfqsas(string, STRING_LEN, timefmt, (double) tn, plsc->qsasconfig); } else { - plform(tn, yscale, yprec, string, STRING_LEN, lly, lfy); + plform(PL_Y_AXIS, tn, yscale, yprec, string, STRING_LEN, lly, lfy, loy); } pos = (vpwymax > vpwymin)? (tn - vpwymi) / (vpwyma - vpwymi): @@ -1330,18 +1347,26 @@ /* Write separate exponential label if mode = 1. */ - if (!lly && !ldy && ymode) { + if (!lly && !ldy && !loy && ymode) { snprintf(string, STRING_LEN, "(x10#u%d#d)", (int) yscale); - offset = 0.02; - height = 2.0; - if (lny) { - pos = 0.0 - offset; - plmtex("t", height, pos, 1.0, string); - } - if (lmy) { - pos = 1.0 + offset; - plmtex("t", height, pos, 0.0, string); - } + if (plsc->label_data) { + height = ((PLLabelDefaults *)plsc->label_data)->exp_label_disp; + pos = ((PLLabelDefaults *)plsc->label_data)->exp_label_pos; + just = ((PLLabelDefaults *)plsc->label_data)->exp_label_just; + } + else { + offset = 0.02; + height = 2.0; + if (lny) { + pos = 0.0 - offset; + just = 1.0; + } + if (lmy) { + pos = 1.0 + offset; + just = 0.0; + } + } + plmtex("t", height, pos, just, string); } } } @@ -1366,62 +1391,108 @@ * - If scale == 1, use scientific notation with one place before the * decimal point and "prec" places after. In this case, the value * must be divided by 10^scale. + * + * The axis argument is included to support PLplot's custom axis labeling. It + * is passed on to the custom labeling function if it exists. Otherwise, it + * is ignored. \*--------------------------------------------------------------------------*/ static void -plform(PLFLT value, PLINT scale, PLINT prec, char *string, PLINT len, PLINT ll, PLINT lf) +plform(PLINT axis, PLFLT value, PLINT scale, PLINT prec, char *string, PLINT len, PLBOOL ll, PLBOOL lf, PLBOOL lo) { - if (ll) { + const char *custom_string; - /* Logarithmic */ + /* Check to see if a custom labeling function is defined. If not, */ + if (lo && plsc->label_func) { + (*plsc->label_func)(axis, value, custom_string, plsc->label_data); + snprintf(string, len, "%s", custom_string); + } + else { + if (lo) { + plwarn("Custom axis labels requested without a labeling function \ + - using default."); + } + if (ll) { - if (lf) { + /* Logarithmic */ - /* Fixed point, i.e. .1, 1, 10, etc */ + if (lf) { - int exponent = ROUND(value); + /* Fixed point, i.e. .1, 1, 10, etc */ - value = pow(10.0, exponent); - if (exponent < 0) { - char form[FORMAT_LEN]; - snprintf(form, FORMAT_LEN, "%%.%df", ABS(exponent)); - snprintf(string, len, form, value); - } - else { - snprintf(string, len, "%d", (int) value); - } - } - else { + int exponent = ROUND(value); - /* Exponential, i.e. 10^-1, 10^0, 10^1, etc */ + value = pow(10.0, exponent); + if (exponent < 0) { + char form[FORMAT_LEN]; + snprintf(form, FORMAT_LEN, "%%.%df", ABS(exponent)); + snprintf(string, len, form, value); + } + else { + snprintf(string, len, "%d", (int) value); + } + } + else { - snprintf(string, len, "10#u%d", (int) ROUND(value)); - } - } - else { + /* Exponential, i.e. 10^-1, 10^0, 10^1, etc */ - /* Linear */ + snprintf(string, len, "10#u%d", (int) ROUND(value)); + } + } + else { - PLINT setpre, precis; - char form[FORMAT_LEN], temp[TEMP_LEN]; - double scale2; + /* Linear */ - plP_gprec(&setpre, &precis); + PLINT setpre, precis; + char form[FORMAT_LEN], temp[TEMP_LEN]; + double scale2; - if (setpre) - prec = precis; + plP_gprec(&setpre, &precis); - if (scale) - value /= pow(10.,(double)scale); + if (setpre) + prec = precis; - /* This is necessary to prevent labels like "-0.0" on some systems */ + if (scale) + value /= pow(10.,(double)scale); - scale2 = pow(10., prec); - value = floor((value * scale2) + .5) / scale2; + /* This is necessary to prevent labels like "-0.0" on some systems */ - snprintf(form, FORMAT_LEN, "%%.%df", (int) prec); - snprintf(temp, TEMP_LEN, form, value); - strncpy(string, temp, len-1); - string[len-1] = '\0'; + scale2 = pow(10., prec); + value = floor((value * scale2) + .5) / scale2; + + snprintf(form, FORMAT_LEN, "%%.%df", (int) prec); + snprintf(temp, TEMP_LEN, form, value); + strncpy(string, temp, len-1); + string[len-1] = '\0'; + } } } + +/*--------------------------------------------------------------------------*\ + * plslabelfunc + * + * Formats a PLFLT value in one of the following formats. + * + * label_func - A pointer to a function which will provide a string to use + * as the label for the given floating point value. + * Pass this as NULL to clear the custom function and reset it to + * the default PLplot labeling function. + * + * label_data - Extra data to pass to the label function. + * + * The label_func function arguments are, in order: + * + * axis: PL_X_AXIS, PL_Y_AXIS or PL_Z_AXIS to indicate which axis is being + * labeled + * value: The value at this position on the axis + * string: The resulting label string should be stored here + * data: A pointer to whatever extra information the custom plotting function + * requires + * +\*--------------------------------------------------------------------------*/ +void +c_plslabelfunc(void (*label_func)(PLINT, PLFLT, const char *, PLPointer), PLPointer label_data) +{ + plsc->label_func = label_func; + plsc->label_data = label_data; +} Modified: trunk/src/plvpor.c =================================================================== --- trunk/src/plvpor.c 2009-08-03 20:32:05 UTC (rev 10205) +++ trunk/src/plvpor.c 2009-08-04 01:38:53 UTC (rev 10206) @@ -81,6 +81,10 @@ * axis=61 : Same as 1 except date / time X,Y tick marks. * axis=62 : Same as 2 except date / time X,Y tick marks. * axis=63 : Same as 62, but the grid will be also at the minor ticks. + * axis=70 : Same as 0 except custom X,Y labels. + * axis=71 : Same as 1 except custom X,Y labels. + * axis=72 : Same as 2 except custom X,Y labels. + * axis=73 : Same as 72, but the grid will be also at the minor ticks. \*--------------------------------------------------------------------------*/ void @@ -269,6 +273,18 @@ case 63: plbox("abcgdnsth", (PLFLT) 0.0, 0, "abcgdnstvh", (PLFLT) 0.0, 0); break; + case 70: + plbox("bcnost", (PLFLT) 0.0, 0, "bcnostv", (PLFLT) 0.0, 0); + break; + case 71: + plbox("abcnost", (PLFLT) 0.0, 0, "abcnostv", (PLFLT) 0.0, 0); + break; + case 72: + plbox("abcgnost", (PLFLT) 0.0, 0, "abcgnostv", (PLFLT) 0.0, 0); + break; + case 73: + plbox("abcgnosth", (PLFLT) 0.0, 0, "abcgnostvh", (PLFLT) 0.0, 0); + break; default: plwarn("plenv: Invalid axis argument"); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |