The ticks I print from function buildMajorTicks( ) is (-1e+18, -3.16228e+11, -100000, 31.6228, 1e+08, 3.16228e+14, 1e+21),
but my axis can't display correctly.What the problem is?
qwt_scale.jpg
The ticks I print from function buildMajorTicks( ) is (-1e+18, -3.16228e+11, -100000, 31.6228, 1e+08, 3.16228e+14, 1e+21),
but my axis can't display correctly.What the problem is?
qwt_scale.jpg
Are talking about QwtLinearScaleEngine::buildMajorTicks() from Qwt 6.1 - if yes the parameters from your posting doesn't match.
And to be able to check your situation it would help to know the parameters of QwtLinearScaleEngine::divideScale instead.
Uwe
yellowfisher (25th February 2016)
no, i build a class which derived from QwtScaleEngine to draw sign(x)*log(|x|). datalistis build from MyScaleEngine::buildMajorTicks().Qt Code:
(-1e+18, -3.16228e+11, -100000, 31.6228, 1e+08, 3.16228e+14, 1e+21)To copy to clipboard, switch view to plain text mode
in my transform class ,i set boundaries as.Qt Code:
qBound(-LOG_MAX, value, LOG_MAX)To copy to clipboard, switch view to plain text mode
Added after 1 45 minutes:
Here is the code i write in myBuildMajorTicks() function.
It works fine while the log aixs's data is all negative or all positive.Qt Code:
QList<double> DocPlot::PlotSignScaleEngine::buildMajorTicks( const QwtInterval& interval, double stepSize) const { qDebug()<<"in function buildMajorTicks"<<endl; double minValue = interval.minValue(); double maxValue = interval.maxValue(); double width = qwtLogInterval(base(), interval).normalized().width(); if(minValue * maxValue < 0.0) width = qwtLogInterval(base(), QwtInterval(1, maxValue)).normalized().width() + qwtLogInterval(base(), QwtInterval(minValue, 1)).normalized().width(); qDebug()<<"width = "<<width<<" stepSize = "<<stepSize<<endl; int numTicks = qRound( width / stepSize ) + 1; if ( numTicks > 10 ) numTicks = 10; qDebug()<<"numTicks = "<<numTicks<<endl; const double lxmin = ::log( qAbs(interval.minValue()) ); const double lxmax = ::log( qAbs(interval.maxValue()) ); const double lstep = (lxmax-lxmin) / double(numTicks-1); qDebug()<<"lxmin = "<<lxmin<<" lxmax = "<<lxmax<<endl; QList<double> ticks; ticks += interval.minValue(); if(maxValue < 0.0) { for(int i = 1; i < numTicks - 1; i++) ticks += -qExp(lxmin + double(i) * lstep); } else { if(minValue * maxValue < 0.0) { qDebug()<<"1111111111111111111111111111111111111"<<endl; int number = qRound(numTicks * (lxmin / (lxmin + lxmax))); qDebug()<<"number = "<<number<<endl; double blstep = (0 - lxmin) / double(number - 1); qDebug()<<"blstep = "<<blstep<<endl; double glstep = (lxmax - 1) / double(numTicks - number - 1); qDebug()<<"glstep = "<<glstep<<endl; int j = 1; for (int i = 1; i < numTicks - 1; i++) { if((lxmin + blstep * double(i)) > 0.0) { j++; ticks += -qExp(lxmin + double(i) * blstep); } else ticks += qExp((double(i) - j - 1) * glstep); } } else for(int i = 1; i < numTicks - 1; i++) ticks += qExp(lxmin + double(i) * lstep); } // for(int i = 1; i < numTicks - 1; i++) // ticks += qExp(lxmin + double(i) * lstep); ticks += interval.maxValue(); qDebug()<<"ticks = "<<ticks<<endl; return ticks; }To copy to clipboard, switch view to plain text mode
The attachment file is the curve data I want to plot.
Last edited by yellowfisher; 25th February 2016 at 09:01.
The parameters I pass to divideScale() are: x1=-1e+18, x2=1e+21, maxMajorSteps=8, maxMinorSteps=5, stepSize=1.
And this is my align function:
Qt Code:
QwtInterval intv = qwtLogInterval(base(), interval); if (intv.minValue() > intv.maxValue()) intv = QwtInterval(intv.maxValue(), intv.minValue()); if(interval.minValue() * interval.maxValue() < 0.0) if(qwtFuzzyCompare(interval.minValue(), x1, stepSize) == 0) x1 = interval.minValue(); if(qwtFuzzyCompare(interval.maxValue(), x2, stepSize) == 0) x2 = interval.maxValue(); return qwtPowInterval(base(), QwtInterval(x1, x2), interval);To copy to clipboard, switch view to plain text mode
I also overwrited function qwtPowInterval() as:
The interval_ref i pass to qwtPowInterval is QwtInterval(-1e+18, 1e+21).Qt Code:
qwtPowInterval(double base, const QwtInterval& interval, const QwtInterval& interval_ref) { double minValue = interval_ref.minValue(); double maxValue = interval_ref.maxValue(); QwtInterval intv; if (maxValue < 0.0) { intv = QwtInterval(-qPow(base, interval.minValue()), -qPow(base, interval.maxValue())); if(intv.maxValue() < intv.minValue()) return QwtInterval(intv.maxValue(), intv.minValue()); else return intv; } else if(maxValue == 0.0) return QwtInterval(-qPow(base, interval.minValue()), -LOG_MIN); else { if(minValue < 0.0) return QwtInterval(-qPow(base, interval.minValue()), qPow(base, interval.maxValue())); else if (minValue == 0.0) return QwtInterval(LOG_MIN, qPow(base, interval.maxValue())); else return QwtInterval(qPow(base, interval.minValue()), qPow(base, interval.maxValue())); } }To copy to clipboard, switch view to plain text mode
Last edited by yellowfisher; 26th February 2016 at 02:19.
O.k. so you want to implement your own type of scale engine and we are not talking about Qwt code ?
You wrote you want to implement something like "sign(x)*log(|x|)", what should be an easy one with QwtLogarithmicScaleEngine as long as your scales are positive or negative.
As soon as you have a scale with a range, that includes the 0, you have the problem, that you need to define a small interval with a non logarithmic transformation to work around the 0.
F.e. you could use a linear or transformation for the range [-1, 1] - or maybe using a power based one. ( see the scaleengine example ).
But without knowing, what type of scale + transformation you want to have ...
Uwe
The scale transformation is my problem, I don't know how to write a transformation to transforme negative log scales.
No your problem is that you have to cross the 0, when having a transformation that goes from -LOG_MAX, value, LOG_MAX.
Uwe
I still don't know how to cross the 0, do you mean I should split (-1e+18, 1e+21) into 3 intervals like : (-LOG_MAX, -LOG_MIN), (-LOG_MIN, LOG_MIN), (LOG_MIN, LOG_MAX)?
If so, which function or class i need to work on?
Last edited by yellowfisher; 29th February 2016 at 03:30.
Yes of course - not because of Qwt, but because of the underlying maths that are needed for a transformation.
First of all you need to define something bijective to map between plot and widget coordinates. Using a linear or power based formula might be candidates for the segment around the 0.If so, which function or class i need to work on?
[-LOG_MIN, LOG_MIN] is probably too small for this segment, better start with [ -1.0, 1.0 ] - or something that makes sense, in your context, when you have a curve that passes 0.
Start with checking the code of qwt_scale_map.[h|cpp] and qwt_transform.[h|cpp]. Then you will understand the code of the scaleengine example, where you f.e find the At400 transformation. Its implementation is also splitting into 3 intervals ( linear/pow/linear ) and might serve as a starting point for you.
I recommend to simply use a QwtLinearScaleEngine in the beginning - maybe even assigning the ticks manually like in the example. Once you have the transformation running we can see how to tweak the logarithmic engine to calculate useful ticks positions.
Uwe
Thanks for your reply.
I have checked scaleengine example in qwt-6.1.1/palyground, i wrote my MyLogTransformation::transform() like this:
And it doesn't work. I have no idea of how to write this function. Can you give me more recommendation?Qt Code:
double transform(double value) const { if(value >= 1) return ::log(value - 1); if(value <= -1) return -::log(qAbs(value) + 1); return value; }To copy to clipboard, switch view to plain text mode
Another problem is that my data is loaded from files, there has possibilities that all values are in interval like [-1, 0.5]. Maybe I should pass the maximum value and minimum value in my data as parameters to transform( ), but how to get plot data from QwtPlot?
for now i can draw curve correctly. but the first tick in MajorTicks still can't display correctly.qwt_bug.png
I want to know what makes this happened.
Finally it works.qwt_signeLog_scale.jpg
But there still has a problem with plot. There has no variable in [-2e16, 2e16] in my data sheet, so I want it plot like this:example.png
The interval [-2e16, 2e16] just takes a little scale of axis so that there has more places for meaningful variables.
Bookmarks