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

Last change on this file since 10083 was 9383, checked in by stoecker, 4 years ago

update to qwt verion 6.1.1 to fix build with newer Qt5

File size: 11.6 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#if __GNUC__ >= 9
285#pragma GCC diagnostic push
286#pragma GCC diagnostic ignored "-Wdeprecated-copy"
287#endif
288
289 for ( int y = 0; y < raster.height() - 1; y++ )
290 {
291 enum Position
292 {
293 Center,
294
295 TopLeft,
296 TopRight,
297 BottomRight,
298 BottomLeft,
299
300 NumPositions
301 };
302
303 QwtPoint3D xy[NumPositions];
304
305 for ( int x = 0; x < raster.width() - 1; x++ )
306 {
307 const QPointF pos( rect.x() + x * dx, rect.y() + y * dy );
308
309 if ( x == 0 )
310 {
311 xy[TopRight].setX( pos.x() );
312 xy[TopRight].setY( pos.y() );
313 xy[TopRight].setZ(
314 value( xy[TopRight].x(), xy[TopRight].y() )
315 );
316
317 xy[BottomRight].setX( pos.x() );
318 xy[BottomRight].setY( pos.y() + dy );
319 xy[BottomRight].setZ(
320 value( xy[BottomRight].x(), xy[BottomRight].y() )
321 );
322 }
323
324 xy[TopLeft] = xy[TopRight];
325 xy[BottomLeft] = xy[BottomRight];
326
327 xy[TopRight].setX( pos.x() + dx );
328 xy[TopRight].setY( pos.y() );
329 xy[BottomRight].setX( pos.x() + dx );
330 xy[BottomRight].setY( pos.y() + dy );
331
332 xy[TopRight].setZ(
333 value( xy[TopRight].x(), xy[TopRight].y() )
334 );
335 xy[BottomRight].setZ(
336 value( xy[BottomRight].x(), xy[BottomRight].y() )
337 );
338
339 double zMin = xy[TopLeft].z();
340 double zMax = zMin;
341 double zSum = zMin;
342
343 for ( int i = TopRight; i <= BottomLeft; i++ )
344 {
345 const double z = xy[i].z();
346
347 zSum += z;
348 if ( z < zMin )
349 zMin = z;
350 if ( z > zMax )
351 zMax = z;
352 }
353
354 if ( qIsNaN( zSum ) )
355 {
356 // one of the points is NaN
357 continue;
358 }
359
360 if ( ignoreOutOfRange )
361 {
362 if ( !range.contains( zMin ) || !range.contains( zMax ) )
363 continue;
364 }
365
366 if ( zMax < levels[0] ||
367 zMin > levels[levels.size() - 1] )
368 {
369 continue;
370 }
371
372 xy[Center].setX( pos.x() + 0.5 * dx );
373 xy[Center].setY( pos.y() + 0.5 * dy );
374 xy[Center].setZ( 0.25 * zSum );
375
376 const int numLevels = levels.size();
377 for ( int l = 0; l < numLevels; l++ )
378 {
379 const double level = levels[l];
380 if ( level < zMin || level > zMax )
381 continue;
382 QPolygonF &lines = contourLines[level];
383 const ContourPlane plane( level );
384
385 QPointF line[2];
386 QwtPoint3D 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 lines += line[0];
399 lines += line[1];
400 }
401 }
402 }
403 }
404 }
405
406#if __GNUC__ >= 9
407#pragma GCC diagnostic pop
408#endif
409
410 that->discardRaster();
411
412 return contourLines;
413}
Note: See TracBrowser for help on using the repository browser.