qwt_polar_spectrogram.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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 
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 <qnumeric.h>
21 #include <qthread.h>
22 #include <qfuture.h>
23 #include <qtconcurrentrun.h>
24 
26 {
27 public:
28  QPoint imagePos;
29  QRect rect;
30  QImage *image;
31 };
32 
34 {
35 public:
37  data( NULL )
38  {
40  }
41 
43  {
44  delete data;
45  delete colorMap;
46  }
47 
50 
52 };
53 
56  QwtPolarItem( QwtText( "Spectrogram" ) )
57 {
58  d_data = new PrivateData;
59 
62 
63  setZ( 20.0 );
64 }
65 
68 {
69  delete d_data;
70 }
71 
74 {
76 }
77 
89 {
90  if ( data != d_data->data )
91  {
92  delete d_data->data;
93  d_data->data = data;
94 
95  itemChanged();
96  }
97 }
98 
104 {
105  return d_data->data;
106 }
107 
120 {
121  if ( d_data->colorMap != colorMap )
122  {
123  delete d_data->colorMap;
125  }
126 
127  itemChanged();
128 }
129 
135 {
136  return d_data->colorMap;
137 }
138 
147 {
148  if ( on )
149  d_data->paintAttributes |= attribute;
150  else
151  d_data->paintAttributes &= ~attribute;
152 }
153 
160 {
161  return ( d_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 
233  const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
234  const QPointF &pole, const QRect &rect ) const
235 {
236  if ( d_data->data == NULL || d_data->colorMap == NULL )
237  return QImage();
238 
239  QImage image( rect.size(), d_data->colorMap->format() == QwtColorMap::RGB
240  ? QImage::Format_ARGB32 : QImage::Format_Indexed8 );
241 
242  const QwtInterval intensityRange = d_data->data->interval( Qt::ZAxis );
243  if ( !intensityRange.isValid() )
244  return image;
245 
247  image.setColorTable( d_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  d_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  renderTile( azimuthMap, radialMap, pole, &tileInfos[i] );
291  }
292  else
293  {
295  azimuthMap, radialMap, pole, &tileInfos[i] );
296  }
297  }
298  for ( int i = 0; i < futures.size(); i++ )
299  futures[i].waitForFinished();
300 
301 #else
302  renderTile( azimuthMap, radialMap, pole, rect.topLeft(), rect, &image );
303 #endif
304 
306 
307  return image;
308 }
309 
311  const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
312  const QPointF &pole, TileInfo *tileInfo ) const
313 {
314  renderTile( azimuthMap, radialMap, pole,
315  tileInfo->imagePos, tileInfo->rect, tileInfo->image );
316 }
317 
335  const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
336  const QPointF &pole, const QPoint &imagePos,
337  const QRect &tile, QImage *image ) const
338 {
339  const QwtInterval intensityRange = d_data->data->interval( Qt::ZAxis );
340  if ( !intensityRange.isValid() )
341  return;
342 
343  const bool doFastAtan = testPaintAttribute( ApproximatedAtan );
344 
345  const int y0 = imagePos.y();
346  const int y1 = tile.top();
347  const int y2 = tile.bottom();
348 
349  const int x0 = imagePos.x();
350  const int x1 = tile.left();
351  const int x2 = tile.right();
352 
353  if ( d_data->colorMap->format() == QwtColorMap::RGB )
354  {
355  for ( int y = y1; y <= y2; y++ )
356  {
357  const double dy = pole.y() - y;
358  const double dy2 = qwtSqr( dy );
359 
360  QRgb *line = reinterpret_cast<QRgb *>( image->scanLine( y - y0 ) );
361  line += x1 - x0;
362 
363  for ( int x = x1; x <= x2; x++ )
364  {
365  const double dx = x - pole.x();
366 
367  double a = doFastAtan ? qwtFastAtan2( dy, dx ) : qAtan2( dy, dx );
368 
369  if ( a < 0.0 )
370  a += 2 * M_PI;
371 
372  if ( a < azimuthMap.p1() )
373  a += 2 * M_PI;
374 
375  const double r = qSqrt( qwtSqr( dx ) + dy2 );
376 
377  const double azimuth = azimuthMap.invTransform( a );
378  const double radius = radialMap.invTransform( r );
379 
380  const double value = d_data->data->value( azimuth, radius );
381  if ( qIsNaN( value ) )
382  {
383  *line++ = 0u;
384  }
385  else
386  {
387  *line++ = d_data->colorMap->rgb( intensityRange, value );
388  }
389  }
390  }
391  }
392  else if ( d_data->colorMap->format() == QwtColorMap::Indexed )
393  {
394  for ( int y = y1; y <= y2; y++ )
395  {
396  const double dy = pole.y() - y;
397  const double dy2 = qwtSqr( dy );
398 
399  unsigned char *line = image->scanLine( y - y0 );
400  line += x1 - x0;
401  for ( int x = x1; x <= x2; x++ )
402  {
403  const double dx = x - pole.x();
404 
405  double a = doFastAtan ? qwtFastAtan2( dy, dx ) : qAtan2( dy, dx );
406  if ( a < 0.0 )
407  a += 2 * M_PI;
408  if ( a < azimuthMap.p1() )
409  a += 2 * M_PI;
410 
411  const double r = qSqrt( qwtSqr( dx ) + dy2 );
412 
413  const double azimuth = azimuthMap.invTransform( a );
414  const double radius = radialMap.invTransform( r );
415 
416  const double value = d_data->data->value( azimuth, radius );
417 
418  const uint index = d_data->colorMap->colorIndex( 256, intensityRange, value );
419  *line++ = static_cast<unsigned char>( index );
420  }
421  }
422  }
423 }
424 
435 {
436  if ( scaleId == QwtPolar::ScaleRadius )
437  return d_data->data->interval( Qt::YAxis );
438 
439  return QwtPolarItem::boundingInterval( scaleId );
440 }
virtual void discardRaster()
Discard a raster.
double p1() const
Definition: qwt_scale_map.h:99
void setPaintAttribute(PaintAttribute, bool on=true)
enum MQTTPropertyCodes value
virtual QwtInterval boundingInterval(int scaleId) const
const QwtColorMap * colorMap() const
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.
virtual QVector< QRgb > colorTable256() const
A class representing an interval.
Definition: qwt_interval.h:22
QRectF plotRect() const
double minValue() const
Definition: qwt_interval.h:190
QwtPolarSpectrogram::PaintAttributes paintAttributes
QwtPolarPlot * plot() const
virtual ~QwtPolarSpectrogram()
Destructor.
bool testPaintAttribute(PaintAttribute) const
virtual void initRaster(const QRectF &, const QSize &raster)
Initialize a raster.
double maxValue() const
Definition: qwt_interval.h:196
QwtPolarSpectrogram()
Constructor.
virtual QwtInterval interval(Qt::Axis) const =0
Base class for items on a polar plot.
const QwtRasterData * data() const
virtual uint colorIndex(int numColors, const QwtInterval &interval, double value) const
Map a value of a given interval into a color index.
void setItemAttribute(ItemAttribute, bool on=true)
void setZ(double z)
Set the z value.
bool isValid() const
Definition: qwt_interval.h:208
QFlags< PaintAttribute > PaintAttributes
Paint attributes.
A class representing a text.
Definition: qwt_text.h:51
QwtColorMap is used to map values into colors.
Definition: qwt_color_map.h:34
virtual int rtti() const QWT_OVERRIDE
virtual double value(double x, double y) const =0
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.
virtual void draw(QPainter *painter, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const QWT_OVERRIDE
QwtLinearColorMap builds a color map from color stops.
Definition: qwt_color_map.h:96
A scale map.
Definition: qwt_scale_map.h:26
void setData(QwtRasterData *data)
double invTransform(double p) const
The map is intended to map into RGB values.
Definition: qwt_color_map.h:45
virtual QwtInterval boundingInterval(int scaleId) const QWT_OVERRIDE
def run()
Definition: mqttsas.py:276
#define M_PI
Definition: qwt_math.h:56
For QwtPolarSpectrogram.
QwtRasterData defines an interface to any type of raster data.
Radial scale.
Definition: qwt_polar.h:77
virtual QRgb rgb(const QwtInterval &interval, double value) const =0
The item is represented on the legend.
double qwtSqr(double x)
Return the square of a number.
Definition: qwt_math.h:191
double transform(double s) const
void setColorMap(QwtColorMap *)
Format format() const
double qwtFastAtan2(double y, double x)
Approximation of arc tangent ( error below 0,005 radians )
Definition: qwt_math.h:209
uint renderThreadCount() const
virtual void itemChanged()


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10