1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
10
#include "qwt_plot_intervalcurve.h"
11
#include "qwt_interval_symbol.h"
12
#include "qwt_scale_map.h"
13
#include "qwt_clipper.h"
14
#include "qwt_painter.h"
18
static inline bool qwtIsHSampleInside( const QwtIntervalSample &sample,
19
double xMin, double xMax, double yMin, double yMax )
21
const double y = sample.value;
22
const double x1 = sample.interval.minValue();
23
const double x2 = sample.interval.maxValue();
25
const bool isOffScreen = ( y < yMin ) || ( y > yMax )
26
|| ( x1 < xMin && x2 < xMin ) || ( x1 > yMax && x2 > xMax );
31
static inline bool qwtIsVSampleInside( const QwtIntervalSample &sample,
32
double xMin, double xMax, double yMin, double yMax )
34
const double x = sample.value;
35
const double y1 = sample.interval.minValue();
36
const double y2 = sample.interval.maxValue();
38
const bool isOffScreen = ( x < xMin ) || ( x > xMax )
39
|| ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax );
44
class QwtPlotIntervalCurve::PrivateData
53
paintAttributes = QwtPlotIntervalCurve::ClipPolygons;
54
paintAttributes |= QwtPlotIntervalCurve::ClipSymbol;
56
pen.setCapStyle( Qt::FlatCap );
65
const QwtIntervalSymbol *symbol;
70
QwtPlotIntervalCurve::PaintAttributes paintAttributes;
75
\param title Title of the curve
77
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText &title ):
78
QwtPlotSeriesItem<QwtIntervalSample>( title )
85
\param title Title of the curve
87
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString &title ):
88
QwtPlotSeriesItem<QwtIntervalSample>( QwtText( title ) )
94
QwtPlotIntervalCurve::~QwtPlotIntervalCurve()
99
//! Initialize internal members
100
void QwtPlotIntervalCurve::init()
102
setItemAttribute( QwtPlotItem::Legend, true );
103
setItemAttribute( QwtPlotItem::AutoScale, true );
105
d_data = new PrivateData;
106
d_series = new QwtIntervalSeriesData();
111
//! \return QwtPlotItem::Rtti_PlotIntervalCurve
112
int QwtPlotIntervalCurve::rtti() const
114
return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve;
118
Specify an attribute how to draw the curve
120
\param attribute Paint attribute
122
\sa testPaintAttribute()
124
void QwtPlotIntervalCurve::setPaintAttribute(
125
PaintAttribute attribute, bool on )
128
d_data->paintAttributes |= attribute;
130
d_data->paintAttributes &= ~attribute;
134
\brief Return the current paint attributes
135
\sa PaintAttribute, setPaintAttribute()
137
bool QwtPlotIntervalCurve::testPaintAttribute(
138
PaintAttribute attribute ) const
140
return ( d_data->paintAttributes & attribute );
144
Initialize data with an array of samples.
145
\param samples Vector of samples
147
void QwtPlotIntervalCurve::setSamples(
148
const QVector<QwtIntervalSample> &samples )
151
d_series = new QwtIntervalSeriesData( samples );
156
Set the curve's drawing style
158
\param style Curve style
159
\sa CurveStyle, style()
161
void QwtPlotIntervalCurve::setStyle( CurveStyle style )
163
if ( style != d_data->style )
165
d_data->style = style;
171
\brief Return the current style
174
QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const
176
return d_data->style;
185
void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol *symbol )
187
if ( symbol != d_data->symbol )
189
delete d_data->symbol;
190
d_data->symbol = symbol;
196
\return Current symbol or NULL, when no symbol has been assigned
199
const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const
201
return d_data->symbol;
209
void QwtPlotIntervalCurve::setPen( const QPen &pen )
211
if ( pen != d_data->pen )
219
\brief Return the pen used to draw the lines
220
\sa setPen(), brush()
222
const QPen& QwtPlotIntervalCurve::pen() const
230
The brush is used to fill the area in Tube style().
233
\sa brush(), pen(), setStyle(), CurveStyle
235
void QwtPlotIntervalCurve::setBrush( const QBrush &brush )
237
if ( brush != d_data->brush )
239
d_data->brush = brush;
245
\return Brush used to fill the area in Tube style()
246
\sa setBrush(), setStyle(), CurveStyle
248
const QBrush& QwtPlotIntervalCurve::brush() const
250
return d_data->brush;
254
\return Bounding rectangle of all samples.
255
For an empty series the rectangle is invalid.
257
QRectF QwtPlotIntervalCurve::boundingRect() const
259
QRectF rect = QwtPlotSeriesItem<QwtIntervalSample>::boundingRect();
260
if ( rect.isValid() && orientation() == Qt::Vertical )
261
rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
267
Draw a subset of the samples
269
\param painter Painter
270
\param xMap Maps x-values into pixel coordinates.
271
\param yMap Maps y-values into pixel coordinates.
272
\param canvasRect Contents rect of the canvas
273
\param from Index of the first sample to be painted
274
\param to Index of the last sample to be painted. If to < 0 the
275
series will be painted to its last sample.
277
\sa drawTube(), drawSymbols()
279
void QwtPlotIntervalCurve::drawSeries( QPainter *painter,
280
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
281
const QRectF &canvasRect, int from, int to ) const
292
switch ( d_data->style )
295
drawTube( painter, xMap, yMap, canvasRect, from, to );
303
if ( d_data->symbol &&
304
( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
306
drawSymbols( painter, *d_data->symbol,
307
xMap, yMap, canvasRect, from, to );
314
Builds 2 curves from the upper and lower limits of the intervals
315
and draws them with the pen(). The area between the curves is
316
filled with the brush().
318
\param painter Painter
319
\param xMap Maps x-values into pixel coordinates.
320
\param yMap Maps y-values into pixel coordinates.
321
\param canvasRect Contents rect of the canvas
322
\param from Index of the first sample to be painted
323
\param to Index of the last sample to be painted. If to < 0 the
324
series will be painted to its last sample.
326
\sa drawSeries(), drawSymbols()
328
void QwtPlotIntervalCurve::drawTube( QPainter *painter,
329
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
330
const QRectF &canvasRect, int from, int to ) const
332
const bool doAlign = QwtPainter::roundingAlignment( painter );
336
const size_t size = to - from + 1;
337
QPolygonF polygon( 2 * size );
338
QPointF *points = polygon.data();
340
for ( uint i = 0; i < size; i++ )
342
QPointF &minValue = points[i];
343
QPointF &maxValue = points[2 * size - 1 - i];
345
const QwtIntervalSample intervalSample = sample( from + i );
346
if ( orientation() == Qt::Vertical )
348
double x = xMap.transform( intervalSample.value );
349
double y1 = yMap.transform( intervalSample.interval.minValue() );
350
double y2 = yMap.transform( intervalSample.interval.maxValue() );
365
double y = yMap.transform( intervalSample.value );
366
double x1 = xMap.transform( intervalSample.interval.minValue() );
367
double x2 = xMap.transform( intervalSample.interval.maxValue() );
382
if ( d_data->brush.style() != Qt::NoBrush )
384
painter->setPen( QPen( Qt::NoPen ) );
385
painter->setBrush( d_data->brush );
387
if ( d_data->paintAttributes & ClipPolygons )
390
const QPolygonF p = QwtClipper::clipPolygonF(
391
canvasRect.adjusted(-m, -m, m, m), polygon, true );
393
QwtPainter::drawPolygon( painter, p );
397
QwtPainter::drawPolygon( painter, polygon );
401
if ( d_data->pen.style() != Qt::NoPen )
403
painter->setPen( d_data->pen );
404
painter->setBrush( Qt::NoBrush );
406
if ( d_data->paintAttributes & ClipPolygons )
408
qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
409
const QRectF clipRect = canvasRect.adjusted(-pw, -pw, pw, pw);
414
qMemCopy( p.data(), points, size * sizeof( QPointF ) );
415
p = QwtClipper::clipPolygonF( canvasRect, p );
416
QwtPainter::drawPolyline( painter, p );
419
qMemCopy( p.data(), points + size, size * sizeof( QPointF ) );
420
p = QwtClipper::clipPolygonF( canvasRect, p );
421
QwtPainter::drawPolyline( painter, p );
425
QwtPainter::drawPolyline( painter, points, size );
426
QwtPainter::drawPolyline( painter, points + size, size );
434
Draw symbols for a subset of the samples
436
\param painter Painter
437
\param symbol Interval symbol
440
\param canvasRect Contents rect of the canvas
441
\param from Index of the first sample to be painted
442
\param to Index of the last sample to be painted
444
\sa setSymbol(), drawSeries(), drawTube()
446
void QwtPlotIntervalCurve::drawSymbols(
447
QPainter *painter, const QwtIntervalSymbol &symbol,
448
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
449
const QRectF &canvasRect, int from, int to ) const
453
QPen pen = symbol.pen();
454
pen.setCapStyle( Qt::FlatCap );
456
painter->setPen( pen );
457
painter->setBrush( symbol.brush() );
459
const QRectF &tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect);
461
const double xMin = tr.left();
462
const double xMax = tr.right();
463
const double yMin = tr.top();
464
const double yMax = tr.bottom();
466
const bool doClip = d_data->paintAttributes & ClipPolygons;
468
for ( int i = from; i <= to; i++ )
470
const QwtIntervalSample s = sample( i );
472
if ( orientation() == Qt::Vertical )
474
if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) )
476
const double x = xMap.transform( s.value );
477
const double y1 = yMap.transform( s.interval.minValue() );
478
const double y2 = yMap.transform( s.interval.maxValue() );
480
symbol.draw( painter, orientation(),
481
QPointF( x, y1 ), QPointF( x, y2 ) );
486
if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) )
488
const double y = yMap.transform( s.value );
489
const double x1 = xMap.transform( s.interval.minValue() );
490
const double x2 = xMap.transform( s.interval.maxValue() );
492
symbol.draw( painter, orientation(),
493
QPointF( x1, y ), QPointF( x2, y ) );
502
In case of Tibe stale() a plain rectangle is painted without a pen filled
503
the brush(). If a symbol is assigned it is painted cebtered into rect.
505
\param painter Painter
506
\param rect Bounding rectangle for the identifier
509
void QwtPlotIntervalCurve::drawLegendIdentifier(
510
QPainter *painter, const QRectF &rect ) const
512
const double dim = qMin( rect.width(), rect.height() );
514
QSizeF size( dim, dim );
516
QRectF r( 0, 0, size.width(), size.height() );
517
r.moveCenter( rect.center() );
519
if ( d_data->style == Tube )
521
painter->fillRect( r, d_data->brush );
524
if ( d_data->symbol &&
525
( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
527
QPen pen = d_data->symbol->pen();
528
pen.setWidthF( pen.widthF() );
529
pen.setCapStyle( Qt::FlatCap );
531
painter->setPen( pen );
532
painter->setBrush( d_data->symbol->brush() );
534
if ( orientation() == Qt::Vertical )
536
d_data->symbol->draw( painter, orientation(),
537
QPointF( r.center().x(), r.top() ),
538
QPointF( r.center().x(), r.bottom() - 1 ) );
542
d_data->symbol->draw( painter, orientation(),
543
QPointF( r.left(), r.center().y() ),
544
QPointF( r.right() - 1, r.center().y() ) );