summaryrefslogtreecommitdiff
path: root/src/libpcp_qwt/src/qwt_matrix_raster_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp_qwt/src/qwt_matrix_raster_data.cpp')
-rw-r--r--src/libpcp_qwt/src/qwt_matrix_raster_data.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/libpcp_qwt/src/qwt_matrix_raster_data.cpp b/src/libpcp_qwt/src/qwt_matrix_raster_data.cpp
new file mode 100644
index 0000000..2176ec9
--- /dev/null
+++ b/src/libpcp_qwt/src/qwt_matrix_raster_data.cpp
@@ -0,0 +1,270 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997 Josef Wilgen
+ * Copyright (C) 2002 Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_matrix_raster_data.h"
+#include <qnumeric.h>
+#include <qmath.h>
+
+class QwtMatrixRasterData::PrivateData
+{
+public:
+ PrivateData():
+ resampleMode(QwtMatrixRasterData::NearestNeighbour),
+ numColumns(0)
+ {
+ }
+
+ inline double value(size_t row, size_t col) const
+ {
+ return values.data()[ row * numColumns + col ];
+ }
+
+ QwtMatrixRasterData::ResampleMode resampleMode;
+
+ QVector<double> values;
+ size_t numColumns;
+ size_t numRows;
+
+ double dx;
+ double dy;
+};
+
+//! Constructor
+QwtMatrixRasterData::QwtMatrixRasterData()
+{
+ d_data = new PrivateData();
+ update();
+}
+
+//! Destructor
+QwtMatrixRasterData::~QwtMatrixRasterData()
+{
+ delete d_data;
+}
+
+/*!
+ \brief Set the resampling algorithm
+
+ \param mode Resampling mode
+ \sa resampleMode(), value()
+*/
+void QwtMatrixRasterData::setResampleMode(ResampleMode mode)
+{
+ d_data->resampleMode = mode;
+}
+
+/*!
+ \return resampling algorithm
+ \sa setResampleMode(), value()
+*/
+QwtMatrixRasterData::ResampleMode QwtMatrixRasterData::resampleMode() const
+{
+ return d_data->resampleMode;
+}
+
+/*!
+ \brief Assign the bounding interval for an axis
+
+ Setting the bounding intervals for the X/Y axis is mandatory
+ to define the positions for the values of the value matrix.
+ The interval in Z direction defines the possible range for
+ the values in the matrix, what is f.e used by QwtPlotSpectrogram
+ to map values to colors. The Z-interval might be the bounding
+ interval of the values in the matrix, but usually it isn't.
+ ( f.e a interval of 0.0-100.0 for values in percentage )
+
+ \param axis X, Y or Z axis
+ \param interval Interval
+
+ \sa QwtRasterData::interval(), setValueMatrix()
+*/
+void QwtMatrixRasterData::setInterval(
+ Qt::Axis axis, const QwtInterval &interval )
+{
+ QwtRasterData::setInterval( axis, interval );
+ update();
+}
+
+/*!
+ \brief Assign a value matrix
+
+ The positions of the values are calculated by dividing
+ the bounding rectangle of the X/Y intervals into equidistant
+ rectangles ( pixels ). Each value corresponds to the center of
+ a pixel.
+
+ \param values Vector of values
+ \param numColumns Number of columns
+
+ \sa valueMatrix(), numColumns(), numRows(), setInterval()()
+*/
+void QwtMatrixRasterData::setValueMatrix(
+ const QVector<double> &values, size_t numColumns )
+{
+ d_data->values = values;
+ d_data->numColumns = numColumns;
+ update();
+}
+
+/*!
+ \return Value matrix
+ \sa setValueMatrix(), numColumns(), numRows(), setInterval()
+*/
+const QVector<double> QwtMatrixRasterData::valueMatrix() const
+{
+ return d_data->values;
+}
+
+/*!
+ \return Number of columns of the value matrix
+ \sa valueMatrix(), numRows(), setValueMatrix()
+*/
+size_t QwtMatrixRasterData::numColumns() const
+{
+ return d_data->numColumns;
+}
+
+/*!
+ \return Number of rows of the value matrix
+ \sa valueMatrix(), numColumns(), setValueMatrix()
+*/
+size_t QwtMatrixRasterData::numRows() const
+{
+ return d_data->numRows;
+}
+
+/*!
+ \brief Pixel hint
+
+ - NearestNeighbour\n
+ pixelHint() returns the surrounding pixel of the top left value
+ in the matrix.
+
+ - BilinearInterpolation\n
+ Returns an empty rectangle recommending
+ to render in target device ( f.e. screen ) resolution.
+
+ \sa ResampleMode, setMatrix(), setInterval()
+*/
+QRectF QwtMatrixRasterData::pixelHint( const QRectF & ) const
+{
+ QRectF rect;
+ if ( d_data->resampleMode == NearestNeighbour )
+ {
+ const QwtInterval intervalX = interval( Qt::XAxis );
+ const QwtInterval intervalY = interval( Qt::YAxis );
+ if ( intervalX.isValid() && intervalY.isValid() )
+ {
+ rect = QRectF( intervalX.minValue(), intervalY.minValue(),
+ d_data->dx, d_data->dy );
+ }
+ }
+
+ return rect;
+}
+
+/*!
+ \return the value at a raster position
+
+ \param x X value in plot coordinates
+ \param y Y value in plot coordinates
+
+ \sa ResampleMode
+*/
+double QwtMatrixRasterData::value( double x, double y ) const
+{
+ const QwtInterval xInterval = interval( Qt::XAxis );
+ const QwtInterval yInterval = interval( Qt::YAxis );
+
+ if ( !( xInterval.contains(x) && yInterval.contains(y) ) )
+ return qQNaN();
+
+ double value;
+
+ switch( d_data->resampleMode )
+ {
+ case BilinearInterpolation:
+ {
+ int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1;
+ int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1;
+ int col2 = col1 + 1;
+ int row2 = row1 + 1;
+
+ if ( col1 < 0 )
+ col1 = col2;
+ else if ( col2 >= (int)d_data->numColumns )
+ col2 = col1;
+
+ if ( row1 < 0 )
+ row1 = row2;
+ else if ( row2 >= (int)d_data->numRows )
+ row2 = row1;
+
+ const double v11 = d_data->value( row1, col1 );
+ const double v21 = d_data->value( row1, col2 );
+ const double v12 = d_data->value( row2, col1 );
+ const double v22 = d_data->value( row2, col2 );
+
+ const double x2 = xInterval.minValue() +
+ ( col2 + 0.5 ) * d_data->dx;
+ const double y2 = yInterval.minValue() +
+ ( row2 + 0.5 ) * d_data->dy;
+
+ const double rx = ( x2 - x ) / d_data->dx;
+ const double ry = ( y2 - y ) / d_data->dy;
+
+ const double vr1 = rx * v11 + ( 1.0 - rx ) * v21;
+ const double vr2 = rx * v12 + ( 1.0 - rx ) * v22;
+
+ value = ry * vr1 + ( 1.0 - ry ) * vr2;
+
+ break;
+ }
+ case NearestNeighbour:
+ default:
+ {
+ uint row = uint( (y - yInterval.minValue() ) / d_data->dy );
+ uint col = uint( (x - xInterval.minValue() ) / d_data->dx );
+
+ // In case of intervals, where the maximum is included
+ // we get out of bound for row/col, when the value for the
+ // maximum is requested. Instead we return the value
+ // from the last row/col
+
+ if ( row >= d_data->numRows )
+ row = d_data->numRows - 1;
+
+ if ( col >= d_data->numColumns )
+ col = d_data->numColumns - 1;
+
+ value = d_data->value( row, col );
+ }
+ }
+
+ return value;
+}
+
+void QwtMatrixRasterData::update()
+{
+ d_data->numRows = 0;
+ d_data->dx = 0.0;
+ d_data->dy = 0.0;
+
+ if ( d_data->numColumns > 0 )
+ {
+ d_data->numRows = d_data->values.size() / d_data->numColumns;
+
+ const QwtInterval xInterval = interval( Qt::XAxis );
+ const QwtInterval yInterval = interval( Qt::YAxis );
+ if ( xInterval.isValid() )
+ d_data->dx = xInterval.width() / d_data->numColumns;
+ if ( yInterval.isValid() )
+ d_data->dy = yInterval.width() / d_data->numRows;
+ }
+}