Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
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
21static inline bool qwtInsidePole( const QwtScaleMap& map, double radius )
22{
23 return map.isInverting() ? ( radius > map.s1() ) : ( radius < map.s1() );
24}
25
26static 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
40class 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
58 const QwtSymbol* symbol;
59 QPen pen;
60 QwtCurveFitter* curveFitter;
61
62 QwtPolarCurve::LegendAttributes legendAttributes;
63};
64
71
77 : QwtPolarItem( title )
78{
79 init();
80}
81
86QwtPolarCurve::QwtPolarCurve( const QString& title )
87 : QwtPolarItem( QwtText( title ) )
88{
89 init();
90}
91
94{
95 delete m_series;
96 delete m_data;
97}
98
101{
102 m_data = new PrivateData;
103 m_series = NULL;
104
107 setZ( 20.0 );
108
110}
111
114{
116}
117
126{
127 if ( on )
128 m_data->legendAttributes |= attribute;
129 else
130 m_data->legendAttributes &= ~attribute;
131}
132
142{
143 return ( m_data->legendAttributes & attribute );
144}
145
153{
154 if ( style != m_data->style )
155 {
156 m_data->style = style;
157 itemChanged();
158 }
159}
160
166{
167 return m_data->style;
168}
169
176{
177 if ( symbol != m_data->symbol )
178 {
179 delete m_data->symbol;
180 m_data->symbol = symbol;
181 itemChanged();
182 }
183}
184
190{
191 return m_data->symbol;
192}
193
199void QwtPolarCurve::setPen( const QPen& pen )
200{
201 if ( pen != m_data->pen )
202 {
203 m_data->pen = pen;
204 itemChanged();
205 }
206}
207
212const QPen& QwtPolarCurve::pen() const
213{
214 return m_data->pen;
215}
216
226{
227 if ( m_series != data )
228 {
229 delete m_series;
230 m_series = data;
231 itemChanged();
232 }
233}
234
247{
248 if ( curveFitter != m_data->curveFitter )
249 {
250 delete m_data->curveFitter;
251 m_data->curveFitter = curveFitter;
252
253 itemChanged();
254 }
255}
256
262{
263 return m_data->curveFitter;
264}
265
276void 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
299void 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
341void 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
367void 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
459void 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
500{
501 return m_series->size();
502}
503
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 );
524
525 QPainter painter( &graphic );
526 painter.setRenderHint( QPainter::Antialiasing,
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
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}
Abstract base class for a curve fitter.
virtual QPolygonF fitCurve(const QPolygonF &polygon) const =0
A paint device for scalable graphics.
Definition qwt_graphic.h:76
@ RenderPensUnscaled
Definition qwt_graphic.h:96
void setRenderHint(RenderHint, bool on=true)
void setDefaultSize(const QSizeF &)
Set a default size.
A class representing an interval.
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
A point in polar coordinates.
double radius() const
Returns the radius.
double azimuth() const
Returns the azimuth.
An item, that represents a series of points.
bool testLegendAttribute(LegendAttribute) const
Test if a legend attribute is enabled.
virtual QwtInterval boundingInterval(int scaleId) const override
virtual void drawSymbols(QPainter *, const QwtSymbol &, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
virtual void drawCurve(QPainter *, int style, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
void setStyle(CurveStyle style)
LegendAttribute
Attributes how to represent the curve on the legend.
@ LegendShowSymbol
If the curve has a valid symbol it is painted.
QFlags< LegendAttribute > LegendAttributes
const QwtSeriesData< QwtPointPolar > * data() const
CurveStyle style() const
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
void setPen(const QPen &)
Assign a pen.
const QPen & pen() const
const QwtSymbol * symbol() const
@ NoCurve
Don't draw a curve. Note: This doesn't affect the symbols.
void setSymbol(QwtSymbol *)
Assign a symbol.
size_t dataSize() const
QwtPointPolar sample(int i) const
void setLegendAttribute(LegendAttribute, bool on=true)
QwtPolarCurve()
Constructor.
virtual void draw(QPainter *p, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, double radius, const QRectF &canvasRect) const override
void setCurveFitter(QwtCurveFitter *)
Insert a curve fitter.
QwtCurveFitter * curveFitter() const
void init()
Initialize data members.
virtual int rtti() const override
void setData(QwtSeriesData< QwtPointPolar > *data)
virtual ~QwtPolarCurve()
Destructor.
void drawLines(QPainter *, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to) const
Base class for items on a polar plot.
virtual void itemChanged()
@ Legend
The item is represented on the legend.
bool testRenderHint(RenderHint) const
@ Rtti_PolarCurve
For QwtPolarCurve.
void setItemAttribute(ItemAttribute, bool on=true)
@ RenderAntialiased
Enable antialiasing.
void setRenderHint(RenderHint, bool on=true)
void setZ(double z)
Set the z value.
A scale map.
bool isInverting() const
double transform(double s) const
double s1() const
virtual size_t size() const =0
virtual QRectF boundingRect() const
A class for drawing symbols.
Definition qwt_symbol.h:32
Style style() const
const QBrush & brush() const
void drawSymbol(QPainter *, const QRectF &) const
Draw the symbol into a rectangle.
void drawSymbols(QPainter *, const QPolygonF &) const
Draw symbols at the specified points.
Definition qwt_symbol.h:251
@ NoSymbol
No Style. The symbol cannot be drawn.
Definition qwt_symbol.h:41
const QPen & pen() const
A class representing a text.
Definition qwt_text.h:52
QWT_EXPORT void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)