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

Reply via email to