C++ 具有对数刻度的QWT谱图

C++ 具有对数刻度的QWT谱图,c++,qt,qwt,C++,Qt,Qwt,我想在光谱图旁边放一个对数刻度。我希望显示的图像与线性数据相同。线性比例版本的代码如下所示: #include <QApplication> #include <QMainWindow> #include <qwt_plot.h> #include <qwt_plot_spectrogram.h> #include <qwt_matrix_raster_data.h> #include <qwt_color_map.h>

我想在光谱图旁边放一个对数刻度。我希望显示的图像与线性数据相同。线性比例版本的代码如下所示:

#include <QApplication>
#include <QMainWindow>

#include <qwt_plot.h>
#include <qwt_plot_spectrogram.h>
#include <qwt_matrix_raster_data.h>
#include <qwt_color_map.h>
#include <qwt_scale_engine.h>

int main( int argc, char* argv[] ) {
  QApplication app( argc, argv );
  QMainWindow wnd;

  QVector<double> heat_values( 100 * 100 );
  for( int n = 0; n < 100 * 100; ++n ) {
    heat_values[n] = ( n % 100 ) + n / 100;
  };

  QwtPlotSpectrogram heat;
  auto heat_data = std::make_unique<QwtMatrixRasterData>();
  heat_data->setValueMatrix( heat_values, 100 );
  heat_data->setResampleMode(
      QwtMatrixRasterData::ResampleMode::NearestNeighbour );
  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.setDisplayMode( QwtPlotSpectrogram::DisplayMode::ImageMode, true );
  heat.setColorMap( new QwtLinearColorMap( Qt::white, Qt::black ) );
  heat.setData( heat_data.release() );

  QwtPlot p;
  p.setAutoDelete( false );
  heat.attach( &p );
  p.repaint();

  wnd.setCentralWidget( &p );
  wnd.resize( 400, 300 );
  wnd.show();

  return QApplication::exec();
}
  p.setAxisScaleEngine( QwtPlot::yLeft, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::yLeft, 1.0, 101.0 );
  p.setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::xBottom, 1.0, 101.0 );
然后光谱图就全搞乱了

有人知道如何改变显示的比例吗

msvc 2017,x64,qwt 6.1.4,qt 5.12.2

编辑

我可以通过定义自己的光栅数据并将坐标映射回箱子中来实现这一点,但它仍然缺少逆变换,因此显示的数据是原始数据的“日志”版本

class RasterData : public QwtRasterData
{
public:
  double value( double const x, double const y ) const override {  
    int const ix = std::min<int>( std::max<int>( 0, x ), m_cols-1 );
    int const iy = std::min<int>( std::max<int>( 0, y ), m_cols-1 );
    return m_values[iy * m_cols + ix];
  }

  void setValueMatrix( QVector<double> const& values, int const cols ) {
    m_values = values;
    m_cols = cols;
  }

private: 
  QVector<double> m_values;
  int m_cols;
};
class RasterData:公共QwtRasterData
{
公众:
双值(双常量x,双常量y)常量重写{
int const ix=std::min(std::max(0,x),m_cols-1);
int const iy=std::min(std::max(0,y),m_cols-1);
返回m_值[iy*m_cols+ix];
}
void setValueMatrix(QVector常量和值,int常量){
m_值=值;
m_cols=cols;
}
私人:
q向量m_值;
国际货币基金组织;
};
结果如下所示:

#include <QApplication>
#include <QMainWindow>

#include <qwt_plot.h>
#include <qwt_plot_spectrogram.h>
#include <qwt_matrix_raster_data.h>
#include <qwt_color_map.h>
#include <qwt_scale_engine.h>

