Qwt User's Guide: qwt_raster_data.cpp Source File

Qwt User's Guide 6.2.0

qwt_raster_data.cpp
1 /******************************************************************************
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 "qwt_interval.h"
13
14 #include <qrect.h>
15 #include <qpolygon.h>
16 #include <qnumeric.h>
17 #include <qlist.h>
18 #include <qmap.h>
19
20 class QwtRasterData::ContourPlane
21 {
22 public:
23 explicit inline ContourPlane( double z ):
24 m_z( z )
25 {
26 }
27
28 inline bool intersect( const QwtPoint3D vertex[3],
29 QPointF line[2], bool ignoreOnPlane ) const;
30
31 inline double z() const { return m_z; }
32
33 private:
34 inline int compare( double z ) const;
35 inline QPointF intersection(
36 const QwtPoint3D& p1, const QwtPoint3D& p2 ) const;
37
38 double m_z;
39 };
40
41 inline bool QwtRasterData::ContourPlane::intersect(
42 const QwtPoint3D vertex[3], QPointF line[2],
43 bool ignoreOnPlane ) const
44 {
45 bool found = true;
46
47 // Are the vertices below (-1), on (0) or above (1) the plan ?
48 const int eq1 = compare( vertex[0].z() );
49 const int eq2 = compare( vertex[1].z() );
50 const int eq3 = compare( vertex[2].z() );
51
52 /*
53 (a) All the vertices lie below the contour level.
54 (b) Two vertices lie below and one on the contour level.
55 (c) Two vertices lie below and one above the contour level.
56 (d) One vertex lies below and two on the contour level.
57 (e) One vertex lies below, one on and one above the contour level.
58 (f) One vertex lies below and two above the contour level.
59 (g) Three vertices lie on the contour level.
60 (h) Two vertices lie on and one above the contour level.
61 (i) One vertex lies on and two above the contour level.
62 (j) All the vertices lie above the contour level.
63 */
64
65 static const int tab[3][3][3] =
66 {
67 // jump table to avoid nested case statements
68 { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
69 { { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } },
70 { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
71 };
72
73 const int edgeType = tab[eq1 + 1][eq2 + 1][eq3 + 1];
74 switch ( edgeType )
75 {
76 case 1:
77 // d(0,0,-1), h(0,0,1)
78 line[0] = vertex[0].toPoint();
79 line[1] = vertex[1].toPoint();
80 break;
81 case 2:
82 // d(-1,0,0), h(1,0,0)
83 line[0] = vertex[1].toPoint();
84 line[1] = vertex[2].toPoint();
85 break;
86 case 3:
87 // d(0,-1,0), h(0,1,0)
88 line[0] = vertex[2].toPoint();
89 line[1] = vertex[0].toPoint();
90 break;
91 case 4:
92 // e(0,-1,1), e(0,1,-1)
93 line[0] = vertex[0].toPoint();
94 line[1] = intersection( vertex[1], vertex[2] );
95 break;
96 case 5:
97 // e(-1,0,1), e(1,0,-1)
98 line[0] = vertex[1].toPoint();
99 line[1] = intersection( vertex[2], vertex[0] );
100 break;
101 case 6:
102 // e(-1,1,0), e(1,0,-1)
103 line[0] = vertex[2].toPoint();
104 line[1] = intersection( vertex[0], vertex[1] );
105 break;
106 case 7:
107 // c(-1,1,-1), f(1,1,-1)
108 line[0] = intersection( vertex[0], vertex[1] );
109 line[1] = intersection( vertex[1], vertex[2] );
110 break;
111 case 8:
112 // c(-1,-1,1), f(1,1,-1)
113 line[0] = intersection( vertex[1], vertex[2] );
114 line[1] = intersection( vertex[2], vertex[0] );
115 break;
116 case 9:
117 // f(-1,1,1), c(1,-1,-1)
118 line[0] = intersection( vertex[2], vertex[0] );
119 line[1] = intersection( vertex[0], vertex[1] );
120 break;
121 case 10:
122 // g(0,0,0)
123 // The CONREC algorithm has no satisfying solution for
124 // what to do, when all vertices are on the plane.
125
126 if ( ignoreOnPlane )
127 found = false;
128 else
129 {
130 line[0] = vertex[2].toPoint();
131 line[1] = vertex[0].toPoint();
132 }
133 break;
134 default:
135 found = false;
136 }
137
138 return found;
139 }
140
141 inline int QwtRasterData::ContourPlane::compare( double z ) const
142 {
143 if ( z > m_z )
144 return 1;
145
146 if ( z < m_z )
147 return -1;
148
149 return 0;
150 }
151
152 inline QPointF QwtRasterData::ContourPlane::intersection(
153 const QwtPoint3D& p1, const QwtPoint3D& p2 ) const
154 {
155 const double h1 = p1.z() - m_z;
156 const double h2 = p2.z() - m_z;
157
158 const double x = ( h2 * p1.x() - h1 * p2.x() ) / ( h2 - h1 );
159 const double y = ( h2 * p1.y() - h1 * p2.y() ) / ( h2 - h1 );
160
161 return QPointF( x, y );
162 }
163
164 class QwtRasterData::PrivateData
165 {
166 public:
167 QwtRasterData::Attributes attributes;
168 };
169
171 QwtRasterData::QwtRasterData()
172 {
173 m_data = new PrivateData();
174 }
175
177 QwtRasterData::~QwtRasterData()
178 {
179 delete m_data;
180 }
181
189 void QwtRasterData::setAttribute( Attribute attribute, bool on )
190 {
191 if ( on )
192 m_data->attributes |= attribute;
193 else
194 m_data->attributes &= ~attribute;
195 }
196
201 bool QwtRasterData::testAttribute( Attribute attribute ) const
202 {
203 return m_data->attributes & attribute;
204 }
205
221 void QwtRasterData::initRaster( const QRectF& area, const QSize& raster )
222 {
223 Q_UNUSED( area );
224 Q_UNUSED( raster );
225 }
226
237 void QwtRasterData::discardRaster()
238 {
239 }
240
267 QRectF QwtRasterData::pixelHint( const QRectF& area ) const
268 {
269 Q_UNUSED( area );
270 return QRectF();
271 }
272
286 QwtRasterData::ContourLines QwtRasterData::contourLines(
287 const QRectF& rect, const QSize& raster,
288 const QList< double >& levels, ConrecFlags flags ) const
289 {
290 ContourLines contourLines;
291
292 if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
293 return contourLines;
294
295 const double dx = rect.width() / raster.width();
296 const double dy = rect.height() / raster.height();
297
298 const bool ignoreOnPlane =
299 flags & QwtRasterData::IgnoreAllVerticesOnLevel;
300
301 const QwtInterval range = interval( Qt::ZAxis );
302 bool ignoreOutOfRange = false;
303 if ( range.isValid() )
304 ignoreOutOfRange = flags & IgnoreOutOfRange;
305
306 QwtRasterData* that = const_cast< QwtRasterData* >( this );
307 that->initRaster( rect, raster );
308
309 for ( int y = 0; y < raster.height() - 1; y++ )
310 {
311 enum Position
312 {
313 Center,
314
315 TopLeft,
316 TopRight,
317 BottomRight,
318 BottomLeft,
319
320 NumPositions
321 };
322
323 QwtPoint3D xy[NumPositions];
324
325 for ( int x = 0; x < raster.width() - 1; x++ )
326 {
327 const QPointF pos( rect.x() + x * dx, rect.y() + y * dy );
328
329 if ( x == 0 )
330 {
331 xy[TopRight].setX( pos.x() );
332 xy[TopRight].setY( pos.y() );
333 xy[TopRight].setZ(
334 value( xy[TopRight].x(), xy[TopRight].y() )
335 );
336
337 xy[BottomRight].setX( pos.x() );
338 xy[BottomRight].setY( pos.y() + dy );
339 xy[BottomRight].setZ(
340 value( xy[BottomRight].x(), xy[BottomRight].y() )
341 );
342 }
343
344 xy[TopLeft] = xy[TopRight];
345 xy[BottomLeft] = xy[BottomRight];
346
347 xy[TopRight].setX( pos.x() + dx );
348 xy[TopRight].setY( pos.y() );
349 xy[BottomRight].setX( pos.x() + dx );
350 xy[BottomRight].setY( pos.y() + dy );
351
352 xy[TopRight].setZ(
353 value( xy[TopRight].x(), xy[TopRight].y() )
354 );
355 xy[BottomRight].setZ(
356 value( xy[BottomRight].x(), xy[BottomRight].y() )
357 );
358
359 double zMin = xy[TopLeft].z();
360 double zMax = zMin;
361 double zSum = zMin;
362
363 for ( int i = TopRight; i <= BottomLeft; i++ )
364 {
365 const double z = xy[i].z();
366
367 zSum += z;
368 if ( z < zMin )
369 zMin = z;
370 if ( z > zMax )
371 zMax = z;
372 }
373
374 if ( qIsNaN( zSum ) )
375 {
376 // one of the points is NaN
377 continue;
378 }
379
380 if ( ignoreOutOfRange )
381 {
382 if ( !range.contains( zMin ) || !range.contains( zMax ) )
383 continue;
384 }
385
386 if ( zMax < levels[0] ||
387 zMin > levels[levels.size() - 1] )
388 {
389 continue;
390 }
391
392 xy[Center].setX( pos.x() + 0.5 * dx );
393 xy[Center].setY( pos.y() + 0.5 * dy );
394 xy[Center].setZ( 0.25 * zSum );
395
396 const int numLevels = levels.size();
397 for ( int l = 0; l < numLevels; l++ )
398 {
399 const double level = levels[l];
400 if ( level < zMin || level > zMax )
401 continue;
402 QPolygonF& lines = contourLines[level];
403 const ContourPlane plane( level );
404
405 QPointF line[2];
406 QwtPoint3D vertex[3];
407
408 for ( int m = TopLeft; m < NumPositions; m++ )
409 {
410 vertex[0] = xy[m];
411 vertex[1] = xy[0];
412 vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
413
414 const bool intersects =
415 plane.intersect( vertex, line, ignoreOnPlane );
416 if ( intersects )
417 {
418 lines += line[0];
419 lines += line[1];
420 }
421 }
422 }
423 }
424 }
425
426 that->discardRaster();
427
428 return contourLines;
429 }
QList< double >
QMap
Definition: qwt_compass.h:19
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:23
QwtInterval::isValid
bool isValid() const
Definition: qwt_interval.h:210
QwtInterval::contains
bool contains(double value) const
Definition: qwt_interval.cpp:67
QwtPoint3D
QwtPoint3D class defines a 3D point in double coordinates.
Definition: qwt_point_3d.h:23
QwtPoint3D::z
double z() const
Definition: qwt_point_3d.h:115
QwtPoint3D::y
double y() const
Definition: qwt_point_3d.h:109
QwtPoint3D::setY
void setY(double y)
Sets the y-coordinate of the point to the value specified by y.
Definition: qwt_point_3d.h:145
QwtPoint3D::x
double x() const
Definition: qwt_point_3d.h:103
QwtPoint3D::setZ
void setZ(double y)
Sets the z-coordinate of the point to the value specified by z.
Definition: qwt_point_3d.h:151
QwtPoint3D::toPoint
QPointF toPoint() const
Definition: qwt_point_3d.h:159
QwtPoint3D::setX
void setX(double x)
Sets the x-coordinate of the point to the value specified by x.
Definition: qwt_point_3d.h:139
QwtRasterData
QwtRasterData defines an interface to any type of raster data.
Definition: qwt_raster_data.h:43
QwtRasterData::pixelHint
virtual QRectF pixelHint(const QRectF &) const
Pixel hint.
Definition: qwt_raster_data.cpp:267
QwtRasterData::testAttribute
bool testAttribute(Attribute) const
Definition: qwt_raster_data.cpp:201
QwtRasterData::QwtRasterData
QwtRasterData()
Constructor.
Definition: qwt_raster_data.cpp:171
QwtRasterData::ConrecFlags
QFlags< ConrecFlag > ConrecFlags
Definition: qwt_raster_data.h:86
QwtRasterData::discardRaster
virtual void discardRaster()
Discard a raster.
Definition: qwt_raster_data.cpp:237
QwtRasterData::value
virtual double value(double x, double y) const =0
QwtRasterData::initRaster
virtual void initRaster(const QRectF &, const QSize &raster)
Initialize a raster.
Definition: qwt_raster_data.cpp:221
QwtRasterData::Attributes
QFlags< Attribute > Attributes
Definition: qwt_raster_data.h:74
QwtRasterData::contourLines
virtual ContourLines contourLines(const QRectF &rect, const QSize &raster, const QList< double > &levels, ConrecFlags) const
Definition: qwt_raster_data.cpp:286
QwtRasterData::~QwtRasterData
virtual ~QwtRasterData()
Destructor.
Definition: qwt_raster_data.cpp:177
QwtRasterData::setAttribute
void setAttribute(Attribute, bool on=true)
Definition: qwt_raster_data.cpp:189
QwtRasterData::Attribute
Attribute
Raster data attributes.
Definition: qwt_raster_data.h:55
QwtRasterData::interval
virtual QwtInterval interval(Qt::Axis) const =0
QwtRasterData::IgnoreOutOfRange
@ IgnoreOutOfRange
Ignore all values, that are out of range.
Definition: qwt_raster_data.h:83
QwtRasterData::IgnoreAllVerticesOnLevel
@ IgnoreAllVerticesOnLevel
Ignore all vertices on the same level.
Definition: qwt_raster_data.h:80