Qwt User's Guide 6.3.0

Loading...
Searching...
No Matches
qwt_polar_spectrogram.cpp
1/******************************************************************************
2 * QwtPolar Widget Library
3 * Copyright (C) 2008 Uwe Rathmann
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the Qwt License, Version 1.0
7 *****************************************************************************/
8
9#include "qwt_polar_spectrogram.h"
10#include "qwt_polar.h"
11#include "qwt_polar_plot.h"
12#include "qwt_color_map.h"
13#include "qwt_scale_map.h"
14#include "qwt_raster_data.h"
15#include "qwt_math.h"
16#include "qwt_clipper.h"
17
18#include <qpainter.h>
19#include <qpainterpath.h>
20#include <qthread.h>
21#include <qfuture.h>
22#include <qtconcurrentrun.h>
23#include <qnumeric.h>
24
25 class QwtPolarSpectrogram::TileInfo
26{
27 public:
28 QPoint imagePos;
29 QRect rect;
30 QImage* image;
31};
32
33 class QwtPolarSpectrogram::PrivateData
34{
35 public:
36 PrivateData()
37 : data( NULL )
38 {
39 colorMap = new QwtLinearColorMap();
40 }
41
42 ~PrivateData()
43 {
44 delete data;
45 delete colorMap;
46 }
47
48 QwtRasterData* data;
49 QwtColorMap* colorMap;
50
51 QwtPolarSpectrogram::PaintAttributes paintAttributes;
52};
53
55 QwtPolarSpectrogram::QwtPolarSpectrogram()
56 : QwtPolarItem( QwtText( "Spectrogram" ) )
57{
58 m_data = new PrivateData;
59
60 setItemAttribute( QwtPolarItem::AutoScale );
61 setItemAttribute( QwtPolarItem::Legend, false );
62
63 setZ( 20.0 );
64}
65
67 QwtPolarSpectrogram::~QwtPolarSpectrogram()
68{
69 delete m_data;
70}
71
73 int QwtPolarSpectrogram::rtti() const
74{
75 return QwtPolarItem::Rtti_PolarSpectrogram;
76}
77
88 void QwtPolarSpectrogram::setData( QwtRasterData* data )
89{
90 if ( data != m_data->data )
91 {
92 delete m_data->data;
93 m_data->data = data;
94
95 itemChanged();
96 }
97}
98
103 const QwtRasterData* QwtPolarSpectrogram::data() const
104{
105 return m_data->data;
106}
107
119 void QwtPolarSpectrogram::setColorMap( QwtColorMap* colorMap )
120{
121 if ( m_data->colorMap != colorMap )
122 {
123 delete m_data->colorMap;
124 m_data->colorMap = colorMap;
125 }
126
127 itemChanged();
128}
129
134 const QwtColorMap* QwtPolarSpectrogram::colorMap() const
135{
136 return m_data->colorMap;
137}
138
146 void QwtPolarSpectrogram::setPaintAttribute( PaintAttribute attribute, bool on )
147{
148 if ( on )
149 m_data->paintAttributes |= attribute;
150 else
151 m_data->paintAttributes &= ~attribute;
152}
153
159 bool QwtPolarSpectrogram::testPaintAttribute( PaintAttribute attribute ) const
160{
161 return ( m_data->paintAttributes & attribute );
162}
163
174 void QwtPolarSpectrogram::draw( QPainter* painter,
175 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
176 const QPointF& pole, double,
177 const QRectF& canvasRect ) const
178{
179 const QRectF plotRect = plot()->plotRect( canvasRect.toRect() );
180 QRect imageRect = canvasRect.toRect();
181
182 painter->save();
183
184 painter->setClipRect( canvasRect );
185
186 QPainterPath clipPathCanvas;
187 clipPathCanvas.addEllipse( plotRect );
188 painter->setClipPath( clipPathCanvas, Qt::IntersectClip );
189
190 imageRect &= plotRect.toAlignedRect(); // outer rect
191
192 const QwtInterval radialInterval = boundingInterval( QwtPolar::ScaleRadius );
193 if ( radialInterval.isValid() )
194 {
195 const double radius = radialMap.transform( radialInterval.maxValue() ) -
196 radialMap.transform( radialInterval.minValue() );
197
198 QRectF clipRect( 0, 0, 2 * radius, 2 * radius );
199 clipRect.moveCenter( pole );
200
201 imageRect &= clipRect.toRect(); // inner rect, we don't have points outside
202
203 QPainterPath clipPathRadial;
204 clipPathRadial.addEllipse( clipRect );
205 painter->setClipPath( clipPathRadial, Qt::IntersectClip );
206 }
207
208 const QImage image = renderImage( azimuthMap, radialMap, pole, imageRect );
209 painter->drawImage( imageRect, image );
210
211 painter->restore();
212}
213
232QImage QwtPolarSpectrogram::renderImage(
233 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
234 const QPointF& pole, const QRect& rect ) const
235{
236 if ( m_data->data == NULL || m_data->colorMap == NULL )
237 return QImage();
238
239 QImage image( rect.size(), m_data->colorMap->format() == QwtColorMap::RGB
240 ? QImage::Format_ARGB32 : QImage::Format_Indexed8 );
241
242 const QwtInterval intensityRange = m_data->data->interval( Qt::ZAxis );
243 if ( !intensityRange.isValid() )
244 return image;
245
246 if ( m_data->colorMap->format() == QwtColorMap::Indexed )
247 image.setColorTable( m_data->colorMap->colorTable256() );
248
249 /*
250 For the moment we only announce the composition of the image by
251 calling initRaster(), but we don't pass any useful parameters.
252 ( How to map rect into something, that is useful to initialize a matrix
253 of values in polar coordinates ? )
254 */
255 m_data->data->initRaster( QRectF(), QSize() );
256
257
258#if !defined( QT_NO_QFUTURE )
259 uint numThreads = renderThreadCount();
260
261 if ( numThreads <= 0 )
262 numThreads = QThread::idealThreadCount();
263
264 if ( numThreads <= 0 )
265 numThreads = 1;
266
267 const int numRows = rect.height() / numThreads;
268
269
270 QVector< TileInfo > tileInfos;
271 for ( uint i = 0; i < numThreads; i++ )
272 {
273 QRect tile( rect.x(), rect.y() + i * numRows, rect.width(), numRows );
274 if ( i == numThreads - 1 )
275 tile.setHeight( rect.height() - i * numRows );
276
277 TileInfo tileInfo;
278 tileInfo.imagePos = rect.topLeft();
279 tileInfo.rect = tile;
280 tileInfo.image = &image;
281
282 tileInfos += tileInfo;
283 }
284
285 QVector< QFuture< void > > futures;
286 for ( int i = 0; i < tileInfos.size(); i++ )
287 {
288 if ( i == tileInfos.size() - 1 )
289 {
290 renderTileInfo( azimuthMap, radialMap, pole, &tileInfos[i] );
291 }
292 else
293 {
294 futures += QtConcurrent::run(
295#if QT_VERSION >= 0x060000
296 &QwtPolarSpectrogram::renderTileInfo, this,
297#else
298 this, &QwtPolarSpectrogram::renderTileInfo,
299#endif
300 azimuthMap, radialMap, pole, &tileInfos[i] );
301 }
302 }
303
304 for ( int i = 0; i < futures.size(); i++ )
305 futures[i].waitForFinished();
306
307#else
308 renderTile( azimuthMap, radialMap, pole, rect.topLeft(), rect, &image );
309#endif
310
311 m_data->data->discardRaster();
312
313 return image;
314}
315
316 void QwtPolarSpectrogram::renderTileInfo(
317 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
318 const QPointF& pole, TileInfo* tileInfo ) const
319{
320 renderTile( azimuthMap, radialMap, pole,
321 tileInfo->imagePos, tileInfo->rect, tileInfo->image );
322}
323
340 void QwtPolarSpectrogram::renderTile(
341 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
342 const QPointF& pole, const QPoint& imagePos,
343 const QRect& tile, QImage* image ) const
344{
345 const QwtInterval intensityRange = m_data->data->interval( Qt::ZAxis );
346 if ( !intensityRange.isValid() )
347 return;
348
349 const bool doFastAtan = testPaintAttribute( ApproximatedAtan );
350
351 const int y0 = imagePos.y();
352 const int y1 = tile.top();
353 const int y2 = tile.bottom();
354
355 const int x0 = imagePos.x();
356 const int x1 = tile.left();
357 const int x2 = tile.right();
358
359 if ( m_data->colorMap->format() == QwtColorMap::RGB )
360 {
361 for ( int y = y1; y <= y2; y++ )
362 {
363 const double dy = pole.y() - y;
364 const double dy2 = qwtSqr( dy );
365
366 QRgb* line = reinterpret_cast< QRgb* >( image->scanLine( y - y0 ) );
367 line += x1 - x0;
368
369 for ( int x = x1; x <= x2; x++ )
370 {
371 const double dx = x - pole.x();
372
373 double a = doFastAtan ? qwtFastAtan2( dy, dx ) : qAtan2( dy, dx );
374
375 if ( a < 0.0 )
376 a += 2 * M_PI;
377
378 if ( a < azimuthMap.p1() )
379 a += 2 * M_PI;
380
381 const double r = qSqrt( qwtSqr( dx ) + dy2 );
382
383 const double azimuth = azimuthMap.invTransform( a );
384 const double radius = radialMap.invTransform( r );
385
386 const double value = m_data->data->value( azimuth, radius );
387 if ( qIsNaN( value ) )
388 {
389 *line++ = 0u;
390 }
391 else
392 {
393 *line++ = m_data->colorMap->rgb( intensityRange, value );
394 }
395 }
396 }
397 }
398 else if ( m_data->colorMap->format() == QwtColorMap::Indexed )
399 {
400 for ( int y = y1; y <= y2; y++ )
401 {
402 const double dy = pole.y() - y;
403 const double dy2 = qwtSqr( dy );
404
405 unsigned char* line = image->scanLine( y - y0 );
406 line += x1 - x0;
407 for ( int x = x1; x <= x2; x++ )
408 {
409 const double dx = x - pole.x();
410
411 double a = doFastAtan ? qwtFastAtan2( dy, dx ) : qAtan2( dy, dx );
412 if ( a < 0.0 )
413 a += 2 * M_PI;
414 if ( a < azimuthMap.p1() )
415 a += 2 * M_PI;
416
417 const double r = qSqrt( qwtSqr( dx ) + dy2 );
418
419 const double azimuth = azimuthMap.invTransform( a );
420 const double radius = radialMap.invTransform( r );
421
422 const double value = m_data->data->value( azimuth, radius );
423
424 const uint index = m_data->colorMap->colorIndex( 256, intensityRange, value );
425 *line++ = static_cast< unsigned char >( index );
426 }
427 }
428 }
429}
430
440 QwtInterval QwtPolarSpectrogram::boundingInterval( int scaleId ) const
441{
442 if ( scaleId == QwtPolar::ScaleRadius )
443 return m_data->data->interval( Qt::YAxis );
444
445 return QwtPolarItem::boundingInterval( scaleId );
446}
QVector
Definition qwt_clipper.h:23
QwtColorMap
QwtColorMap is used to map values into colors.
Definition qwt_color_map.h:38
QwtColorMap::colorIndex
virtual uint colorIndex(int numColors, const QwtInterval &interval, double value) const
Map a value of a given interval into a color index.
Definition qwt_color_map.cpp:278
QwtColorMap::Indexed
@ Indexed
Definition qwt_color_map.h:60
QwtColorMap::RGB
@ RGB
The map is intended to map into RGB values.
Definition qwt_color_map.h:48
QwtColorMap::colorTable256
virtual QVector< QRgb > colorTable256() const
Definition qwt_color_map.cpp:304
QwtColorMap::rgb
virtual QRgb rgb(const QwtInterval &interval, double value) const =0
QwtInterval
A class representing an interval.
Definition qwt_interval.h:23
QwtInterval::minValue
double minValue() const
Definition qwt_interval.h:192
QwtInterval::maxValue
double maxValue() const
Definition qwt_interval.h:198
QwtInterval::isValid
bool isValid() const
Definition qwt_interval.h:210
QwtLinearColorMap
QwtLinearColorMap builds a color map from color stops.
Definition qwt_color_map.h:99
QwtPolarItem
Base class for items on a polar plot.
Definition qwt_polar_item.h:38
QwtPolarItem::boundingInterval
virtual QwtInterval boundingInterval(int scaleId) const
Definition qwt_polar_item.cpp:381
QwtPolarItem::itemChanged
virtual void itemChanged()
Definition qwt_polar_item.cpp:355
QwtPolarItem::Legend
@ Legend
The item is represented on the legend.
Definition qwt_polar_item.h:77
QwtPolarItem::AutoScale
@ AutoScale
Definition qwt_polar_item.h:83
QwtPolarItem::Rtti_PolarSpectrogram
@ Rtti_PolarSpectrogram
For QwtPolarSpectrogram.
Definition qwt_polar_item.h:61
QwtPolarItem::plot
QwtPolarPlot * plot() const
Definition qwt_polar_item.cpp:118
QwtPolarItem::renderThreadCount
uint renderThreadCount() const
Definition qwt_polar_item.cpp:282
QwtPolarItem::setItemAttribute
void setItemAttribute(ItemAttribute, bool on=true)
Definition qwt_polar_item.cpp:201
QwtPolarItem::setZ
void setZ(double z)
Set the z value.
Definition qwt_polar_item.cpp:142
QwtPolarPlot::plotRect
QRectF plotRect() const
Definition qwt_polar_plot.cpp:1120
QwtPolarSpectrogram::QwtPolarSpectrogram
QwtPolarSpectrogram()
Constructor.
Definition qwt_polar_spectrogram.cpp:55
QwtPolarSpectrogram::colorMap
const QwtColorMap * colorMap() const
Definition qwt_polar_spectrogram.cpp:134
QwtPolarSpectrogram::data
const QwtRasterData * data() const
Definition qwt_polar_spectrogram.cpp:103
QwtPolarSpectrogram::PaintAttribute
PaintAttribute
Definition qwt_polar_spectrogram.h:38
QwtPolarSpectrogram::ApproximatedAtan
@ ApproximatedAtan
Definition qwt_polar_spectrogram.h:44
QwtPolarSpectrogram::setData
void setData(QwtRasterData *data)
Definition qwt_polar_spectrogram.cpp:88
QwtPolarSpectrogram::~QwtPolarSpectrogram
virtual ~QwtPolarSpectrogram()
Destructor.
Definition qwt_polar_spectrogram.cpp:67
QwtPolarSpectrogram::rtti
virtual int rtti() const override
Definition qwt_polar_spectrogram.cpp:73
QwtPolarSpectrogram::setColorMap
void setColorMap(QwtColorMap *)
Definition qwt_polar_spectrogram.cpp:119
QwtPolarSpectrogram::renderImage
virtual QImage renderImage(const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, const QRect &rect) const
Render an image from the data and color map.
Definition qwt_polar_spectrogram.cpp:232
QwtPolarSpectrogram::setPaintAttribute
void setPaintAttribute(PaintAttribute, bool on=true)
Definition qwt_polar_spectrogram.cpp:146
QwtPolarSpectrogram::testPaintAttribute
bool testPaintAttribute(PaintAttribute) const
Definition qwt_polar_spectrogram.cpp:159
QwtPolarSpectrogram::PaintAttributes
QFlags< PaintAttribute > PaintAttributes
Definition qwt_polar_spectrogram.h:47
QwtPolarSpectrogram::renderTile
virtual void renderTile(const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, const QPoint &imagePos, const QRect &tile, QImage *image) const
Render a sub-rectangle of an image.
Definition qwt_polar_spectrogram.cpp:340
QwtPolarSpectrogram::boundingInterval
virtual QwtInterval boundingInterval(int scaleId) const override
Definition qwt_polar_spectrogram.cpp:440
QwtPolarSpectrogram::draw
virtual void draw(QPainter *painter, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const override
Definition qwt_polar_spectrogram.cpp:174
QwtRasterData
QwtRasterData defines an interface to any type of raster data.
Definition qwt_raster_data.h:43
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::interval
virtual QwtInterval interval(Qt::Axis) const =0
QwtScaleMap
A scale map.
Definition qwt_scale_map.h:27
QwtScaleMap::p1
double p1() const
Definition qwt_scale_map.h:99
QwtScaleMap::transform
double transform(double s) const
Definition qwt_scale_map.h:137
QwtScaleMap::invTransform
double invTransform(double p) const
Definition qwt_scale_map.h:154
QwtText
A class representing a text.
Definition qwt_text.h:52