1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
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
*****************************************************************************/
10
#include "qwt_raster_data.h"
12
class QwtRasterData::Contour3DPoint
15
inline void setPos(double x, double y)
21
inline QwtDoublePoint pos() const
23
return QwtDoublePoint(d_x, d_y);
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; }
30
inline double x() const { return d_x; }
31
inline double y() const { return d_y; }
32
inline double z() const { return d_z; }
40
class QwtRasterData::ContourPlane
43
inline ContourPlane(double z):
48
inline bool intersect(const Contour3DPoint vertex[3],
49
QwtDoublePoint line[2], bool ignoreOnPlane) const;
51
inline double z() const { return d_z; }
54
inline int compare(double z) const;
55
inline QwtDoublePoint intersection(
56
const Contour3DPoint& p1, const Contour3DPoint &p2) const;
61
inline bool QwtRasterData::ContourPlane::intersect(
62
const Contour3DPoint vertex[3], QwtDoublePoint line[2],
63
bool ignoreOnPlane) const
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());
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.
85
static const int tab[3][3][3] =
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 } }
93
const int edgeType = tab[eq1+1][eq2+1][eq3+1];
97
// d(0,0,-1), h(0,0,1)
98
line[0] = vertex[0].pos();
99
line[1] = vertex[1].pos();
102
// d(-1,0,0), h(1,0,0)
103
line[0] = vertex[1].pos();
104
line[1] = vertex[2].pos();
107
// d(0,-1,0), h(0,1,0)
108
line[0] = vertex[2].pos();
109
line[1] = vertex[0].pos();
112
// e(0,-1,1), e(0,1,-1)
113
line[0] = vertex[0].pos();
114
line[1] = intersection(vertex[1], vertex[2]);
117
// e(-1,0,1), e(1,0,-1)
118
line[0] = vertex[1].pos();
119
line[1] = intersection(vertex[2], vertex[0]);
122
// e(-1,1,0), e(1,0,-1)
123
line[0] = vertex[1].pos();
124
line[1] = intersection(vertex[0], vertex[1]);
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]);
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]);
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]);
143
// The CONREC algorithm has no satisfying solution for
144
// what to do, when all vertices are on the plane.
150
line[0] = vertex[2].pos();
151
line[1] = vertex[0].pos();
161
inline int QwtRasterData::ContourPlane::compare(double z) const
172
inline QwtDoublePoint QwtRasterData::ContourPlane::intersection(
173
const Contour3DPoint& p1, const Contour3DPoint &p2) const
175
const double h1 = p1.z() - d_z;
176
const double h2 = p2.z() - d_z;
178
const double x = (h2 * p1.x() - h1 * p2.x()) / (h2 - h1);
179
const double y = (h2 * p1.y() - h1 * p2.y()) / (h2 - h1);
181
return QwtDoublePoint(x, y);
184
QwtRasterData::QwtRasterData()
188
QwtRasterData::QwtRasterData(const QwtDoubleRect &boundingRect):
189
d_boundingRect(boundingRect)
193
QwtRasterData::~QwtRasterData()
197
void QwtRasterData::setBoundingRect(const QwtDoubleRect &boundingRect)
199
d_boundingRect = boundingRect;
202
QwtDoubleRect QwtRasterData::boundingRect() const
204
return d_boundingRect;
208
\brief Initialize a raster
210
Before the composition of an image QwtPlotSpectrogram calls initRaster,
211
announcing the area and its resolution that will be requested.
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.
217
\param rect Area of the raster
218
\param raster Number of horizontal and vertical pixels
220
\sa initRaster(), value()
222
void QwtRasterData::initRaster(const QwtDoubleRect &, const QSize&)
227
\brief Discard a raster
229
After the composition of an image QwtPlotSpectrogram calls discardRaster().
231
The default implementation does nothing, but if data has been loaded
232
in initRaster(), it could deleted now.
234
\sa initRaster(), value()
236
void QwtRasterData::discardRaster()
241
\brief Find the raster of the data for an area
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.
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.
251
The default implementation returns an invalid resolution (size)
253
\param rect In most implementations the resolution of the data doesn't
254
depend on the requested rectangle.
256
\return Resolution, as number of horizontal and vertical pixels
258
QSize QwtRasterData::rasterHint(const QwtDoubleRect &) const
260
return QSize(); // use screen resolution
264
Calculate contour lines
266
An adaption of CONREC, a simple contouring algorithm.
267
http://astronomy.swin.edu.au/~pbourke/projection/conrec
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
274
QwtRasterData::ContourLines QwtRasterData::contourLines(
275
const QwtDoubleRect &rect, const QSize &raster,
276
const QValueList<double> &levels, int flags) const
279
ContourLines contourLines;
281
if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
284
const double dx = rect.width() / raster.width();
285
const double dy = rect.height() / raster.height();
287
const bool ignoreOnPlane =
288
flags & QwtRasterData::IgnoreAllVerticesOnLevel;
290
const QwtDoubleInterval range = this->range();
291
bool ignoreOutOfRange = false;
292
if ( range.isValid() )
293
ignoreOutOfRange = flags & IgnoreOutOfRange;
295
((QwtRasterData*)this)->initRaster(rect, raster);
297
for ( int y = 0; y < raster.height() - 1; y++ )
311
Contour3DPoint xy[NumPositions];
313
for ( int x = 0; x < raster.width() - 1; x++ )
315
const QwtDoublePoint pos(rect.x() + x * dx, rect.y() + y * dy);
319
xy[TopRight].setPos(pos.x(), pos.y());
321
value( xy[TopRight].x(), xy[TopRight].y())
324
xy[BottomRight].setPos(pos.x(), pos.y() + dy);
325
xy[BottomRight].setZ(
326
value(xy[BottomRight].x(), xy[BottomRight].y())
330
xy[TopLeft] = xy[TopRight];
331
xy[BottomLeft] = xy[BottomRight];
333
xy[TopRight].setPos(pos.x() + dx, pos.y());
334
xy[BottomRight].setPos(pos.x() + dx, pos.y() + dy);
337
value(xy[TopRight].x(), xy[TopRight].y())
339
xy[BottomRight].setZ(
340
value(xy[BottomRight].x(), xy[BottomRight].y())
343
double zMin = xy[TopLeft].z();
347
for ( int i = TopRight; i <= BottomLeft; i++ )
349
const double z = xy[i].z();
358
if ( ignoreOutOfRange )
360
if ( !range.contains(zMin) || !range.contains(zMax) )
364
if ( zMax < levels[0] ||
365
zMin > levels[levels.size() - 1] )
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++)
375
const double level = levels[l];
376
if ( level < zMin || level > zMax )
378
#if QT_VERSION >= 0x040000
379
QPolygonF &lines = contourLines[level];
381
QwtArray<QwtDoublePoint> &lines = contourLines[level];
383
const ContourPlane plane(level);
385
QwtDoublePoint line[2];
386
Contour3DPoint vertex[3];
388
for (int m = TopLeft; m < NumPositions; m++)
392
vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
394
const bool intersects =
395
plane.intersect(vertex, line, ignoreOnPlane);
398
#if QT_VERSION >= 0x040000
402
const int index = lines.size();
403
lines.resize(lines.size() + 2, QGArray::SpeedOptim);
405
lines[index] = line[0];
406
lines[index+1] = line[1];
414
((QwtRasterData*)this)->discardRaster();