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_scale_map.h"
00018 #include "qwt_double_rect.h"
00019 #include "qwt_math.h"
00020 #include "qwt_clipper.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 #include <qpaintengine.h>
00032 
00033 class QwtPlotCurvePaintHelper: public QObject
00034 {
00035 public:
00036     QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00037         _curve(curve),
00038         _from(from),
00039         _to(to)
00040     {
00041     }
00042 
00043     virtual bool eventFilter(QObject *, QEvent *event)
00044     {
00045         if ( event->type() == QEvent::Paint )
00046         {
00047             _curve->draw(_from, _to);
00048             return true;
00049         }
00050         return false;
00051     }
00052 private:
00053     const QwtPlotCurve *_curve;
00054     int _from;
00055     int _to;
00056 };
00057 
00058 #endif // QT_VERSION >= 0x040000
00059 
00060 static int verifyRange(int size, int &i1, int &i2)
00061 {
00062     if (size < 1) 
00063         return 0;
00064 
00065     i1 = qwtLim(i1, 0, size-1);
00066     i2 = qwtLim(i2, 0, size-1);
00067 
00068     if ( i1 > i2 )
00069         qSwap(i1, i2);
00070 
00071     return (i2 - i1 + 1);
00072 }
00073 
00074 class QwtPlotCurve::PrivateData
00075 {
00076 public:
00077     class PixelMatrix: private QBitArray
00078     {
00079     public:
00080         PixelMatrix(const QRect& rect):
00081             QBitArray(rect.width() * rect.height()),
00082             _rect(rect)
00083         {
00084             fill(false);
00085         }
00086 
00087         inline bool testPixel(const QPoint& pos)
00088         {
00089             if ( !_rect.contains(pos) )
00090                 return false;
00091 
00092             const int idx = _rect.width() * (pos.y() - _rect.y()) + 
00093                 (pos.x() - _rect.x());
00094 
00095             const bool marked = testBit(idx);
00096             if ( !marked )
00097                 setBit(idx, true);
00098 
00099             return !marked;
00100         }
00101 
00102     private:
00103         QRect _rect;
00104     };
00105 
00106     PrivateData():
00107         curveType(Yfx),
00108         style(QwtPlotCurve::Lines),
00109         reference(0.0),
00110         attributes(0),
00111         paintAttributes(0)
00112     {
00113         symbol = new QwtSymbol();
00114         pen = QPen(Qt::black);
00115         curveFitter = new QwtSplineCurveFitter;
00116     }
00117 
00118     ~PrivateData()
00119     {
00120         delete symbol;
00121         delete curveFitter;
00122     }
00123 
00124     QwtPlotCurve::CurveType curveType;
00125     QwtPlotCurve::CurveStyle style;
00126     double reference;
00127 
00128     QwtSymbol *symbol;
00129     QwtCurveFitter *curveFitter;
00130 
00131     QPen pen;
00132     QBrush brush;
00133 
00134     int attributes;
00135     int paintAttributes;
00136 };
00137 
00139 QwtPlotCurve::QwtPlotCurve():
00140     QwtPlotItem(QwtText())
00141 {
00142     init();
00143 }
00144 
00149 QwtPlotCurve::QwtPlotCurve(const QwtText &title):
00150     QwtPlotItem(title)
00151 {
00152     init();
00153 }
00154 
00159 QwtPlotCurve::QwtPlotCurve(const QString &title):
00160     QwtPlotItem(QwtText(title))
00161 {
00162     init();
00163 }
00164 
00166 QwtPlotCurve::~QwtPlotCurve()
00167 {
00168     delete d_xy;
00169     delete d_data;
00170 }
00171 
00175 void QwtPlotCurve::init()
00176 {
00177     setItemAttribute(QwtPlotItem::Legend);
00178     setItemAttribute(QwtPlotItem::AutoScale);
00179 
00180     d_data = new PrivateData;
00181     d_xy = new QwtPolygonFData(QwtArray<QwtDoublePoint>());
00182 
00183     setZ(20.0);
00184 }
00185 
00187 int QwtPlotCurve::rtti() const
00188 {
00189     return QwtPlotItem::Rtti_PlotCurve;
00190 }
00191 
00215 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00216 {
00217     if ( on )
00218         d_data->paintAttributes |= attribute;
00219     else
00220         d_data->paintAttributes &= ~attribute;
00221 }
00222 
00227 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00228 {
00229     return (d_data->paintAttributes & attribute);
00230 }
00231 
00259 void QwtPlotCurve::setStyle(CurveStyle style)
00260 {
00261     if ( style != d_data->style )
00262     {
00263         d_data->style = style;
00264         itemChanged();
00265     }
00266 }
00267 
00272 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const 
00273 { 
00274     return d_data->style; 
00275 }
00276 
00282 void QwtPlotCurve::setSymbol(const QwtSymbol &symbol )
00283 {
00284     delete d_data->symbol;
00285     d_data->symbol = symbol.clone();
00286     itemChanged();
00287 }
00288 
00293 const QwtSymbol &QwtPlotCurve::symbol() const 
00294 { 
00295     return *d_data->symbol; 
00296 }
00297 
00303 void QwtPlotCurve::setPen(const QPen &pen)
00304 {
00305     if ( pen != d_data->pen )
00306     {
00307         d_data->pen = pen;
00308         itemChanged();
00309     }
00310 }
00311 
00316 const QPen& QwtPlotCurve::pen() const 
00317 { 
00318     return d_data->pen; 
00319 }
00320 
00333 void QwtPlotCurve::setBrush(const QBrush &brush)
00334 {
00335     if ( brush != d_data->brush )
00336     {
00337         d_data->brush = brush;
00338         itemChanged();
00339     }
00340 }
00341 
00346 const QBrush& QwtPlotCurve::brush() const 
00347 {
00348     return d_data->brush;
00349 }
00350 
00351 
00363 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00364 {
00365     delete d_xy;
00366     d_xy = new QwtArrayData(xData, yData, size);
00367     itemChanged();
00368 }
00369 
00378 void QwtPlotCurve::setData(const QwtArray<double> &xData, 
00379     const QwtArray<double> &yData)
00380 {
00381     delete d_xy;
00382     d_xy = new QwtArrayData(xData, yData);
00383     itemChanged();
00384 }
00385 
00392 #if QT_VERSION < 0x040000
00393 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00394 #else
00395 void QwtPlotCurve::setData(const QPolygonF &data)
00396 #endif
00397 {
00398     delete d_xy;
00399     d_xy = new QwtPolygonFData(data);
00400     itemChanged();
00401 }
00402 
00409 void QwtPlotCurve::setData(const QwtData &data)
00410 {
00411     delete d_xy;
00412     d_xy = data.copy();
00413     itemChanged();
00414 }
00415 
00429 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00430 {
00431     delete d_xy;
00432     d_xy = new QwtCPointerData(xData, yData, size);
00433     itemChanged();
00434 }
00435 
00442 QwtDoubleRect QwtPlotCurve::boundingRect() const
00443 {
00444     if ( d_xy == NULL )
00445         return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid
00446 
00447     return d_xy->boundingRect();
00448 }
00449 
00459 void QwtPlotCurve::draw(QPainter *painter,
00460     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00461     const QRect &) const
00462 {
00463     draw(painter, xMap, yMap, 0, -1);
00464 }
00465 
00483 void QwtPlotCurve::draw(int from, int to) const
00484 {
00485     if ( !plot() )
00486         return;
00487 
00488     QwtPlotCanvas *canvas = plot()->canvas();
00489 
00490 #if QT_VERSION >= 0x040000
00491     if ( canvas->paintEngine()->type() == QPaintEngine::OpenGL )
00492     {
00493         /*
00494             OpenGL alway repaint the complete widget.
00495             So for this operation OpenGL is one of the slowest
00496             environments.
00497          */
00498         canvas->repaint();
00499         return;
00500     }
00501 
00502     if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00503         !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00504     {
00505         /*
00506           We save curve and range in helper and call repaint.
00507           The helper filters the Paint event, to repeat
00508           the QwtPlotCurve::draw, but now from inside the paint
00509           event.
00510          */
00511 
00512         QwtPlotCurvePaintHelper helper(this, from, to);
00513         canvas->installEventFilter(&helper);
00514 
00515         const bool noSystemBackground =
00516             canvas->testAttribute(Qt::WA_NoSystemBackground);
00517         canvas->setAttribute(Qt::WA_NoSystemBackground, true);
00518         canvas->repaint();
00519         canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground);
00520 
00521         return;
00522     }
00523 #endif
00524 
00525     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00526     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00527 
00528     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00529         canvas->paintCache() && !canvas->paintCache()->isNull() )
00530     {
00531         QPainter cachePainter((QPixmap *)canvas->paintCache());
00532         cachePainter.translate(-canvas->contentsRect().x(),
00533             -canvas->contentsRect().y());
00534 
00535         draw(&cachePainter, xMap, yMap, from, to);
00536     }
00537 
00538     QPainter painter(canvas);
00539 
00540     painter.setClipping(true);
00541     painter.setClipRect(canvas->contentsRect());
00542 
00543     draw(&painter, xMap, yMap, from, to);
00544 }
00545 
00557 void QwtPlotCurve::draw(QPainter *painter,
00558     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00559     int from, int to) const
00560 {
00561     if ( !painter || dataSize() <= 0 )
00562         return;
00563 
00564     if (to < 0)
00565         to = dataSize() - 1;
00566 
00567     if ( verifyRange(dataSize(), from, to) > 0 )
00568     {
00569         painter->save();
00570         painter->setPen(d_data->pen);
00571 
00572         /*
00573           Qt 4.0.0 is slow when drawing lines, but it's even 
00574           slower when the painter has a brush. So we don't
00575           set the brush before we really need it.
00576          */
00577 
00578         drawCurve(painter, d_data->style, xMap, yMap, from, to);
00579         painter->restore();
00580 
00581         if (d_data->symbol->style() != QwtSymbol::NoSymbol)
00582         {
00583             painter->save();
00584             drawSymbols(painter, *d_data->symbol, xMap, yMap, from, to);
00585             painter->restore();
00586         }
00587     }
00588 }
00589 
00601 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00602     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00603     int from, int to) const
00604 {
00605     switch (style)
00606     {
00607         case Lines:
00608             if ( testCurveAttribute(Fitted) )
00609             {
00610                 // we always need the complete 
00611                 // curve for fitting
00612                 from = 0;
00613                 to = dataSize() - 1;
00614             }
00615             drawLines(painter, xMap, yMap, from, to);
00616             break;
00617         case Sticks:
00618             drawSticks(painter, xMap, yMap, from, to);
00619             break;
00620         case Steps:
00621             drawSteps(painter, xMap, yMap, from, to);
00622             break;
00623         case Dots:
00624             drawDots(painter, xMap, yMap, from, to);
00625             break;
00626         case NoCurve:
00627         default:
00628             break;
00629     }
00630 }
00631 
00647 void QwtPlotCurve::drawLines(QPainter *painter,
00648     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00649     int from, int to) const
00650 {
00651     int size = to - from + 1;
00652     if ( size <= 0 )
00653         return;
00654 
00655     QwtPolygon polyline;
00656     if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00657     {
00658         // Transform x and y values to window coordinates
00659         // to avoid a distinction between linear and
00660         // logarithmic scales.
00661 
00662 #if QT_VERSION < 0x040000
00663         QwtArray<QwtDoublePoint> points(size);
00664 #else
00665         QPolygonF points(size);
00666 #endif
00667         for (int i = from; i <= to; i++)
00668         {
00669             QwtDoublePoint &p = points[i];
00670             p.setX( xMap.xTransform(x(i)) );
00671             p.setY( yMap.xTransform(y(i)) );
00672         }
00673 
00674         points = d_data->curveFitter->fitCurve(points);
00675         size = points.size();
00676 
00677         if ( size == 0 )
00678             return;
00679 
00680         // Round QwtDoublePoints to QPoints
00681         // When Qwt support for Qt3 has been dropped (Qwt 6.x)
00682         // we will use a doubles for painting and the following
00683         // step will be obsolete.
00684 
00685         polyline.resize(size);
00686 
00687         const QwtDoublePoint *p = points.data();
00688         QPoint *pl = polyline.data();
00689         if ( d_data->paintAttributes & PaintFiltered )
00690         {
00691 
00692             QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00693             pl[0] = pp;
00694 
00695             int count = 1;
00696             for (int i = 1; i < size; i++)
00697             {
00698                 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00699                 if ( pi != pp )
00700                 {
00701                     pl[count++] = pi;
00702                     pp = pi;
00703                 }
00704             }
00705             if ( count != size )
00706                 polyline.resize(count);
00707         }
00708         else
00709         {
00710             for ( int i = 0; i < size; i++ )
00711             {
00712                 pl[i].setX( qRound(p[i].x()) );
00713                 pl[i].setY( qRound(p[i].y()) );
00714             }
00715         }
00716     }
00717     else
00718     {
00719         polyline.resize(size);
00720 
00721         if ( d_data->paintAttributes & PaintFiltered )
00722         {
00723             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00724             polyline.setPoint(0, pp);
00725 
00726             int count = 1;
00727             for (int i = from + 1; i <= to; i++)
00728             {
00729                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00730                 if ( pi != pp )
00731                 {
00732                     polyline.setPoint(count, pi);
00733                     count++;
00734 
00735                     pp = pi;
00736                 }
00737             }
00738             if ( count != size )
00739                 polyline.resize(count);
00740         }
00741         else
00742         {
00743             for (int i = from; i <= to; i++)
00744             {
00745                 int xi = xMap.transform(x(i));
00746                 int yi = yMap.transform(y(i));
00747 
00748                 polyline.setPoint(i - from, xi, yi);
00749             }
00750         }
00751     }
00752 
00753     if ( d_data->paintAttributes & ClipPolygons )
00754         polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00755 
00756     QwtPainter::drawPolyline(painter, polyline);
00757 
00758     if ( d_data->brush.style() != Qt::NoBrush )
00759         fillCurve(painter, xMap, yMap, polyline);
00760 }
00761 
00773 void QwtPlotCurve::drawSticks(QPainter *painter,
00774     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00775     int from, int to) const
00776 {
00777     int x0 = xMap.transform(d_data->reference);
00778     int y0 = yMap.transform(d_data->reference);
00779 
00780     for (int i = from; i <= to; i++)
00781     {
00782         const int xi = xMap.transform(x(i));
00783         const int yi = yMap.transform(y(i));
00784 
00785         if (d_data->curveType == Xfy)
00786             QwtPainter::drawLine(painter, x0, yi, xi, yi);
00787         else
00788             QwtPainter::drawLine(painter, xi, y0, xi, yi);
00789     }
00790 }
00791 
00803 void QwtPlotCurve::drawDots(QPainter *painter,
00804     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00805     int from, int to) const
00806 {
00807     const QRect window = painter->window();
00808     if ( window.isEmpty() )
00809         return;
00810 
00811     const bool doFill = d_data->brush.style() != Qt::NoBrush;
00812 
00813     QwtPolygon polyline;
00814     if ( doFill )
00815         polyline.resize(to - from + 1);
00816 
00817     if ( to > from && d_data->paintAttributes & PaintFiltered )
00818     {
00819         if ( doFill )   
00820         {
00821             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00822 
00823             QwtPainter::drawPoint(painter, pp.x(), pp.y());
00824             polyline.setPoint(0, pp);
00825 
00826             int count = 1;
00827             for (int i = from + 1; i <= to; i++)
00828             {
00829                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00830                 if ( pi != pp )
00831                 {
00832                     QwtPainter::drawPoint(painter, pi.x(), pi.y());
00833 
00834                     polyline.setPoint(count, pi);
00835                     count++;
00836 
00837                     pp = pi;
00838                 }
00839             }
00840             if ( int(polyline.size()) != count )
00841                 polyline.resize(count);
00842         }
00843         else
00844         {
00845             // if we don't need to fill, we can sort out
00846             // duplicates independent from the order
00847 
00848             PrivateData::PixelMatrix pixelMatrix(window);
00849 
00850             for (int i = from; i <= to; i++)
00851             {
00852                 const QPoint p( xMap.transform(x(i)),
00853                     yMap.transform(y(i)) );
00854 
00855                 if ( pixelMatrix.testPixel(p) )
00856                     QwtPainter::drawPoint(painter, p.x(), p.y());
00857             }
00858         }
00859     }
00860     else
00861     {
00862         for (int i = from; i <= to; i++)
00863         {
00864             const int xi = xMap.transform(x(i));
00865             const int yi = yMap.transform(y(i));
00866             QwtPainter::drawPoint(painter, xi, yi);
00867 
00868             if ( doFill )
00869                 polyline.setPoint(i - from, xi, yi);
00870         }
00871     }
00872 
00873     if ( doFill )
00874     {
00875         if ( d_data->paintAttributes & ClipPolygons )
00876             polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00877 
00878         fillCurve(painter, xMap, yMap, polyline);
00879     }
00880 }
00881 
00896 void QwtPlotCurve::drawSteps(QPainter *painter,
00897     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00898     int from, int to) const
00899 {
00900     QwtPolygon polyline(2 * (to - from) + 1);
00901 
00902     bool inverted = d_data->curveType == Yfx;
00903     if ( d_data->attributes & Inverted )
00904         inverted = !inverted;
00905 
00906     int i,ip;
00907     for (i = from, ip = 0; i <= to; i++, ip += 2)
00908     {
00909         const int xi = xMap.transform(x(i));
00910         const int yi = yMap.transform(y(i));
00911 
00912         if ( ip > 0 )
00913         {
00914             if (inverted)
00915                 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00916             else
00917                 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00918         }
00919 
00920         polyline.setPoint(ip, xi, yi);
00921     }
00922 
00923     if ( d_data->paintAttributes & ClipPolygons )
00924         polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00925 
00926     QwtPainter::drawPolyline(painter, polyline);
00927 
00928     if ( d_data->brush.style() != Qt::NoBrush )
00929         fillCurve(painter, xMap, yMap, polyline);
00930 }
00931 
00932 
00955 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
00956 {
00957     if ( bool(d_data->attributes & attribute) == on )
00958         return;
00959 
00960     if ( on )
00961         d_data->attributes |= attribute;
00962     else
00963         d_data->attributes &= ~attribute;
00964 
00965     itemChanged();
00966 }
00967 
00972 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const 
00973 { 
00974     return d_data->attributes & attribute;
00975 }
00976 
00993 void QwtPlotCurve::setCurveType(CurveType curveType)
00994 {
00995     if ( d_data->curveType != curveType )
00996     {
00997         d_data->curveType = curveType;
00998         itemChanged();
00999     }
01000 }
01001 
01006 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01007 {
01008     return d_data->curveType;
01009 }
01010 
01011 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01012 {
01013     delete d_data->curveFitter;
01014     d_data->curveFitter = curveFitter;
01015 
01016     itemChanged();
01017 }
01018 
01019 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01020 {
01021     return d_data->curveFitter;
01022 }
01023 
01036 void QwtPlotCurve::fillCurve(QPainter *painter,
01037     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01038     QwtPolygon &pa) const
01039 {
01040     if ( d_data->brush.style() == Qt::NoBrush )
01041         return;
01042 
01043     closePolyline(xMap, yMap, pa);
01044     if ( pa.count() <= 2 ) // a line can't be filled
01045         return;
01046 
01047     QBrush b = d_data->brush;
01048     if ( !b.color().isValid() )
01049         b.setColor(d_data->pen.color());
01050 
01051     painter->save();
01052 
01053     painter->setPen(QPen(Qt::NoPen));
01054     painter->setBrush(b);
01055 
01056     QwtPainter::drawPolygon(painter, pa);
01057 
01058     painter->restore();
01059 }
01060 
01070 void QwtPlotCurve::closePolyline(
01071     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01072     QwtPolygon &pa) const
01073 {
01074     const int sz = pa.size();
01075     if ( sz < 2 )
01076         return;
01077 
01078     pa.resize(sz + 2);
01079 
01080     if ( d_data->curveType == QwtPlotCurve::Xfy )
01081     {
01082         pa.setPoint(sz,
01083             xMap.transform(d_data->reference), pa.point(sz - 1).y());
01084         pa.setPoint(sz + 1,
01085             xMap.transform(d_data->reference), pa.point(0).y());
01086     }
01087     else
01088     {
01089         pa.setPoint(sz,
01090             pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01091         pa.setPoint(pa.size() - 1,
01092             pa.point(0).x(), yMap.transform(d_data->reference));
01093     }
01094 }
01095 
01107 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01108     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
01109     int from, int to) const
01110 {
01111     painter->setBrush(symbol.brush());
01112     painter->setPen(symbol.pen());
01113 
01114     QRect rect;
01115     rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01116 
01117     if ( to > from && d_data->paintAttributes & PaintFiltered )
01118     {
01119         const QRect window = painter->window();
01120         if ( window.isEmpty() )
01121             return;
01122 
01123         PrivateData::PixelMatrix pixelMatrix(window);
01124 
01125         for (int i = from; i <= to; i++)
01126         {
01127             const QPoint pi( xMap.transform(x(i)),
01128                 yMap.transform(y(i)) );
01129 
01130             if ( pixelMatrix.testPixel(pi) )
01131             {
01132                 rect.moveCenter(pi);
01133                 symbol.draw(painter, rect);
01134             }
01135         }
01136     }
01137     else
01138     {
01139         for (int i = from; i <= to; i++)
01140         {
01141             const int xi = xMap.transform(x(i));
01142             const int yi = yMap.transform(y(i));
01143 
01144             rect.moveCenter(QPoint(xi, yi));
01145             symbol.draw(painter, rect);
01146         }
01147     }
01148 }
01149 
01163 void QwtPlotCurve::setBaseline(double reference)
01164 {
01165     if ( d_data->reference != reference )
01166     {
01167         d_data->reference = reference;
01168         itemChanged();
01169     }
01170 }
01171 
01176 double QwtPlotCurve::baseline() const 
01177 { 
01178     return d_data->reference; 
01179 }
01180 
01185 int QwtPlotCurve::dataSize() const
01186 {
01187     return d_xy->size();
01188 }
01189 
01190 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01191 {
01192     if ( plot() == NULL || dataSize() <= 0 )
01193         return -1;
01194 
01195     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01196     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01197 
01198     int index = -1;
01199     double dmin = 1.0e10;
01200 
01201     for (int i=0; i < dataSize(); i++)
01202     {
01203         const double cx = xMap.xTransform(x(i)) - pos.x();
01204         const double cy = yMap.xTransform(y(i)) - pos.y();
01205 
01206         const double f = qwtSqr(cx) + qwtSqr(cy);
01207         if (f < dmin)
01208         {
01209             index = i;
01210             dmin = f;
01211         }
01212     }
01213     if ( dist )
01214         *dist = sqrt(dmin);
01215 
01216     return index;
01217 }
01218 
01220 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01221 {
01222     if ( !legend )
01223         return;
01224 
01225     QwtPlotItem::updateLegend(legend);
01226 
01227     QWidget *widget = legend->find(this);
01228     if ( !widget || !widget->inherits("QwtLegendItem") )
01229         return;
01230 
01231     QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01232 
01233 #if QT_VERSION < 0x040000
01234     const bool doUpdate = legendItem->isUpdatesEnabled();
01235 #else
01236     const bool doUpdate = legendItem->updatesEnabled();
01237 #endif
01238     legendItem->setUpdatesEnabled(false);
01239 
01240     const int policy = legend->displayPolicy();
01241 
01242     if (policy == QwtLegend::FixedIdentifier)
01243     {
01244         int mode = legend->identifierMode();
01245 
01246         if (mode & QwtLegendItem::ShowLine)
01247             legendItem->setCurvePen(pen());
01248 
01249         if (mode & QwtLegendItem::ShowSymbol)
01250             legendItem->setSymbol(symbol());
01251 
01252         if (mode & QwtLegendItem::ShowText)
01253             legendItem->setText(title());
01254         else
01255             legendItem->setText(QwtText());
01256 
01257         legendItem->setIdentifierMode(mode);
01258     }
01259     else if (policy == QwtLegend::AutoIdentifier)
01260     {
01261         int mode = 0;
01262 
01263         if (QwtPlotCurve::NoCurve != style())
01264         {
01265             legendItem->setCurvePen(pen());
01266             mode |= QwtLegendItem::ShowLine;
01267         }
01268         if (QwtSymbol::NoSymbol != symbol().style())
01269         {
01270             legendItem->setSymbol(symbol());
01271             mode |= QwtLegendItem::ShowSymbol;
01272         }
01273         if ( !title().isEmpty() )
01274         {
01275             legendItem->setText(title());
01276             mode |= QwtLegendItem::ShowText;
01277         }
01278         else
01279         {
01280             legendItem->setText(QwtText());
01281         }
01282         legendItem->setIdentifierMode(mode);
01283     }
01284 
01285     legendItem->setUpdatesEnabled(doUpdate);
01286     legendItem->update();
01287 }

Generated on Thu May 1 15:44:09 2008 for Qwt User's Guide by  doxygen 1.5.0