00001
00002
00003
00004
00005
00006
00007
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);
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
00493
00494
00495
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
00537
00538
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
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
00586
00587
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
00623
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
00671
00672
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
00693
00694
00695
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
00861
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 )
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 }