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_spline.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 #if QT_VERSION < 0x040000
00060 #define QwtPointArray QPointArray
00061 #else
00062 #define QwtPointArray QPolygon
00063 #endif
00064
00065 class QwtPlotCurve::PrivateData
00066 {
00067 public:
00068 class PixelMatrix: private QBitArray
00069 {
00070 public:
00071 PixelMatrix(const QRect& rect):
00072 QBitArray(rect.width() * rect.height()),
00073 _rect(rect)
00074 {
00075 fill(false);
00076 }
00077
00078 inline bool testPixel(const QPoint& pos)
00079 {
00080 if ( !_rect.contains(pos) )
00081 return false;
00082
00083 const int idx = _rect.width() * (pos.y() - _rect.y()) +
00084 (pos.x() - _rect.x());
00085
00086 const bool marked = testBit(idx);
00087 if ( !marked )
00088 setBit(idx, true);
00089
00090 return !marked;
00091 }
00092
00093 private:
00094 QRect _rect;
00095 };
00096
00097 PrivateData()
00098 {
00099 pen = QPen(Qt::black, 0);
00100 reference = 0.0;
00101 splineSize = 250;
00102 attributes = Auto;
00103 paintAttributes = 0;
00104 style = QwtPlotCurve::Lines;
00105 }
00106
00107 QwtPlotCurve::CurveStyle style;
00108 double reference;
00109
00110 QwtSymbol sym;
00111
00112 QPen pen;
00113 QBrush brush;
00114 QwtText title;
00115
00116 int attributes;
00117 int splineSize;
00118 int paintAttributes;
00119 };
00120
00121 static int qwtChkMono(const double *array, int size)
00122 {
00123 if (size < 2)
00124 return 0;
00125
00126 int rv = qwtSign(array[1] - array[0]);
00127 for (int i = 1; i < size - 1; i++)
00128 {
00129 if ( qwtSign(array[i+1] - array[i]) != rv )
00130 {
00131 rv = 0;
00132 break;
00133 }
00134 }
00135 return rv;
00136 }
00137
00138 static void qwtTwistArray(double *array, int size)
00139 {
00140 const int s2 = size / 2;
00141
00142 for (int i=0; i < s2; i++)
00143 {
00144 const int itmp = size - 1 - i;
00145 const double dtmp = array[i];
00146 array[i] = array[itmp];
00147 array[itmp] = dtmp;
00148 }
00149 }
00150
00154 QwtPlotCurve::QwtPlotCurve()
00155 {
00156 init(QwtText());
00157 }
00158
00163 QwtPlotCurve::QwtPlotCurve(const QwtText &title)
00164 {
00165 init(title);
00166 }
00167
00172 QwtPlotCurve::QwtPlotCurve(const QString &title)
00173 {
00174 init(title);
00175 }
00176
00180 QwtPlotCurve::QwtPlotCurve(const QwtPlotCurve &c):
00181 QwtPlotItem(c)
00182 {
00183 init(c.d_data->title);
00184 copy(c);
00185 }
00186
00188 QwtPlotCurve::~QwtPlotCurve()
00189 {
00190 delete d_xy;
00191 delete d_data;
00192 }
00193
00197 void QwtPlotCurve::init(const QwtText &title)
00198 {
00199 setItemAttribute(QwtPlotItem::Legend);
00200 setItemAttribute(QwtPlotItem::AutoScale);
00201
00202 d_data = new PrivateData;
00203 d_data->title = title;
00204
00205 d_xy = new QwtDoublePointData(QwtArray<QwtDoublePoint>());
00206
00207 setZ(20.0);
00208 }
00209
00213 void QwtPlotCurve::copy(const QwtPlotCurve &c)
00214 {
00215 if (this != &c)
00216 {
00217 *d_data = *c.d_data;
00218
00219 delete d_xy;
00220 d_xy = c.d_xy->copy();
00221
00222 itemChanged();
00223 }
00224 }
00225
00226
00230 const QwtPlotCurve& QwtPlotCurve::operator=(const QwtPlotCurve &c)
00231 {
00232 copy(c);
00233 return *this;
00234 }
00235
00236 int QwtPlotCurve::rtti() const
00237 {
00238 return QwtPlotItem::Rtti_PlotCurve;
00239 }
00240
00262 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00263 {
00264 if ( on )
00265 d_data->paintAttributes |= attribute;
00266 else
00267 d_data->paintAttributes &= ~attribute;
00268 }
00269
00274 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00275 {
00276 return (d_data->paintAttributes & attribute);
00277 }
00278
00309 void QwtPlotCurve::setStyle(CurveStyle style)
00310 {
00311 if ( style != d_data->style )
00312 {
00313 d_data->style = style;
00314 itemChanged();
00315 }
00316 }
00317
00323 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00324 {
00325 return d_data->style;
00326 }
00327
00333 void QwtPlotCurve::setSymbol(const QwtSymbol &s )
00334 {
00335 d_data->sym = s;
00336 itemChanged();
00337 }
00338
00343 const QwtSymbol &QwtPlotCurve::symbol() const
00344 {
00345 return d_data->sym;
00346 }
00347
00352 void QwtPlotCurve::setPen(const QPen &p)
00353 {
00354 if ( p != d_data->pen )
00355 {
00356 d_data->pen = p;
00357 itemChanged();
00358 }
00359 }
00360
00365 const QPen& QwtPlotCurve::pen() const
00366 {
00367 return d_data->pen;
00368 }
00369
00382 void QwtPlotCurve::setBrush(const QBrush &brush)
00383 {
00384 if ( brush != d_data->brush )
00385 {
00386 d_data->brush = brush;
00387 itemChanged();
00388 }
00389 }
00390
00396 const QBrush& QwtPlotCurve::brush() const
00397 {
00398 return d_data->brush;
00399 }
00400
00401
00413 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00414 {
00415 delete d_xy;
00416 d_xy = new QwtArrayData(xData, yData, size);
00417 itemChanged();
00418 }
00419
00428 void QwtPlotCurve::setData(const QwtArray<double> &xData,
00429 const QwtArray<double> &yData)
00430 {
00431 delete d_xy;
00432 d_xy = new QwtArrayData(xData, yData);
00433 itemChanged();
00434 }
00435
00443 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00444 {
00445 delete d_xy;
00446 d_xy = new QwtDoublePointData(data);
00447 itemChanged();
00448 }
00449
00457 void QwtPlotCurve::setData(const QwtData &data)
00458 {
00459 delete d_xy;
00460 d_xy = data.copy();
00461 itemChanged();
00462 }
00463
00477 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00478 {
00479 delete d_xy;
00480 d_xy = new QwtCPointerData(xData, yData, size);
00481 itemChanged();
00482 }
00483
00488 void QwtPlotCurve::setTitle(const QString &title)
00489 {
00490 setTitle(QwtText(title));
00491 }
00492
00497 void QwtPlotCurve::setTitle(const QwtText &title)
00498 {
00499 d_data->title = title;
00500 itemChanged();
00501 }
00502
00507 const QwtText &QwtPlotCurve::title() const
00508 {
00509 return d_data->title;
00510 }
00511
00518 QwtDoubleRect QwtPlotCurve::boundingRect() const
00519 {
00520 if ( d_xy == NULL )
00521 return QwtDoubleRect(1.0, 1.0, -2.0, -2.0);
00522
00523 return d_xy->boundingRect();
00524 }
00525
00526
00532 int QwtPlotCurve::verifyRange(int &i1, int &i2) const
00533 {
00534 int size = dataSize();
00535
00536 if (size < 1) return 0;
00537
00538 i1 = qwtLim(i1, 0, size-1);
00539 i2 = qwtLim(i2, 0, size-1);
00540
00541 if ( i1 > i2 )
00542 qSwap(i1, i2);
00543
00544 return (i2 - i1 + 1);
00545 }
00546
00547 void QwtPlotCurve::draw(QPainter *painter,
00548 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00549 const QRect &) const
00550 {
00551 draw(painter, xMap, yMap, 0, -1);
00552 }
00553
00571 void QwtPlotCurve::draw(int from, int to) const
00572 {
00573 if ( !plot() )
00574 return;
00575
00576 QwtPlotCanvas *canvas = plot()->canvas();
00577
00578 bool directPaint = true;
00579
00580 #if QT_VERSION >= 0x040000
00581 if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00582 !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00583 {
00584
00585
00586
00587
00588
00589
00590
00591 QwtPlotCurvePaintHelper helper(this, from, to);
00592 canvas->installEventFilter(&helper);
00593 canvas->repaint();
00594
00595 return;
00596 }
00597 #endif
00598
00599 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00600 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00601
00602 if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00603 canvas->paintCache() && !canvas->paintCache()->isNull() )
00604 {
00605 QPainter cachePainter((QPixmap *)canvas->paintCache());
00606 cachePainter.translate(-canvas->contentsRect().x(),
00607 -canvas->contentsRect().y());
00608
00609 draw(&cachePainter, xMap, yMap, from, to);
00610 }
00611
00612 if ( directPaint )
00613 {
00614 QPainter painter(canvas);
00615
00616 painter.setClipping(true);
00617 painter.setClipRect(canvas->contentsRect());
00618
00619 draw(&painter, xMap, yMap, from, to);
00620
00621 return;
00622 }
00623
00624 #if QT_VERSION >= 0x040000
00625 if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00626 canvas->paintCache() )
00627 {
00628
00629
00630
00631
00632
00633
00634 const bool noBG = canvas->testAttribute(Qt::WA_NoBackground);
00635 if ( !noBG )
00636 canvas->setAttribute(Qt::WA_NoBackground, true);
00637
00638 canvas->repaint(canvas->contentsRect());
00639
00640 if ( !noBG )
00641 canvas->setAttribute(Qt::WA_NoBackground, false);
00642
00643 return;
00644 }
00645 #endif
00646
00647
00648 canvas->repaint(canvas->contentsRect());
00649 }
00650
00664 void QwtPlotCurve::draw(QPainter *painter,
00665 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00666 int from, int to) const
00667 {
00668 if ( !painter || dataSize() <= 0 )
00669 return;
00670
00671 if (to < 0)
00672 to = dataSize() - 1;
00673
00674 if ( verifyRange(from, to) > 0 )
00675 {
00676 painter->save();
00677 painter->setPen(d_data->pen);
00678
00679
00680
00681
00682
00683
00684
00685 drawCurve(painter, d_data->style, xMap, yMap, from, to);
00686 painter->restore();
00687
00688 if (d_data->sym.style() != QwtSymbol::None)
00689 {
00690 painter->save();
00691 drawSymbols(painter, d_data->sym, xMap, yMap, from, to);
00692 painter->restore();
00693 }
00694 }
00695 }
00696
00709 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00710 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00711 int from, int to) const
00712 {
00713 switch (style)
00714 {
00715 case Lines:
00716 drawLines(painter, xMap, yMap, from, to);
00717 break;
00718 case Sticks:
00719 drawSticks(painter, xMap, yMap, from, to);
00720 break;
00721 case Steps:
00722 drawSteps(painter, xMap, yMap, from, to);
00723 break;
00724 case Spline:
00725 if ( from > 0 || to < dataSize() - 1 )
00726 drawLines(painter, xMap, yMap, from, to);
00727 else
00728 drawSpline(painter, xMap, yMap);
00729 break;
00730 case Dots:
00731 drawDots(painter, xMap, yMap, from, to);
00732 break;
00733 case NoCurve:
00734 default:
00735 break;
00736 }
00737 }
00738
00749 void QwtPlotCurve::drawLines(QPainter *painter,
00750 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00751 int from, int to) const
00752 {
00753 const int size = to - from + 1;
00754 if ( size <= 0 )
00755 return;
00756
00757 QwtPointArray polyline(size);
00758
00759 if ( d_data->paintAttributes & PaintFiltered )
00760 {
00761 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00762 polyline.setPoint(0, pp);
00763
00764 int count = 1;
00765 for (int i = from + 1; i <= to; i++)
00766 {
00767 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00768 if ( pi != pp )
00769 {
00770 polyline.setPoint(count, pi);
00771 count++;
00772
00773 pp = pi;
00774 }
00775 }
00776 if ( count != size )
00777 polyline.resize(count);
00778 }
00779 else
00780 {
00781 for (int i = from; i <= to; i++)
00782 {
00783 int xi = xMap.transform(x(i));
00784 int yi = yMap.transform(y(i));
00785
00786 polyline.setPoint(i - from, xi, yi);
00787 }
00788 }
00789
00790 if ( d_data->paintAttributes & ClipPolygons )
00791 {
00792 QwtRect r = painter->window();
00793 polyline = r.clip(polyline);
00794 }
00795
00796 QwtPainter::drawPolyline(painter, polyline);
00797
00798 if ( d_data->brush.style() != Qt::NoBrush )
00799 fillCurve(painter, xMap, yMap, polyline);
00800 }
00801
00812 void QwtPlotCurve::drawSticks(QPainter *painter,
00813 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00814 int from, int to) const
00815 {
00816 int x0 = xMap.transform(d_data->reference);
00817 int y0 = yMap.transform(d_data->reference);
00818
00819 for (int i = from; i <= to; i++)
00820 {
00821 const int xi = xMap.transform(x(i));
00822 const int yi = yMap.transform(y(i));
00823
00824 if (d_data->attributes & Xfy)
00825 QwtPainter::drawLine(painter, x0, yi, xi, yi);
00826 else
00827 QwtPainter::drawLine(painter, xi, y0, xi, yi);
00828 }
00829 }
00830
00842 void QwtPlotCurve::drawDots(QPainter *painter,
00843 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00844 int from, int to) const
00845 {
00846 const QRect window = painter->window();
00847 if ( window.isEmpty() )
00848 return;
00849
00850 const bool doFill = d_data->brush.style() != Qt::NoBrush;
00851
00852 QwtPointArray polyline;
00853 if ( doFill )
00854 polyline.resize(to - from + 1);
00855
00856 if ( to > from && d_data->paintAttributes & PaintFiltered )
00857 {
00858 int count = 0;
00859
00860 if ( doFill )
00861 {
00862 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00863 polyline.setPoint(0, pp);
00864
00865 int count = 1;
00866 for (int i = from + 1; i <= to; i++)
00867 {
00868 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00869 if ( pi != pp )
00870 {
00871 polyline.setPoint(count, pi);
00872 count++;
00873
00874 pp = pi;
00875 }
00876 }
00877 }
00878 else
00879 {
00880
00881
00882
00883 PrivateData::PixelMatrix pixelMatrix(window);
00884
00885 for (int i = from; i <= to; i++)
00886 {
00887 const QPoint p( xMap.transform(x(i)),
00888 yMap.transform(y(i)) );
00889
00890 if ( pixelMatrix.testPixel(p) )
00891 {
00892 polyline[count] = p;
00893 count++;
00894 }
00895 }
00896 }
00897 if ( int(polyline.size()) != count )
00898 polyline.resize(count);
00899 }
00900 else
00901 {
00902 for (int i = from; i <= to; i++)
00903 {
00904 const int xi = xMap.transform(x(i));
00905 const int yi = yMap.transform(y(i));
00906 QwtPainter::drawPoint(painter, xi, yi);
00907
00908 if ( doFill )
00909 polyline.setPoint(i - from, xi, yi);
00910 }
00911 }
00912
00913 if ( d_data->paintAttributes & ClipPolygons )
00914 {
00915 const QwtRect r = painter->window();
00916 polyline = r.clip(polyline);
00917 }
00918
00919 if ( doFill )
00920 fillCurve(painter, xMap, yMap, polyline);
00921 }
00922
00933 void QwtPlotCurve::drawSteps(QPainter *painter,
00934 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00935 int from, int to) const
00936 {
00937 QwtPointArray polyline(2 * (to - from) + 1);
00938
00939 bool inverted = d_data->attributes & Yfx;
00940 if ( d_data->attributes & Inverted )
00941 inverted = !inverted;
00942
00943 int i,ip;
00944 for (i = from, ip = 0; i <= to; i++, ip += 2)
00945 {
00946 const int xi = xMap.transform(x(i));
00947 const int yi = yMap.transform(y(i));
00948
00949 if ( ip > 0 )
00950 {
00951 if (inverted)
00952 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00953 else
00954 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00955 }
00956
00957 polyline.setPoint(ip, xi, yi);
00958 }
00959
00960 if ( d_data->paintAttributes & ClipPolygons )
00961 {
00962 const QwtRect r = painter->window();
00963 polyline = r.clip(polyline);
00964 }
00965
00966 QwtPainter::drawPolyline(painter, polyline);
00967
00968 if ( d_data->brush.style() != Qt::NoBrush )
00969 fillCurve(painter, xMap, yMap, polyline);
00970 }
00971
00980 void QwtPlotCurve::drawSpline(QPainter *painter,
00981 const QwtScaleMap &xMap, const QwtScaleMap &yMap) const
00982 {
00983 int i;
00984
00985 const int size = dataSize();
00986 double *txval = new double[size];
00987 double *tyval = new double[size];
00988
00989
00990
00991
00992
00993
00994 for (i=0;i<size;i++)
00995 {
00996 txval[i] = xMap.xTransform(x(i));
00997 tyval[i] = yMap.xTransform(y(i));
00998 }
00999
01000 int stype;
01001 if (! (d_data->attributes & (Yfx|Xfy|Parametric)))
01002 {
01003 if (qwtChkMono(txval, size))
01004 {
01005 stype = Yfx;
01006 }
01007 else if(qwtChkMono(tyval, size))
01008 {
01009 stype = Xfy;
01010 }
01011 else
01012 {
01013 stype = Parametric;
01014 if ( (d_data->attributes & Periodic) ||
01015 ( (x(0) == x(size-1))
01016 && (y(0) == y(size-1))))
01017 {
01018 stype |= Periodic;
01019 }
01020 }
01021 }
01022 else
01023 {
01024 stype = d_data->attributes;
01025 }
01026
01027 bool ok = false;
01028 QwtPointArray polyline(d_data->splineSize);
01029
01030 if (stype & Parametric)
01031 {
01032
01033
01034
01035 double *param = new double[size];
01036 param[0] = 0.0;
01037 for (i=1; i<size; i++)
01038 {
01039 const double delta = sqrt( qwtSqr(txval[i] - txval[i-1])
01040 + qwtSqr( tyval[i] - tyval[i-1]));
01041 param[i] = param[i-1] + qwtMax(delta, 1.0);
01042 }
01043
01044
01045
01046 QwtSpline spx, spy;
01047 ok = spx.recalc(param, txval, size, stype & Periodic);
01048 if (ok)
01049 ok = spy.recalc(param, tyval, size, stype & Periodic);
01050
01051 if ( ok )
01052 {
01053
01054 const double delta =
01055 param[size - 1] / double(d_data->splineSize-1);
01056 for (i = 0; i < d_data->splineSize; i++)
01057 {
01058 const double dtmp = delta * double(i);
01059 polyline.setPoint(i, qRound(spx.value(dtmp)),
01060 qRound(spy.value(dtmp)) );
01061 }
01062 }
01063 delete[] param;
01064 }
01065 else if (stype & Xfy)
01066 {
01067 if (tyval[size-1] < tyval[0])
01068 {
01069 qwtTwistArray(txval, size);
01070 qwtTwistArray(tyval, size);
01071 }
01072
01073
01074 QwtSpline spx;
01075 ok = spx.recalc(tyval, txval, size, stype & Periodic);
01076 if ( ok )
01077 {
01078 const double ymin = qwtGetMin(tyval, size);
01079 const double ymax = qwtGetMax(tyval, size);
01080 const double delta = (ymax - ymin) / double(d_data->splineSize - 1);
01081
01082 for (i = 0; i < d_data->splineSize; i++)
01083 {
01084 const double dtmp = ymin + delta * double(i);
01085 polyline.setPoint(i,
01086 qRound(spx.value(dtmp)), qRound(dtmp + 0.5));
01087 }
01088 }
01089 }
01090 else
01091 {
01092 if (txval[size-1] < txval[0])
01093 {
01094 qwtTwistArray(tyval, size);
01095 qwtTwistArray(txval, size);
01096 }
01097
01098
01099 QwtSpline spy;
01100 ok = spy.recalc(txval, tyval, size, stype & Periodic);
01101 if ( ok )
01102 {
01103 const double xmin = qwtGetMin(txval, size);
01104 const double xmax = qwtGetMax(txval, size);
01105 const double delta = (xmax - xmin) / double(d_data->splineSize - 1);
01106
01107 for (i = 0; i < d_data->splineSize; i++)
01108 {
01109 double dtmp = xmin + delta * double(i);
01110 polyline.setPoint(i,
01111 qRound(dtmp), qRound(spy.value(dtmp)));
01112 }
01113 }
01114 }
01115
01116 delete[] txval;
01117 delete[] tyval;
01118
01119 if ( ok )
01120 {
01121 if ( d_data->paintAttributes & ClipPolygons )
01122 {
01123 const QwtRect r = painter->window();
01124 polyline = r.clip(polyline);
01125 }
01126
01127 QwtPainter::drawPolyline(painter, polyline);
01128
01129 if ( d_data->brush.style() != Qt::NoBrush )
01130 fillCurve(painter, xMap, yMap, polyline);
01131 }
01132 else
01133 drawLines(painter, xMap, yMap, 0, size - 1);
01134 }
01135
01166 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
01167 {
01168 if ( bool(d_data->attributes & attribute) == on )
01169 return;
01170
01171 if ( on )
01172 d_data->attributes |= attribute;
01173 else
01174 d_data->attributes &= ~attribute;
01175
01176 itemChanged();
01177 }
01178
01183 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const
01184 {
01185 return d_data->attributes & attribute;
01186 }
01187
01193 void QwtPlotCurve::setSplineSize(int s)
01194 {
01195 d_data->splineSize = qwtMax(s, 10);
01196 itemChanged();
01197 }
01198
01205 int QwtPlotCurve::splineSize() const
01206 {
01207 return d_data->splineSize;
01208 }
01209
01222 void QwtPlotCurve::fillCurve(QPainter *painter,
01223 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01224 QwtPointArray &pa) const
01225 {
01226 if ( d_data->brush.style() == Qt::NoBrush )
01227 return;
01228
01229 closePolyline(xMap, yMap, pa);
01230 if ( pa.count() <= 2 )
01231 return;
01232
01233 QBrush b = d_data->brush;
01234 if ( !b.color().isValid() )
01235 b.setColor(d_data->pen.color());
01236
01237 painter->save();
01238
01239 painter->setPen(QPen(Qt::NoPen));
01240 painter->setBrush(b);
01241
01242 QwtPainter::drawPolygon(painter, pa);
01243
01244 painter->restore();
01245 }
01246
01256 void QwtPlotCurve::closePolyline(
01257 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01258 QwtPointArray &pa) const
01259 {
01260 const int sz = pa.size();
01261 if ( sz < 2 )
01262 return;
01263
01264 pa.resize(sz + 2);
01265
01266 if ( d_data->attributes & QwtPlotCurve::Xfy )
01267 {
01268 pa.setPoint(sz,
01269 xMap.transform(d_data->reference), pa.point(sz - 1).y());
01270 pa.setPoint(sz + 1,
01271 xMap.transform(d_data->reference), pa.point(0).y());
01272 }
01273 else
01274 {
01275 pa.setPoint(sz,
01276 pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01277 pa.setPoint(pa.size() - 1,
01278 pa.point(0).x(), yMap.transform(d_data->reference));
01279 }
01280 }
01281
01291 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01292 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01293 int from, int to) const
01294 {
01295 painter->setBrush(symbol.brush());
01296 painter->setPen(symbol.pen());
01297
01298 QRect rect;
01299 rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01300
01301 if ( to > from && d_data->paintAttributes & PaintFiltered )
01302 {
01303 const QRect window = painter->window();
01304 if ( window.isEmpty() )
01305 return;
01306
01307 PrivateData::PixelMatrix pixelMatrix(window);
01308
01309 for (int i = from; i <= to; i++)
01310 {
01311 const QPoint pi( xMap.transform(x(i)),
01312 yMap.transform(y(i)) );
01313
01314 if ( pixelMatrix.testPixel(pi) )
01315 {
01316 rect.moveCenter(pi);
01317 symbol.draw(painter, rect);
01318 }
01319 }
01320 }
01321 else
01322 {
01323 for (int i = from; i <= to; i++)
01324 {
01325 const int xi = xMap.transform(x(i));
01326 const int yi = yMap.transform(y(i));
01327
01328 rect.moveCenter(QPoint(xi, yi));
01329 symbol.draw(painter, rect);
01330 }
01331 }
01332 }
01333
01347 void QwtPlotCurve::setBaseline(double reference)
01348 {
01349 if ( d_data->reference != reference )
01350 {
01351 d_data->reference = reference;
01352 itemChanged();
01353 }
01354 }
01355
01360 double QwtPlotCurve::baseline() const
01361 {
01362 return d_data->reference;
01363 }
01364
01368 int QwtPlotCurve::dataSize() const
01369 {
01370 return d_xy->size();
01371 }
01372
01373 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01374 {
01375 if ( plot() == NULL || dataSize() <= 0 )
01376 return -1;
01377
01378 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01379 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01380
01381 int index = -1;
01382 double dmin = 1.0e10;
01383
01384 for (int i=0; i < dataSize(); i++)
01385 {
01386 const double cx = xMap.xTransform(x(i)) - pos.x();
01387 const double cy = yMap.xTransform(y(i)) - pos.y();
01388
01389 const double f = qwtSqr(cx) + qwtSqr(cy);
01390 if (f < dmin)
01391 {
01392 index = i;
01393 dmin = f;
01394 }
01395 }
01396 if ( dist )
01397 *dist = sqrt(dmin);
01398
01399 return index;
01400 }
01401
01402 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01403 {
01404 if ( !legend )
01405 return;
01406
01407 QwtPlotItem::updateLegend(legend);
01408
01409 QWidget *widget = legend->find(this);
01410 if ( !widget || !widget->inherits("QwtLegendItem") )
01411 return;
01412
01413 QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01414
01415 #if QT_VERSION < 0x040000
01416 const bool doUpdate = legendItem->isUpdatesEnabled();
01417 #else
01418 const bool doUpdate = legendItem->updatesEnabled();
01419 #endif
01420 legendItem->setUpdatesEnabled(false);
01421
01422 const int policy = legend->displayPolicy();
01423
01424 if (policy == QwtLegend::Fixed)
01425 {
01426 int mode = legend->identifierMode();
01427
01428 if (mode & QwtLegendItem::ShowLine)
01429 legendItem->setCurvePen(pen());
01430
01431 if (mode & QwtLegendItem::ShowSymbol)
01432 legendItem->setSymbol(symbol());
01433
01434 if (mode & QwtLegendItem::ShowText)
01435 legendItem->setText(title());
01436 else
01437 legendItem->setText(QwtText());
01438
01439 legendItem->setIdentifierMode(mode);
01440 }
01441 else if (policy == QwtLegend::Auto)
01442 {
01443 int mode = 0;
01444
01445 if (QwtPlotCurve::NoCurve != style())
01446 {
01447 legendItem->setCurvePen(pen());
01448 mode |= QwtLegendItem::ShowLine;
01449 }
01450 if (QwtSymbol::None != symbol().style())
01451 {
01452 legendItem->setSymbol(symbol());
01453 mode |= QwtLegendItem::ShowSymbol;
01454 }
01455 if ( !title().isEmpty() )
01456 {
01457 legendItem->setText(title());
01458 mode |= QwtLegendItem::ShowText;
01459 }
01460 else
01461 {
01462 legendItem->setText(QwtText());
01463 }
01464 legendItem->setIdentifierMode(mode);
01465 }
01466
01467 legendItem->setUpdatesEnabled(doUpdate);
01468 legendItem->update();
01469 }