qwt_plot_histogram.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_histogram.h"
#include "qwt_painter.h"
#include "qwt_column_symbol.h"
#include "qwt_scale_map.h"
#include "qwt_graphic.h"
#include <qstring.h>
#include <qpainter.h>
static inline bool qwtIsCombinable( const QwtInterval& d1,
const QwtInterval& d2 )
{
if ( d1.isValid() && d2.isValid() )
{
if ( d1.maxValue() == d2.minValue() )
{
if ( !( d1.borderFlags() & QwtInterval::ExcludeMaximum
&& d2.borderFlags() & QwtInterval::ExcludeMinimum ) )
{
return true;
}
}
}
return false;
}
class QwtPlotHistogram::PrivateData
{
public:
PrivateData()
: baseline( 0.0 )
, style( Columns )
, symbol( NULL )
{
}
~PrivateData()
{
delete symbol;
}
double baseline;
QPen pen;
QBrush brush;
QwtPlotHistogram::HistogramStyle style;
const QwtColumnSymbol* symbol;
};
QwtPlotHistogram::QwtPlotHistogram( const QwtText& title )
: QwtPlotSeriesItem( title )
{
init();
}
QwtPlotHistogram::QwtPlotHistogram( const QString& title )
: QwtPlotSeriesItem( title )
{
init();
}
QwtPlotHistogram::~QwtPlotHistogram()
{
delete m_data;
}
void QwtPlotHistogram::init()
{
m_data = new PrivateData();
setData( new QwtIntervalSeriesData() );
setItemAttribute( QwtPlotItem::AutoScale, true );
setItemAttribute( QwtPlotItem::Legend, true );
setZ( 20.0 );
}
void QwtPlotHistogram::setStyle( HistogramStyle style )
{
if ( style != m_data->style )
{
m_data->style = style;
legendChanged();
itemChanged();
}
}
QwtPlotHistogram::HistogramStyle QwtPlotHistogram::style() const
{
return m_data->style;
}
void QwtPlotHistogram::setPen( const QColor& color, qreal width, Qt::PenStyle style )
{
setPen( QPen( color, width, style ) );
}
void QwtPlotHistogram::setPen( const QPen& pen )
{
if ( pen != m_data->pen )
{
m_data->pen = pen;
legendChanged();
itemChanged();
}
}
const QPen& QwtPlotHistogram::pen() const
{
return m_data->pen;
}
void QwtPlotHistogram::setBrush( const QBrush& brush )
{
if ( brush != m_data->brush )
{
m_data->brush = brush;
legendChanged();
itemChanged();
}
}
const QBrush& QwtPlotHistogram::brush() const
{
return m_data->brush;
}
void QwtPlotHistogram::setSymbol( const QwtColumnSymbol* symbol )
{
if ( symbol != m_data->symbol )
{
delete m_data->symbol;
m_data->symbol = symbol;
legendChanged();
itemChanged();
}
}
const QwtColumnSymbol* QwtPlotHistogram::symbol() const
{
return m_data->symbol;
}
void QwtPlotHistogram::setBaseline( double value )
{
if ( m_data->baseline != value )
{
m_data->baseline = value;
itemChanged();
}
}
double QwtPlotHistogram::baseline() const
{
return m_data->baseline;
}
QRectF QwtPlotHistogram::boundingRect() const
{
QRectF rect = data()->boundingRect();
if ( !rect.isValid() )
return rect;
if ( orientation() == Qt::Horizontal )
{
rect = QRectF( rect.y(), rect.x(),
rect.height(), rect.width() );
if ( rect.left() > m_data->baseline )
rect.setLeft( m_data->baseline );
else if ( rect.right() < m_data->baseline )
rect.setRight( m_data->baseline );
}
else
{
if ( rect.bottom() < m_data->baseline )
rect.setBottom( m_data->baseline );
else if ( rect.top() > m_data->baseline )
rect.setTop( m_data->baseline );
}
return rect;
}
int QwtPlotHistogram::rtti() const
{
return QwtPlotItem::Rtti_PlotHistogram;
}
void QwtPlotHistogram::setSamples(
const QVector< QwtIntervalSample >& samples )
{
setData( new QwtIntervalSeriesData( samples ) );
}
void QwtPlotHistogram::setSamples(
QwtSeriesData< QwtIntervalSample >* data )
{
setData( data );
}
void QwtPlotHistogram::drawSeries( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
const QRectF& canvasRect, int from, int to ) const
{
Q_UNUSED( canvasRect )
if ( !painter || dataSize() <= 0 )
return;
if ( to < 0 )
to = dataSize() - 1;
switch ( m_data->style )
{
case Outline:
drawOutline( painter, xMap, yMap, from, to );
break;
case Lines:
drawLines( painter, xMap, yMap, from, to );
break;
case Columns:
drawColumns( painter, xMap, yMap, from, to );
break;
default:
break;
}
}
void QwtPlotHistogram::drawOutline( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
int from, int to ) const
{
const bool doAlign = QwtPainter::roundingAlignment( painter );
double v0 = ( orientation() == Qt::Horizontal ) ?
xMap.transform( baseline() ) : yMap.transform( baseline() );
if ( doAlign )
v0 = qRound( v0 );
QwtIntervalSample previous;
QPolygonF polygon;
for ( int i = from; i <= to; i++ )
{
const QwtIntervalSample sample = this->sample( i );
if ( !sample.interval.isValid() )
{
flushPolygon( painter, v0, polygon );
previous = sample;
continue;
}
if ( previous.interval.isValid() )
{
if ( !qwtIsCombinable( previous.interval, sample.interval ) )
flushPolygon( painter, v0, polygon );
}
if ( orientation() == Qt::Vertical )
{
double x1 = xMap.transform( sample.interval.minValue() );
double x2 = xMap.transform( sample.interval.maxValue() );
double y = yMap.transform( sample.value );
if ( doAlign )
{
x1 = qRound( x1 );
x2 = qRound( x2 );
y = qRound( y );
}
if ( polygon.size() == 0 )
polygon += QPointF( x1, v0 );
polygon += QPointF( x1, y );
polygon += QPointF( x2, y );
}
else
{
double y1 = yMap.transform( sample.interval.minValue() );
double y2 = yMap.transform( sample.interval.maxValue() );
double x = xMap.transform( sample.value );
if ( doAlign )
{
y1 = qRound( y1 );
y2 = qRound( y2 );
x = qRound( x );
}
if ( polygon.size() == 0 )
polygon += QPointF( v0, y1 );
polygon += QPointF( x, y1 );
polygon += QPointF( x, y2 );
}
previous = sample;
}
flushPolygon( painter, v0, polygon );
}
void QwtPlotHistogram::drawColumns( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
int from, int to ) const
{
painter->setPen( m_data->pen );
painter->setBrush( m_data->brush );
const QwtSeriesData< QwtIntervalSample >* series = data();
for ( int i = from; i <= to; i++ )
{
const QwtIntervalSample sample = series->sample( i );
if ( !sample.interval.isNull() )
{
const QwtColumnRect rect = columnRect( sample, xMap, yMap );
drawColumn( painter, rect, sample );
}
}
}
void QwtPlotHistogram::drawLines( QPainter* painter,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
int from, int to ) const
{
const bool doAlign = QwtPainter::roundingAlignment( painter );
painter->setPen( m_data->pen );
painter->setBrush( Qt::NoBrush );
const QwtSeriesData< QwtIntervalSample >* series = data();
for ( int i = from; i <= to; i++ )
{
const QwtIntervalSample sample = series->sample( i );
if ( !sample.interval.isNull() )
{
const QwtColumnRect rect = columnRect( sample, xMap, yMap );
QRectF r = rect.toRect();
if ( doAlign )
{
r.setLeft( qRound( r.left() ) );
r.setRight( qRound( r.right() ) );
r.setTop( qRound( r.top() ) );
r.setBottom( qRound( r.bottom() ) );
}
switch ( rect.direction )
{
case QwtColumnRect::LeftToRight:
{
QwtPainter::drawLine( painter,
r.topRight(), r.bottomRight() );
break;
}
case QwtColumnRect::RightToLeft:
{
QwtPainter::drawLine( painter,
r.topLeft(), r.bottomLeft() );
break;
}
case QwtColumnRect::TopToBottom:
{
QwtPainter::drawLine( painter,
r.bottomRight(), r.bottomLeft() );
break;
}
case QwtColumnRect::BottomToTop:
{
QwtPainter::drawLine( painter,
r.topRight(), r.topLeft() );
break;
}
}
}
}
}
void QwtPlotHistogram::flushPolygon( QPainter* painter,
double baseLine, QPolygonF& polygon ) const
{
if ( polygon.size() == 0 )
return;
if ( orientation() == Qt::Horizontal )
polygon += QPointF( baseLine, polygon.last().y() );
else
polygon += QPointF( polygon.last().x(), baseLine );
if ( m_data->brush.style() != Qt::NoBrush )
{
painter->setPen( Qt::NoPen );
painter->setBrush( m_data->brush );
if ( orientation() == Qt::Horizontal )
{
polygon += QPointF( polygon.last().x(), baseLine );
polygon += QPointF( polygon.first().x(), baseLine );
}
else
{
polygon += QPointF( baseLine, polygon.last().y() );
polygon += QPointF( baseLine, polygon.first().y() );
}
QwtPainter::drawPolygon( painter, polygon );
polygon.pop_back();
polygon.pop_back();
}
if ( m_data->pen.style() != Qt::NoPen )
{
painter->setBrush( Qt::NoBrush );
painter->setPen( m_data->pen );
QwtPainter::drawPolyline( painter, polygon );
}
polygon.clear();
}
QwtColumnRect QwtPlotHistogram::columnRect( const QwtIntervalSample& sample,
const QwtScaleMap& xMap, const QwtScaleMap& yMap ) const
{
QwtColumnRect rect;
const QwtInterval& iv = sample.interval;
if ( !iv.isValid() )
return rect;
if ( orientation() == Qt::Horizontal )
{
const double x0 = xMap.transform( baseline() );
const double x = xMap.transform( sample.value );
const double y1 = yMap.transform( iv.minValue() );
const double y2 = yMap.transform( iv.maxValue() );
rect.hInterval.setInterval( x0, x );
rect.vInterval.setInterval( y1, y2, iv.borderFlags() );
rect.direction = ( x < x0 ) ? QwtColumnRect::RightToLeft :
QwtColumnRect::LeftToRight;
}
else
{
const double x1 = xMap.transform( iv.minValue() );
const double x2 = xMap.transform( iv.maxValue() );
const double y0 = yMap.transform( baseline() );
const double y = yMap.transform( sample.value );
rect.hInterval.setInterval( x1, x2, iv.borderFlags() );
rect.vInterval.setInterval( y0, y );
rect.direction = ( y < y0 ) ? QwtColumnRect::BottomToTop :
QwtColumnRect::TopToBottom;
}
return rect;
}
void QwtPlotHistogram::drawColumn( QPainter* painter,
const QwtColumnRect& rect, const QwtIntervalSample& sample ) const
{
Q_UNUSED( sample );
if ( m_data->symbol &&
( m_data->symbol->style() != QwtColumnSymbol::NoStyle ) )
{
m_data->symbol->draw( painter, rect );
}
else
{
QRectF r = rect.toRect();
if ( QwtPainter::roundingAlignment( painter ) )
{
r.setLeft( qRound( r.left() ) );
r.setRight( qRound( r.right() ) );
r.setTop( qRound( r.top() ) );
r.setBottom( qRound( r.bottom() ) );
}
QwtPainter::drawRect( painter, r );
}
}
QwtGraphic QwtPlotHistogram::legendIcon( int index, const QSizeF& size ) const
{
Q_UNUSED( index );
return defaultIcon( m_data->brush, size );
}
QVector
Definition: qwt_clipper.h:23
QwtColumnRect
Directed rectangle representing bounding rectangle and orientation of a column.
Definition: qwt_column_symbol.h:27
QwtColumnRect::vInterval
QwtInterval vInterval
Interval for the vertical coordinates.
Definition: qwt_column_symbol.h:67
QwtColumnRect::hInterval
QwtInterval hInterval
Interval for the horizontal coordinates.
Definition: qwt_column_symbol.h:64
QwtColumnRect::LeftToRight
@ LeftToRight
From left to right.
Definition: qwt_column_symbol.h:33
QwtColumnRect::TopToBottom
@ TopToBottom
From top to bottom.
Definition: qwt_column_symbol.h:42
QwtColumnRect::BottomToTop
@ BottomToTop
From bottom to top.
Definition: qwt_column_symbol.h:39
QwtColumnRect::RightToLeft
@ RightToLeft
From right to left.
Definition: qwt_column_symbol.h:36
QwtColumnRect::direction
Direction direction
Direction.
Definition: qwt_column_symbol.h:70
QwtColumnRect::toRect
QRectF toRect() const
Definition: qwt_column_symbol.cpp:296
QwtColumnSymbol
A drawing primitive for columns.
Definition: qwt_column_symbol.h:75
QwtColumnSymbol::NoStyle
@ NoStyle
No Style, the symbol draws nothing.
Definition: qwt_column_symbol.h:84
QwtGraphic
A paint device for scalable graphics.
Definition: qwt_graphic.h:76
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:23
QwtInterval::setInterval
void setInterval(double minValue, double maxValue, BorderFlags=IncludeBorders)
Definition: qwt_interval.h:143
QwtInterval::minValue
double minValue() const
Definition: qwt_interval.h:192
QwtInterval::ExcludeMaximum
@ ExcludeMaximum
Max value is not included in the interval.
Definition: qwt_interval.h:38
QwtInterval::ExcludeMinimum
@ ExcludeMinimum
Min value is not included in the interval.
Definition: qwt_interval.h:35
QwtInterval::maxValue
double maxValue() const
Definition: qwt_interval.h:198
QwtInterval::borderFlags
BorderFlags borderFlags() const
Definition: qwt_interval.h:166
QwtInterval::isNull
bool isNull() const
Definition: qwt_interval.h:314
QwtInterval::isValid
bool isValid() const
Definition: qwt_interval.h:210
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
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::drawRect
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
Definition: qwt_painter.cpp:347
QwtPainter::roundingAlignment
static bool roundingAlignment()
Definition: qwt_painter.h:183
QwtPainter::drawLine
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:154
QwtPlotHistogram::columnRect
virtual QwtColumnRect columnRect(const QwtIntervalSample &, const QwtScaleMap &, const QwtScaleMap &) const
Definition: qwt_plot_histogram.cpp:602
QwtPlotHistogram::setBrush
void setBrush(const QBrush &)
Definition: qwt_plot_histogram.cpp:174
QwtPlotHistogram::style
HistogramStyle style() const
Definition: qwt_plot_histogram.cpp:119
QwtPlotHistogram::QwtPlotHistogram
QwtPlotHistogram(const QString &title=QString())
Definition: qwt_plot_histogram.cpp:74
QwtPlotHistogram::HistogramStyle
HistogramStyle
Definition: qwt_plot_histogram.h:53
QwtPlotHistogram::Lines
@ Lines
Definition: qwt_plot_histogram.h:72
QwtPlotHistogram::Columns
@ Columns
Definition: qwt_plot_histogram.h:67
QwtPlotHistogram::Outline
@ Outline
Definition: qwt_plot_histogram.h:60
QwtPlotHistogram::legendIcon
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
Definition: qwt_plot_histogram.cpp:688
QwtPlotHistogram::setStyle
void setStyle(HistogramStyle style)
Definition: qwt_plot_histogram.cpp:104
QwtPlotHistogram::setBaseline
void setBaseline(double)
Set the value of the baseline.
Definition: qwt_plot_histogram.cpp:240
QwtPlotHistogram::setPen
void setPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
Definition: qwt_plot_histogram.cpp:137
QwtPlotHistogram::~QwtPlotHistogram
virtual ~QwtPlotHistogram()
Destructor.
Definition: qwt_plot_histogram.cpp:81
QwtPlotHistogram::setSamples
void setSamples(const QVector< QwtIntervalSample > &)
Definition: qwt_plot_histogram.cpp:299
QwtPlotHistogram::drawLines
void drawLines(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
Definition: qwt_plot_histogram.cpp:493
QwtPlotHistogram::drawOutline
void drawOutline(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
Definition: qwt_plot_histogram.cpp:376
QwtPlotHistogram::rtti
virtual int rtti() const override
Definition: qwt_plot_histogram.cpp:290
QwtPlotHistogram::pen
const QPen & pen() const
Definition: qwt_plot_histogram.cpp:163
QwtPlotHistogram::boundingRect
virtual QRectF boundingRect() const override
Definition: qwt_plot_histogram.cpp:262
QwtPlotHistogram::baseline
double baseline() const
Definition: qwt_plot_histogram.cpp:253
QwtPlotHistogram::setSymbol
void setSymbol(const QwtColumnSymbol *)
Assign a symbol.
Definition: qwt_plot_histogram.cpp:208
QwtPlotHistogram::symbol
const QwtColumnSymbol * symbol() const
Definition: qwt_plot_histogram.cpp:224
QwtPlotHistogram::drawColumns
void drawColumns(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
Definition: qwt_plot_histogram.cpp:461
QwtPlotHistogram::brush
const QBrush & brush() const
Definition: qwt_plot_histogram.cpp:189
QwtPlotHistogram::drawColumn
virtual void drawColumn(QPainter *, const QwtColumnRect &, const QwtIntervalSample &) const
Definition: qwt_plot_histogram.cpp:653
QwtPlotHistogram::drawSeries
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const override
Definition: qwt_plot_histogram.cpp:334
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::defaultIcon
QwtGraphic defaultIcon(const QBrush &, const QSizeF &) const
Return a default icon from a brush.
Definition: qwt_plot_item.cpp:422
QwtPlotItem::Rtti_PlotHistogram
@ Rtti_PlotHistogram
For QwtPlotHistogram.
Definition: qwt_plot_item.h:102
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
QwtScaleMap
A scale map.
Definition: qwt_scale_map.h:27
QwtScaleMap::transform
double transform(double s) const
Definition: qwt_scale_map.h:137
QwtSeriesData
Abstract interface for iterating over samples.
Definition: qwt_series_data.h:50
QwtSeriesData::sample
virtual T sample(size_t i) const =0
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