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_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 #include <qguardedptr.h>
00030 #else
00031 #include <qpointer.h>
00032 #endif
00033
00034 #if QT_VERSION >= 0x040000
00035
00036 #include <qevent.h>
00037 #include <qpaintengine.h>
00038
00039 class QwtPlotCurvePaintHelper: public QObject
00040 {
00041 public:
00042 QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00043 _curve(curve),
00044 _from(from),
00045 _to(to)
00046 {
00047 }
00048
00049 virtual bool eventFilter(QObject *, QEvent *event)
00050 {
00051 if ( event->type() == QEvent::Paint )
00052 {
00053 _curve->draw(_from, _to);
00054 return true;
00055 }
00056 return false;
00057 }
00058 private:
00059 const QwtPlotCurve *_curve;
00060 int _from;
00061 int _to;
00062 };
00063
00064 #endif // QT_VERSION >= 0x040000
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 class QwtGuardedPainter: public QObject
00078 {
00079 public:
00080 ~QwtGuardedPainter()
00081 {
00082 end();
00083 }
00084
00085 QPainter *begin(QwtPlotCanvas *canvas)
00086 {
00087 _canvas = canvas;
00088
00089 QMap<QwtPlotCanvas *, QPainter *>::iterator it = _map.find(_canvas);
00090 if ( it == _map.end() )
00091 {
00092 QPainter *painter = new QPainter(_canvas);
00093 painter->setClipping(true);
00094 painter->setClipRect(_canvas->contentsRect());
00095
00096 it = _map.insert(_canvas, painter);
00097 _canvas->installEventFilter(this);
00098 }
00099 #if QT_VERSION < 0x040000
00100 return it.data();
00101 #else
00102 return it.value();
00103 #endif
00104 }
00105
00106 void end()
00107 {
00108 if ( _canvas )
00109 {
00110 QMap<QwtPlotCanvas *, QPainter *>::iterator it = _map.find(_canvas);
00111 if ( it != _map.end() )
00112 {
00113 _canvas->removeEventFilter(this);
00114
00115 #if QT_VERSION < 0x040000
00116 delete it.data();
00117 #else
00118 delete it.value();
00119 #endif
00120 _map.erase(it);
00121 }
00122 }
00123 }
00124
00125 virtual bool eventFilter(QObject *, QEvent *event)
00126 {
00127 if ( event->type() == QEvent::Paint )
00128 end();
00129
00130 return false;
00131 }
00132
00133 private:
00134 #if QT_VERSION < 0x040000
00135 QGuardedPtr<QwtPlotCanvas> _canvas;
00136 #else
00137 QPointer<QwtPlotCanvas> _canvas;
00138 #endif
00139 static QMap<QwtPlotCanvas *, QPainter *> _map;
00140 };
00141
00142 QMap<QwtPlotCanvas *, QPainter *> QwtGuardedPainter::_map;
00143
00144 static int verifyRange(int size, int &i1, int &i2)
00145 {
00146 if (size < 1)
00147 return 0;
00148
00149 i1 = qwtLim(i1, 0, size-1);
00150 i2 = qwtLim(i2, 0, size-1);
00151
00152 if ( i1 > i2 )
00153 qSwap(i1, i2);
00154
00155 return (i2 - i1 + 1);
00156 }
00157
00158 class QwtPlotCurve::PrivateData
00159 {
00160 public:
00161 class PixelMatrix: private QBitArray
00162 {
00163 public:
00164 PixelMatrix(const QRect& rect):
00165 QBitArray(rect.width() * rect.height()),
00166 _rect(rect)
00167 {
00168 fill(false);
00169 }
00170
00171 inline bool testPixel(const QPoint& pos)
00172 {
00173 if ( !_rect.contains(pos) )
00174 return false;
00175
00176 const int idx = _rect.width() * (pos.y() - _rect.y()) +
00177 (pos.x() - _rect.x());
00178
00179 const bool marked = testBit(idx);
00180 if ( !marked )
00181 setBit(idx, true);
00182
00183 return !marked;
00184 }
00185
00186 private:
00187 QRect _rect;
00188 };
00189
00190 PrivateData():
00191 curveType(Yfx),
00192 style(QwtPlotCurve::Lines),
00193 reference(0.0),
00194 attributes(0),
00195 paintAttributes(0)
00196 {
00197 symbol = new QwtSymbol();
00198 pen = QPen(Qt::black);
00199 curveFitter = new QwtSplineCurveFitter;
00200 }
00201
00202 ~PrivateData()
00203 {
00204 delete symbol;
00205 delete curveFitter;
00206 }
00207
00208 QwtPlotCurve::CurveType curveType;
00209 QwtPlotCurve::CurveStyle style;
00210 double reference;
00211
00212 QwtSymbol *symbol;
00213 QwtCurveFitter *curveFitter;
00214
00215 QPen pen;
00216 QBrush brush;
00217
00218 int attributes;
00219 int paintAttributes;
00220
00221 QwtGuardedPainter guardedPainter;
00222 };
00223
00225 QwtPlotCurve::QwtPlotCurve():
00226 QwtPlotItem(QwtText())
00227 {
00228 init();
00229 }
00230
00235 QwtPlotCurve::QwtPlotCurve(const QwtText &title):
00236 QwtPlotItem(title)
00237 {
00238 init();
00239 }
00240
00245 QwtPlotCurve::QwtPlotCurve(const QString &title):
00246 QwtPlotItem(QwtText(title))
00247 {
00248 init();
00249 }
00250
00252 QwtPlotCurve::~QwtPlotCurve()
00253 {
00254 delete d_xy;
00255 delete d_data;
00256 }
00257
00261 void QwtPlotCurve::init()
00262 {
00263 setItemAttribute(QwtPlotItem::Legend);
00264 setItemAttribute(QwtPlotItem::AutoScale);
00265
00266 d_data = new PrivateData;
00267 d_xy = new QwtPolygonFData(QwtArray<QwtDoublePoint>());
00268
00269 setZ(20.0);
00270 }
00271
00273 int QwtPlotCurve::rtti() const
00274 {
00275 return QwtPlotItem::Rtti_PlotCurve;
00276 }
00277
00285 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00286 {
00287 if ( on )
00288 d_data->paintAttributes |= attribute;
00289 else
00290 d_data->paintAttributes &= ~attribute;
00291 }
00292
00297 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00298 {
00299 return (d_data->paintAttributes & attribute);
00300 }
00301
00308 void QwtPlotCurve::setStyle(CurveStyle style)
00309 {
00310 if ( style != d_data->style )
00311 {
00312 d_data->style = style;
00313 itemChanged();
00314 }
00315 }
00316
00321 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00322 {
00323 return d_data->style;
00324 }
00325
00331 void QwtPlotCurve::setSymbol(const QwtSymbol &symbol )
00332 {
00333 delete d_data->symbol;
00334 d_data->symbol = symbol.clone();
00335 itemChanged();
00336 }
00337
00342 const QwtSymbol &QwtPlotCurve::symbol() const
00343 {
00344 return *d_data->symbol;
00345 }
00346
00356 void QwtPlotCurve::setPen(const QPen &pen)
00357 {
00358 if ( pen != d_data->pen )
00359 {
00360 d_data->pen = pen;
00361 itemChanged();
00362 }
00363 }
00364
00369 const QPen& QwtPlotCurve::pen() const
00370 {
00371 return d_data->pen;
00372 }
00373
00389 void QwtPlotCurve::setBrush(const QBrush &brush)
00390 {
00391 if ( brush != d_data->brush )
00392 {
00393 d_data->brush = brush;
00394 itemChanged();
00395 }
00396 }
00397
00402 const QBrush& QwtPlotCurve::brush() const
00403 {
00404 return d_data->brush;
00405 }
00406
00407
00419 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00420 {
00421 delete d_xy;
00422 d_xy = new QwtArrayData(xData, yData, size);
00423 itemChanged();
00424 }
00425
00435 void QwtPlotCurve::setData(const QwtArray<double> &xData,
00436 const QwtArray<double> &yData)
00437 {
00438 delete d_xy;
00439 d_xy = new QwtArrayData(xData, yData);
00440 itemChanged();
00441 }
00442
00449 #if QT_VERSION < 0x040000
00450 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00451 #else
00452 void QwtPlotCurve::setData(const QPolygonF &data)
00453 #endif
00454 {
00455 delete d_xy;
00456 d_xy = new QwtPolygonFData(data);
00457 itemChanged();
00458 }
00459
00466 void QwtPlotCurve::setData(const QwtData &data)
00467 {
00468 delete d_xy;
00469 d_xy = data.copy();
00470 itemChanged();
00471 }
00472
00486 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00487 {
00488 delete d_xy;
00489 d_xy = new QwtCPointerData(xData, yData, size);
00490 itemChanged();
00491 }
00492
00499 QwtDoubleRect QwtPlotCurve::boundingRect() const
00500 {
00501 if ( d_xy == NULL )
00502 return QwtDoubleRect(1.0, 1.0, -2.0, -2.0);
00503
00504 return d_xy->boundingRect();
00505 }
00506
00516 void QwtPlotCurve::draw(QPainter *painter,
00517 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00518 const QRect &) const
00519 {
00520 draw(painter, xMap, yMap, 0, -1);
00521 }
00522
00540 void QwtPlotCurve::draw(int from, int to) const
00541 {
00542 if ( !plot() )
00543 return;
00544
00545 QwtPlotCanvas *canvas = plot()->canvas();
00546
00547 #if QT_VERSION >= 0x040000
00548 #if 0
00549 if ( canvas->paintEngine()->type() == QPaintEngine::OpenGL )
00550 {
00551
00552
00553
00554
00555
00556 canvas->repaint();
00557 return;
00558 }
00559 #endif
00560
00561 if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00562 !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00563 {
00564
00565
00566
00567
00568
00569
00570
00571 QwtPlotCurvePaintHelper helper(this, from, to);
00572 canvas->installEventFilter(&helper);
00573
00574 const bool noSystemBackground =
00575 canvas->testAttribute(Qt::WA_NoSystemBackground);
00576 canvas->setAttribute(Qt::WA_NoSystemBackground, true);
00577 canvas->repaint();
00578 canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground);
00579
00580 return;
00581 }
00582 #endif
00583
00584 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00585 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00586
00587 if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00588 canvas->paintCache() && !canvas->paintCache()->isNull() )
00589 {
00590 QPainter cachePainter((QPixmap *)canvas->paintCache());
00591 cachePainter.translate(-canvas->contentsRect().x(),
00592 -canvas->contentsRect().y());
00593
00594 draw(&cachePainter, xMap, yMap, from, to);
00595 }
00596
00597 #if QT_VERSION >= 0x040000
00598 if ( canvas->testAttribute(Qt::WA_WState_InPaintEvent) )
00599 {
00600 QPainter painter(canvas);
00601
00602 painter.setClipping(true);
00603 painter.setClipRect(canvas->contentsRect());
00604
00605 draw(&painter, xMap, yMap, from, to);
00606 }
00607 else
00608 #endif
00609 {
00610 QPainter *painter = d_data->guardedPainter.begin(canvas);
00611 draw(painter, xMap, yMap, from, to);
00612 }
00613 }
00614
00626 void QwtPlotCurve::draw(QPainter *painter,
00627 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00628 int from, int to) const
00629 {
00630 if ( !painter || dataSize() <= 0 )
00631 return;
00632
00633 if (to < 0)
00634 to = dataSize() - 1;
00635
00636 if ( verifyRange(dataSize(), from, to) > 0 )
00637 {
00638 painter->save();
00639 painter->setPen(QwtPainter::scaledPen(d_data->pen));
00640
00641
00642
00643
00644
00645
00646
00647 drawCurve(painter, d_data->style, xMap, yMap, from, to);
00648 painter->restore();
00649
00650 if (d_data->symbol->style() != QwtSymbol::NoSymbol)
00651 {
00652 painter->save();
00653 drawSymbols(painter, *d_data->symbol, xMap, yMap, from, to);
00654 painter->restore();
00655 }
00656 }
00657 }
00658
00670 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00671 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00672 int from, int to) const
00673 {
00674 switch (style)
00675 {
00676 case Lines:
00677 if ( testCurveAttribute(Fitted) )
00678 {
00679
00680
00681 from = 0;
00682 to = dataSize() - 1;
00683 }
00684 drawLines(painter, xMap, yMap, from, to);
00685 break;
00686 case Sticks:
00687 drawSticks(painter, xMap, yMap, from, to);
00688 break;
00689 case Steps:
00690 drawSteps(painter, xMap, yMap, from, to);
00691 break;
00692 case Dots:
00693 drawDots(painter, xMap, yMap, from, to);
00694 break;
00695 case NoCurve:
00696 default:
00697 break;
00698 }
00699 }
00700
00716 void QwtPlotCurve::drawLines(QPainter *painter,
00717 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00718 int from, int to) const
00719 {
00720 int size = to - from + 1;
00721 if ( size <= 0 )
00722 return;
00723
00724 QwtPolygon polyline;
00725 if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00726 {
00727
00728
00729
00730
00731 #if QT_VERSION < 0x040000
00732 QwtArray<QwtDoublePoint> points(size);
00733 #else
00734 QPolygonF points(size);
00735 #endif
00736 for (int i = from; i <= to; i++)
00737 {
00738 QwtDoublePoint &p = points[i];
00739 p.setX( xMap.xTransform(x(i)) );
00740 p.setY( yMap.xTransform(y(i)) );
00741 }
00742
00743 points = d_data->curveFitter->fitCurve(points);
00744 size = points.size();
00745
00746 if ( size == 0 )
00747 return;
00748
00749
00750
00751
00752
00753
00754 polyline.resize(size);
00755
00756 const QwtDoublePoint *p = points.data();
00757 QPoint *pl = polyline.data();
00758 if ( d_data->paintAttributes & PaintFiltered )
00759 {
00760
00761 QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00762 pl[0] = pp;
00763
00764 int count = 1;
00765 for (int i = 1; i < size; i++)
00766 {
00767 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00768 if ( pi != pp )
00769 {
00770 pl[count++] = pi;
00771 pp = pi;
00772 }
00773 }
00774 if ( count != size )
00775 polyline.resize(count);
00776 }
00777 else
00778 {
00779 for ( int i = 0; i < size; i++ )
00780 {
00781 pl[i].setX( qRound(p[i].x()) );
00782 pl[i].setY( qRound(p[i].y()) );
00783 }
00784 }
00785 }
00786 else
00787 {
00788 polyline.resize(size);
00789
00790 if ( d_data->paintAttributes & PaintFiltered )
00791 {
00792 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00793 polyline.setPoint(0, pp);
00794
00795 int count = 1;
00796 for (int i = from + 1; i <= to; i++)
00797 {
00798 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00799 if ( pi != pp )
00800 {
00801 polyline.setPoint(count, pi);
00802 count++;
00803
00804 pp = pi;
00805 }
00806 }
00807 if ( count != size )
00808 polyline.resize(count);
00809 }
00810 else
00811 {
00812 for (int i = from; i <= to; i++)
00813 {
00814 int xi = xMap.transform(x(i));
00815 int yi = yMap.transform(y(i));
00816
00817 polyline.setPoint(i - from, xi, yi);
00818 }
00819 }
00820 }
00821
00822 if ( d_data->paintAttributes & ClipPolygons )
00823 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00824
00825 QwtPainter::drawPolyline(painter, polyline);
00826
00827 if ( d_data->brush.style() != Qt::NoBrush )
00828 fillCurve(painter, xMap, yMap, polyline);
00829 }
00830
00842 void QwtPlotCurve::drawSticks(QPainter *painter,
00843 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00844 int from, int to) const
00845 {
00846 int x0 = xMap.transform(d_data->reference);
00847 int y0 = yMap.transform(d_data->reference);
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
00854 if (d_data->curveType == Xfy)
00855 QwtPainter::drawLine(painter, x0, yi, xi, yi);
00856 else
00857 QwtPainter::drawLine(painter, xi, y0, xi, yi);
00858 }
00859 }
00860
00872 void QwtPlotCurve::drawDots(QPainter *painter,
00873 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00874 int from, int to) const
00875 {
00876 const QRect window = painter->window();
00877 if ( window.isEmpty() )
00878 return;
00879
00880 const bool doFill = d_data->brush.style() != Qt::NoBrush;
00881
00882 QwtPolygon polyline;
00883 if ( doFill )
00884 polyline.resize(to - from + 1);
00885
00886 if ( to > from && d_data->paintAttributes & PaintFiltered )
00887 {
00888 if ( doFill )
00889 {
00890 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00891
00892 QwtPainter::drawPoint(painter, pp.x(), pp.y());
00893 polyline.setPoint(0, pp);
00894
00895 int count = 1;
00896 for (int i = from + 1; i <= to; i++)
00897 {
00898 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00899 if ( pi != pp )
00900 {
00901 QwtPainter::drawPoint(painter, pi.x(), pi.y());
00902
00903 polyline.setPoint(count, pi);
00904 count++;
00905
00906 pp = pi;
00907 }
00908 }
00909 if ( int(polyline.size()) != count )
00910 polyline.resize(count);
00911 }
00912 else
00913 {
00914
00915
00916
00917 PrivateData::PixelMatrix pixelMatrix(window);
00918
00919 for (int i = from; i <= to; i++)
00920 {
00921 const QPoint p( xMap.transform(x(i)),
00922 yMap.transform(y(i)) );
00923
00924 if ( pixelMatrix.testPixel(p) )
00925 QwtPainter::drawPoint(painter, p.x(), p.y());
00926 }
00927 }
00928 }
00929 else
00930 {
00931 for (int i = from; i <= to; i++)
00932 {
00933 const int xi = xMap.transform(x(i));
00934 const int yi = yMap.transform(y(i));
00935 QwtPainter::drawPoint(painter, xi, yi);
00936
00937 if ( doFill )
00938 polyline.setPoint(i - from, xi, yi);
00939 }
00940 }
00941
00942 if ( doFill )
00943 {
00944 if ( d_data->paintAttributes & ClipPolygons )
00945 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00946
00947 fillCurve(painter, xMap, yMap, polyline);
00948 }
00949 }
00950
00965 void QwtPlotCurve::drawSteps(QPainter *painter,
00966 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00967 int from, int to) const
00968 {
00969 QwtPolygon polyline(2 * (to - from) + 1);
00970
00971 bool inverted = d_data->curveType == Yfx;
00972 if ( d_data->attributes & Inverted )
00973 inverted = !inverted;
00974
00975 int i,ip;
00976 for (i = from, ip = 0; i <= to; i++, ip += 2)
00977 {
00978 const int xi = xMap.transform(x(i));
00979 const int yi = yMap.transform(y(i));
00980
00981 if ( ip > 0 )
00982 {
00983 if (inverted)
00984 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00985 else
00986 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00987 }
00988
00989 polyline.setPoint(ip, xi, yi);
00990 }
00991
00992 if ( d_data->paintAttributes & ClipPolygons )
00993 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00994
00995 QwtPainter::drawPolyline(painter, polyline);
00996
00997 if ( d_data->brush.style() != Qt::NoBrush )
00998 fillCurve(painter, xMap, yMap, polyline);
00999 }
01000
01001
01010 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
01011 {
01012 if ( bool(d_data->attributes & attribute) == on )
01013 return;
01014
01015 if ( on )
01016 d_data->attributes |= attribute;
01017 else
01018 d_data->attributes &= ~attribute;
01019
01020 itemChanged();
01021 }
01022
01027 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const
01028 {
01029 return d_data->attributes & attribute;
01030 }
01031
01038 void QwtPlotCurve::setCurveType(CurveType curveType)
01039 {
01040 if ( d_data->curveType != curveType )
01041 {
01042 d_data->curveType = curveType;
01043 itemChanged();
01044 }
01045 }
01046
01051 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01052 {
01053 return d_data->curveType;
01054 }
01055
01062 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01063 {
01064 delete d_data->curveFitter;
01065 d_data->curveFitter = curveFitter;
01066
01067 itemChanged();
01068 }
01069
01074 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01075 {
01076 return d_data->curveFitter;
01077 }
01078
01090 void QwtPlotCurve::fillCurve(QPainter *painter,
01091 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01092 QwtPolygon &pa) const
01093 {
01094 if ( d_data->brush.style() == Qt::NoBrush )
01095 return;
01096
01097 closePolyline(xMap, yMap, pa);
01098 if ( pa.count() <= 2 )
01099 return;
01100
01101 QBrush b = d_data->brush;
01102 if ( !b.color().isValid() )
01103 b.setColor(d_data->pen.color());
01104
01105 painter->save();
01106
01107 painter->setPen(QPen(Qt::NoPen));
01108 painter->setBrush(b);
01109
01110 QwtPainter::drawPolygon(painter, pa);
01111
01112 painter->restore();
01113 }
01114
01123 void QwtPlotCurve::closePolyline(
01124 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01125 QwtPolygon &pa) const
01126 {
01127 const int sz = pa.size();
01128 if ( sz < 2 )
01129 return;
01130
01131 pa.resize(sz + 2);
01132
01133 if ( d_data->curveType == QwtPlotCurve::Xfy )
01134 {
01135 pa.setPoint(sz,
01136 xMap.transform(d_data->reference), pa.point(sz - 1).y());
01137 pa.setPoint(sz + 1,
01138 xMap.transform(d_data->reference), pa.point(0).y());
01139 }
01140 else
01141 {
01142 pa.setPoint(sz,
01143 pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01144 pa.setPoint(pa.size() - 1,
01145 pa.point(0).x(), yMap.transform(d_data->reference));
01146 }
01147 }
01148
01160 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01161 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01162 int from, int to) const
01163 {
01164 painter->setBrush(symbol.brush());
01165 painter->setPen(QwtPainter::scaledPen(symbol.pen()));
01166
01167 const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
01168
01169 QRect rect;
01170 rect.setSize(metricsMap.screenToLayout(symbol.size()));
01171
01172 if ( to > from && d_data->paintAttributes & PaintFiltered )
01173 {
01174 const QRect window = painter->window();
01175 if ( window.isEmpty() )
01176 return;
01177
01178 PrivateData::PixelMatrix pixelMatrix(window);
01179
01180 for (int i = from; i <= to; i++)
01181 {
01182 const QPoint pi( xMap.transform(x(i)),
01183 yMap.transform(y(i)) );
01184
01185 if ( pixelMatrix.testPixel(pi) )
01186 {
01187 rect.moveCenter(pi);
01188 symbol.draw(painter, rect);
01189 }
01190 }
01191 }
01192 else
01193 {
01194 for (int i = from; i <= to; i++)
01195 {
01196 const int xi = xMap.transform(x(i));
01197 const int yi = yMap.transform(y(i));
01198
01199 rect.moveCenter(QPoint(xi, yi));
01200 symbol.draw(painter, rect);
01201 }
01202 }
01203 }
01204
01218 void QwtPlotCurve::setBaseline(double reference)
01219 {
01220 if ( d_data->reference != reference )
01221 {
01222 d_data->reference = reference;
01223 itemChanged();
01224 }
01225 }
01226
01231 double QwtPlotCurve::baseline() const
01232 {
01233 return d_data->reference;
01234 }
01235
01240 int QwtPlotCurve::dataSize() const
01241 {
01242 return d_xy->size();
01243 }
01244
01256 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01257 {
01258 if ( plot() == NULL || dataSize() <= 0 )
01259 return -1;
01260
01261 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01262 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01263
01264 int index = -1;
01265 double dmin = 1.0e10;
01266
01267 for (int i=0; i < dataSize(); i++)
01268 {
01269 const double cx = xMap.xTransform(x(i)) - pos.x();
01270 const double cy = yMap.xTransform(y(i)) - pos.y();
01271
01272 const double f = qwtSqr(cx) + qwtSqr(cy);
01273 if (f < dmin)
01274 {
01275 index = i;
01276 dmin = f;
01277 }
01278 }
01279 if ( dist )
01280 *dist = sqrt(dmin);
01281
01282 return index;
01283 }
01284
01286 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01287 {
01288 if ( !legend )
01289 return;
01290
01291 QwtPlotItem::updateLegend(legend);
01292
01293 QWidget *widget = legend->find(this);
01294 if ( !widget || !widget->inherits("QwtLegendItem") )
01295 return;
01296
01297 QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01298
01299 #if QT_VERSION < 0x040000
01300 const bool doUpdate = legendItem->isUpdatesEnabled();
01301 #else
01302 const bool doUpdate = legendItem->updatesEnabled();
01303 #endif
01304 legendItem->setUpdatesEnabled(false);
01305
01306 const int policy = legend->displayPolicy();
01307
01308 if (policy == QwtLegend::FixedIdentifier)
01309 {
01310 int mode = legend->identifierMode();
01311
01312 if (mode & QwtLegendItem::ShowLine)
01313 legendItem->setCurvePen(pen());
01314
01315 if (mode & QwtLegendItem::ShowSymbol)
01316 legendItem->setSymbol(symbol());
01317
01318 if (mode & QwtLegendItem::ShowText)
01319 legendItem->setText(title());
01320 else
01321 legendItem->setText(QwtText());
01322
01323 legendItem->setIdentifierMode(mode);
01324 }
01325 else if (policy == QwtLegend::AutoIdentifier)
01326 {
01327 int mode = 0;
01328
01329 if (QwtPlotCurve::NoCurve != style())
01330 {
01331 legendItem->setCurvePen(pen());
01332 mode |= QwtLegendItem::ShowLine;
01333 }
01334 if (QwtSymbol::NoSymbol != symbol().style())
01335 {
01336 legendItem->setSymbol(symbol());
01337 mode |= QwtLegendItem::ShowSymbol;
01338 }
01339 if ( !title().isEmpty() )
01340 {
01341 legendItem->setText(title());
01342 mode |= QwtLegendItem::ShowText;
01343 }
01344 else
01345 {
01346 legendItem->setText(QwtText());
01347 }
01348 legendItem->setIdentifierMode(mode);
01349 }
01350
01351 legendItem->setUpdatesEnabled(doUpdate);
01352 legendItem->update();
01353 }