QwtPlotSpectrogram with log scales
I have 2d histogram data that I want to display. This essentially requires that I can set an arbitrary scale to match the binning used to calculate the data set with QwtMatrixRasterData::setValueMatrix. I posted about this on SO. I also managed to make this work the way that I want. I posted this answer that explains my solution.
Uwe suggested that I usw a QwtRasterData based solution but my previous experiments had shows that this does not lead to the result that I want as it re-scales the image to the scales of the plot.
As I have a working solution, I guess my only questions are:
a) is this the right way to approach the situation?
b) does a different solution exists that works OOTB?
c) is there some other way to get Qwt to draw a density plot so that I don't have to do the binning myself?
Code:
#include <QApplication>
#include <QMainWindow>
#include <QRect>
#include <QStyleFactory>
#include <qwt_color_map.h>
#include <qwt_matrix_raster_data.h>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_spectrogram.h>
#include <qwt_scale_engine.h>
public:
void draw(
const QwtScaleMap& xMap,
const QwtScaleMap& yMap,
const QRectF& canvasRect ) const override {
auto const xi = data()->interval( Qt::XAxis );
auto const yi = data()->interval( Qt::YAxis );
auto const dx = xMapLin.transform( xMap.s1() );
xMapLin.setScaleInterval( xi.minValue(), xi.maxValue() );
auto const dy = yMapLin.transform( yMap.s2() );
yMapLin.setScaleInterval( yi.minValue(), yi.maxValue() );
xMapLin.setTransformation( new QwtNullTransform() );
yMapLin.setTransformation( new QwtNullTransform() );
painter, xMapLin, yMapLin, canvasRect.translated( dx, -dy ) );
}
};
int
main( int argc, char* argv[] ) {
QVector<double> heat_values( 100 * 100 );
for( int n = 0; n < 100 * 100; ++n ) {
heat_values[n] = ( n % 100 ) + n / 100;
};
//QwtPlotSpectrogram heat;
PlotSpectrogram heat;
auto heat_data = std::make_unique<QwtMatrixRasterData>();
heat_data->setValueMatrix( heat_values, 100 );
heat_data->setInterval( Qt::XAxis, QwtInterval( 0, 100.0 ) );
heat_data->setInterval( Qt::YAxis, QwtInterval( 0, 100.0 ) );
heat_data->setInterval( Qt::ZAxis, QwtInterval( 0, 200.0 ) );
heat.setData( heat_data.release() );
p.
setAxisScaleEngine( QwtPlot::yLeft,
new QwtLogScaleEngine
() );
p.
setAxisScale( QwtPlot::yLeft,
20.0,
50.0 );
p.
setAxisScaleEngine( QwtPlot::xBottom,
new QwtLogScaleEngine
() );
p.
setAxisScale( QwtPlot::xBottom,
200,
500.0 );
p.setAutoDelete( false );
heat.attach( &p );
p.repaint();
wnd.setCentralWidget( &p );
wnd.resize( 400, 300 );
wnd.show();
}