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 #if QT_VERSION >= 0x040000
00486     if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00487         !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00488     {
00489         /*
00490           We save curve and range in helper and call repaint.
00491           The helper filters the Paint event, to repeat
00492           the QwtPlotCurve::draw, but now from inside the paint
00493           event.
00494          */
00495 
00496         QwtPlotCurvePaintHelper helper(this, from, to);
00497         canvas->installEventFilter(&helper);
00498 
00499         const bool noSystemBackground =
00500             canvas->testAttribute(Qt::WA_NoSystemBackground);
00501         canvas->setAttribute(Qt::WA_NoSystemBackground, true);
00502         canvas->repaint();
00503         canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground);
00504 
00505         return;
00506     }
00507 #endif
00508 
00509     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00510     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00511 
00512     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00513         canvas->paintCache() && !canvas->paintCache()->isNull() )
00514     {
00515         QPainter cachePainter((QPixmap *)canvas->paintCache());
00516         cachePainter.translate(-canvas->contentsRect().x(),
00517             -canvas->contentsRect().y());
00518 
00519         draw(&cachePainter, xMap, yMap, from, to);
00520     }
00521 
00522     QPainter painter(canvas);
00523 
00524     painter.setClipping(true);
00525     painter.setClipRect(canvas->contentsRect());
00526 
00527     draw(&painter, xMap, yMap, from, to);
00528 }
00529 
00541 void QwtPlotCurve::draw(QPainter *painter,
00542     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00543     int from, int to) const
00544 {
00545     if ( !painter || dataSize() <= 0 )
00546         return;
00547 
00548     if (to < 0)
00549         to = dataSize() - 1;
00550 
00551     if ( verifyRange(dataSize(), from, to) > 0 )
00552     {
00553         painter->save();
00554         painter->setPen(d_data->pen);
00555 
00556         /*
00557           Qt 4.0.0 is slow when drawing lines, but it´s even 
00558           slower when the painter has a brush. So we don't
00559           set the brush before we really need it.
00560          */
00561 
00562         drawCurve(painter, d_data->style, xMap, yMap, from, to);
00563         painter->restore();
00564 
00565         if (d_data->sym.style() != QwtSymbol::NoSymbol)
00566         {
00567             painter->save();
00568             drawSymbols(painter, d_data->sym, xMap, yMap, from, to);
00569             painter->restore();
00570         }
00571     }
00572 }
00573 
00585 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00586     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00587     int from, int to) const
00588 {
00589     switch (style)
00590     {
00591         case Lines:
00592             if ( testCurveAttribute(Fitted) )
00593             {
00594                 // we always need the complete 
00595                 // curve for fitting
00596                 from = 0;
00597                 to = dataSize() - 1;
00598             }
00599             drawLines(painter, xMap, yMap, from, to);
00600             break;
00601         case Sticks:
00602             drawSticks(painter, xMap, yMap, from, to);
00603             break;
00604         case Steps:
00605             drawSteps(painter, xMap, yMap, from, to);
00606             break;
00607         case Dots:
00608             drawDots(painter, xMap, yMap, from, to);
00609             break;
00610         case NoCurve:
00611         default:
00612             break;
00613     }
00614 }
00615 
00631 void QwtPlotCurve::drawLines(QPainter *painter,
00632     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00633     int from, int to) const
00634 {
00635     int size = to - from + 1;
00636     if ( size <= 0 )
00637         return;
00638 
00639     QwtPolygon polyline;
00640     if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00641     {
00642         // Transform x and y values to window coordinates
00643         // to avoid a distinction between linear and
00644         // logarithmic scales.
00645 
00646 #if QT_VERSION < 0x040000
00647         QwtArray<QwtDoublePoint> points(size);
00648 #else
00649         QPolygonF points(size);
00650 #endif
00651         for (int i = from; i <= to; i++)
00652         {
00653             QwtDoublePoint &p = points[i];
00654             p.setX( xMap.xTransform(x(i)) );
00655             p.setY( yMap.xTransform(y(i)) );
00656         }
00657 
00658         points = d_data->curveFitter->fitCurve(points);
00659         size = points.size();
00660 
00661         if ( size == 0 )
00662             return;
00663 
00664         // Round QwtDoublePoints to QPoints
00665         // When Qwt support for Qt3 has been dropped (Qwt 6.x)
00666         // we will use a doubles for painting and the following
00667         // step will be obsolete.
00668 
00669         polyline.resize(size);
00670 
00671         const QwtDoublePoint *p = points.data();
00672         QPoint *pl = polyline.data();
00673         if ( d_data->paintAttributes & PaintFiltered )
00674         {
00675 
00676             QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00677             pl[0] = pp;
00678 
00679             int count = 1;
00680             for (int i = 1; i < size; i++)
00681             {
00682                 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00683                 if ( pi != pp )
00684                 {
00685                     pl[count++] = pi;
00686                     pp = pi;
00687                 }
00688             }
00689             if ( count != size )
00690                 polyline.resize(count);
00691         }
00692         else
00693         {
00694             for ( int i = 0; i < size; i++ )
00695             {
00696                 pl[i].setX( qRound(p[i].x()) );
00697                 pl[i].setY( qRound(p[i].y()) );
00698             }
00699         }
00700     }
00701     else
00702     {
00703         polyline.resize(size);
00704 
00705         if ( d_data->paintAttributes & PaintFiltered )
00706         {
00707             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00708             polyline.setPoint(0, pp);
00709 
00710             int count = 1;
00711             for (int i = from + 1; i <= to; i++)
00712             {
00713                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00714                 if ( pi != pp )
00715                 {
00716                     polyline.setPoint(count, pi);
00717                     count++;
00718 
00719                     pp = pi;
00720                 }
00721             }
00722             if ( count != size )
00723                 polyline.resize(count);
00724         }
00725         else
00726         {
00727             for (int i = from; i <= to; i++)
00728             {
00729                 int xi = xMap.transform(x(i));
00730                 int yi = yMap.transform(y(i));
00731 
00732                 polyline.setPoint(i - from, xi, yi);
00733             }
00734         }
00735     }
00736 
00737     if ( d_data->paintAttributes & ClipPolygons )
00738     {
00739         QwtRect r = painter->window();
00740         polyline = r.clip(polyline);
00741     }
00742 
00743     QwtPainter::drawPolyline(painter, polyline);
00744 
00745     if ( d_data->brush.style() != Qt::NoBrush )
00746         fillCurve(painter, xMap, yMap, polyline);
00747 }
00748 
00760 void QwtPlotCurve::drawSticks(QPainter *painter,
00761     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00762     int from, int to) const
00763 {
00764     int x0 = xMap.transform(d_data->reference);
00765     int y0 = yMap.transform(d_data->reference);
00766 
00767     for (int i = from; i <= to; i++)
00768     {
00769         const int xi = xMap.transform(x(i));
00770         const int yi = yMap.transform(y(i));
00771 
00772         if (d_data->curveType == Xfy)
00773             QwtPainter::drawLine(painter, x0, yi, xi, yi);
00774         else
00775             QwtPainter::drawLine(painter, xi, y0, xi, yi);
00776     }
00777 }
00778 
00790 void QwtPlotCurve::drawDots(QPainter *painter,
00791     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00792     int from, int to) const
00793 {
00794     const QRect window = painter->window();
00795     if ( window.isEmpty() )
00796         return;
00797 
00798     const bool doFill = d_data->brush.style() != Qt::NoBrush;
00799 
00800     QwtPolygon polyline;
00801     if ( doFill )
00802         polyline.resize(to - from + 1);
00803 
00804     if ( to > from && d_data->paintAttributes & PaintFiltered )
00805     {
00806         if ( doFill )   
00807         {
00808             QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00809 
00810             QwtPainter::drawPoint(painter, pp.x(), pp.y());
00811             polyline.setPoint(0, pp);
00812 
00813             int count = 1;
00814             for (int i = from + 1; i <= to; i++)
00815             {
00816                 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00817                 if ( pi != pp )
00818                 {
00819                     QwtPainter::drawPoint(painter, pi.x(), pi.y());
00820 
00821                     polyline.setPoint(count, pi);
00822                     count++;
00823 
00824                     pp = pi;
00825                 }
00826             }
00827             if ( int(polyline.size()) != count )
00828                 polyline.resize(count);
00829         }
00830         else
00831         {
00832             // if we don't need to fill, we can sort out
00833             // duplicates independent from the order
00834 
00835             PrivateData::PixelMatrix pixelMatrix(window);
00836 
00837             for (int i = from; i <= to; i++)
00838             {
00839                 const QPoint p( xMap.transform(x(i)),
00840                     yMap.transform(y(i)) );
00841 
00842                 if ( pixelMatrix.testPixel(p) )
00843                     QwtPainter::drawPoint(painter, p.x(), p.y());
00844             }
00845         }
00846     }
00847     else
00848     {
00849         for (int i = from; i <= to; i++)
00850         {
00851             const int xi = xMap.transform(x(i));
00852             const int yi = yMap.transform(y(i));
00853             QwtPainter::drawPoint(painter, xi, yi);
00854 
00855             if ( doFill )
00856                 polyline.setPoint(i - from, xi, yi);
00857         }
00858     }
00859 
00860     if ( doFill )
00861     {
00862         if ( d_data->paintAttributes & ClipPolygons )
00863         {
00864             const QwtRect r = painter->window();
00865             polyline = r.clip(polyline);
00866         }
00867 
00868         fillCurve(painter, xMap, yMap, polyline);
00869     }
00870 }
00871 
00886 void QwtPlotCurve::drawSteps(QPainter *painter,
00887     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00888     int from, int to) const
00889 {
00890     QwtPolygon polyline(2 * (to - from) + 1);
00891 
00892     bool inverted = d_data->curveType == Yfx;
00893     if ( d_data->attributes & Inverted )
00894         inverted = !inverted;
00895 
00896     int i,ip;
00897     for (i = from, ip = 0; i <= to; i++, ip += 2)
00898     {
00899         const int xi = xMap.transform(x(i));
00900         const int yi = yMap.transform(y(i));
00901 
00902         if ( ip > 0 )
00903         {
00904             if (inverted)
00905                 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00906             else
00907                 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00908         }
00909 
00910         polyline.setPoint(ip, xi, yi);
00911     }
00912 
00913     if ( d_data->paintAttributes & ClipPolygons )
00914     {
00915         const QwtRect r = painter->window();
00916         polyline = r.clip(polyline);
00917     }
00918 
00919     QwtPainter::drawPolyline(painter, polyline);
00920 
00921     if ( d_data->brush.style() != Qt::NoBrush )
00922         fillCurve(painter, xMap, yMap, polyline);
00923 }
00924 
00925 
00948 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
00949 {
00950     if ( bool(d_data->attributes & attribute) == on )
00951         return;
00952 
00953     if ( on )
00954         d_data->attributes |= attribute;
00955     else
00956         d_data->attributes &= ~attribute;
00957 
00958     itemChanged();
00959 }
00960 
00965 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const 
00966 { 
00967     return d_data->attributes & attribute;
00968 }
00969 
00986 void QwtPlotCurve::setCurveType(CurveType curveType)
00987 {
00988     if ( d_data->curveType != curveType )
00989     {
00990         d_data->curveType = curveType;
00991         itemChanged();
00992     }
00993 }
00994 
00999 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01000 {
01001     return d_data->curveType;
01002 }
01003 
01004 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01005 {
01006     delete d_data->curveFitter;
01007     d_data->curveFitter = curveFitter;
01008 
01009     itemChanged();
01010 }
01011 
01012 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01013 {
01014     return d_data->curveFitter;
01015 }
01016 
01029 void QwtPlotCurve::fillCurve(QPainter *painter,
01030     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01031     QwtPolygon &pa) const
01032 {
01033     if ( d_data->brush.style() == Qt::NoBrush )
01034         return;
01035 
01036     closePolyline(xMap, yMap, pa);
01037     if ( pa.count() <= 2 ) // a line can't be filled
01038         return;
01039 
01040     QBrush b = d_data->brush;
01041     if ( !b.color().isValid() )
01042         b.setColor(d_data->pen.color());
01043 
01044     painter->save();
01045 
01046     painter->setPen(QPen(Qt::NoPen));
01047     painter->setBrush(b);
01048 
01049     QwtPainter::drawPolygon(painter, pa);
01050 
01051     painter->restore();
01052 }
01053 
01063 void QwtPlotCurve::closePolyline(
01064     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01065     QwtPolygon &pa) const
01066 {
01067     const int sz = pa.size();
01068     if ( sz < 2 )
01069         return;
01070 
01071     pa.resize(sz + 2);
01072 
01073     if ( d_data->curveType == QwtPlotCurve::Xfy )
01074     {
01075         pa.setPoint(sz,
01076             xMap.transform(d_data->reference), pa.point(sz - 1).y());
01077         pa.setPoint(sz + 1,
01078             xMap.transform(d_data->reference), pa.point(0).y());
01079     }
01080     else
01081     {
01082         pa.setPoint(sz,
01083             pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01084         pa.setPoint(pa.size() - 1,
01085             pa.point(0).x(), yMap.transform(d_data->reference));
01086     }
01087 }
01088 
01100 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01101     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
01102     int from, int to) const
01103 {
01104     painter->setBrush(symbol.brush());
01105     painter->setPen(symbol.pen());
01106 
01107     QRect rect;
01108     rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01109 
01110     if ( to > from && d_data->paintAttributes & PaintFiltered )
01111     {
01112         const QRect window = painter->window();
01113         if ( window.isEmpty() )
01114             return;
01115 
01116         PrivateData::PixelMatrix pixelMatrix(window);
01117 
01118         for (int i = from; i <= to; i++)
01119         {
01120             const QPoint pi( xMap.transform(x(i)),
01121                 yMap.transform(y(i)) );
01122 
01123             if ( pixelMatrix.testPixel(pi) )
01124             {
01125                 rect.moveCenter(pi);
01126                 symbol.draw(painter, rect);
01127             }
01128         }
01129     }
01130     else
01131     {
01132         for (int i = from; i <= to; i++)
01133         {
01134             const int xi = xMap.transform(x(i));
01135             const int yi = yMap.transform(y(i));
01136 
01137             rect.moveCenter(QPoint(xi, yi));
01138             symbol.draw(painter, rect);
01139         }
01140     }
01141 }
01142 
01156 void QwtPlotCurve::setBaseline(double reference)
01157 {
01158     if ( d_data->reference != reference )
01159     {
01160         d_data->reference = reference;
01161         itemChanged();
01162     }
01163 }
01164 
01169 double QwtPlotCurve::baseline() const 
01170 { 
01171     return d_data->reference; 
01172 }
01173 
01178 int QwtPlotCurve::dataSize() const
01179 {
01180     return d_xy->size();
01181 }
01182 
01183 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01184 {
01185     if ( plot() == NULL || dataSize() <= 0 )
01186         return -1;
01187 
01188     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01189     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01190 
01191     int index = -1;
01192     double dmin = 1.0e10;
01193 
01194     for (int i=0; i < dataSize(); i++)
01195     {
01196         const double cx = xMap.xTransform(x(i)) - pos.x();
01197         const double cy = yMap.xTransform(y(i)) - pos.y();
01198 
01199         const double f = qwtSqr(cx) + qwtSqr(cy);
01200         if (f < dmin)
01201         {
01202             index = i;
01203             dmin = f;
01204         }
01205     }
01206     if ( dist )
01207         *dist = sqrt(dmin);
01208 
01209     return index;
01210 }
01211 
01212 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01213 {
01214     if ( !legend )
01215         return;
01216 
01217     QwtPlotItem::updateLegend(legend);
01218 
01219     QWidget *widget = legend->find(this);
01220     if ( !widget || !widget->inherits("QwtLegendItem") )
01221         return;
01222 
01223     QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01224 
01225 #if QT_VERSION < 0x040000
01226     const bool doUpdate = legendItem->isUpdatesEnabled();
01227 #else
01228     const bool doUpdate = legendItem->updatesEnabled();
01229 #endif
01230     legendItem->setUpdatesEnabled(false);
01231 
01232     const int policy = legend->displayPolicy();
01233 
01234     if (policy == QwtLegend::FixedIdentifier)
01235     {
01236         int mode = legend->identifierMode();
01237 
01238         if (mode & QwtLegendItem::ShowLine)
01239             legendItem->setCurvePen(pen());
01240 
01241         if (mode & QwtLegendItem::ShowSymbol)
01242             legendItem->setSymbol(symbol());
01243 
01244         if (mode & QwtLegendItem::ShowText)
01245             legendItem->setText(title());
01246         else
01247             legendItem->setText(QwtText());
01248 
01249         legendItem->setIdentifierMode(mode);
01250     }
01251     else if (policy == QwtLegend::AutoIdentifier)
01252     {
01253         int mode = 0;
01254 
01255         if (QwtPlotCurve::NoCurve != style())
01256         {
01257             legendItem->setCurvePen(pen());
01258             mode |= QwtLegendItem::ShowLine;
01259         }
01260         if (QwtSymbol::NoSymbol != symbol().style())
01261         {
01262             legendItem->setSymbol(symbol());
01263             mode |= QwtLegendItem::ShowSymbol;
01264         }
01265         if ( !title().isEmpty() )
01266         {
01267             legendItem->setText(title());
01268             mode |= QwtLegendItem::ShowText;
01269         }
01270         else
01271         {
01272             legendItem->setText(QwtText());
01273         }
01274         legendItem->setIdentifierMode(mode);
01275     }
01276 
01277     legendItem->setUpdatesEnabled(doUpdate);
01278     legendItem->update();
01279 }

Generated on Sun Jul 22 11:26:54 2007 for Qwt User's Guide by  doxygen 1.5.2