source: ntrip/trunk/BNC/qwt/qwt_raster_data.cpp@ 8474

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

update qwt and qwtpolar, many QT5 fixes (unfinished)

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