qwt_plot_curve.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include <qpainter.h>
00011 #include <qpixmap.h>
00012 #include <qbitarray.h>
00013 #include "qwt_global.h"
00014 #include "qwt_legend.h"
00015 #include "qwt_legend_item.h"
00016 #include "qwt_data.h"
00017 #include "qwt_rect.h"
00018 #include "qwt_scale_map.h"
00019 #include "qwt_double_rect.h"
00020 #include "qwt_math.h"
00021 #include "qwt_painter.h"
00022 #include "qwt_plot.h"
00023 #include "qwt_plot_canvas.h"
00024 #include "qwt_curve_fitter.h"
00025 #include "qwt_symbol.h"
00026 #include "qwt_plot_curve.h"
00027 
00028 #if QT_VERSION >= 0x040000
00029 
00030 #include <qevent.h>
00031 
00032 class QwtPlotCurvePaintHelper: public QObject
00033 {
00034 public:
00035     QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00036         _curve(curve),
00037         _from(from),
00038         _to(to)
00039     {
00040     }
00041 
00042     virtual bool eventFilter(QObject *, QEvent *event)
00043     {
00044         if ( event->type() == QEvent::Paint )
00045         {
00046             _curve->draw(_from, _to);
00047             return true;
00048         }
00049         return false;
00050     }
00051 private:
00052     const QwtPlotCurve *_curve;
00053     int _from;
00054     int _to;
00055 };
00056 
00057 #endif // QT_VERSION >= 0x040000
00058 
00059 static int verifyRange(int size, int &i1, int &i2)
00060 {
00061     if (size < 1) 
00062         return 0;
00063 
00064     i1 = qwtLim(i1, 0, size-1);
00065     i2 = qwtLim(i2, 0, size-1);
00066 
00067     if ( i1 > i2 )
00068         qSwap(i1, i2);
00069 
00070     return (i2 - i1 + 1);
00071 }
00072 
00073 class QwtPlotCurve::PrivateData
00074 {
00075 public:
00076     class PixelMatrix: private QBitArray
00077     {
00078     public:
00079         PixelMatrix(const QRect& rect):
00080             QBitArray(rect.width() * rect.height()),
00081             _rect(rect)
00082         {
00083             fill(false);
00084         }
00085 
00086         inline bool testPixel(const QPoint& pos)
00087         {
00088             if ( !_rect.contains(pos) )
00089                 return false;
00090 
00091             const int idx = _rect.width() * (pos.y() - _rect.y()) + 
00092                 (pos.x() - _rect.x());
00093 
00094             const bool marked = testBit(idx);
00095             if ( !marked )
00096                 setBit(idx, true);
00097 
00098             return !marked;
00099         }
00100 
00101     private:
00102         QRect _rect;
00103     };
00104 
00105     PrivateData():
00106         curveType(Yfx),
00107         style(QwtPlotCurve::Lines),
00108         reference(0.0),
00109         attributes(0),
00110         paintAttributes(0)
00111     {
00112         pen = QPen(Qt::black, 0);
00113         curveFitter = new QwtSplineCurveFitter;
00114     }
00115 
00116     ~PrivateData()
00117     {
00118         delete curveFitter;
00119     }
00120 
00121     QwtPlotCurve::CurveType curveType;
00122     QwtPlotCurve::CurveStyle style;
00123     double reference;
00124 
00125     QwtSymbol sym;
00126     QwtCurveFitter *curveFitter;
00127 
00128     QPen pen;
00129     QBrush brush;
00130 
00131     int attributes;
00132     int paintAttributes;
00133 };
00134 
00138 QwtPlotCurve::QwtPlotCurve():
00139     QwtPlotItem(QwtText())
00140 {
00141     init();
00142 }
00143 
00148 QwtPlotCurve::QwtPlotCurve(const QwtText &title):
00149     QwtPlotItem(title)
00150 {
00151     init();
00152 }
00153 
00158 QwtPlotCurve::QwtPlotCurve(const QString &title):
00159     QwtPlotItem(QwtText(title))
00160 {
00161     init();
00162 }
00163 
00165 QwtPlotCurve::~QwtPlotCurve()
00166 {
00167     delete d_xy;
00168     delete d_data;
00169 }
00170 
00174 void QwtPlotCurve::init()
00175 {
00176     setItemAttribute(QwtPlotItem::Legend);
00177     setItemAttribute(QwtPlotItem::AutoScale);
00178 
00179     d_data = new PrivateData;
00180     d_xy = new QwtPolygonFData(QwtArray<QwtDoublePoint>());
00181 
00182     setZ(20.0);
00183 }
00184 
00185 int QwtPlotCurve::rtti() const
00186 {
00187     return QwtPlotItem::Rtti_PlotCurve;
00188 }
00189 
00211 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00212 {
00213     if ( on )
00214         d_data->paintAttributes |= attribute;
00215     else
00216         d_data->paintAttributes &= ~attribute;
00217 }
00218 
00223 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00224 {
00225     return (d_data->paintAttributes & attribute);
00226 }
00227 
00255 void QwtPlotCurve::setStyle(CurveStyle style)
00256 {
00257     if ( style != d_data->style )
00258     {
00259         d_data->style = style;
00260         itemChanged();
00261     }
00262 }
00263 
00268 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const 
00269 { 
00270     return d_data->style; 
00271 }
00272 
00278 void QwtPlotCurve::setSymbol(const QwtSymbol &s )
00279 {
00280     d_data->sym = s;
00281     itemChanged();
00282 }
00283 
00288 const QwtSymbol &QwtPlotCurve::symbol() const 
00289 { 
00290     return d_data->sym; 
00291 }
00292 
00298 void QwtPlotCurve::setPen(const QPen &p)
00299 {
00300     if ( p != d_data->pen )
00301     {
00302         d_data->pen = p;
00303         itemChanged();
00304     }
00305 }
00306 
00311 const QPen& QwtPlotCurve::pen() const 
00312 { 
00313     return d_data->pen; 
00314 }
00315 
00328 void QwtPlotCurve::setBrush(const QBrush &brush)
00329 {
00330     if ( brush != d_data->brush )
00331     {
00332         d_data->brush = brush;
00333         itemChanged();
00334     }
00335 }
00336 
00341 const QBrush& QwtPlotCurve::brush() const 
00342 {
00343     return d_data->brush;
00344 }
00345 
00346 
00358 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00359 {
00360     delete d_xy;
00361     d_xy = new QwtArrayData(xData, yData, size);
00362     itemChanged();
00363 }
00364 
00373 void QwtPlotCurve::setData(const QwtArray<double> &xData, 
00374     const QwtArray<double> &yData)
00375 {
00376     delete d_xy;
00377     d_xy = new QwtArrayData(xData, yData);
00378     itemChanged();
00379 }
00380 
00387 #if QT_VERSION < 0x040000
00388 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00389 #else
00390 void QwtPlotCurve::setData(const QPolygonF &data)
00391 #endif
00392 {
00393     delete d_xy;
00394     d_xy = new QwtPolygonFData(data);
00395     itemChanged();
00396 }
00397 
00404 void QwtPlotCurve::setData(const QwtData &data)
00405 {
00406     delete d_xy;
00407     d_xy = data.copy();
00408     itemChanged();
00409 }
00410 
00424 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00425 {
00426     delete d_xy;
00427     d_xy = new QwtCPointerData(xData, yData, size);
00428     itemChanged();
00429 }
00430 
00437 QwtDoubleRect QwtPlotCurve::boundingRect() const
00438 {
00439     if ( d_xy == NULL )
00440         return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid
00441 
00442     return d_xy->boundingRect();
00443 }
00444 
00454 void QwtPlotCurve::draw(QPainter *painter,
00455     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00456     const QRect &) const
00457 {
00458     draw(painter, xMap, yMap, 0, -1);
00459 }
00460 
00478 void QwtPlotCurve::draw(int from, int to) const
00479 {
00480     if ( !plot() )
00481         return;
00482 
00483     QwtPlotCanvas *canvas = plot()->canvas();
00484 
00485     bool directPaint = true;
00486 
00487 #if QT_VERSION >= 0x040000
00488     if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00489         !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00490     {
00491         /*
00492           We save curve and range in helper and call repaint.
00493           The helper filters the Paint event, to repeat
00494           the QwtPlotCurve::draw, but now from inside the paint
00495           event.
00496          */
00497 
00498         QwtPlotCurvePaintHelper helper(this, from, to);
00499         canvas->installEventFilter(&helper);
00500         canvas->repaint();
00501 
00502         return;
00503     }
00504 #endif
00505 
00506     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00507     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00508 
00509     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00510         canvas->paintCache() && !canvas->paintCache()->isNull() )
00511     {
00512         QPainter cachePainter((QPixmap *)canvas->paintCache());
00513         cachePainter.translate(-canvas->contentsRect().x(),
00514             -canvas->contentsRect().y());
00515 
00516         draw(&cachePainter, xMap, yMap, from, to);
00517     }
00518 
00519     if ( directPaint )
00520     {
00521         QPainter painter(canvas);
00522 
00523         painter.setClipping(true);
00524         painter.setClipRect(canvas->contentsRect());
00525 
00526         draw(&painter, xMap, yMap, from, to);
00527 
00528         return;
00529     }
00530 
00531 #if QT_VERSION >= 0x040000
00532     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00533         canvas->paintCache() )
00534     {
00535         /*
00536           The cache is up to date. We flush it via repaint to the
00537           canvas. This works flicker free but is much ( > 10x )
00538           slower than direct painting.
00539          */
00540 
00541         const bool noBG = canvas->testAttribute(Qt::WA_NoBackground);
00542         if ( !noBG )
00543             canvas->setAttribute(Qt::WA_NoBackground, true);
00544 
00545         canvas->repaint(canvas->contentsRect());
00546 
00547         if ( !noBG )
00548             canvas->setAttribute(Qt::WA_NoBackground, false);
00549 
00550         return;
00551     }
00552 #endif
00553 
00554     // Ok, we give up 
00555     canvas->repaint(canvas->contentsRect());
00556 }
00557 
00569 void QwtPlotCurve::draw(QPainter *painter,
00570     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00571     int from, int to) const
00572 {
00573     if ( !painter || dataSize() <= 0 )
00574         return;
00575 
00576     if (to < 0)
00577         to = dataSize() - 1;
00578 
00579     if ( verifyRange(dataSize(), from, to) > 0 )
00580     {
00581         painter->save();
00582         painter->setPen(d_data->pen);
00583 
00584         /*
00585           Qt 4.0.0 is slow when drawing lines, but it´s even 
00586           slower when the painter has a brush. So we don't
00587           set the brush before we really need it.
00588          */
00589 
00590         drawCurve(painter, d_data->style, xMap, yMap, from, to);
00591         painter->restore();
00592 
00593         if (d_data->sym.style() != QwtSymbol::NoSymbol)
00594         {
00595             painter->save();
00596             drawSymbols(painter, d_data->sym, xMap, yMap, from, to);
00597             painter->restore();
00598         }
00599     }
00600 }
00601 
00613 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00614     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00615     int from, int to) const
00616 {
00617     switch (style)
00618     {
00619         case Lines:
00620             if ( testCurveAttribute(Fitted) )
00621             {
00622                 // we always need the complete 
00623                 // curve for fitting
00624                 from = 0;
00625                 to = dataSize() - 1;
00626             }
00627             drawLines(painter, xMap, yMap, from, to);
00628             break;
00629         case Sticks:
00630             drawSticks(painter, xMap, yMap, from, to);
00631             break;
00632         case Steps:
00633             drawSteps(painter, xMap, yMap, from, to);
00634             break;
00635         case Dots:
00636             drawDots(painter, xMap, yMap, from, to);
00637             break;
00638         case NoCurve:
00639         default:
00640             break;
00641     }
00642 }
00643 
00659 void QwtPlotCurve::drawLines(QPainter *painter,
00660     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00661     int from, int to) const
00662 {
00663     int size = to - from + 1;
00664     if ( size <= 0 )
00665         return;
00666 
00667     QwtPolygon polyline;
00668     if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00669     {
00670         // Transform x and y values to window coordinates
00671         // to avoid a distinction between linear and
00672         // logarithmic scales.
00673 
00674 #if QT_VERSION < 0x040000
00675         QwtArray<QwtDoublePoint> points(size);
00676 #else
00677         QPolygonF points(size);
00678 #endif
00679         for (int i = from; i <= to; i++)
00680         {
00681             QwtDoublePoint &p = points[i];
00682             p.setX( xMap.xTransform(x(i)) );
00683             p.setY( yMap.xTransform(y(i)) );
00684         }
00685 
00686         points = d_data->curveFitter->fitCurve(points);
00687         size = points.size();
00688 
00689         if ( size == 0 )
00690             return;
00691 
00692         // Round QwtDoublePoints to QPoints
00693         // When Qwt support for Qt3 has been dropped (Qwt 6.x)
00694         // we will use a doubles for painting and the following
00695         // step will be obsolete.
00696 
00697         polyline.resize(size);
00698 
00699         const QwtDoublePoint *p = points.data();
00700         QPoint *pl = polyline.data();
00701         if ( d_data->paintAttributes & PaintFiltered )
00702         {
00703 
00704             QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00705             pl[0] = pp;
00706 
00707             int count = 1;
00708             for (int i = 1; i < size; i++)
00709             {
00710                 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00711                 if ( pi != pp )
00712                 {
00713                     pl[count++] = pi;
00714                     pp = pi;
00715                 }
00716             }
00717             if ( count != size )
00718                 polyline.resize(count);
00719         }
00720         else
00721         {
00722             for ( int i = 0; i < size; i++ )
00723             {
00724                 pl[i].setX( qRound(p[i].x()) );
00725                 pl[i].setY( qRound(p[i].y()) );
00726             }
00727         }
00728     }
00729     else
00730     {
00731         polyline.resize(size);
00732 
00733         if ( d_data->paintAttributes & PaintFiltered )
00734         {
00735             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00736             polyline.setPoint(0, pp);
00737 
00738             int count = 1;
00739             for (int i = from + 1; i <= to; i++)
00740             {
00741                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00742                 if ( pi != pp )
00743                 {
00744                     polyline.setPoint(count, pi);
00745                     count++;
00746 
00747                     pp = pi;
00748                 }
00749             }
00750             if ( count != size )
00751                 polyline.resize(count);
00752         }
00753         else
00754         {
00755             for (int i = from; i <= to; i++)
00756             {
00757                 int xi = xMap.transform(x(i));
00758                 int yi = yMap.transform(y(i));
00759 
00760                 polyline.setPoint(i - from, xi, yi);
00761             }
00762         }
00763     }
00764 
00765     if ( d_data->paintAttributes & ClipPolygons )
00766     {
00767         QwtRect r = painter->window();
00768         polyline = r.clip(polyline);
00769     }
00770 
00771     QwtPainter::drawPolyline(painter, polyline);
00772 
00773     if ( d_data->brush.style() != Qt::NoBrush )
00774         fillCurve(painter, xMap, yMap, polyline);
00775 }
00776 
00788 void QwtPlotCurve::drawSticks(QPainter *painter,
00789     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00790     int from, int to) const
00791 {
00792     int x0 = xMap.transform(d_data->reference);
00793     int y0 = yMap.transform(d_data->reference);
00794 
00795     for (int i = from; i <= to; i++)
00796     {
00797         const int xi = xMap.transform(x(i));
00798         const int yi = yMap.transform(y(i));
00799 
00800         if (d_data->attributes & Xfy)
00801             QwtPainter::drawLine(painter, x0, yi, xi, yi);
00802         else
00803             QwtPainter::drawLine(painter, xi, y0, xi, yi);
00804     }
00805 }
00806 
00818 void QwtPlotCurve::drawDots(QPainter *painter,
00819     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00820     int from, int to) const
00821 {
00822     const QRect window = painter->window();
00823     if ( window.isEmpty() )
00824         return;
00825 
00826     const bool doFill = d_data->brush.style() != Qt::NoBrush;
00827 
00828     QwtPolygon polyline;
00829     if ( doFill )
00830         polyline.resize(to - from + 1);
00831 
00832     if ( to > from && d_data->paintAttributes & PaintFiltered )
00833     {
00834         if ( doFill )   
00835         {
00836             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00837 
00838             QwtPainter::drawPoint(painter, pp.x(), pp.y());
00839             polyline.setPoint(0, pp);
00840 
00841             int count = 1;
00842             for (int i = from + 1; i <= to; i++)
00843             {
00844                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00845                 if ( pi != pp )
00846                 {
00847                     QwtPainter::drawPoint(painter, pi.x(), pi.y());
00848 
00849                     polyline.setPoint(count, pi);
00850                     count++;
00851 
00852                     pp = pi;
00853                 }
00854             }
00855             if ( int(polyline.size()) != count )
00856                 polyline.resize(count);
00857         }
00858         else
00859         {
00860             // if we don't need to fill, we can sort out
00861             // duplicates independent from the order
00862 
00863             PrivateData::PixelMatrix pixelMatrix(window);
00864 
00865             for (int i = from; i <= to; i++)
00866             {
00867                 const QPoint p( xMap.transform(x(i)),
00868                     yMap.transform(y(i)) );
00869 
00870                 if ( pixelMatrix.testPixel(p) )
00871                     QwtPainter::drawPoint(painter, p.x(), p.y());
00872             }
00873         }
00874     }
00875     else
00876     {
00877         for (int i = from; i <= to; i++)
00878         {
00879             const int xi = xMap.transform(x(i));
00880             const int yi = yMap.transform(y(i));
00881             QwtPainter::drawPoint(painter, xi, yi);
00882 
00883             if ( doFill )
00884                 polyline.setPoint(i - from, xi, yi);
00885         }
00886     }
00887 
00888     if ( doFill )
00889     {
00890         if ( d_data->paintAttributes & ClipPolygons )
00891         {
00892             const QwtRect r = painter->window();
00893             polyline = r.clip(polyline);
00894         }
00895 
00896         fillCurve(painter, xMap, yMap, polyline);
00897     }
00898 }
00899 
00914 void QwtPlotCurve::drawSteps(QPainter *painter,
00915     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00916     int from, int to) const
00917 {
00918     QwtPolygon polyline(2 * (to - from) + 1);
00919 
00920     bool inverted = d_data->attributes & Yfx;
00921     if ( d_data->attributes & Inverted )
00922         inverted = !inverted;
00923 
00924     int i,ip;
00925     for (i = from, ip = 0; i <= to; i++, ip += 2)
00926     {
00927         const int xi = xMap.transform(x(i));
00928         const int yi = yMap.transform(y(i));
00929 
00930         if ( ip > 0 )
00931         {
00932             if (inverted)
00933                 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00934             else
00935                 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00936         }
00937 
00938         polyline.setPoint(ip, xi, yi);
00939     }
00940 
00941     if ( d_data->paintAttributes & ClipPolygons )
00942     {
00943         const QwtRect r = painter->window();
00944         polyline = r.clip(polyline);
00945     }
00946 
00947     QwtPainter::drawPolyline(painter, polyline);
00948 
00949     if ( d_data->brush.style() != Qt::NoBrush )
00950         fillCurve(painter, xMap, yMap, polyline);
00951 }
00952 
00953 
00976 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
00977 {
00978     if ( bool(d_data->attributes & attribute) == on )
00979         return;
00980 
00981     if ( on )
00982         d_data->attributes |= attribute;
00983     else
00984         d_data->attributes &= ~attribute;
00985 
00986     itemChanged();
00987 }
00988 
00993 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const 
00994 { 
00995     return d_data->attributes & attribute;
00996 }
00997 
01014 void QwtPlotCurve::setCurveType(CurveType curveType)
01015 {
01016     if ( d_data->curveType != curveType )
01017     {
01018         d_data->curveType = curveType;
01019         itemChanged();
01020     }
01021 }
01022 
01027 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01028 {
01029     return d_data->curveType;
01030 }
01031 
01032 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01033 {
01034     delete d_data->curveFitter;
01035     d_data->curveFitter = curveFitter;
01036 
01037     itemChanged();
01038 }
01039 
01040 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01041 {
01042     return d_data->curveFitter;
01043 }
01044 
01057 void QwtPlotCurve::fillCurve(QPainter *painter,
01058     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01059     QwtPolygon &pa) const
01060 {
01061     if ( d_data->brush.style() == Qt::NoBrush )
01062         return;
01063 
01064     closePolyline(xMap, yMap, pa);
01065     if ( pa.count() <= 2 ) // a line can't be filled
01066         return;
01067 
01068     QBrush b = d_data->brush;
01069     if ( !b.color().isValid() )
01070         b.setColor(d_data->pen.color());
01071 
01072     painter->save();
01073 
01074     painter->setPen(QPen(Qt::NoPen));
01075     painter->setBrush(b);
01076 
01077     QwtPainter::drawPolygon(painter, pa);
01078 
01079     painter->restore();
01080 }
01081 
01091 void QwtPlotCurve::closePolyline(
01092     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01093     QwtPolygon &pa) const
01094 {
01095     const int sz = pa.size();
01096     if ( sz < 2 )
01097         return;
01098 
01099     pa.resize(sz + 2);
01100 
01101     if ( d_data->attributes & QwtPlotCurve::Xfy )
01102     {
01103         pa.setPoint(sz,
01104             xMap.transform(d_data->reference), pa.point(sz - 1).y());
01105         pa.setPoint(sz + 1,
01106             xMap.transform(d_data->reference), pa.point(0).y());
01107     }
01108     else
01109     {
01110         pa.setPoint(sz,
01111             pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01112         pa.setPoint(pa.size() - 1,
01113             pa.point(0).x(), yMap.transform(d_data->reference));
01114     }
01115 }
01116 
01128 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01129     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
01130     int from, int to) const
01131 {
01132     painter->setBrush(symbol.brush());
01133     painter->setPen(symbol.pen());
01134 
01135     QRect rect;
01136     rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01137 
01138     if ( to > from && d_data->paintAttributes & PaintFiltered )
01139     {
01140         const QRect window = painter->window();
01141         if ( window.isEmpty() )
01142             return;
01143 
01144         PrivateData::PixelMatrix pixelMatrix(window);
01145 
01146         for (int i = from; i <= to; i++)
01147         {
01148             const QPoint pi( xMap.transform(x(i)),
01149                 yMap.transform(y(i)) );
01150 
01151             if ( pixelMatrix.testPixel(pi) )
01152             {
01153                 rect.moveCenter(pi);
01154                 symbol.draw(painter, rect);
01155             }
01156         }
01157     }
01158     else
01159     {
01160         for (int i = from; i <= to; i++)
01161         {
01162             const int xi = xMap.transform(x(i));
01163             const int yi = yMap.transform(y(i));
01164 
01165             rect.moveCenter(QPoint(xi, yi));
01166             symbol.draw(painter, rect);
01167         }
01168     }
01169 }
01170 
01184 void QwtPlotCurve::setBaseline(double reference)
01185 {
01186     if ( d_data->reference != reference )
01187     {
01188         d_data->reference = reference;
01189         itemChanged();
01190     }
01191 }
01192 
01197 double QwtPlotCurve::baseline() const 
01198 { 
01199     return d_data->reference; 
01200 }
01201 
01206 int QwtPlotCurve::dataSize() const
01207 {
01208     return d_xy->size();
01209 }
01210 
01211 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01212 {
01213     if ( plot() == NULL || dataSize() <= 0 )
01214         return -1;
01215 
01216     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01217     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01218 
01219     int index = -1;
01220     double dmin = 1.0e10;
01221 
01222     for (int i=0; i < dataSize(); i++)
01223     {
01224         const double cx = xMap.xTransform(x(i)) - pos.x();
01225         const double cy = yMap.xTransform(y(i)) - pos.y();
01226 
01227         const double f = qwtSqr(cx) + qwtSqr(cy);
01228         if (f < dmin)
01229         {
01230             index = i;
01231             dmin = f;
01232         }
01233     }
01234     if ( dist )
01235         *dist = sqrt(dmin);
01236 
01237     return index;
01238 }
01239 
01240 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01241 {
01242     if ( !legend )
01243         return;
01244 
01245     QwtPlotItem::updateLegend(legend);
01246 
01247     QWidget *widget = legend->find(this);
01248     if ( !widget || !widget->inherits("QwtLegendItem") )
01249         return;
01250 
01251     QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01252 
01253 #if QT_VERSION < 0x040000
01254     const bool doUpdate = legendItem->isUpdatesEnabled();
01255 #else
01256     const bool doUpdate = legendItem->updatesEnabled();
01257 #endif
01258     legendItem->setUpdatesEnabled(false);
01259 
01260     const int policy = legend->displayPolicy();
01261 
01262     if (policy == QwtLegend::FixedIdentifier)
01263     {
01264         int mode = legend->identifierMode();
01265 
01266         if (mode & QwtLegendItem::ShowLine)
01267             legendItem->setCurvePen(pen());
01268 
01269         if (mode & QwtLegendItem::ShowSymbol)
01270             legendItem->setSymbol(symbol());
01271 
01272         if (mode & QwtLegendItem::ShowText)
01273             legendItem->setText(title());
01274         else
01275             legendItem->setText(QwtText());
01276 
01277         legendItem->setIdentifierMode(mode);
01278     }
01279     else if (policy == QwtLegend::AutoIdentifier)
01280     {
01281         int mode = 0;
01282 
01283         if (QwtPlotCurve::NoCurve != style())
01284         {
01285             legendItem->setCurvePen(pen());
01286             mode |= QwtLegendItem::ShowLine;
01287         }
01288         if (QwtSymbol::NoSymbol != symbol().style())
01289         {
01290             legendItem->setSymbol(symbol());
01291             mode |= QwtLegendItem::ShowSymbol;
01292         }
01293         if ( !title().isEmpty() )
01294         {
01295             legendItem->setText(title());
01296             mode |= QwtLegendItem::ShowText;
01297         }
01298         else
01299         {
01300             legendItem->setText(QwtText());
01301         }
01302         legendItem->setIdentifierMode(mode);
01303     }
01304 
01305     legendItem->setUpdatesEnabled(doUpdate);
01306     legendItem->update();
01307 }

Generated on Mon Feb 26 21:22:37 2007 for Qwt User's Guide by  doxygen 1.4.6