int main( int argc, char* argv[] ) {
  QApplication app( argc, argv );
  QMainWindow wnd;

  QVector<double> heat_values( 100 * 100 );
  for( int n = 0; n < 100 * 100; ++n ) {
    heat_values[n] = ( n % 100 ) + n / 100;
  };

  QwtPlotSpectrogram heat;
  auto heat_data = std::make_unique<QwtMatrixRasterData>();
  heat_data->setValueMatrix( heat_values, 100 );
  heat_data->setResampleMode(
      QwtMatrixRasterData::ResampleMode::NearestNeighbour );
  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.setDisplayMode( QwtPlotSpectrogram::DisplayMode::ImageMode, true );
  heat.setColorMap( new QwtLinearColorMap( Qt::white, Qt::black ) );
  heat.setData( heat_data.release() );

  QwtPlot p;
  p.setAutoDelete( false );
  heat.attach( &p );
  p.repaint();

  wnd.setCentralWidget( &p );
  wnd.resize( 400, 300 );
  wnd.show();

  return QApplication::exec();
}
  p.setAxisScaleEngine( QwtPlot::yLeft, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::yLeft, 1.0, 101.0 );
  p.setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::xBottom, 1.0, 101.0 );


但本质上我想避免所有这些转变。我希望它只是使用设置的颜色映射将通过
setValueMatrix
传入的图像数据转换为图像,并拉伸该图像以适合绘图。

我发现实现这一工作的最佳方法是从
QwtPlotSpectrogram
导出,并将转换更改为线性,以便调用
draw

class PlotSpectrogram : public QwtPlotSpectrogram {
public:
  void draw(
      QPainter* painter,
      QwtScaleMap const& xMap,
      QwtScaleMap const & yMap,
      QRectF const& canvasRect ) const override {

    QwtScaleMap xMapLin( xMap );
    QwtScaleMap yMapLin( yMap );

    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() );

    QwtPlotSpectrogram::draw(
        painter, xMapLin, yMapLin, canvasRect.translated( dx, -dy ) );
  }
};
将主刻度从20..50更改为刻度对数刻度,并使用
PlotSpectrogram

  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.setDisplayMode( QwtPlotSpectrogram::DisplayMode::ImageMode, true );
  heat.setColorMap( new QwtLinearColorMap( Qt::white, Qt::black ) );
  heat.setData( heat_data.release() );

  QwtPlot p;

  p.setAxisScaleEngine( QwtPlot::yLeft, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::yLeft, 20.0, 50.0 );
  p.setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine() );
  p.setAxisScale( QwtPlot::xBottom, 20.0, 50.0 );

  p.setAutoDelete( false );
  heat.attach( &p );
绘制光谱图;
自动加热_数据=标准::使_唯一();
加热数据->设置值矩阵(加热值,100);
加热数据->设定间隔(Qt::XAxis,QwtInterval(01100.0));
加热数据->设定间隔(Qt::YAxis,QwtInterval(01100.0));
加热数据->设定间隔(Qt::ZAxis,QwtInterval(0200.0));
heat.setDisplayMode(QwtPlotSpectrogram::DisplayMode::ImageMode,true);
setColorMap(新的QwtLinearColorMap(Qt::白色,Qt::黑色));
heat.setData(heat_data.release());
qwtp图;
p、 setAxisScaleEngine(QwtPlot::yLeft,新的QwtLogScaleEngine());
p、 setAxisScale(QwtPlot::yLeft,20.0,50.0);
p、 setAxisScaleEngine(QwtPlot::xBottom,新的QwtLogScaleEngine());
p、 setAxisScale(QwtPlot::xBottom,20.0,50.0);
p、 setAutoDelete(false);
加热。连接(&p);
然后我得到所需的输出


QwtPlotMatrixRasterData无法使用非线性比例


当使用QwtRasterData时,任何类型的天平都可以开箱即用。

我不明白你想要什么,你可以详细解释,也许你想要得到什么图像就可以了help@eyllanesc我把这两幅图像结合起来伪造了结果。我希望这能更好地解释。基本上,我想在预先计算好的图像旁边放置一个任意比例。你希望线性和对数比例上的“可见行为”相同吗?是的,我只是不想改变比例。我不希望数据被重新缩放。图像应该保持不变(线性)。你没有错。对数刻度的作用是使斜率平滑,我们使用数字,以便您了解:您的数字范围为1到101。这个范围内的对数是多少?然后从0到2,在该比例上,具有任何坡度的直线将转换为坡度约为0的直线,这意味着不区分这些值。不同的是,如果您的数据具有指数趋势,那么对数尺度会将其更改为线性
QwtRasterData
是一个接口。我已经尝试了我自己的实现(见上面的编辑),但没有达到预期的效果。请继续通过一个官方Qwt支持渠道,可能会发布一个简短且可编译的演示。那我就去看看。