~ubuntu-branches/ubuntu/oneiric/qwt/oneiric-proposed

« back to all changes in this revision

Viewing changes to qwt-5.1.0/src/qwt_raster_data.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-05-26 10:26:31 UTC
  • mfrom: (1.1.3 upstream) (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526102631-bp95mfccnrb957nx
Tags: 5.1.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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_raster_data.h"
11
 
 
12
 
class QwtRasterData::Contour3DPoint
13
 
{
14
 
public:
15
 
    inline void setPos(double x, double y)
16
 
    {
17
 
        d_x = x;
18
 
        d_y = y;
19
 
    }
20
 
 
21
 
    inline QwtDoublePoint pos() const
22
 
    {
23
 
        return QwtDoublePoint(d_x, d_y);
24
 
    }
25
 
 
26
 
    inline void setX(double x) { d_x = x; }
27
 
    inline void setY(double y) { d_y = y; }
28
 
    inline void setZ(double z) { d_z = z; }
29
 
 
30
 
    inline double x() const { return d_x; }
31
 
    inline double y() const { return d_y; }
32
 
    inline double z() const { return d_z; }
33
 
 
34
 
private:
35
 
    double d_x;
36
 
    double d_y;
37
 
    double d_z;
38
 
};
39
 
 
40
 
class QwtRasterData::ContourPlane
41
 
{
42
 
public:
43
 
    inline ContourPlane(double z):
44
 
        d_z(z)
45
 
    {
46
 
    }
47
 
 
48
 
    inline bool intersect(const Contour3DPoint vertex[3],
49
 
        QwtDoublePoint line[2], bool ignoreOnPlane) const;
50
 
 
51
 
    inline double z() const { return d_z; }
52
 
 
53
 
private:
54
 
    inline int compare(double z) const;
55
 
    inline QwtDoublePoint intersection(
56
 
        const Contour3DPoint& p1, const Contour3DPoint &p2) const;
57
 
 
58
 
    double d_z;
59
 
};
60
 
 
61
 
inline bool QwtRasterData::ContourPlane::intersect(
62
 
    const Contour3DPoint vertex[3], QwtDoublePoint line[2],
63
 
    bool ignoreOnPlane) const
64
 
{
65
 
    bool found = true;
66
 
 
67
 
    // Are the vertices below (-1), on (0) or above (1) the plan ?
68
 
    const int eq1 = compare(vertex[0].z());
69
 
    const int eq2 = compare(vertex[1].z());
70
 
    const int eq3 = compare(vertex[2].z());
71
 
 
72
 
    /*
73
 
        (a) All the vertices lie below the contour level.
74
 
        (b) Two vertices lie below and one on the contour level.
75
 
        (c) Two vertices lie below and one above the contour level.
76
 
        (d) One vertex lies below and two on the contour level.
77
 
        (e) One vertex lies below, one on and one above the contour level.
78
 
        (f) One vertex lies below and two above the contour level.
79
 
        (g) Three vertices lie on the contour level.
80
 
        (h) Two vertices lie on and one above the contour level.
81
 
        (i) One vertex lies on and two above the contour level.
82
 
        (j) All the vertices lie above the contour level.
83
 
     */
84
 
 
85
 
    static const int tab[3][3][3] =
86
 
    {
87
 
        // jump table to avoid nested case statements
88
 
        { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
89
 
        { { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } },
90
 
        { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
91
 
    };
92
 
 
93
 
    const int edgeType = tab[eq1+1][eq2+1][eq3+1];
94
 
    switch (edgeType)  
95
 
    {
96
 
        case 1:
97
 
            // d(0,0,-1), h(0,0,1)
98
 
            line[0] = vertex[0].pos();
99
 
            line[1] = vertex[1].pos();
100
 
            break;
101
 
        case 2:
102
 
            // d(-1,0,0), h(1,0,0)
103
 
            line[0] = vertex[1].pos();
104
 
            line[1] = vertex[2].pos();
105
 
            break;
106
 
        case 3:
107
 
            // d(0,-1,0), h(0,1,0)
108
 
            line[0] = vertex[2].pos();
109
 
            line[1] = vertex[0].pos();
110
 
            break;
111
 
        case 4:
112
 
            // e(0,-1,1), e(0,1,-1)
113
 
            line[0] = vertex[0].pos();
114
 
            line[1] = intersection(vertex[1], vertex[2]);
115
 
            break;
116
 
        case 5:
117
 
            // e(-1,0,1), e(1,0,-1)
118
 
            line[0] = vertex[1].pos();
119
 
            line[1] = intersection(vertex[2], vertex[0]);
120
 
            break;
121
 
        case 6:
122
 
            // e(-1,1,0), e(1,0,-1)
123
 
            line[0] = vertex[1].pos();
124
 
            line[1] = intersection(vertex[0], vertex[1]);
125
 
            break;
126
 
        case 7:
127
 
            // c(-1,1,-1), f(1,1,-1)
128
 
            line[0] = intersection(vertex[0], vertex[1]);
129
 
            line[1] = intersection(vertex[1], vertex[2]);
130
 
            break;
131
 
        case 8:
132
 
            // c(-1,-1,1), f(1,1,-1)
133
 
            line[0] = intersection(vertex[1], vertex[2]);
134
 
            line[1] = intersection(vertex[2], vertex[0]);
135
 
            break;
136
 
        case 9:
137
 
            // f(-1,1,1), c(1,-1,-1)
138
 
            line[0] = intersection(vertex[2], vertex[0]);
139
 
            line[1] = intersection(vertex[0], vertex[1]);
140
 
            break;
141
 
        case 10:
142
 
            // g(0,0,0)
143
 
            // The CONREC algorithm has no satisfying solution for
144
 
            // what to do, when all vertices are on the plane.
145
 
 
146
 
            if ( ignoreOnPlane )
147
 
                found = false;
148
 
            else
149
 
            {
150
 
                line[0] = vertex[2].pos();
151
 
                line[1] = vertex[0].pos();
152
 
            }
153
 
            break;
154
 
        default:
155
 
            found = false;
156
 
    }
157
 
 
158
 
    return found;
159
 
}
160
 
 
161
 
inline int QwtRasterData::ContourPlane::compare(double z) const
162
 
{
163
 
    if (z > d_z)
164
 
        return 1;
165
 
 
166
 
    if (z < d_z)
167
 
        return -1;
168
 
 
169
 
    return 0;
170
 
}
171
 
 
172
 
inline QwtDoublePoint QwtRasterData::ContourPlane::intersection(
173
 
    const Contour3DPoint& p1, const Contour3DPoint &p2) const
174
 
{
175
 
    const double h1 = p1.z() - d_z;
176
 
    const double h2 = p2.z() - d_z;
177
 
 
178
 
    const double x = (h2 * p1.x() - h1 * p2.x()) / (h2 - h1);
179
 
    const double y = (h2 * p1.y() - h1 * p2.y()) / (h2 - h1);
180
 
 
181
 
    return QwtDoublePoint(x, y);
182
 
}
183
 
 
184
 
QwtRasterData::QwtRasterData()
185
 
{
186
 
}
187
 
 
188
 
QwtRasterData::QwtRasterData(const QwtDoubleRect &boundingRect):
189
 
    d_boundingRect(boundingRect)
190
 
{
191
 
}
192
 
 
193
 
QwtRasterData::~QwtRasterData()
194
 
{
195
 
}
196
 
 
197
 
void QwtRasterData::setBoundingRect(const QwtDoubleRect &boundingRect)
198
 
{
199
 
    d_boundingRect = boundingRect;
200
 
}
201
 
 
202
 
QwtDoubleRect QwtRasterData::boundingRect() const
203
 
{
204
 
    return d_boundingRect;
205
 
}
206
 
 
207
 
/*!
208
 
  \brief Initialize a raster
209
 
 
210
 
  Before the composition of an image QwtPlotSpectrogram calls initRaster,
211
 
  announcing the area and its resolution that will be requested.
212
 
  
213
 
  The default implementation does nothing, but for data sets that
214
 
  are stored in files, it might be good idea to reimplement initRaster,
215
 
  where the data is resampled and loaded into memory.
216
 
  
217
 
  \param rect Area of the raster
218
 
  \param raster Number of horizontal and vertical pixels
219
 
 
220
 
  \sa initRaster(), value()
221
 
*/
222
 
void QwtRasterData::initRaster(const QwtDoubleRect &, const QSize&)
223
 
{
224
 
}
225
 
 
226
 
/*!
227
 
  \brief Discard a raster
228
 
 
229
 
  After the composition of an image QwtPlotSpectrogram calls discardRaster().
230
 
  
231
 
  The default implementation does nothing, but if data has been loaded
232
 
  in initRaster(), it could deleted now.
233
 
 
234
 
  \sa initRaster(), value()
235
 
*/
236
 
void QwtRasterData::discardRaster()
237
 
{
238
 
}
239
 
 
240
 
/*!
241
 
   \brief Find the raster of the data for an area
242
 
 
243
 
   The resolution is the number of horizontal and vertical pixels
244
 
   that the data can return for an area. An invalid resolution
245
 
   indicates that the data can return values for any detail level.
246
 
 
247
 
   The resolution will limit the size of the image that is rendered 
248
 
   from the data. F.e. this might be important when printing a spectrogram
249
 
   to a A0 printer with 600 dpi.
250
 
   
251
 
   The default implementation returns an invalid resolution (size)
252
 
 
253
 
   \param rect In most implementations the resolution of the data doesn't 
254
 
               depend on the requested rectangle.
255
 
 
256
 
   \return Resolution, as number of horizontal and vertical pixels
257
 
*/
258
 
QSize QwtRasterData::rasterHint(const QwtDoubleRect &) const
259
 
{
260
 
    return QSize(); // use screen resolution
261
 
}
262
 
 
263
 
/*!
264
 
   Calculate contour lines
265
 
   
266
 
   An adaption of CONREC, a simple contouring algorithm.
267
 
   http://astronomy.swin.edu.au/~pbourke/projection/conrec
268
 
*/ 
269
 
#if QT_VERSION >= 0x040000
270
 
QwtRasterData::ContourLines QwtRasterData::contourLines(
271
 
    const QwtDoubleRect &rect, const QSize &raster, 
272
 
    const QList<double> &levels, int flags) const
273
 
#else
274
 
QwtRasterData::ContourLines QwtRasterData::contourLines(
275
 
    const QwtDoubleRect &rect, const QSize &raster, 
276
 
    const QValueList<double> &levels, int flags) const
277
 
#endif
278
 
{   
279
 
    ContourLines contourLines;
280
 
    
281
 
    if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
282
 
        return contourLines;
283
 
 
284
 
    const double dx = rect.width() / raster.width();
285
 
    const double dy = rect.height() / raster.height();
286
 
 
287
 
    const bool ignoreOnPlane =
288
 
        flags & QwtRasterData::IgnoreAllVerticesOnLevel;
289
 
 
290
 
    const QwtDoubleInterval range = this->range();
291
 
    bool ignoreOutOfRange = false;
292
 
    if ( range.isValid() )
293
 
        ignoreOutOfRange = flags & IgnoreOutOfRange;
294
 
 
295
 
    ((QwtRasterData*)this)->initRaster(rect, raster);
296
 
 
297
 
    for ( int y = 0; y < raster.height() - 1; y++ )
298
 
    {
299
 
        enum Position
300
 
        {
301
 
            Center,
302
 
 
303
 
            TopLeft,
304
 
            TopRight,
305
 
            BottomRight,
306
 
            BottomLeft,
307
 
 
308
 
            NumPositions
309
 
        };
310
 
 
311
 
        Contour3DPoint xy[NumPositions];
312
 
 
313
 
        for ( int x = 0; x < raster.width() - 1; x++ )
314
 
        {
315
 
            const QwtDoublePoint pos(rect.x() + x * dx, rect.y() + y * dy);
316
 
 
317
 
            if ( x == 0 )
318
 
            {
319
 
                xy[TopRight].setPos(pos.x(), pos.y());
320
 
                xy[TopRight].setZ(
321
 
                    value( xy[TopRight].x(), xy[TopRight].y())
322
 
                );
323
 
 
324
 
                xy[BottomRight].setPos(pos.x(), pos.y() + dy);
325
 
                xy[BottomRight].setZ(
326
 
                    value(xy[BottomRight].x(), xy[BottomRight].y())
327
 
                );
328
 
            }
329
 
 
330
 
            xy[TopLeft] = xy[TopRight];
331
 
            xy[BottomLeft] = xy[BottomRight];
332
 
 
333
 
            xy[TopRight].setPos(pos.x() + dx, pos.y());
334
 
            xy[BottomRight].setPos(pos.x() + dx, pos.y() + dy);
335
 
 
336
 
            xy[TopRight].setZ(
337
 
                value(xy[TopRight].x(), xy[TopRight].y())
338
 
            );
339
 
            xy[BottomRight].setZ(
340
 
                value(xy[BottomRight].x(), xy[BottomRight].y())
341
 
            );
342
 
 
343
 
            double zMin = xy[TopLeft].z();
344
 
            double zMax = zMin;
345
 
            double zSum = zMin;
346
 
 
347
 
            for ( int i = TopRight; i <= BottomLeft; i++ )
348
 
            {
349
 
                const double z = xy[i].z();
350
 
 
351
 
                zSum += z;
352
 
                if ( z < zMin )
353
 
                    zMin = z;
354
 
                if ( z > zMax )
355
 
                    zMax = z;
356
 
            }
357
 
 
358
 
            if ( ignoreOutOfRange )
359
 
            {
360
 
                if ( !range.contains(zMin) || !range.contains(zMax) )
361
 
                    continue;
362
 
            }
363
 
 
364
 
            if ( zMax < levels[0] ||
365
 
                zMin > levels[levels.size() - 1] )
366
 
            {
367
 
                continue;
368
 
            }
369
 
 
370
 
            xy[Center].setPos(pos.x() + 0.5 * dx, pos.y() + 0.5 * dy);
371
 
            xy[Center].setZ(0.25 * zSum);
372
 
            const int numLevels = (int)levels.size();
373
 
            for (int l = 0; l < numLevels; l++)
374
 
            {
375
 
                const double level = levels[l];
376
 
                if ( level < zMin || level > zMax )
377
 
                    continue;
378
 
#if QT_VERSION >= 0x040000
379
 
                QPolygonF &lines = contourLines[level];
380
 
#else
381
 
                QwtArray<QwtDoublePoint> &lines = contourLines[level];
382
 
#endif
383
 
                const ContourPlane plane(level);
384
 
 
385
 
                QwtDoublePoint line[2];
386
 
                Contour3DPoint vertex[3];
387
 
 
388
 
                for (int m = TopLeft; m < NumPositions; m++)
389
 
                {
390
 
                    vertex[0] = xy[m];
391
 
                    vertex[1] = xy[0];
392
 
                    vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
393
 
 
394
 
                    const bool intersects =
395
 
                        plane.intersect(vertex, line, ignoreOnPlane);
396
 
                    if ( intersects )
397
 
                    {
398
 
#if QT_VERSION >= 0x040000
399
 
                        lines += line[0];
400
 
                        lines += line[1];
401
 
#else
402
 
                        const int index = lines.size();
403
 
                        lines.resize(lines.size() + 2, QGArray::SpeedOptim);
404
 
 
405
 
                        lines[index] = line[0];
406
 
                        lines[index+1] = line[1];
407
 
#endif
408
 
                    }
409
 
                }
410
 
            }
411
 
        }
412
 
    }
413
 
 
414
 
    ((QwtRasterData*)this)->discardRaster();
415
 
 
416
 
    return contourLines;
417
 
}