Qwt User's Guide: qwt_polar_curve.cpp Source File

Qwt User's Guide 6.2.0

qwt_polar_curve.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_curve.h"
10 #include "qwt_polar.h"
11 #include "qwt_painter.h"
12 #include "qwt_scale_map.h"
13 #include "qwt_math.h"
14 #include "qwt_symbol.h"
15 #include "qwt_legend.h"
16 #include "qwt_curve_fitter.h"
17 #include "qwt_clipper.h"
18
19 #include <qpainter.h>
20
21 static inline bool qwtInsidePole( const QwtScaleMap& map, double radius )
22 {
23 return map.isInverting() ? ( radius > map.s1() ) : ( radius < map.s1() );
24 }
25
26 static int qwtVerifyRange( int size, int& i1, int& i2 )
27 {
28 if ( size < 1 )
29 return 0;
30
31 i1 = qBound( 0, i1, size - 1 );
32 i2 = qBound( 0, i2, size - 1 );
33
34 if ( i1 > i2 )
35 qSwap( i1, i2 );
36
37 return ( i2 - i1 + 1 );
38 }
39
40 class QwtPolarCurve::PrivateData
41 {
42 public:
43 PrivateData()
44 : style( QwtPolarCurve::Lines )
45 , curveFitter( NULL )
46 {
47 symbol = new QwtSymbol();
48 pen = QPen( Qt::black );
49 }
50
51 ~PrivateData()
52 {
53 delete symbol;
54 delete curveFitter;
55 }
56
57 QwtPolarCurve::CurveStyle style;
58 const QwtSymbol* symbol;
59 QPen pen;
60 QwtCurveFitter* curveFitter;
61
62 QwtPolarCurve::LegendAttributes legendAttributes;
63 };
64
66 QwtPolarCurve::QwtPolarCurve()
67 : QwtPolarItem( QwtText() )
68 {
69 init();
70 }
71
76 QwtPolarCurve::QwtPolarCurve( const QwtText& title )
77 : QwtPolarItem( title )
78 {
79 init();
80 }
81
86 QwtPolarCurve::QwtPolarCurve( const QString& title )
87 : QwtPolarItem( QwtText( title ) )
88 {
89 init();
90 }
91
93 QwtPolarCurve::~QwtPolarCurve()
94 {
95 delete m_series;
96 delete m_data;
97 }
98
100 void QwtPolarCurve::init()
101 {
102 m_data = new PrivateData;
103 m_series = NULL;
104
105 setItemAttribute( QwtPolarItem::AutoScale );
106 setItemAttribute( QwtPolarItem::Legend );
107 setZ( 20.0 );
108
109 setRenderHint( RenderAntialiased, true );
110 }
111
113 int QwtPolarCurve::rtti() const
114 {
115 return QwtPolarItem::Rtti_PolarCurve;
116 }
117
125 void QwtPolarCurve::setLegendAttribute( LegendAttribute attribute, bool on )
126 {
127 if ( on )
128 m_data->legendAttributes |= attribute;
129 else
130 m_data->legendAttributes &= ~attribute;
131 }
132
141 bool QwtPolarCurve::testLegendAttribute( LegendAttribute attribute ) const
142 {
143 return ( m_data->legendAttributes & attribute );
144 }
145
152 void QwtPolarCurve::setStyle( CurveStyle style )
153 {
154 if ( style != m_data->style )
155 {
156 m_data->style = style;
157 itemChanged();
158 }
159 }
160
165 QwtPolarCurve::CurveStyle QwtPolarCurve::style() const
166 {
167 return m_data->style;
168 }
169
175 void QwtPolarCurve::setSymbol( QwtSymbol* symbol )
176 {
177 if ( symbol != m_data->symbol )
178 {
179 delete m_data->symbol;
180 m_data->symbol = symbol;
181 itemChanged();
182 }
183 }
184
189 const QwtSymbol* QwtPolarCurve::symbol() const
190 {
191 return m_data->symbol;
192 }
193
199 void QwtPolarCurve::setPen( const QPen& pen )
200 {
201 if ( pen != m_data->pen )
202 {
203 m_data->pen = pen;
204 itemChanged();
205 }
206 }
207
212 const QPen& QwtPolarCurve::pen() const
213 {
214 return m_data->pen;
215 }
216
225 void QwtPolarCurve::setData( QwtSeriesData< QwtPointPolar >* data )
226 {
227 if ( m_series != data )
228 {
229 delete m_series;
230 m_series = data;
231 itemChanged();
232 }
233 }
234
246 void QwtPolarCurve::setCurveFitter( QwtCurveFitter* curveFitter )
247 {
248 if ( curveFitter != m_data->curveFitter )
249 {
250 delete m_data->curveFitter;
251 m_data->curveFitter = curveFitter;
252
253 itemChanged();
254 }
255 }
256
261 QwtCurveFitter* QwtPolarCurve::curveFitter() const
262 {
263 return m_data->curveFitter;
264 }
265
276 void QwtPolarCurve::draw( QPainter* painter,
277 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
278 const QPointF& pole, double radius,
279 const QRectF& canvasRect ) const
280 {
281 Q_UNUSED( radius );
282 Q_UNUSED( canvasRect );
283
284 draw( painter, azimuthMap, radialMap, pole, 0, -1 );
285 }
286
299 void QwtPolarCurve::draw( QPainter* painter,
300 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
301 const QPointF& pole, int from, int to ) const
302 {
303 if ( !painter || dataSize() <= 0 )
304 return;
305
306 if ( to < 0 )
307 to = dataSize() - 1;
308
309 if ( qwtVerifyRange( dataSize(), from, to ) > 0 )
310 {
311 painter->save();
312 painter->setPen( m_data->pen );
313
314 drawCurve( painter, m_data->style,
315 azimuthMap, radialMap, pole, from, to );
316
317 painter->restore();
318
319 if ( m_data->symbol->style() != QwtSymbol::NoSymbol )
320 {
321 painter->save();
322 drawSymbols( painter, *m_data->symbol,
323 azimuthMap, radialMap, pole, from, to );
324 painter->restore();
325 }
326 }
327 }
328
341 void QwtPolarCurve::drawCurve( QPainter* painter, int style,
342 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
343 const QPointF& pole, int from, int to ) const
344 {
345 switch ( style )
346 {
347 case Lines:
348 drawLines( painter, azimuthMap, radialMap, pole, from, to );
349 break;
350 case NoCurve:
351 default:
352 break;
353 }
354 }
355
367 void QwtPolarCurve::drawLines( QPainter* painter,
368 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
369 const QPointF& pole, int from, int to ) const
370 {
371 int size = to - from + 1;
372 if ( size <= 0 )
373 return;
374
375 QPolygonF polyline;
376
377 if ( m_data->curveFitter )
378 {
379 QPolygonF points( size );
380 for ( int j = from; j <= to; j++ )
381 {
382 const QwtPointPolar point = sample( j );
383 points[j - from] = QPointF( point.azimuth(), point.radius() );
384 }
385
386 points = m_data->curveFitter->fitCurve( points );
387
388 polyline.resize( points.size() );
389
390 QPointF* polylineData = polyline.data();
391 QPointF* pointsData = points.data();
392
393 for ( int i = 0; i < points.size(); i++ )
394 {
395 const QwtPointPolar point( pointsData[i].x(), pointsData[i].y() );
396
397 double r = radialMap.transform( point.radius() );
398 const double a = azimuthMap.transform( point.azimuth() );
399
400 polylineData[i] = qwtPolar2Pos( pole, r, a );
401 }
402 }
403 else
404 {
405 polyline.resize( size );
406 QPointF* polylineData = polyline.data();
407
408 for ( int i = from; i <= to; i++ )
409 {
410 QwtPointPolar point = sample( i );
411 if ( !qwtInsidePole( radialMap, point.radius() ) )
412 {
413 double r = radialMap.transform( point.radius() );
414 const double a = azimuthMap.transform( point.azimuth() );
415 polylineData[i - from] = qwtPolar2Pos( pole, r, a );
416 }
417 else
418 {
419 polylineData[i - from] = pole;
420 }
421 }
422 }
423
424 QRectF clipRect;
425 if ( painter->hasClipping() )
426 {
427 clipRect = painter->clipRegion().boundingRect();
428 }
429 else
430 {
431 clipRect = painter->window();
432 if ( !clipRect.isEmpty() )
433 clipRect = painter->transform().inverted().mapRect( clipRect );
434 }
435
436 if ( !clipRect.isEmpty() )
437 {
438 double off = qCeil( qMax( qreal( 1.0 ), painter->pen().widthF() ) );
439 clipRect = clipRect.toRect().adjusted( -off, -off, off, off );
440 QwtClipper::clipPolygonF( clipRect, polyline );
441 }
442
443 QwtPainter::drawPolyline( painter, polyline );
444 }
445
459 void QwtPolarCurve::drawSymbols( QPainter* painter, const QwtSymbol& symbol,
460 const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
461 const QPointF& pole, int from, int to ) const
462 {
463 painter->setBrush( symbol.brush() );
464 painter->setPen( symbol.pen() );
465
466 const int chunkSize = 500;
467
468 for ( int i = from; i <= to; i += chunkSize )
469 {
470 const int n = qMin( chunkSize, to - i + 1 );
471
472 QPolygonF points;
473 for ( int j = 0; j < n; j++ )
474 {
475 const QwtPointPolar point = sample( i + j );
476
477 if ( !qwtInsidePole( radialMap, point.radius() ) )
478 {
479 const double r = radialMap.transform( point.radius() );
480 const double a = azimuthMap.transform( point.azimuth() );
481
482 points += qwtPolar2Pos( pole, r, a );
483 }
484 else
485 {
486 points += pole;
487 }
488 }
489
490 if ( points.size() > 0 )
491 symbol.drawSymbols( painter, points );
492 }
493 }
494
499 size_t QwtPolarCurve::dataSize() const
500 {
501 return m_series->size();
502 }
503
513 QwtGraphic QwtPolarCurve::legendIcon( int index,
514 const QSizeF& size ) const
515 {
516 Q_UNUSED( index );
517
518 if ( size.isEmpty() )
519 return QwtGraphic();
520
521 QwtGraphic graphic;
522 graphic.setDefaultSize( size );
523 graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
524
525 QPainter painter( &graphic );
526 painter.setRenderHint( QPainter::Antialiasing,
527 testRenderHint( QwtPolarItem::RenderAntialiased ) );
528
529 if ( m_data->legendAttributes == 0 )
530 {
531 QBrush brush;
532
533 if ( style() != QwtPolarCurve::NoCurve )
534 {
535 brush = QBrush( pen().color() );
536 }
537 else if ( m_data->symbol &&
538 ( m_data->symbol->style() != QwtSymbol::NoSymbol ) )
539 {
540 brush = QBrush( m_data->symbol->pen().color() );
541 }
542
543 if ( brush.style() != Qt::NoBrush )
544 {
545 QRectF r( 0, 0, size.width(), size.height() );
546 painter.fillRect( r, brush );
547 }
548 }
549
550 if ( m_data->legendAttributes & QwtPolarCurve::LegendShowLine )
551 {
552 if ( pen() != Qt::NoPen )
553 {
554 QPen pn = pen();
555 pn.setCapStyle( Qt::FlatCap );
556
557 painter.setPen( pn );
558
559 const double y = 0.5 * size.height();
560 QwtPainter::drawLine( &painter, 0.0, y, size.width(), y );
561 }
562 }
563
564 if ( m_data->legendAttributes & QwtPolarCurve::LegendShowSymbol )
565 {
566 if ( m_data->symbol )
567 {
568 QRectF r( 0, 0, size.width(), size.height() );
569 m_data->symbol->drawSymbol( &painter, r );
570 }
571 }
572
573 return graphic;
574 }
575
585 QwtInterval QwtPolarCurve::boundingInterval( int scaleId ) const
586 {
587 const QRectF boundingRect = m_series->boundingRect();
588
589 if ( scaleId == QwtPolar::ScaleAzimuth )
590 return QwtInterval( boundingRect.left(), boundingRect.right() );
591
592 if ( scaleId == QwtPolar::ScaleRadius )
593 return QwtInterval( boundingRect.top(), boundingRect.bottom() );
594
595 return QwtInterval();
596 }
QwtCurveFitter
Abstract base class for a curve fitter.
Definition: qwt_curve_fitter.h:22
QwtGraphic
A paint device for scalable graphics.
Definition: qwt_graphic.h:76
QwtGraphic::RenderPensUnscaled
@ RenderPensUnscaled
Definition: qwt_graphic.h:96
QwtGraphic::setRenderHint
void setRenderHint(RenderHint, bool on=true)
Definition: qwt_graphic.cpp:443
QwtGraphic::setDefaultSize
void setDefaultSize(const QSizeF &)
Set a default size.
Definition: qwt_graphic.cpp:553
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:23
QwtPainter::drawPolyline
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
Definition: qwt_painter.cpp:578
QwtPainter::drawLine
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:154
QwtPointPolar
A point in polar coordinates.
Definition: qwt_point_polar.h:29
QwtPointPolar::radius
double radius() const
Returns the radius.
Definition: qwt_point_polar.h:102
QwtPointPolar::azimuth
double azimuth() const
Returns the azimuth.
Definition: qwt_point_polar.h:108
QwtPolarCurve
An item, that represents a series of points.
Definition: qwt_polar_curve.h:31
QwtPolarCurve::testLegendAttribute
bool testLegendAttribute(LegendAttribute) const
Test if a legend attribute is enabled.
Definition: qwt_polar_curve.cpp:141
QwtPolarCurve::boundingInterval
virtual QwtInterval boundingInterval(int scaleId) const override
Definition: qwt_polar_curve.cpp:585
QwtPolarCurve::drawSymbols
virtual void drawSymbols(QPainter *, const QwtSymbol &, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
Definition: qwt_polar_curve.cpp:459
QwtPolarCurve::drawCurve
virtual void drawCurve(QPainter *, int style, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
Definition: qwt_polar_curve.cpp:341
QwtPolarCurve::setStyle
void setStyle(CurveStyle style)
Definition: qwt_polar_curve.cpp:152
QwtPolarCurve::LegendAttribute
LegendAttribute
Attributes how to represent the curve on the legend.
Definition: qwt_polar_curve.h:64
QwtPolarCurve::LegendShowLine
@ LegendShowLine
Definition: qwt_polar_curve.h:69
QwtPolarCurve::LegendShowSymbol
@ LegendShowSymbol
If the curve has a valid symbol it is painted.
Definition: qwt_polar_curve.h:72
QwtPolarCurve::LegendAttributes
QFlags< LegendAttribute > LegendAttributes
Definition: qwt_polar_curve.h:75
QwtPolarCurve::data
const QwtSeriesData< QwtPointPolar > * data() const
Definition: qwt_polar_curve.h:144
QwtPolarCurve::style
CurveStyle style() const
Definition: qwt_polar_curve.cpp:165
QwtPolarCurve::legendIcon
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
Definition: qwt_polar_curve.cpp:513
QwtPolarCurve::setPen
void setPen(const QPen &)
Assign a pen.
Definition: qwt_polar_curve.cpp:199
QwtPolarCurve::pen
const QPen & pen() const
Definition: qwt_polar_curve.cpp:212
QwtPolarCurve::symbol
const QwtSymbol * symbol() const
Definition: qwt_polar_curve.cpp:189
QwtPolarCurve::CurveStyle
CurveStyle
Definition: qwt_polar_curve.h:38
QwtPolarCurve::NoCurve
@ NoCurve
Don't draw a curve. Note: This doesn't affect the symbols.
Definition: qwt_polar_curve.h:40
QwtPolarCurve::Lines
@ Lines
Definition: qwt_polar_curve.h:47
QwtPolarCurve::setSymbol
void setSymbol(QwtSymbol *)
Assign a symbol.
Definition: qwt_polar_curve.cpp:175
QwtPolarCurve::dataSize
size_t dataSize() const
Definition: qwt_polar_curve.cpp:499
QwtPolarCurve::sample
QwtPointPolar sample(int i) const
Definition: qwt_polar_curve.h:153
QwtPolarCurve::setLegendAttribute
void setLegendAttribute(LegendAttribute, bool on=true)
Definition: qwt_polar_curve.cpp:125
QwtPolarCurve::QwtPolarCurve
QwtPolarCurve()
Constructor.
Definition: qwt_polar_curve.cpp:66
QwtPolarCurve::draw
virtual void draw(QPainter *p, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const override
Definition: qwt_polar_curve.cpp:276
QwtPolarCurve::setCurveFitter
void setCurveFitter(QwtCurveFitter *)
Insert a curve fitter.
Definition: qwt_polar_curve.cpp:246
QwtPolarCurve::curveFitter
QwtCurveFitter * curveFitter() const
Definition: qwt_polar_curve.cpp:261
QwtPolarCurve::init
void init()
Initialize data members.
Definition: qwt_polar_curve.cpp:100
QwtPolarCurve::rtti
virtual int rtti() const override
Definition: qwt_polar_curve.cpp:113
QwtPolarCurve::setData
void setData(QwtSeriesData< QwtPointPolar > *data)
Definition: qwt_polar_curve.cpp:225
QwtPolarCurve::~QwtPolarCurve
virtual ~QwtPolarCurve()
Destructor.
Definition: qwt_polar_curve.cpp:93
QwtPolarCurve::drawLines
void drawLines(QPainter *, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
Definition: qwt_polar_curve.cpp:367
QwtPolarItem
Base class for items on a polar plot.
Definition: qwt_polar_item.h:38
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::testRenderHint
bool testRenderHint(RenderHint) const
Definition: qwt_polar_item.cpp:254
QwtPolarItem::Rtti_PolarCurve
@ Rtti_PolarCurve
For QwtPolarCurve.
Definition: qwt_polar_item.h:58
QwtPolarItem::setItemAttribute
void setItemAttribute(ItemAttribute, bool on=true)
Definition: qwt_polar_item.cpp:201
QwtPolarItem::RenderAntialiased
@ RenderAntialiased
Enable antialiasing.
Definition: qwt_polar_item.h:95
QwtPolarItem::setRenderHint
void setRenderHint(RenderHint, bool on=true)
Definition: qwt_polar_item.cpp:234
QwtPolarItem::setZ
void setZ(double z)
Set the z value.
Definition: qwt_polar_item.cpp:142
QwtScaleMap
A scale map.
Definition: qwt_scale_map.h:27
QwtScaleMap::isInverting
bool isInverting() const
Definition: qwt_scale_map.h:164
QwtScaleMap::transform
double transform(double s) const
Definition: qwt_scale_map.h:137
QwtScaleMap::s1
double s1() const
Definition: qwt_scale_map.h:83
QwtSeriesData< QwtPointPolar >
QwtSeriesData::size
virtual size_t size() const =0
QwtSeriesData::boundingRect
virtual QRectF boundingRect() const =0
QwtSymbol
A class for drawing symbols.
Definition: qwt_symbol.h:32
QwtSymbol::brush
const QBrush & brush() const
Definition: qwt_symbol.cpp:1123
QwtSymbol::drawSymbols
void drawSymbols(QPainter *, const QPolygonF &) const
Draw symbols at the specified points.
Definition: qwt_symbol.h:251
QwtSymbol::NoSymbol
@ NoSymbol
No Style. The symbol cannot be drawn.
Definition: qwt_symbol.h:41
QwtSymbol::pen
const QPen & pen() const
Definition: qwt_symbol.cpp:1171
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtClipper::clipPolygonF
QWT_EXPORT void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)
Definition: qwt_clipper.cpp:404