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

Last change on this file since 4271 was 4271, checked in by mervart, 7 years ago
File size: 7.1 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(size_t row, size_t col) const
24    {
25        return values.data()[ row * numColumns + col ];
26    }
27
28    QwtMatrixRasterData::ResampleMode resampleMode;
29
30    QVector<double> values;
31    size_t numColumns;
32    size_t 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, size_t numColumns )
109{
110    d_data->values = values;
111    d_data->numColumns = numColumns;
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   \return Number of columns of the value matrix
126   \sa valueMatrix(), numRows(), setValueMatrix()
127*/
128size_t QwtMatrixRasterData::numColumns() const
129{
130    return d_data->numColumns;
131}
132
133/*!
134   \return Number of rows of the value matrix
135   \sa valueMatrix(), numColumns(), setValueMatrix()
136*/
137size_t QwtMatrixRasterData::numRows() const
138{
139    return d_data->numRows;
140}
141
142/*!
143   \brief Pixel hint
144
145   - NearestNeighbour\n
146     pixelHint() returns the surrounding pixel of the top left value
147     in the matrix.
148
149   - BilinearInterpolation\n
150     Returns an empty rectangle recommending
151     to render in target device ( f.e. screen ) resolution.
152
153   \sa ResampleMode, setMatrix(), setInterval()
154*/
155QRectF QwtMatrixRasterData::pixelHint( const QRectF & ) const
156{
157    QRectF rect;
158    if ( d_data->resampleMode == NearestNeighbour )
159    {
160        const QwtInterval intervalX = interval( Qt::XAxis );
161        const QwtInterval intervalY = interval( Qt::YAxis );
162        if ( intervalX.isValid() && intervalY.isValid() )
163        {
164            rect = QRectF( intervalX.minValue(), intervalY.minValue(),
165                d_data->dx, d_data->dy );
166        }
167    }
168
169    return rect;
170}
171
172/*!
173   \return the value at a raster position
174
175   \param x X value in plot coordinates
176   \param y Y value in plot coordinates
177
178   \sa ResampleMode
179*/
180double QwtMatrixRasterData::value( double x, double y ) const
181{
182    const QwtInterval xInterval = interval( Qt::XAxis );
183    const QwtInterval yInterval = interval( Qt::YAxis );
184
185    if ( !( xInterval.contains(x) && yInterval.contains(y) ) )
186        return qQNaN();
187
188    double value;
189
190    switch( d_data->resampleMode )
191    {
192        case BilinearInterpolation:
193        {
194            int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1;
195            int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1;
196            int col2 = col1 + 1;
197            int row2 = row1 + 1;
198
199            if ( col1 < 0 )
200                col1 = col2;
201            else if ( col2 >= (int)d_data->numColumns )
202                col2 = col1;
203
204            if ( row1 < 0 )
205                row1 = row2;
206            else if ( row2 >= (int)d_data->numRows )
207                row2 = row1;
208
209            const double v11 = d_data->value( row1, col1 );
210            const double v21 = d_data->value( row1, col2 );
211            const double v12 = d_data->value( row2, col1 );
212            const double v22 = d_data->value( row2, col2 );
213
214            const double x2 = xInterval.minValue() + 
215                ( col2 + 0.5 ) * d_data->dx;
216            const double y2 = yInterval.minValue() + 
217                ( row2 + 0.5 ) * d_data->dy;
218               
219            const double rx = ( x2 - x ) / d_data->dx;
220            const double ry = ( y2 - y ) / d_data->dy;
221
222            const double vr1 = rx * v11 + ( 1.0 - rx ) * v21;
223            const double vr2 = rx * v12 + ( 1.0 - rx ) * v22;
224
225            value = ry * vr1 + ( 1.0 - ry ) * vr2;
226
227            break;
228        }
229        case NearestNeighbour:
230        default:
231        {
232            uint row = uint( (y - yInterval.minValue() ) / d_data->dy );
233            uint col = uint( (x - xInterval.minValue() ) / d_data->dx );
234
235            // In case of intervals, where the maximum is included
236            // we get out of bound for row/col, when the value for the
237            // maximum is requested. Instead we return the value
238            // from the last row/col
239
240            if ( row >= d_data->numRows )
241                row = d_data->numRows - 1;
242
243            if ( col >= d_data->numColumns )
244                col = d_data->numColumns - 1;
245
246            value = d_data->value( row, col );
247        }
248    }
249
250    return value;
251}
252
253void QwtMatrixRasterData::update()
254{
255    d_data->numRows = 0;
256    d_data->dx = 0.0;
257    d_data->dy = 0.0;
258
259    if ( d_data->numColumns > 0 )
260    {
261        d_data->numRows = d_data->values.size() / d_data->numColumns;
262
263        const QwtInterval xInterval = interval( Qt::XAxis );
264        const QwtInterval yInterval = interval( Qt::YAxis );
265        if ( xInterval.isValid() )
266            d_data->dx = xInterval.width() / d_data->numColumns;
267        if ( yInterval.isValid() )
268            d_data->dy = yInterval.width() / d_data->numRows;
269    }
270}
Note: See TracBrowser for help on using the repository browser.