Dear All,
Many moons ago I started a discussion which ended up with the provision of
plslabelfunc to allow user control of axis labelling, including positioning of
the separate exponential string. It turns out that code works fine for the
horizontal (x) axis, but not for the vertical (y) axis. I attach a simple
example that illustrates this. When run with the latest release (5.9.9) of
plplot, there are no exponential strings for the y-axis. You will see that I
only use plslabelfunc to set the position of the exponential label, passing it
a NULL pointer to a labelling function, and not using the "o" axis option.
I have dug into the label_box code (contained within plbox.c) and hacked it to
work correctly I think. This involved several changes, which are tagged with
//sjs comments in the attached label_box_sjs.c file. All this is in areas of
the code that deal with boxbb settings about which I know nothing, so I'm not
confident that everything I've done will be robust against things used by other
routines (perhaps only pllegend).
Here is a summary of the basic changes. I looked at how the x-axis was handled
and tried to make the y-axis handling completely parallel in its construction
apart from the added complication of a "v" option for the y-axis labelling. I
only dealt with the sections that explicitly deal with the exponential label.
1) I moved code that calculated/set "pos" and "just" up to within the same
bracket as "height". Messier here than in the x-axis case because I had to
replicate the if(lny) and if(lmy) clauses. This isn't needed to get my example
to work, but looked necessary to preserve the behaviour of the code. I don't
have an example that exercises this set of changes, but if the old bits did
what you wanted them to then I think my version will as well.
2) I then inserted a "}" after this to effectively out-dent the remaining code.
This enables the call to plmtex to be reached (which is why the exponential
label for the y-axis doesn't appear in my test case). I removed one of the
closing "}"'s from the end of the routine to rebalance the curly braces. I
haven't reformatted the indentation here.
3) Finally I replaced the single call to plmtex("t", ...) by a pair of calls in
an if(lvy) clause to plmtex("lv" or plmtex("l" - I think whatever else was
going on the original was in error here.
I haven't replicated the above in label_box_custom, but this would need to be
done I think.
I hope this makes sense and that those of you in more control of the code can
decide if indeed the code needs fixing and if my fix, or something else, is the
most appropriate way to fix it.
Best wishes
Steve
--------------------------------------------------------------------
Professor Steven J Schwartz Phone: +44 (0)207 594 7660
Head, Space & Atmospheric Physics Fax: +44 (0)207 594 7772
The Blackett Laboratory Email: s.schwa...@imperial.ac.uk
Imperial College London Office: Huxley 6M67A
London SW7 2AZ, UK Web: www.sp.ph.ic.ac.uk/~sjs
--------------------------------------------------------------------
/* sjs plplot test Feb 2013 */
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "plConfig.h"
#include "plplot.h"
/* prototpyes */
void plot1(PLFLT xmax);
/*************************************************/
int main(int argc, const char *argv[]){
plparseopts(&argc, argv, PL_PARSE_FULL);
plstar(2,2);
plot1(10.);
plot1(1000.);
plot1(100000.);
plot1(10000000000.);
plend();
exit(0);
}
void plot1(PLFLT xmax) {
PLFLT x[2],y[2];
PLLabelDefaults label_opt;
x[0]=0.; y[0]=0.;
x[1]=xmax;
y[1]=x[1];
/* plenv(-0.5*xmax, 1.5*xmax, -0.5*xmax, 1.5*xmax, 0, 70) */;
pladv(0);
plvpor(0.2,0.8,0.2,0.8);
plwind(-0.5*xmax, 1.5*xmax, -0.5*xmax, 1.5*xmax);
label_opt.exp_label_disp = 3.5;
label_opt.exp_label_pos = 1.0;
label_opt.exp_label_just = 1.0;
plslabelfunc(NULL,&label_opt);
plbox("bcnmst",0,0,"",0,0);
label_opt.exp_label_disp = 3.0;
label_opt.exp_label_pos = 1.0;
label_opt.exp_label_just = 1.0;
plslabelfunc(NULL,&label_opt);
plbox("",0,0,"bcmnstv",0,0);
pllab("(x)", "(y)", "test");
plline(2,x,y);
plslabelfunc(NULL,NULL);
}
//--------------------------------------------------------------------------
// void label_box()
//
// Writes numeric labels on side(s) of box.
//--------------------------------------------------------------------------
static void
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, lox, lxx;
PLBOOL ldy, lfy, liy, lly, lmy, lny, lty, lvy, loy, lxy;
PLFLT vpwxmi, vpwxma, vpwymi, vpwyma;
PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
PLFLT pos, tn, tp, offset, height, just;
PLFLT factor, tstart;
const char *timefmt;
PLFLT default_mm, char_height_mm, height_mm;
PLFLT string_length_mm, pos_mm;
plgchr( &default_mm, &char_height_mm );
// Set plot options from input
ldx = plP_stsearch( xopt, 'd' );
lfx = plP_stsearch( xopt, 'f' );
lix = plP_stsearch( xopt, 'i' );
llx = plP_stsearch( xopt, 'l' );
lmx = plP_stsearch( xopt, 'm' );
lnx = plP_stsearch( xopt, 'n' );
ltx = plP_stsearch( xopt, 't' );
lox = plP_stsearch( xopt, 'o' );
lxx = plP_stsearch( xopt, 'x' );
ldy = plP_stsearch( yopt, 'd' );
lfy = plP_stsearch( yopt, 'f' );
liy = plP_stsearch( yopt, 'i' );
lly = plP_stsearch( yopt, 'l' );
lmy = plP_stsearch( yopt, 'm' );
lny = plP_stsearch( yopt, 'n' );
lty = plP_stsearch( yopt, 't' );
lvy = plP_stsearch( yopt, 'v' );
loy = plP_stsearch( yopt, 'o' );
lxy = plP_stsearch( yopt, 'x' );
plP_xgvpw( &vpwxmin, &vpwxmax, &vpwymin, &vpwymax );
// vpwxmi always numerically less than vpwxma, and
// similarly for vpwymi
vpwxmi = ( vpwxmax > vpwxmin ) ? vpwxmin : vpwxmax;
vpwxma = ( vpwxmax > vpwxmin ) ? vpwxmax : vpwxmin;
vpwymi = ( vpwymax > vpwymin ) ? vpwymin : vpwymax;
vpwyma = ( vpwymax > vpwymin ) ? vpwymax : vpwymin;
// Write label(s) for horizontal axes.
if ( ( lmx || lnx ) && ( ltx || lxx ) )
{
PLINT xmode, xprec, xdigmax, xdigits, xscale;
plgxax( &xdigmax, &xdigits );
pldprec( vpwxmi, vpwxma, xtick1, lfx, &xmode, &xprec, xdigmax, &xscale
);
timefmt = plP_gtimefmt();
if ( ldx )
{
pldtfac( vpwxmi, vpwxma, &factor, &tstart );
tp = xtick1 * ( 1. + floor( ( vpwxmi - tstart ) / xtick1 ) ) +
tstart;
}
else
{
tp = xtick1 * ( 1. + floor( vpwxmi / xtick1 ) );
}
height = lix ? 1.75 : 1.5;
if ( plsc->if_boxbb )
{
// For horizontal axes, height of zero corresponds to
// character centred on edge so should add 0.5 to height
// to obtain bounding box edge in direction away from
// edge. However, experimentally found 0.7 gave a better
// looking result.
height_mm = ( height + 0.7 ) * char_height_mm;
if ( lnx )
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin, plsc->vppymi /
plsc->ypmm - height_mm );
if ( lmx )
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax, plsc->vppyma /
plsc->ypmm + height_mm );
}
for ( tn = tp; BETW( tn, vpwxmi, vpwxma ); tn += xtick1 )
{
if ( ldx )
{
strfqsas( string, STRING_LEN, timefmt, (double) tn,
plsc->qsasconfig );
}
else
{
plform( PL_X_AXIS, tn, xscale, xprec, string, STRING_LEN, llx,
lfx, lox );
}
pos = ( vpwxmax > vpwxmin ) ?
( tn - vpwxmi ) / ( vpwxma - vpwxmi ) :
( vpwxma - tn ) / ( vpwxma - vpwxmi );
if ( plsc->if_boxbb )
{
string_length_mm = plstrl( string );
pos_mm = ( plsc->vppxmi + pos *
( plsc->vppxma - plsc->vppxmi ) ) /
plsc->xpmm;
}
if ( lnx )
{
// Bottom axis.
if ( plsc->if_boxbb )
{
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "b", height, pos, 0.5, string );
}
}
if ( lmx )
{
// Top axis.
if ( plsc->if_boxbb )
{
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "t", height, pos, 0.5, string );
}
}
}
xdigits = 2;
plsxax( xdigmax, xdigits );
// Write separate exponential label if mode = 1.
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 )
{
// Bottom axis exponent.
if ( plsc->if_boxbb )
{
// For horizontal axes, height of zero corresponds
// to character centred on edge so should add 0.5
// to height to obtain bounding box edge in
// direction away from edge if no exponent. Add
// an additional offset to make exponent fit.
height_mm = ( height + 0.9 ) * char_height_mm;
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin, plsc->vppymi /
plsc->ypmm - height_mm );
string_length_mm = plstrl( string );
pos_mm = ( plsc->vppxmi + pos *
( plsc->vppxma - plsc->vppxmi ) ) /
plsc->xpmm;
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "b", height, pos, just, string );
}
}
if ( lmx )
{
// Top axis exponent.
if ( plsc->if_boxbb )
{
// For horizontal axes, height of zero corresponds
// to character centred on edge so should add 0.5
// to height to obtain bounding box edge in
// direction away from edge if no exponent. Add
// an additional offset to make exponent fit.
height_mm = ( height + 1.4 ) * char_height_mm;
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax, plsc->vppyma /
plsc->ypmm + height_mm );
string_length_mm = plstrl( string );
pos_mm = ( plsc->vppxmi + pos *
( plsc->vppxma - plsc->vppxmi ) ) /
plsc->xpmm;
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "t", height, pos, just, string );
}
}
}
}
// Write label(s) for vertical axes.
if ( ( lmy || lny ) && ( lty || lxy ) )
{
PLINT ymode, yprec, ydigmax, ydigits, yscale;
plgyax( &ydigmax, &ydigits );
pldprec( vpwymi, vpwyma, ytick1, lfy, &ymode, &yprec, ydigmax, &yscale
);
ydigits = 0;
if ( ldy )
{
pldtfac( vpwymi, vpwyma, &factor, &tstart );
tp = ytick1 * ( 1. + floor( ( vpwymi - tstart ) / ytick1 ) ) +
tstart;
}
else
{
tp = ytick1 * ( 1. + floor( vpwymi / ytick1 ) );
}
for ( tn = tp; BETW( tn, vpwymi, vpwyma ); tn += ytick1 )
{
if ( ldy )
{
strfqsas( string, STRING_LEN, timefmt, (double) tn,
plsc->qsasconfig );
}
else
{
plform( PL_Y_AXIS, tn, yscale, yprec, string, STRING_LEN, lly,
lfy, loy );
}
pos = ( vpwymax > vpwymin ) ?
( tn - vpwymi ) / ( vpwyma - vpwymi ) :
( vpwyma - tn ) / ( vpwyma - vpwymi );
if ( lny )
{
if ( lvy )
{
// Left axis with text written perpendicular to edge.
height = liy ? 1.0 : 0.5;
if ( plsc->if_boxbb )
{
// For vertical axes with text written
// perpendicular to edge, height of zero
// corresponds character centred on edge so
// should add 0.5 to height to obtain bounding
// box edge in direction away from edge, and
// that value apparently works.
height_mm = ( height + 0.0 ) * char_height_mm;
string_length_mm = plstrl( string );
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin, plsc->vppxmi /
plsc->xpmm - height_mm - string_length_mm );
pos_mm = ( plsc->vppymi + pos *
( plsc->vppyma - plsc->vppymi ) ) /
plsc->ypmm;
// Expected offset is 0.5, but adjust to improve
// look of result.
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin,
pos_mm - 0.6 * char_height_mm );
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax,
pos_mm + 0.7 * char_height_mm );
}
else
{
plmtex( "lv", height, pos, 1.0, string );
}
}
else
{
// Left axis with text written parallel to edge.
height = liy ? 1.75 : 1.5;
if ( plsc->if_boxbb )
{
// For vertical axes with text written
// parallel to edge, height of zero
// corresponds to character centred on edge so
// should add 0.5 to height to obtain bounding
// box edge in direction away from edge,
// However, experimentally found 0.8 gave a
// better looking result.
height_mm = ( height + 0.8 ) * char_height_mm;
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin, plsc->vppxmi /
plsc->xpmm - height_mm );
pos_mm = ( plsc->vppymi + pos *
( plsc->vppyma - plsc->vppymi ) ) /
plsc->ypmm;
string_length_mm = plstrl( string );
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "l", height, pos, 0.5, string );
}
}
}
if ( lmy )
{
if ( lvy )
{
// Right axis with text written perpendicular to edge.
height = liy ? 1.0 : 0.5;
if ( plsc->if_boxbb )
{
// For vertical axes with text written
// perpendicular to edge, height of zero
// corresponds character centred on edge so
// should add 0.5 to height to obtain bounding
// box edge in direction away from edge, and
// that value apparently works.
height_mm = ( height + 0.0 ) * char_height_mm;
string_length_mm = plstrl( string );
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax, plsc->vppxma /
plsc->xpmm + height_mm + string_length_mm );
pos_mm = ( plsc->vppymi + pos *
( plsc->vppyma - plsc->vppymi ) ) /
plsc->ypmm;
// Expected offset is 0.5, but adjust to improve
// look of result.
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin,
pos_mm - 0.6 * char_height_mm );
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax,
pos_mm + 0.7 * char_height_mm );
}
else
{
plmtex( "rv", height, pos, 0.0, string );
}
}
else
{
// Right axis with text written parallel to edge.
height = liy ? 1.75 : 1.5;
if ( plsc->if_boxbb )
{
// For vertical axes with text written
// parallel to edge, height of zero
// corresponds to character centred on edge so
// should add 0.5 to height to obtain bounding
// box edge in direction away from edge,
// However, experimentally found 0.8 gave a
// better looking result.
height_mm = ( height + 0.8 ) * char_height_mm;
plsc->boxbb_xmax = MAX( plsc->boxbb_xmax, plsc->vppxma /
plsc->xpmm + height_mm );
pos_mm = ( plsc->vppymi + pos *
( plsc->vppyma - plsc->vppymi ) ) /
plsc->ypmm;
string_length_mm = plstrl( string );
plsc->boxbb_ymin = MIN( plsc->boxbb_ymin,
pos_mm - 0.5 * string_length_mm );
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax,
pos_mm + 0.5 * string_length_mm );
}
else
{
plmtex( "r", height, pos, 0.5, string );
}
}
}
ydigits = MAX( ydigits, (PLINT) strlen( string ) );
}
if ( !lvy )
ydigits = 2;
plsyax( ydigmax, ydigits );
// Write separate exponential label if mode = 1.
if ( !lly && !ldy && !loy && ymode )
{
snprintf( string, STRING_LEN, "(x10#u%d#d)", (int) yscale );
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 ) // sjs moved from below to set pos and just
{
pos = 0.0 - offset;
just = 1.0;
}
if ( lmy )
{
pos = 1.0 + offset;
just = 0.0;
} // sjs end of moved bits - pos and just now set
} //sjs insert }
// Left axis exponent
if ( lny )
{
//pos = 0.0 - offset; sjs moved to above
//just = 1.0;
if ( plsc->if_boxbb )
{
// For horizontal axes, height of zero corresponds
// to character centred on edge so should add 0.5
// to height to obtain bounding box edge in
// direction away from edge if no exponent. Add
// an additional offset to make exponent fit.
height_mm = ( height + 1.4 ) * char_height_mm;
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax, plsc->vppyma /
plsc->ypmm + height_mm );
string_length_mm = plstrl( string );
pos_mm = ( plsc->vppxmi + pos *
( plsc->vppxma - plsc->vppxmi ) ) /
plsc->xpmm;
plsc->boxbb_xmin = MIN( plsc->boxbb_xmin,
pos_mm - string_length_mm );
}
else
{
if (lvy) // sjs add this if and change t to l or lv
{
plmtex( "lv", height, pos, just, string );
}
else
{
plmtex( "l", height, pos, just, string );
}
}
}
// Right axis exponent.
if ( lmy )
{
//pos = 1.0 + offset; sjs moved this to above
//just = 0.0;
if ( plsc->if_boxbb )
{
// For horizontal axes, height of zero corresponds
// to character centred on edge so should add 0.5
// to height to obtain bounding box edge in
// direction away from edge if no exponent. Add
// an additional offset to make exponent fit.
height_mm = ( height + 1.4 ) * char_height_mm;
plsc->boxbb_ymax = MAX( plsc->boxbb_ymax, plsc->vppyma /
plsc->ypmm + height_mm );
string_length_mm = plstrl( string );
pos_mm = ( plsc->vppxmi + pos *
( plsc->vppxma - plsc->vppxmi ) ) /
plsc->xpmm;
plsc->boxbb_xmax = MAX( plsc->boxbb_xmin,
pos_mm + string_length_mm );
}
else
{
if (lvy) // sjs add this if and change t to r or rv
{
plmtex( "rv", height, pos, just, string );
}
else
{
plmtex( "r", height, pos, just, string );
}
}
}
//} sjs remove
}
}
}
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel