~ubuntu-branches/ubuntu/oneiric/qwt/oneiric-proposed

« back to all changes in this revision

Viewing changes to src/qwt_plot_intervalcurve.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2011-06-10 11:22:47 UTC
  • mfrom: (1.1.6 upstream) (2.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110610112247-0i1019vvmzaq6p86
Tags: 6.0.0-1
* New upstream release (Closes: #624107):
  - drop Qt3 support. (Closes: #604379, #626868)
* Register documentation with doc-base. (Closes: #626567)
* Drop patches:
  - 01_makefiles.diff
  - 02_add_missing_warnings.diff
  - 03_qwt_branch_pull_r544.diff
* Add qwt_install_paths.patch to fix the hardcoded installation paths.
* Update debian/control:
  - drop libqt3-mt-dev build dependency.
  - bump Standards-Version to 3.9.2 (no changes).
  - drop Qt3 related packages.
  - due to bump soname (and as we dropper Qt3 support):
    - libqwt5-qt4-dev -> libqwt-dev
    - libqwt5-qt4 -> libqwt6
    - libqwt5-doc -> libqwt-doc
* Update debian/copyright file.
* Update debian/rules: drop Qt3 packages support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
2
 * Qwt Widget Library
 
3
 * Copyright (C) 1997   Josef Wilgen
 
4
 * Copyright (C) 2002   Uwe Rathmann
 
5
 *
 
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
 *****************************************************************************/
 
9
 
 
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"
 
15
 
 
16
#include <qpainter.h>
 
17
 
 
18
static inline bool qwtIsHSampleInside( const QwtIntervalSample &sample,
 
19
    double xMin, double xMax, double yMin, double yMax )
 
20
{
 
21
    const double y = sample.value;
 
22
    const double x1 = sample.interval.minValue();
 
23
    const double x2 = sample.interval.maxValue();
 
24
 
 
25
    const bool isOffScreen = ( y < yMin ) || ( y > yMax )
 
26
        || ( x1 < xMin && x2 < xMin ) || ( x1 > yMax && x2 > xMax );
 
27
 
 
28
    return !isOffScreen;
 
29
}
 
30
 
 
31
static inline bool qwtIsVSampleInside( const QwtIntervalSample &sample,
 
32
    double xMin, double xMax, double yMin, double yMax )
 
33
{
 
34
    const double x = sample.value;
 
35
    const double y1 = sample.interval.minValue();
 
36
    const double y2 = sample.interval.maxValue();
 
37
 
 
38
    const bool isOffScreen = ( x < xMin ) || ( x > xMax )
 
39
        || ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax );
 
40
 
 
41
    return !isOffScreen;
 
42
}
 
43
 
 
44
class QwtPlotIntervalCurve::PrivateData
 
45
{
 
46
public:
 
47
    PrivateData():
 
48
        style( Tube ),
 
49
        symbol( NULL ),
 
50
        pen( Qt::black ),
 
51
        brush( Qt::white )
 
52
    {
 
53
        paintAttributes = QwtPlotIntervalCurve::ClipPolygons;
 
54
        paintAttributes |= QwtPlotIntervalCurve::ClipSymbol;
 
55
    
 
56
        pen.setCapStyle( Qt::FlatCap );
 
57
    }
 
58
 
 
59
    ~PrivateData()
 
60
    {
 
61
        delete symbol;
 
62
    }
 
63
 
 
64
    CurveStyle style;
 
65
    const QwtIntervalSymbol *symbol;
 
66
 
 
67
    QPen pen;
 
68
    QBrush brush;
 
69
 
 
70
    QwtPlotIntervalCurve::PaintAttributes paintAttributes;
 
71
};
 
72
 
 
73
/*!
 
74
  Constructor
 
75
  \param title Title of the curve
 
76
*/
 
77
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText &title ):
 
78
    QwtPlotSeriesItem<QwtIntervalSample>( title )
 
79
{
 
80
    init();
 
81
}
 
82
 
 
83
/*!
 
84
  Constructor
 
85
  \param title Title of the curve
 
86
*/
 
87
QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString &title ):
 
88
    QwtPlotSeriesItem<QwtIntervalSample>( QwtText( title ) )
 
89
{
 
90
    init();
 
91
}
 
92
 
 
93
//! Destructor
 
94
QwtPlotIntervalCurve::~QwtPlotIntervalCurve()
 
95
{
 
96
    delete d_data;
 
97
}
 
98
 
 
99
//! Initialize internal members
 
100
void QwtPlotIntervalCurve::init()
 
101
{
 
102
    setItemAttribute( QwtPlotItem::Legend, true );
 
103
    setItemAttribute( QwtPlotItem::AutoScale, true );
 
104
 
 
105
    d_data = new PrivateData;
 
106
    d_series = new QwtIntervalSeriesData();
 
107
 
 
108
    setZ( 19.0 );
 
109
}
 
110
 
 
111
//! \return QwtPlotItem::Rtti_PlotIntervalCurve
 
112
int QwtPlotIntervalCurve::rtti() const
 
113
{
 
114
    return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve;
 
115
}
 
116
 
 
117
/*!
 
118
  Specify an attribute how to draw the curve
 
119
 
 
120
  \param attribute Paint attribute
 
121
  \param on On/Off
 
122
  \sa testPaintAttribute()
 
123
*/
 
124
void QwtPlotIntervalCurve::setPaintAttribute( 
 
125
    PaintAttribute attribute, bool on )
 
126
{
 
127
    if ( on )
 
128
        d_data->paintAttributes |= attribute;
 
129
    else
 
130
        d_data->paintAttributes &= ~attribute;
 
131
}
 
132
 
 
133
/*!
 
134
    \brief Return the current paint attributes
 
135
    \sa PaintAttribute, setPaintAttribute()
 
136
*/
 
137
bool QwtPlotIntervalCurve::testPaintAttribute( 
 
138
    PaintAttribute attribute ) const
 
139
{
 
140
    return ( d_data->paintAttributes & attribute );
 
141
}
 
142
 
 
143
/*!
 
144
  Initialize data with an array of samples.
 
145
  \param samples Vector of samples
 
146
*/
 
147
void QwtPlotIntervalCurve::setSamples(
 
148
    const QVector<QwtIntervalSample> &samples )
 
149
{
 
150
    delete d_series;
 
151
    d_series = new QwtIntervalSeriesData( samples );
 
152
    itemChanged();
 
153
}
 
154
 
 
155
/*!
 
156
  Set the curve's drawing style
 
157
 
 
158
  \param style Curve style
 
159
  \sa CurveStyle, style()
 
160
*/
 
161
void QwtPlotIntervalCurve::setStyle( CurveStyle style )
 
162
{
 
163
    if ( style != d_data->style )
 
164
    {
 
165
        d_data->style = style;
 
166
        itemChanged();
 
167
    }
 
168
}
 
169
 
 
170
/*!
 
171
    \brief Return the current style
 
172
    \sa setStyle()
 
173
*/
 
174
QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const
 
175
{
 
176
    return d_data->style;
 
177
}
 
178
 
 
179
/*!
 
180
  Assign a symbol.
 
181
 
 
182
  \param symbol Symbol
 
183
  \sa symbol()
 
184
*/
 
185
void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol *symbol )
 
186
{
 
187
    if ( symbol != d_data->symbol )
 
188
    {
 
189
        delete d_data->symbol;
 
190
        d_data->symbol = symbol;
 
191
        itemChanged();
 
192
    }
 
193
}
 
194
 
 
195
/*!
 
196
  \return Current symbol or NULL, when no symbol has been assigned
 
197
  \sa setSymbol()
 
198
*/
 
199
const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const
 
200
{
 
201
    return d_data->symbol;
 
202
}
 
203
 
 
204
/*!
 
205
  \brief Assign a pen
 
206
  \param pen New pen
 
207
  \sa pen(), brush()
 
208
*/
 
209
void QwtPlotIntervalCurve::setPen( const QPen &pen )
 
210
{
 
211
    if ( pen != d_data->pen )
 
212
    {
 
213
        d_data->pen = pen;
 
214
        itemChanged();
 
215
    }
 
216
}
 
217
 
 
218
/*!
 
219
    \brief Return the pen used to draw the lines
 
220
    \sa setPen(), brush()
 
221
*/
 
222
const QPen& QwtPlotIntervalCurve::pen() const
 
223
{
 
224
    return d_data->pen;
 
225
}
 
226
 
 
227
/*!
 
228
  Assign a brush.
 
229
 
 
230
  The brush is used to fill the area in Tube style().
 
231
 
 
232
  \param brush Brush
 
233
  \sa brush(), pen(), setStyle(), CurveStyle
 
234
*/
 
235
void QwtPlotIntervalCurve::setBrush( const QBrush &brush )
 
236
{
 
237
    if ( brush != d_data->brush )
 
238
    {
 
239
        d_data->brush = brush;
 
240
        itemChanged();
 
241
    }
 
242
}
 
243
 
 
244
/*!
 
245
  \return Brush used to fill the area in Tube style()
 
246
  \sa setBrush(), setStyle(), CurveStyle
 
247
*/
 
248
const QBrush& QwtPlotIntervalCurve::brush() const
 
249
{
 
250
    return d_data->brush;
 
251
}
 
252
 
 
253
/*!
 
254
  \return Bounding rectangle of all samples.
 
255
  For an empty series the rectangle is invalid.
 
256
*/
 
257
QRectF QwtPlotIntervalCurve::boundingRect() const
 
258
{
 
259
    QRectF rect = QwtPlotSeriesItem<QwtIntervalSample>::boundingRect();
 
260
    if ( rect.isValid() && orientation() == Qt::Vertical )
 
261
        rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
 
262
 
 
263
    return rect;
 
264
}
 
265
 
 
266
/*!
 
267
  Draw a subset of the samples
 
268
 
 
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.
 
276
 
 
277
  \sa drawTube(), drawSymbols()
 
278
*/
 
279
void QwtPlotIntervalCurve::drawSeries( QPainter *painter,
 
280
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
 
281
    const QRectF &canvasRect, int from, int to ) const
 
282
{
 
283
    if ( to < 0 )
 
284
        to = dataSize() - 1;
 
285
 
 
286
    if ( from < 0 )
 
287
        from = 0;
 
288
 
 
289
    if ( from > to )
 
290
        return;
 
291
 
 
292
    switch ( d_data->style )
 
293
    {
 
294
        case Tube:
 
295
            drawTube( painter, xMap, yMap, canvasRect, from, to );
 
296
            break;
 
297
 
 
298
        case NoCurve:
 
299
        default:
 
300
            break;
 
301
    }
 
302
 
 
303
    if ( d_data->symbol &&
 
304
        ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
 
305
    {
 
306
        drawSymbols( painter, *d_data->symbol, 
 
307
            xMap, yMap, canvasRect, from, to );
 
308
    }
 
309
}
 
310
 
 
311
/*!
 
312
  Draw a tube
 
313
 
 
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().
 
317
 
 
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.
 
325
 
 
326
  \sa drawSeries(), drawSymbols()
 
327
*/
 
328
void QwtPlotIntervalCurve::drawTube( QPainter *painter,
 
329
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
 
330
    const QRectF &canvasRect, int from, int to ) const
 
331
{
 
332
    const bool doAlign = QwtPainter::roundingAlignment( painter );
 
333
 
 
334
    painter->save();
 
335
 
 
336
    const size_t size = to - from + 1;
 
337
    QPolygonF polygon( 2 * size );
 
338
    QPointF *points = polygon.data();
 
339
 
 
340
    for ( uint i = 0; i < size; i++ )
 
341
    {
 
342
        QPointF &minValue = points[i];
 
343
        QPointF &maxValue = points[2 * size - 1 - i];
 
344
 
 
345
        const QwtIntervalSample intervalSample = sample( from + i );
 
346
        if ( orientation() == Qt::Vertical )
 
347
        {
 
348
            double x = xMap.transform( intervalSample.value );
 
349
            double y1 = yMap.transform( intervalSample.interval.minValue() );
 
350
            double y2 = yMap.transform( intervalSample.interval.maxValue() );
 
351
            if ( doAlign )
 
352
            {
 
353
                x = qRound( x );
 
354
                y1 = qRound( y1 );
 
355
                y2 = qRound( y2 );
 
356
            }
 
357
 
 
358
            minValue.rx() = x;
 
359
            minValue.ry() = y1;
 
360
            maxValue.rx() = x;
 
361
            maxValue.ry() = y2;
 
362
        }
 
363
        else
 
364
        {
 
365
            double y = yMap.transform( intervalSample.value );
 
366
            double x1 = xMap.transform( intervalSample.interval.minValue() );
 
367
            double x2 = xMap.transform( intervalSample.interval.maxValue() );
 
368
            if ( doAlign )
 
369
            {
 
370
                y = qRound( y );
 
371
                x1 = qRound( x1 );
 
372
                x2 = qRound( x2 );
 
373
            }
 
374
 
 
375
            minValue.rx() = x1;
 
376
            minValue.ry() = y;
 
377
            maxValue.rx() = x2;
 
378
            maxValue.ry() = y;
 
379
        }
 
380
    }
 
381
 
 
382
    if ( d_data->brush.style() != Qt::NoBrush )
 
383
    {
 
384
        painter->setPen( QPen( Qt::NoPen ) );
 
385
        painter->setBrush( d_data->brush );
 
386
 
 
387
        if ( d_data->paintAttributes & ClipPolygons )
 
388
        {
 
389
            const qreal m = 1.0;
 
390
            const QPolygonF p = QwtClipper::clipPolygonF( 
 
391
                canvasRect.adjusted(-m, -m, m, m), polygon, true );
 
392
 
 
393
            QwtPainter::drawPolygon( painter, p );
 
394
        }
 
395
        else
 
396
        {
 
397
            QwtPainter::drawPolygon( painter, polygon );
 
398
        }
 
399
    }
 
400
 
 
401
    if ( d_data->pen.style() != Qt::NoPen )
 
402
    {
 
403
        painter->setPen( d_data->pen );
 
404
        painter->setBrush( Qt::NoBrush );
 
405
 
 
406
        if ( d_data->paintAttributes & ClipPolygons )
 
407
        {
 
408
            qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
 
409
            const QRectF clipRect = canvasRect.adjusted(-pw, -pw, pw, pw);
 
410
 
 
411
            QPolygonF p;
 
412
 
 
413
            p.resize( size );
 
414
            qMemCopy( p.data(), points, size * sizeof( QPointF ) );
 
415
            p = QwtClipper::clipPolygonF( canvasRect, p );
 
416
            QwtPainter::drawPolyline( painter, p );
 
417
 
 
418
            p.resize( size );
 
419
            qMemCopy( p.data(), points + size, size * sizeof( QPointF ) );
 
420
            p = QwtClipper::clipPolygonF( canvasRect, p );
 
421
            QwtPainter::drawPolyline( painter, p );
 
422
        }
 
423
        else
 
424
        {
 
425
            QwtPainter::drawPolyline( painter, points, size );
 
426
            QwtPainter::drawPolyline( painter, points + size, size );
 
427
        }
 
428
    }
 
429
 
 
430
    painter->restore();
 
431
}
 
432
 
 
433
/*!
 
434
  Draw symbols for a subset of the samples
 
435
 
 
436
  \param painter Painter
 
437
  \param symbol Interval symbol
 
438
  \param xMap x map
 
439
  \param yMap y map
 
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
 
443
 
 
444
  \sa setSymbol(), drawSeries(), drawTube()
 
445
*/
 
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
 
450
{
 
451
    painter->save();
 
452
 
 
453
    QPen pen = symbol.pen();
 
454
    pen.setCapStyle( Qt::FlatCap );
 
455
 
 
456
    painter->setPen( pen );
 
457
    painter->setBrush( symbol.brush() );
 
458
 
 
459
    const QRectF &tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect);
 
460
 
 
461
    const double xMin = tr.left();
 
462
    const double xMax = tr.right();
 
463
    const double yMin = tr.top();
 
464
    const double yMax = tr.bottom();
 
465
 
 
466
    const bool doClip = d_data->paintAttributes & ClipPolygons;
 
467
 
 
468
    for ( int i = from; i <= to; i++ )
 
469
    {
 
470
        const QwtIntervalSample s = sample( i );
 
471
 
 
472
        if ( orientation() == Qt::Vertical )
 
473
        {
 
474
            if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) )
 
475
            {
 
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() );
 
479
 
 
480
                symbol.draw( painter, orientation(),
 
481
                    QPointF( x, y1 ), QPointF( x, y2 ) );
 
482
            }
 
