Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Prevent Scale/Axis labels jumping

Help
2010-09-22
2013-05-02
  • Nigel Paton
    Nigel Paton
    2010-09-22

    Hi,

    I've been looking at preventing the axis labels from jumping values when scrolling and have some changes that seem to do the job. If you are unsure what I mean by jumping values try scrolling a graph which is at a zoom level that has some axis ticks that do not have labels. As you scroll the ticks that have labels will change. For example if the ticks at values 1, 3 and 5 have labels and you scroll such that 1 is no longer visible the labels will jump to being on 2, 4 and 6. It is nicer if the labels stay on the same ticks.

    Extract of code from a y-axis plotting routine (based on mpScaleY::Plot but with bits I don't need removed for speed).

            // Modified from original, bit more accurate. The + 0.5 is for pixel rounding errors
            double n = ceil( (w.GetPosY() - (double)((extend - w.GetMarginBottom()) + 0.5)/ w.GetScaleY()) / step ) * step ;
            wxCoord endPx   = w.GetScrX() - w.GetMarginRight();
            wxCoord minYpx  = w.GetMarginTop();
            wxCoord maxYpx  = w.GetScrY() - w.GetMarginBottom();
            int labelW = 0;
            // Before staring cycle, calculate label height
            int labelHeigth = 0;
            s.Printf(fmt,n);
            dc.GetTextExtent(s, &tx, &labelHeigth);
            // Calculate how often to print a tick label
            int labelNumStep = (int)ceil((labelHeigth + mpMIN_Y_AXIS_LABEL_SEPARATION)/(w.GetScaleY() * step));
            // Prevent tick label drawing until the first label index is found
            int labelStepCount = labelNumStep + 1;
            // Calculate the first point at which to display a tick label
            double labelStep = step * labelNumStep;
            double firstLabel = ceil(n / labelStep) * labelStep;
            int firstLabelIndex = (int)(((firstLabel - n) + (step / 2)) / step);
            int stepCount = 0;
            for (;n < end; n += step) 
            {
                // Check whether to trigger the first label
                if (stepCount == firstLabelIndex)
                    labelStepCount = labelNumStep;
                const int p = (int)((w.GetPosY() - n) * w.GetScaleY());
                if ((p >= minYpx) && (p <= maxYpx)) 
                {
                    if (m_ticks) 
                    { // Draw axis ticks
                        if (m_flags == mpALIGN_BORDER_LEFT) 
                            dc.DrawLine( orgx, p, orgx+4, p);
                        else 
                            dc.DrawLine( orgx-4, p, orgx, p); //( orgx, p, orgx+4, p);
                    } 
                    else 
                    {
                        m_pen.SetStyle(wxDOT);
                        dc.SetPen( m_pen);
                        if (m_flags == mpALIGN_LEFT)
                            dc.DrawLine( orgx-4, p, endPx, p);
                        else if (m_flags == mpALIGN_RIGHT) 
                            dc.DrawLine( minYpx, p, orgx+4, p);
                        else 
                            dc.DrawLine( 0/*-w.GetScrX()*/, p, w.GetScrX(), p);
                        m_pen.SetStyle(wxSOLID);
                        dc.SetPen( m_pen);
                    }
                    // Print ticks labels
                    if (labelStepCount == labelNumStep)
                    {
                        s.Printf(fmt, n);
                        dc.GetTextExtent(s, &tx, &ty);
                        labelW = (labelW <= tx) ? tx : labelW;
                        if ((m_flags == mpALIGN_BORDER_LEFT) || (m_flags == mpALIGN_RIGHT))
                            dc.DrawText( s, orgx+4, p-ty/2);
                        else
                            dc.DrawText( s, orgx-4-tx, p-ty/2); 
                        labelStepCount = 1;
                    }
                    else
                    {
                        labelStepCount++;
                    }
                }
                stepCount++;
            }
    

    Can be modified for use in other axis/scale plotting routines.

    Cheers

    Nigel