Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
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
20class 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
41inline 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
141inline 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
152inline 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
164class QwtRasterData::PrivateData
165{
166 public:
167 QwtRasterData::Attributes attributes;
168};
169
172{
173 m_data = new PrivateData();
174}
175
178{
179 delete m_data;
180}
181
189void QwtRasterData::setAttribute( Attribute attribute, bool on )
190{
191 if ( on )
192 m_data->attributes |= attribute;
193 else
194 m_data->attributes &= ~attribute;
195}
196
202{
203 return m_data->attributes & attribute;
204}
205
221void QwtRasterData::initRaster( const QRectF& area, const QSize& raster )
222{
223 Q_UNUSED( area );
224 Q_UNUSED( raster );
225}
226
240
267QRectF QwtRasterData::pixelHint( const QRectF& area ) const
268{
269 Q_UNUSED( area );
270 return QRectF();
271}
272
287 const QRectF& rect, const QSize& raster,
288 const QList< double >& levels, ConrecFlags flags ) const
289{
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 =
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}
A class representing an interval.
bool isValid() const
bool contains(double value) const
QwtPoint3D class defines a 3D point in double coordinates.
double z() const
double y() const
void setY(double y)
Sets the y-coordinate of the point to the value specified by y.
double x() const
void setZ(double y)
Sets the z-coordinate of the point to the value specified by z.
QPointF toPoint() const
void setX(double x)
Sets the x-coordinate of the point to the value specified by x.
QwtRasterData defines an interface to any type of raster data.
virtual QRectF pixelHint(const QRectF &) const
Pixel hint.
bool testAttribute(Attribute) const
QwtRasterData()
Constructor.
QFlags< ConrecFlag > ConrecFlags
virtual void discardRaster()
Discard a raster.
virtual double value(double x, double y) const =0
virtual void initRaster(const QRectF &, const QSize &raster)
Initialize a raster.
QFlags< Attribute > Attributes
virtual ContourLines contourLines(const QRectF &rect, const QSize &raster, const QList< double > &levels, ConrecFlags) const
virtual ~QwtRasterData()
Destructor.
void setAttribute(Attribute, bool on=true)
Attribute
Raster data attributes.
virtual QwtInterval interval(Qt::Axis) const =0
@ IgnoreOutOfRange
Ignore all values, that are out of range.
@ IgnoreAllVerticesOnLevel
Ignore all vertices on the same level.