483
        }
 
484
        else
 
485
        {
 
486
            if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) )
 
487
            {
 
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() );
 
491
 
 
492
                symbol.draw( painter, orientation(),
 
493
                    QPointF( x1, y ), QPointF( x2, y ) );
 
494
            }
 
495
        }
 
496
    }
 
497
 
 
498
    painter->restore();
 
499
}
 
500
 
 
501
/*!
 
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.
 
504
 
 
505
  \param painter Painter
 
506
  \param rect Bounding rectangle for the identifier
 
507
*/
 
508
 
 
509
void QwtPlotIntervalCurve::drawLegendIdentifier(
 
510
    QPainter *painter, const QRectF &rect ) const
 
511
{
 
512
    const double dim = qMin( rect.width(), rect.height() );
 
513
 
 
514
    QSizeF size( dim, dim );
 
515
 
 
516
    QRectF r( 0, 0, size.width(), size.height() );
 
517
    r.moveCenter( rect.center() );
 
518
 
 
519
    if ( d_data->style == Tube )
 
520
    {
 
521
        painter->fillRect( r, d_data->brush );
 
522
    }
 
523
 
 
524
    if ( d_data->symbol &&
 
525
        ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
 
526
    {
 
527
        QPen pen = d_data->symbol->pen();
 
528
        pen.setWidthF( pen.widthF() );
 
529
        pen.setCapStyle( Qt::FlatCap );
 
530
 
 
531
        painter->setPen( pen );
 
532
        painter->setBrush( d_data->symbol->brush() );
 
533
 
 
534
        if ( orientation() == Qt::Vertical )
 
535
        {
 
536
            d_data->symbol->draw( painter, orientation(),
 
537
                QPointF( r.center().x(), r.top() ),
 
538
                QPointF( r.center().x(), r.bottom() - 1 ) );
 
539
        }
 
540
        else
 
541
        {
 
542
            d_data->symbol->draw( painter, orientation(),
 
543
                QPointF( r.left(), r.center().y() ),
 
544
                QPointF( r.right() - 1, r.center().y() ) );
 
545
        }
 
546
    }
 
547
}