Version: 1.4.0_devel (using KDE 3.5.6 "release 25.2" , openSUSE ) Compiler: Target: i586-suse-linux OS: Linux (i686) release 2.6.16.27-0.6-smp When zooming in on a log-scale plot (e.g. the PSD in demo.kst), if the zoom area is between numbers on either axis, no numbers appear on the axis of the zoomed-in plot. For example, zoom in on a box where the Y-axis is just above 0.01 to just below 0.1 and the X-axis is just above 0.001 to just below 0.01. There will be no numbers on either axis.
The solution I have seen on the net is to label some of the minor ticks in this situation. If the user insists on a log plot with small enough dynamic range, eventually it will be impossible to do much of anything with it... and we might wonder why they are using a log plot. In the past we have tried -linear ticks, labelled accurately (*very* ugly and hard to use) -log2 ticks (minor ticks don't make sense, and only gives a small amount of extra dynamic range).
It is surely better to have some labels (no matter how ugly) than nothing. I think most people appreciate the former and understand why they are necessarily "ugly" while the latter approach looks more like a poorly implemented feature or bug.
The 'right' solution, based on google images, is: -always label at least to tick marks. -Prefer major ticks -revert to minor ticks if you have to. -when reverting to minor ticks, chose them maximally far apart. If no ticks are visible, then log plot makes not sense, and you deserve to have a whacked looking plot :-) The architecture of 2dplot currently makes this painful.
SVN commit 681380 by arwalker: CCBUG:141448 First draft of labelling minor ticks M +323 -261 libkstapp/kst2dplot.cpp M +6 -7 libkstapp/kst2dplot.h M +11 -5 libkstmath/kstplotdefines.h
SVN commit 681426 by arwalker: BUG:141448 Label minor ticks maximally far apart M +54 -34 kst2dplot.cpp --- branches/work/kst/1.5/kst/src/libkstapp/kst2dplot.cpp #681425:681426 @@ -1931,21 +1931,21 @@ QString strPrefix; double range; double scale = 1.0; - double value; + double value = 0.0; bool bDuplicate = false; uint uiShortestLength = 1000; uint length; int minorTicks; int iShort = 0; int base = 60; - KstPlotLabel *tick_label; + KstPlotLabel *tickLabel; TickLabelDescription labelDescr; if (isX) { - tick_label = _xTickLabel; + tickLabel = _xTickLabel; minorTicks = _xMinorTicks; } else { - tick_label = _yTickLabel; + tickLabel = _yTickLabel; minorTicks = _yMinorTicks; } @@ -1979,8 +1979,8 @@ value = (double)i * tp.tick + tp.org; if (value >= Min && value <= Max) { genAxisTickLabel(strTmp, value, isLog, logBase, false); - tick_label->setText(strTmp); - QSize lsize = tick_label->size(); + tickLabel->setText(strTmp); + QSize lsize = tickLabel->size(); tp.maxWidth = kMax(tp.maxWidth, double(lsize.width())); tp.maxHeight = kMax(tp.maxHeight, double(lsize.height())); @@ -2004,9 +2004,32 @@ if (isLog && tp.labelMinor) { double step = (pow(logBase, (double)(i+1) * tp.tick + tp.org) - pow(logBase, (double)i * tp.tick + tp.org)) / minorTicks; + bool labelFirst = false; int j; for (j = 1; j < minorTicks; j++) { + if (labelFirst) { + if (j == minorTicks - 1) { + // value of next major tick... + value = (double)(i+1) * tp.tick + tp.org; + if (value >= Min && value <= Max) { + // don't label the current minor tick if we're about to label the next minor tick + continue; + } + } else { + // value of next minor tick... + if (isX) { + value = logXLo(pow(logBase, (double)i * tp.tick + tp.org) + ((double)(j+1) * step)); + } else { + value = logYLo(pow(logBase, (double)i * tp.tick + tp.org) + ((double)(j+1) * step)); + } + if (value > Min && value < Max) { + // don't label the current minor tick if we're about to label the next minor tick + continue; + } + } + } + if (isX) { value = logXLo(pow(logBase, (double)i * tp.tick + tp.org) + ((double)j * step)); } else { @@ -2015,8 +2038,8 @@ if (value > Min && value < Max) { genAxisTickLabel(strTmp, value, true, logBase, true); - tick_label->setText(strTmp); - QSize lsize = tick_label->size(); + tickLabel->setText(strTmp); + QSize lsize = tickLabel->size(); tp.maxWidth = kMax(tp.maxWidth, double(lsize.width())); tp.maxHeight = kMax(tp.maxHeight, double(lsize.height())); @@ -2025,6 +2048,8 @@ labelDescr.position = value; labelDescr.minorTick = true; tp.labels.append(labelDescr); + + labelFirst = true; } } } @@ -2032,33 +2057,28 @@ // also generate labels for opposite axis if needed if ((isX && _xTransformed) || (!isX && _yTransformed)) { - for (int i = tp.iLo; i < tp.iHi; i++) { + for (QValueList<TickLabelDescription>::ConstIterator iter = tp.labels.begin(); iter != tp.labels.end(); ++iter) { double transformedNumber; bool transformedOK = false; - double originalNumber = (double)i * tp.tick + tp.org; + double originalNumber = (*iter).position; - if (originalNumber > Min && originalNumber < Max) { - if (isLog) { - originalNumber = pow(logBase, originalNumber); - } - // case insensitive replace - QString replacedExp = isX ? _xTransformedExp : _yTransformedExp; - replacedExp.replace(isX ? "x" : "y", QString::number(originalNumber), false); - transformedNumber = Equation::interpret(replacedExp.latin1(), &transformedOK, replacedExp.length()); - tick_label->setText(QString::number(transformedNumber, 'g', LABEL_PRECISION)); - if (!transformedOK) { - tick_label->setText("NaN"); - } - labelDescr.label = tick_label->text(); - labelDescr.position = originalNumber; - labelDescr.minorTick = false; - tp.labelsOpposite.append(labelDescr); + // case insensitive replace + QString replacedExp = isX ? _xTransformedExp : _yTransformedExp; + replacedExp.replace(isX ? "x" : "y", QString::number(originalNumber), false); + transformedNumber = Equation::interpret(replacedExp.latin1(), &transformedOK, replacedExp.length()); + tickLabel->setText(QString::number(transformedNumber, 'g', LABEL_PRECISION)); + if (!transformedOK) { + tickLabel->setText("NaN"); + } + labelDescr.label = tickLabel->text(); + labelDescr.position = originalNumber; + labelDescr.minorTick = false; + tp.labelsOpposite.append(labelDescr); - // update the max height and width of opposite labels - QSize lsize = tick_label->size(); - tp.oppMaxWidth = kMax(tp.oppMaxWidth, double(lsize.width())); - tp.oppMaxHeight = kMax(tp.oppMaxHeight, double(lsize.height())); - } + // update the max height and width of opposite labels + QSize lsize = tickLabel->size(); + tp.oppMaxWidth = kMax(tp.oppMaxWidth, double(lsize.width())); + tp.oppMaxHeight = kMax(tp.oppMaxHeight, double(lsize.height())); } } @@ -2090,12 +2110,12 @@ value = (double)i * tp.tick + tp.org; if (value > Min && value < Max) { labelDescr.label = strTmp; - labelDescr.position = (double)i * tp.tick + tp.org; + labelDescr.position = value; labelDescr.minorTick = false; tp.labels.append(labelDescr); - tick_label->setText(strTmp); - QSize lsize = tick_label->size(); + tickLabel->setText(strTmp); + QSize lsize = tickLabel->size(); tp.maxWidth = kMax(tp.maxWidth, double(lsize.width())); tp.maxHeight = kMax(tp.maxHeight, double(lsize.height())); }