source: ntrip/trunk/BNC/qwt/qwt_matrix_raster_data.cpp @ 8127

Last change on this file since 8127 was 8127, checked in by stoecker, 2 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 7.8 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997   Josef Wilgen
4 * Copyright (C) 2002   Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_matrix_raster_data.h"
11#include <qnumeric.h>
12#include <qmath.h>
13
14class QwtMatrixRasterData::PrivateData
15{
16public:
17    PrivateData():
18        resampleMode(QwtMatrixRasterData::NearestNeighbour),
19        numColumns(0)
20    {
21    }
22
23    inline double value(int row, int col) const
24    {
25        return values.data()[ row * numColumns + col ];
26    }
27
28    QwtMatrixRasterData::ResampleMode resampleMode;
29
30    QVector<double> values;
31    int numColumns;
32    int numRows;
33
34    double dx;
35    double dy;
36};
37
38//! Constructor
39QwtMatrixRasterData::QwtMatrixRasterData()
40{
41    d_data = new PrivateData();
42    update();
43}
44
45//! Destructor
46QwtMatrixRasterData::~QwtMatrixRasterData()
47{
48    delete d_data;
49}
50
51/*!
52   \brief Set the resampling algorithm
53
54   \param mode Resampling mode
55   \sa resampleMode(), value()
56*/
57void QwtMatrixRasterData::setResampleMode( ResampleMode mode )
58{
59    d_data->resampleMode = mode;
60}
61
62/*!
63   \return resampling algorithm
64   \sa setResampleMode(), value()
65*/
66QwtMatrixRasterData::ResampleMode QwtMatrixRasterData::resampleMode() const
67{
68    return d_data->resampleMode;
69}
70
71/*!
72   \brief Assign the bounding interval for an axis
73
74   Setting the bounding intervals for the X/Y axis is mandatory
75   to define the positions for the values of the value matrix.
76   The interval in Z direction defines the possible range for
77   the values in the matrix, what is f.e used by QwtPlotSpectrogram
78   to map values to colors. The Z-interval might be the bounding
79   interval of the values in the matrix, but usually it isn't.
80   ( f.e a interval of 0.0-100.0 for values in percentage )
81
82   \param axis X, Y or Z axis
83   \param interval Interval
84   
85   \sa QwtRasterData::interval(), setValueMatrix()
86*/
87void QwtMatrixRasterData::setInterval( 
88    Qt::Axis axis, const QwtInterval &interval )
89{
90    QwtRasterData::setInterval( axis, interval );
91    update();
92}
93
94/*!
95   \brief Assign a value matrix
96
97   The positions of the values are calculated by dividing
98   the bounding rectangle of the X/Y intervals into equidistant
99   rectangles ( pixels ). Each value corresponds to the center of
100   a pixel.
101
102   \param values Vector of values
103   \param numColumns Number of columns
104
105   \sa valueMatrix(), numColumns(), numRows(), setInterval()()
106*/
107void QwtMatrixRasterData::setValueMatrix( 
108    const QVector<double> &values, int numColumns )
109{
110    d_data->values = values;
111    d_data->numColumns = qMax( numColumns, 0 );
112    update();
113}
114
115/*!
116   \return Value matrix
117   \sa setValueMatrix(), numColumns(), numRows(), setInterval()
118*/
119const QVector<double> QwtMatrixRasterData::valueMatrix() const
120{
121    return d_data->values;
122}
123
124/*!
125  \brief Change a single value in the matrix
126
127  \param row Row index
128  \param col Column index
129  \param value New value
130
131  \sa value(), setValueMatrix()
132*/
133void QwtMatrixRasterData::setValue( int row, int col, double value )
134{
135    if ( row >= 0 && row < d_data->numRows &&
136        col >= 0 && col < d_data->numColumns )
137    {
138        const int index = row * d_data->numColumns + col;
139        d_data->values.data()[ index ] = value;
140    }
141}
142
143/*!
144   \return Number of columns of the value matrix
145   \sa valueMatrix(), numRows(), setValueMatrix()
146*/
147int QwtMatrixRasterData::numColumns() const
148{
149    return d_data->numColumns;
150}
151
152/*!
153   \return Number of rows of the value matrix
154   \sa valueMatrix(), numColumns(), setValueMatrix()
155*/
156int QwtMatrixRasterData::numRows() const
157{
158    return d_data->numRows;
159}
160
161/*!
162   \brief Calculate the pixel hint
163
164   pixelHint() returns the geometry of a pixel, that can be used
165   to calculate the resolution and alignment of the plot item, that is
166   representing the data.
167
168   - NearestNeighbour\n
169     pixelHint() returns the surrounding pixel of the top left value
170     in the matrix.
171
172   - BilinearInterpolation\n
173     Returns an empty rectangle recommending
174     to render in target device ( f.e. screen ) resolution.
175
176   \param area Requested area, ignored
177   \return Calculated hint
178
179   \sa ResampleMode, setMatrix(), setInterval()
180*/
181QRectF QwtMatrixRasterData::pixelHint( const QRectF &area ) const
182{
183    Q_UNUSED( area )
184
185    QRectF rect;
186    if ( d_data->resampleMode == NearestNeighbour )
187    {
188        const QwtInterval intervalX = interval( Qt::XAxis );
189        const QwtInterval intervalY = interval( Qt::YAxis );
190        if ( intervalX.isValid() && intervalY.isValid() )
191        {
192            rect = QRectF( intervalX.minValue(), intervalY.minValue(),
193                d_data->dx, d_data->dy );
194        }
195    }
196
197    return rect;
198}
199
200/*!
201   \return the value at a raster position
202
203   \param x X value in plot coordinates
204   \param y Y value in plot coordinates
205
206   \sa ResampleMode
207*/
208double QwtMatrixRasterData::value( double x, double y ) const
209{
210    const QwtInterval xInterval = interval( Qt::XAxis );
211    const QwtInterval yInterval = interval( Qt::YAxis );
212
213    if ( !( xInterval.contains(x) && yInterval.contains(y) ) )
214        return qQNaN();
215
216    double value;
217
218    switch( d_data->resampleMode )
219    {
220        case BilinearInterpolation:
221        {
222            int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1;
223            int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1;
224            int col2 = col1 + 1;
225            int row2 = row1 + 1;
226
227            if ( col1 < 0 )
228                col1 = col2;
229            else if ( col2 >= static_cast<int>( d_data->numColumns ) )
230                col2 = col1;
231
232            if ( row1 < 0 )
233                row1 = row2;
234            else if ( row2 >= static_cast<int>( d_data->numRows ) )
235                row2 = row1;
236
237            const double v11 = d_data->value( row1, col1 );
238            const double v21 = d_data->value( row1, col2 );
239            const double v12 = d_data->value( row2, col1 );
240            const double v22 = d_data->value( row2, col2 );
241
242            const double x2 = xInterval.minValue() + 
243                ( col2 + 0.5 ) * d_data->dx;
244            const double y2 = yInterval.minValue() + 
245                ( row2 + 0.5 ) * d_data->dy;
246               
247            const double rx = ( x2 - x ) / d_data->dx;
248            const double ry = ( y2 - y ) / d_data->dy;
249
250            const double vr1 = rx * v11 + ( 1.0 - rx ) * v21;
251            const double vr2 = rx * v12 + ( 1.0 - rx ) * v22;
252
253            value = ry * vr1 + ( 1.0 - ry ) * vr2;
254
255            break;
256        }
257        case NearestNeighbour:
258        default:
259        {
260            int row = int( (y - yInterval.minValue() ) / d_data->dy );
261            int col = int( (x - xInterval.minValue() ) / d_data->dx );
262
263            // In case of intervals, where the maximum is included
264            // we get out of bound for row/col, when the value for the
265            // maximum is requested. Instead we return the value
266            // from the last row/col
267
268            if ( row >= d_data->numRows )
269                row = d_data->numRows - 1;
270
271            if ( col >= d_data->numColumns )
272                col = d_data->numColumns - 1;
273
274            value = d_data->value( row, col );
275        }
276    }
277
278    return value;
279}
280
281void QwtMatrixRasterData::update()
282{
283    d_data->numRows = 0;
284    d_data->dx = 0.0;
285    d_data->dy = 0.0;
286
287    if ( d_data->numColumns > 0 )
288    {
289        d_data->numRows = d_data->values.size() / d_data->numColumns;
290
291        const QwtInterval xInterval = interval( Qt::XAxis );
292        const QwtInterval yInterval = interval( Qt::YAxis );
293        if ( xInterval.isValid() )
294            d_data->dx = xInterval.width() / d_data->numColumns;
295        if ( yInterval.isValid() )
296            d_data->dy = yInterval.width() / d_data->numRows;
297    }
298}
Note: See TracBrowser for help on using the repository browser.