qwt_plot_intervalcurve.cpp
/******************************************************************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 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_plot_intervalcurve.h"
#include "qwt_interval_symbol.h"
#include "qwt_scale_map.h"
#include "qwt_clipper.h"
#include "qwt_painter.h"
#include "qwt_graphic.h"
#include "qwt_text.h"
#include <qpainter.h>
#include <cstring>
static inline bool qwtIsHSampleInside( const QwtIntervalSample& sample,
double xMin, double xMax, double yMin, double yMax )
{
const double y = sample.value;
const double x1 = sample.interval.minValue();
const double x2 = sample.interval.maxValue();
const bool isOffScreen = ( y < yMin ) || ( y > yMax )
|| ( x1 < xMin && x2 < xMin ) || ( x1 > xMax && x2 > xMax );
return !isOffScreen;
}
static inline bool qwtIsVSampleInside( const QwtIntervalSample& sample,
double xMin, double xMax, double yMin, double yMax )
{
const double x = sample.value;
const double y1 = sample.interval.minValue();
const double y2 = sample.interval.maxValue();
const bool isOffScreen = ( x < xMin ) || ( x > xMax )
|| ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax );
return !isOffScreen;
}
class QwtPlotIntervalCurve::PrivateData
{
public:
PrivateData():
style( QwtPlotIntervalCurve::Tube ),
symbol( NULL ),
pen( Qt::black ),
brush( Qt::white )
{
paintAttributes = QwtPlotIntervalCurve::ClipPolygons;
paintAttributes |= QwtPlotIntervalCurve::ClipSymbol;
pen.setCapStyle( Qt::FlatCap );
}
~PrivateData()
{
delete symbol;
}
QwtPlotIntervalCurve::CurveStyle style;
const QwtIntervalSymbol* symbol;
QPen pen;
QBrush brush;
QwtPlotIntervalCurve::PaintAttributes paintAttributes;
};
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText& title )
: QwtPlotSeriesItem( title )
{
init();
}
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString& title )
: QwtPlotSeriesItem( QwtText( title ) )
{
init();
}
QwtPlotIntervalCurve::~QwtPlotIntervalCurve()
{
delete m_data;
}
void QwtPlotIntervalCurve::init()
{
setItemAttribute( QwtPlotItem::Legend, true );
setItemAttribute( QwtPlotItem::AutoScale, true );
m_data = new PrivateData;
setData( new QwtIntervalSeriesData() );
setZ( 19.0 );
}
int QwtPlotIntervalCurve::rtti() const
{
return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve;
}
void QwtPlotIntervalCurve::setPaintAttribute(
PaintAttribute attribute, bool on )
{
if ( on )
m_data->paintAttributes |= attribute;
else
m_data->paintAttributes &= ~attribute;
}
bool QwtPlotIntervalCurve::testPaintAttribute(
PaintAttribute attribute ) const
{
return ( m_data->paintAttributes & attribute );
}
void QwtPlotIntervalCurve::setSamples(
const QVector< QwtIntervalSample >& samples )
{
setData( new QwtIntervalSeriesData( samples ) );
}
void QwtPlotIntervalCurve::setSamples(
QwtSeriesData< QwtIntervalSample >* data )
{
setData( data );
}
void QwtPlotIntervalCurve::setStyle( CurveStyle style )
{
if ( style != m_data->style )
{
m_data->style = style;
legendChanged();
itemChanged();
}
}
QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const
{
return m_data->style;
}
void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol* symbol )
{
if ( symbol != m_data->symbol )
{
delete m_data->symbol;
m_data->symbol = symbol;
legendChanged();
itemChanged();
}
}
const QwtIntervalSymbol* QwtPlotIntervalCurve::symbol() const
{
return m_data->symbol;
}
void QwtPlotIntervalCurve::setPen( const QColor& color, qreal width, Qt::PenStyle style )
{
setPen( QPen( color, width, style ) );
}
void QwtPlotIntervalCurve::setPen( const QPen& pen )
{
if ( pen != m_data->pen )
{
m_data->pen = pen;
legendChanged();
itemChanged();
}
}
const QPen& QwtPlotIntervalCurve::pen() const
{
return m_data->pen;
}
void QwtPlotIntervalCurve::setBrush( const QBrush& brush )
{
if ( brush != m_data->brush )
{
m_data->brush = brush;
legendChanged();
itemChanged();
}
}
const QBrush& QwtPlotIntervalCurve::brush() const
{
return m_data->brush;
}
QRectF QwtPlotIntervalCurve::boundingRect() const
{
QRectF rect = QwtPlotSeriesItem::boundingRect();
if ( orientation() == Qt::Vertical )
rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
return rect;
}
void QwtPlotIntervalCurve::drawSeries( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
const QRectF& canvasRect, int from, int to ) const
{
if ( to < 0 )
to = dataSize() - 1;
if ( from < 0 )
from = 0;
if ( from > to )
return;
switch ( m_data->style )
{
case Tube:
drawTube( painter, xMap, yMap, canvasRect, from, to );
break;
case NoCurve:
default:
break;
}
if ( m_data->symbol &&
( m_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
{
drawSymbols( painter, *m_data->symbol,
xMap, yMap, canvasRect, from, to );
}
}
void QwtPlotIntervalCurve::drawTube( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
const QRectF& canvasRect, int from, int to ) const
{
const bool doAlign = QwtPainter::roundingAlignment( painter );
painter->save();
const size_t size = to - from + 1;
QPolygonF polygon( 2 * size );
QPointF* points = polygon.data();
for ( uint i = 0; i < size; i++ )
{
QPointF& minValue = points[i];
QPointF& maxValue = points[2 * size - 1 - i];
const QwtIntervalSample intervalSample = sample( from + i );
if ( orientation() == Qt::Vertical )
{
double x = xMap.transform( intervalSample.value );
double y1 = yMap.transform( intervalSample.interval.minValue() );
double y2 = yMap.transform( intervalSample.interval.maxValue() );
if ( doAlign )
{
x = qRound( x );
y1 = qRound( y1 );
y2 = qRound( y2 );
}
minValue.rx() = x;
minValue.ry() = y1;
maxValue.rx() = x;
maxValue.ry() = y2;
}
else
{
double y = yMap.transform( intervalSample.value );
double x1 = xMap.transform( intervalSample.interval.minValue() );
double x2 = xMap.transform( intervalSample.interval.maxValue() );
if ( doAlign )
{
y = qRound( y );
x1 = qRound( x1 );
x2 = qRound( x2 );
}
minValue.rx() = x1;
minValue.ry() = y;
maxValue.rx() = x2;
maxValue.ry() = y;
}
}
if ( m_data->brush.style() != Qt::NoBrush )
{
painter->setPen( QPen( Qt::NoPen ) );
painter->setBrush( m_data->brush );
if ( m_data->paintAttributes & ClipPolygons )
{
const qreal m = 1.0;
const QPolygonF p = QwtClipper::clippedPolygonF(
canvasRect.adjusted( -m, -m, m, m ), polygon, true );
QwtPainter::drawPolygon( painter, p );
}
else
{
QwtPainter::drawPolygon( painter, polygon );
}
}
if ( m_data->pen.style() != Qt::NoPen )
{
painter->setPen( m_data->pen );
painter->setBrush( Qt::NoBrush );
if ( m_data->paintAttributes & ClipPolygons )
{
qreal pw = QwtPainter::effectivePenWidth( painter->pen() );
const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );
QPolygonF p( size );
std::memcpy( p.data(), points, size * sizeof( QPointF ) );
QwtPainter::drawPolyline( painter,
QwtClipper::clippedPolygonF( clipRect, p ) );
std::memcpy( p.data(), points + size, size * sizeof( QPointF ) );
QwtPainter::drawPolyline( painter,
QwtClipper::clippedPolygonF( clipRect, p ) );
}
else
{
QwtPainter::drawPolyline( painter, points, size );
QwtPainter::drawPolyline( painter, points + size, size );
}
}
painter->restore();
}
void QwtPlotIntervalCurve::drawSymbols(
QPainter* painter, const QwtIntervalSymbol& symbol,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
const QRectF& canvasRect, int from, int to ) const
{
painter->save();
QPen pen = symbol.pen();
pen.setCapStyle( Qt::FlatCap );
painter->setPen( pen );
painter->setBrush( symbol.brush() );
const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect );
const double xMin = tr.left();
const double xMax = tr.right();
const double yMin = tr.top();
const double yMax = tr.bottom();
const bool doClip = m_data->paintAttributes & ClipSymbol;
for ( int i = from; i <= to; i++ )
{
const QwtIntervalSample s = sample( i );
if ( orientation() == Qt::Vertical )
{
if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) )
{
const double x = xMap.transform( s.value );
const double y1 = yMap.transform( s.interval.minValue() );
const double y2 = yMap.transform( s.interval.maxValue() );
symbol.draw( painter, orientation(),
QPointF( x, y1 ), QPointF( x, y2 ) );
}
}
else
{
if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) )
{
const double y = yMap.transform( s.value );
const double x1 = xMap.transform( s.interval.minValue() );
const double x2 = xMap.transform( s.interval.maxValue() );
symbol.draw( painter, orientation(),
QPointF( x1, y ), QPointF( x2, y ) );
}
}
}
painter->restore();
}
QwtGraphic QwtPlotIntervalCurve::legendIcon(
int index, const QSizeF& size ) const
{
Q_UNUSED( index );
if ( size.isEmpty() )
return QwtGraphic();
QwtGraphic icon;
icon.setDefaultSize( size );
icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
QPainter painter( &icon );
painter.setRenderHint( QPainter::Antialiasing,
testRenderHint( QwtPlotItem::RenderAntialiased ) );
if ( m_data->style == Tube )
{
QRectF r( 0, 0, size.width(), size.height() );
painter.fillRect( r, m_data->brush );
}
if ( m_data->symbol &&
( m_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
{
QPen pen = m_data->symbol->pen();
pen.setWidthF( pen.widthF() );
pen.setCapStyle( Qt::FlatCap );
painter.setPen( pen );
painter.setBrush( m_data->symbol->brush() );
if ( orientation() == Qt::Vertical )
{
const double x = 0.5 * size.width();
m_data->symbol->draw( &painter, orientation(),
QPointF( x, 0 ), QPointF( x, size.height() - 1.0 ) );
}
else
{
const double y = 0.5 * size.height();
m_data->symbol->draw( &painter, orientation(),
QPointF( 0.0, y ), QPointF( size.width() - 1.0, y ) );
}
}
return icon;
}
QVector
Definition: qwt_clipper.h:23
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::minValue
double minValue() const
Definition: qwt_interval.h:192
QwtInterval::maxValue
double maxValue() const
Definition: qwt_interval.h:198
QwtIntervalSample
A sample of the types (x1-x2, y) or (x, y1-y2)
Definition: qwt_samples.h:21
QwtIntervalSample::interval
QwtInterval interval
Interval.
Definition: qwt_samples.h:34
QwtIntervalSample::value
double value
Value.
Definition: qwt_samples.h:31
QwtIntervalSeriesData
Interface for iterating over an array of intervals.
Definition: qwt_series_data.h:230
QwtIntervalSymbol
A drawing primitive for displaying an interval like an error bar.
Definition: qwt_interval_symbol.h:28
QwtIntervalSymbol::draw
virtual void draw(QPainter *, Qt::Orientation, const QPointF &from, const QPointF &to) const
Definition: qwt_interval_symbol.cpp:200
QwtIntervalSymbol::pen
const QPen & pen() const
Definition: qwt_interval_symbol.cpp:185
QwtIntervalSymbol::NoSymbol
@ NoSymbol
No Style. The symbol cannot be drawn.
Definition: qwt_interval_symbol.h:34
QwtIntervalSymbol::brush
const QBrush & brush() const
Definition: qwt_interval_symbol.cpp:146
QwtPainter::drawPolygon
static void drawPolygon(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolygon()
Definition: qwt_painter.cpp:561
QwtPainter::drawPolyline
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
Definition: qwt_painter.cpp:578
QwtPainter::effectivePenWidth
static qreal effectivePenWidth(const QPen &)
Definition: qwt_painter.h:201
QwtPainter::roundingAlignment
static bool roundingAlignment()
Definition: qwt_painter.h:183
QwtPlotIntervalCurve
QwtPlotIntervalCurve represents a series of samples, where each value is associated with an interval ...
Definition: qwt_plot_intervalcurve.h:30
QwtPlotIntervalCurve::rtti
virtual int rtti() const override
Definition: qwt_plot_intervalcurve.cpp:115
QwtPlotIntervalCurve::~QwtPlotIntervalCurve
virtual ~QwtPlotIntervalCurve()
Destructor.
Definition: qwt_plot_intervalcurve.cpp:97
QwtPlotIntervalCurve::PaintAttributes
QFlags< PaintAttribute > PaintAttributes
Definition: qwt_plot_intervalcurve.h:77
QwtPlotIntervalCurve::setBrush
void setBrush(const QBrush &)
Definition: qwt_plot_intervalcurve.cpp:276
QwtPlotIntervalCurve::QwtPlotIntervalCurve
QwtPlotIntervalCurve(const QString &title=QString())
Definition: qwt_plot_intervalcurve.cpp:90
QwtPlotIntervalCurve::PaintAttribute
PaintAttribute
Definition: qwt_plot_intervalcurve.h:65
QwtPlotIntervalCurve::ClipSymbol
@ ClipSymbol
Check if a symbol is on the plot canvas before painting it.
Definition: qwt_plot_intervalcurve.h:74
QwtPlotIntervalCurve::ClipPolygons
@ ClipPolygons
Definition: qwt_plot_intervalcurve.h:71
QwtPlotIntervalCurve::setPen
void setPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
Definition: qwt_plot_intervalcurve.cpp:238
QwtPlotIntervalCurve::legendIcon
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
Definition: qwt_plot_intervalcurve.cpp:554
QwtPlotIntervalCurve::boundingRect
virtual QRectF boundingRect() const override
Definition: qwt_plot_intervalcurve.cpp:300
QwtPlotIntervalCurve::setSymbol
void setSymbol(const QwtIntervalSymbol *)
Definition: qwt_plot_intervalcurve.cpp:204
QwtPlotIntervalCurve::style
CurveStyle style() const
Definition: qwt_plot_intervalcurve.cpp:193
QwtPlotIntervalCurve::setStyle
void setStyle(CurveStyle style)
Definition: qwt_plot_intervalcurve.cpp:178
QwtPlotIntervalCurve::init
void init()
Initialize internal members.
Definition: qwt_plot_intervalcurve.cpp:103
QwtPlotIntervalCurve::brush
const QBrush & brush() const
Definition: qwt_plot_intervalcurve.cpp:291
QwtPlotIntervalCurve::drawSymbols
virtual void drawSymbols(QPainter *, const QwtIntervalSymbol &, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
Definition: qwt_plot_intervalcurve.cpp:487
QwtPlotIntervalCurve::CurveStyle
CurveStyle
Curve styles. The default setting is QwtPlotIntervalCurve::Tube.
Definition: qwt_plot_intervalcurve.h:39
QwtPlotIntervalCurve::NoCurve
@ NoCurve
Definition: qwt_plot_intervalcurve.h:43
QwtPlotIntervalCurve::Tube
@ Tube
Definition: qwt_plot_intervalcurve.h:50
QwtPlotIntervalCurve::symbol
const QwtIntervalSymbol * symbol() const
Definition: qwt_plot_intervalcurve.cpp:220
QwtPlotIntervalCurve::pen
const QPen & pen() const
Definition: qwt_plot_intervalcurve.cpp:263
QwtPlotIntervalCurve::setPaintAttribute
void setPaintAttribute(PaintAttribute, bool on=true)
Definition: qwt_plot_intervalcurve.cpp:127
QwtPlotIntervalCurve::setSamples
void setSamples(const QVector< QwtIntervalSample > &)
Definition: qwt_plot_intervalcurve.cpp:150
QwtPlotIntervalCurve::drawTube
virtual void drawTube(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
Definition: qwt_plot_intervalcurve.cpp:371
QwtPlotIntervalCurve::drawSeries
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const override
Definition: qwt_plot_intervalcurve.cpp:322
QwtPlotIntervalCurve::testPaintAttribute
bool testPaintAttribute(PaintAttribute) const
Definition: qwt_plot_intervalcurve.cpp:140
QwtPlotItem::legendChanged
virtual void legendChanged()
Definition: qwt_plot_item.cpp:491
QwtPlotItem::setZ
void setZ(double z)
Set the z value.
Definition: qwt_plot_item.cpp:165
QwtPlotItem::setItemAttribute
void setItemAttribute(ItemAttribute, bool on=true)
Definition: qwt_plot_item.cpp:228
QwtPlotItem::Rtti_PlotIntervalCurve
@ Rtti_PlotIntervalCurve
For QwtPlotIntervalCurve.
Definition: qwt_plot_item.h:99
QwtPlotItem::RenderAntialiased
@ RenderAntialiased
Enable antialiasing.
Definition: qwt_plot_item.h:206
QwtPlotItem::testRenderHint
bool testRenderHint(RenderHint) const
Definition: qwt_plot_item.cpp:332
QwtPlotItem::itemChanged
virtual void itemChanged()
Definition: qwt_plot_item.cpp:481
QwtPlotItem::Legend
@ Legend
The item is represented on the legend.
Definition: qwt_plot_item.h:150
QwtPlotItem::AutoScale
@ AutoScale
Definition: qwt_plot_item.h:157
QwtPlotSeriesItem
Base class for plot items representing a series of samples.
Definition: qwt_plot_seriesitem.h:26
QwtPlotSeriesItem::orientation
Qt::Orientation orientation() const
Definition: qwt_plot_seriesitem.cpp:77
QwtPlotSeriesItem::boundingRect
virtual QRectF boundingRect() const override
Definition: qwt_plot_seriesitem.cpp:97
QwtScaleMap
A scale map.
Definition: qwt_scale_map.h:27
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
QwtSeriesData
Abstract interface for iterating over samples.
Definition: qwt_series_data.h:50
QwtSeriesStore< QwtIntervalSample >::sample
QwtIntervalSample sample(int index) const
Definition: qwt_series_store.h:158
QwtSeriesStore< QwtIntervalSample >::dataSize
virtual size_t dataSize() const override
Definition: qwt_series_store.h:175
QwtSeriesStore< QwtIntervalSample >::data
QwtSeriesData< QwtIntervalSample > * data()
Definition: qwt_series_store.h:146
QwtSeriesStore< QwtIntervalSample >::setData
void setData(QwtSeriesData< QwtIntervalSample > *series)
Definition: qwt_series_store.h:164
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtClipper::clippedPolygonF
QWT_EXPORT QPolygonF clippedPolygonF(const QRectF &, const QPolygonF &, bool closePolygon=false)
Definition: qwt_clipper.cpp:455