qwt_polar_curve.cpp
/******************************************************************************
* QwtPolar Widget Library
* Copyright (C) 2008 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_polar_curve.h"
#include "qwt_polar.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
#include "qwt_math.h"
#include "qwt_symbol.h"
#include "qwt_legend.h"
#include "qwt_curve_fitter.h"
#include "qwt_clipper.h"
#include <qpainter.h>
static inline bool qwtInsidePole( const QwtScaleMap& map, double radius )
{
return map.isInverting() ? ( radius > map.s1() ) : ( radius < map.s1() );
}
static int qwtVerifyRange( int size, int& i1, int& i2 )
{
if ( size < 1 )
return 0;
i1 = qBound( 0, i1, size - 1 );
i2 = qBound( 0, i2, size - 1 );
if ( i1 > i2 )
qSwap( i1, i2 );
return ( i2 - i1 + 1 );
}
class QwtPolarCurve::PrivateData
{
public:
PrivateData()
: style( QwtPolarCurve::Lines )
, curveFitter( NULL )
{
symbol = new QwtSymbol();
pen = QPen( Qt::black );
}
~PrivateData()
{
delete symbol;
delete curveFitter;
}
QwtPolarCurve::CurveStyle style;
const QwtSymbol* symbol;
QPen pen;
QwtCurveFitter* curveFitter;
QwtPolarCurve::LegendAttributes legendAttributes;
};
QwtPolarCurve::QwtPolarCurve()
: QwtPolarItem( QwtText() )
{
init();
}
QwtPolarCurve::QwtPolarCurve( const QwtText& title )
: QwtPolarItem( title )
{
init();
}
QwtPolarCurve::QwtPolarCurve( const QString& title )
: QwtPolarItem( QwtText( title ) )
{
init();
}
QwtPolarCurve::~QwtPolarCurve()
{
delete m_series;
delete m_data;
}
void QwtPolarCurve::init()
{
m_data = new PrivateData;
m_series = NULL;
setItemAttribute( QwtPolarItem::AutoScale );
setItemAttribute( QwtPolarItem::Legend );
setZ( 20.0 );
setRenderHint( RenderAntialiased, true );
}
int QwtPolarCurve::rtti() const
{
return QwtPolarItem::Rtti_PolarCurve;
}
void QwtPolarCurve::setLegendAttribute( LegendAttribute attribute, bool on )
{
if ( on )
m_data->legendAttributes |= attribute;
else
m_data->legendAttributes &= ~attribute;
}
bool QwtPolarCurve::testLegendAttribute( LegendAttribute attribute ) const
{
return ( m_data->legendAttributes & attribute );
}
void QwtPolarCurve::setStyle( CurveStyle style )
{
if ( style != m_data->style )
{
m_data->style = style;
itemChanged();
}
}
QwtPolarCurve::CurveStyle QwtPolarCurve::style() const
{
return m_data->style;
}
void QwtPolarCurve::setSymbol( QwtSymbol* symbol )
{
if ( symbol != m_data->symbol )
{
delete m_data->symbol;
m_data->symbol = symbol;
itemChanged();
}
}
const QwtSymbol* QwtPolarCurve::symbol() const
{
return m_data->symbol;
}
void QwtPolarCurve::setPen( const QPen& pen )
{
if ( pen != m_data->pen )
{
m_data->pen = pen;
itemChanged();
}
}
const QPen& QwtPolarCurve::pen() const
{
return m_data->pen;
}
void QwtPolarCurve::setData( QwtSeriesData< QwtPointPolar >* data )
{
if ( m_series != data )
{
delete m_series;
m_series = data;
itemChanged();
}
}
void QwtPolarCurve::setCurveFitter( QwtCurveFitter* curveFitter )
{
if ( curveFitter != m_data->curveFitter )
{
delete m_data->curveFitter;
m_data->curveFitter = curveFitter;
itemChanged();
}
}
QwtCurveFitter* QwtPolarCurve::curveFitter() const
{
return m_data->curveFitter;
}
void QwtPolarCurve::draw( QPainter* painter,
const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
const QPointF& pole, double radius,
const QRectF& canvasRect ) const
{
Q_UNUSED( radius );
Q_UNUSED( canvasRect );
draw( painter, azimuthMap, radialMap, pole, 0, -1 );
}
void QwtPolarCurve::draw( QPainter* painter,
const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
const QPointF& pole, int from, int to ) const
{
if ( !painter || dataSize() <= 0 )
return;
if ( to < 0 )
to = dataSize() - 1;
if ( qwtVerifyRange( dataSize(), from, to ) > 0 )
{
painter->save();
painter->setPen( m_data->pen );
drawCurve( painter, m_data->style,
azimuthMap, radialMap, pole, from, to );
painter->restore();
if ( m_data->symbol->style() != QwtSymbol::NoSymbol )
{
painter->save();
drawSymbols( painter, *m_data->symbol,
azimuthMap, radialMap, pole, from, to );
painter->restore();
}
}
}
void QwtPolarCurve::drawCurve( QPainter* painter, int style,
const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
const QPointF& pole, int from, int to ) const
{
switch ( style )
{
case Lines:
drawLines( painter, azimuthMap, radialMap, pole, from, to );
break;
case NoCurve:
default:
break;
}
}
void QwtPolarCurve::drawLines( QPainter* painter,
const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
const QPointF& pole, int from, int to ) const
{
int size = to - from + 1;
if ( size <= 0 )
return;
QPolygonF polyline;
if ( m_data->curveFitter )
{
QPolygonF points( size );
for ( int j = from; j <= to; j++ )
{
const QwtPointPolar point = sample( j );
points[j - from] = QPointF( point.azimuth(), point.radius() );
}
points = m_data->curveFitter->fitCurve( points );
polyline.resize( points.size() );
QPointF* polylineData = polyline.data();
QPointF* pointsData = points.data();
for ( int i = 0; i < points.size(); i++ )
{
const QwtPointPolar point( pointsData[i].x(), pointsData[i].y() );
double r = radialMap.transform( point.radius() );
const double a = azimuthMap.transform( point.azimuth() );
polylineData[i] = qwtPolar2Pos( pole, r, a );
}
}
else
{
polyline.resize( size );
QPointF* polylineData = polyline.data();
for ( int i = from; i <= to; i++ )
{
QwtPointPolar point = sample( i );
if ( !qwtInsidePole( radialMap, point.radius() ) )
{
double r = radialMap.transform( point.radius() );
const double a = azimuthMap.transform( point.azimuth() );
polylineData[i - from] = qwtPolar2Pos( pole, r, a );
}
else
{
polylineData[i - from] = pole;
}
}
}
QRectF clipRect;
if ( painter->hasClipping() )
{
clipRect = painter->clipRegion().boundingRect();
}
else
{
clipRect = painter->window();
if ( !clipRect.isEmpty() )
clipRect = painter->transform().inverted().mapRect( clipRect );
}
if ( !clipRect.isEmpty() )
{
double off = qCeil( qMax( qreal( 1.0 ), painter->pen().widthF() ) );
clipRect = clipRect.toRect().adjusted( -off, -off, off, off );
QwtClipper::clipPolygonF( clipRect, polyline );
}
QwtPainter::drawPolyline( painter, polyline );
}
void QwtPolarCurve::drawSymbols( QPainter* painter, const QwtSymbol& symbol,
const QwtScaleMap& azimuthMap, const QwtScaleMap& radialMap,
const QPointF& pole, int from, int to ) const
{
painter->setBrush( symbol.brush() );
painter->setPen( symbol.pen() );
const int chunkSize = 500;
for ( int i = from; i <= to; i += chunkSize )
{
const int n = qMin( chunkSize, to - i + 1 );
QPolygonF points;
for ( int j = 0; j < n; j++ )
{
const QwtPointPolar point = sample( i + j );
if ( !qwtInsidePole( radialMap, point.radius() ) )
{
const double r = radialMap.transform( point.radius() );
const double a = azimuthMap.transform( point.azimuth() );
points += qwtPolar2Pos( pole, r, a );
}
else
{
points += pole;
}
}
if ( points.size() > 0 )
symbol.drawSymbols( painter, points );
}
}
size_t QwtPolarCurve::dataSize() const
{
return m_series->size();
}
QwtGraphic QwtPolarCurve::legendIcon( int index,
const QSizeF& size ) const
{
Q_UNUSED( index );
if ( size.isEmpty() )
return QwtGraphic();
QwtGraphic graphic;
graphic.setDefaultSize( size );
graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
QPainter painter( &graphic );
painter.setRenderHint( QPainter::Antialiasing,
testRenderHint( QwtPolarItem::RenderAntialiased ) );
if ( m_data->legendAttributes == 0 )
{
QBrush brush;
if ( style() != QwtPolarCurve::NoCurve )
{
brush = QBrush( pen().color() );
}
else if ( m_data->symbol &&
( m_data->symbol->style() != QwtSymbol::NoSymbol ) )
{
brush = QBrush( m_data->symbol->pen().color() );
}
if ( brush.style() != Qt::NoBrush )
{
QRectF r( 0, 0, size.width(), size.height() );
painter.fillRect( r, brush );
}
}
if ( m_data->legendAttributes & QwtPolarCurve::LegendShowLine )
{
if ( pen() != Qt::NoPen )
{
QPen pn = pen();
pn.setCapStyle( Qt::FlatCap );
painter.setPen( pn );
const double y = 0.5 * size.height();
QwtPainter::drawLine( &painter, 0.0, y, size.width(), y );
}
}
if ( m_data->legendAttributes & QwtPolarCurve::LegendShowSymbol )
{
if ( m_data->symbol )
{
QRectF r( 0, 0, size.width(), size.height() );
m_data->symbol->drawSymbol( &painter, r );
}
}
return graphic;
}
QwtInterval QwtPolarCurve::boundingInterval( int scaleId ) const
{
const QRectF boundingRect = m_series->boundingRect();
if ( scaleId == QwtPolar::ScaleAzimuth )
return QwtInterval( boundingRect.left(), boundingRect.right() );
if ( scaleId == QwtPolar::ScaleRadius )
return QwtInterval( boundingRect.top(), boundingRect.bottom() );
return QwtInterval();
}
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