source: ntrip/branches/BNC_2.12/qwt/qwt_raster_data.cpp@ 10006

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