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 #define SCALE_PEN 0
00029
00030 #if QT_VERSION < 0x040000
00031 #include <qguardedptr.h>
00032 #else
00033 #include <qpointer.h>
00034 #endif
00035
00036 #if QT_VERSION >= 0x040000
00037
00038 #include <qevent.h>
00039 #include <qpaintengine.h>
00040
00041 class QwtPlotCurvePaintHelper: public QObject
00042 {
00043 public:
00044 QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00045 _curve(curve),
00046 _from(from),
00047 _to(to)
00048 {
00049 }
00050
00051 virtual bool eventFilter(QObject *, QEvent *event)
00052 {
00053 if ( event->type() == QEvent::Paint )
00054 {
00055 _curve->draw(_from, _to);
00056 return true;
00057 }
00058 return false;
00059 }
00060 private:
00061 const QwtPlotCurve *_curve;
00062 int _from;
00063 int _to;
00064 };
00065
00066 #endif // QT_VERSION >= 0x040000
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 class QwtGuardedPainter: public QObject
00080 {
00081 public:
00082 ~QwtGuardedPainter()
00083 {
00084 end();
00085 }
00086
00087 QPainter *begin(QwtPlotCanvas *canvas)
00088 {
00089 _canvas = canvas;
00090
00091 QMap<QwtPlotCanvas *, QPainter *>::iterator it = _map.find(_canvas);
00092 if ( it == _map.end() )
00093 {
00094 QPainter *painter = new QPainter(_canvas);
00095 painter->setClipping(true);
00096 painter->setClipRect(_canvas->contentsRect());
00097
00098 it = _map.insert(_canvas, painter);
00099 _canvas->installEventFilter(this);
00100 }
00101 #if QT_VERSION < 0x040000
00102 return it.data();
00103 #else
00104 return it.value();
00105 #endif
00106 }
00107
00108 void end()
00109 {
00110 if ( _canvas )
00111 {
00112 QMap<QwtPlotCanvas *, QPainter *>::iterator it = _map.find(_canvas);
00113 if ( it != _map.end() )
00114 {
00115 _canvas->removeEventFilter(this);
00116
00117 #if QT_VERSION < 0x040000
00118 delete it.data();
00119 #else
00120 delete it.value();
00121 #endif
00122 _map.erase(it);
00123 }
00124 }
00125 }
00126
00127 virtual bool eventFilter(QObject *, QEvent *event)
00128 {
00129 if ( event->type() == QEvent::Paint )
00130 end();
00131
00132 return false;
00133 }
00134
00135 private:
00136 #if QT_VERSION < 0x040000
00137 QGuardedPtr<QwtPlotCanvas> _canvas;
00138 #else
00139 QPointer<QwtPlotCanvas> _canvas;
00140 #endif
00141 static QMap<QwtPlotCanvas *, QPainter *> _map;
00142 };
00143
00144 QMap<QwtPlotCanvas *, QPainter *> QwtGuardedPainter::_map;
00145
00146 static QwtPolygon clipPolygon(QPainter *painter, int attributes,
00147 const QwtPolygon &polygon)
00148 {
00149 bool doClipping = attributes & QwtPlotCurve::ClipPolygons;
00150 QRect clipRect = painter->window();
00151
00152 if ( !doClipping )
00153 {
00154 #if QT_VERSION >= 0x040000
00155 const QPaintEngine *pe = painter->paintEngine();
00156 if ( pe && pe->type() == QPaintEngine::SVG )
00157 #else
00158 if ( painter->device()->devType() == QInternal::Picture )
00159 #endif
00160 {
00161
00162
00163
00164 doClipping = true;
00165 if ( painter->hasClipping() )
00166 clipRect &= painter->clipRegion().boundingRect();
00167 }
00168 }
00169
00170 if ( doClipping )
00171 return QwtClipper::clipPolygon(clipRect, polygon);
00172
00173 return polygon;
00174 }
00175
00176 static int verifyRange(int size, int &i1, int &i2)
00177 {
00178 if (size < 1)
00179 return 0;
00180
00181 i1 = qwtLim(i1, 0, size-1);
00182 i2 = qwtLim(i2, 0, size-1);
00183
00184 if ( i1 > i2 )
00185 qSwap(i1, i2);
00186
00187 return (i2 - i1 + 1);
00188 }
00189
00190 class QwtPlotCurve::PrivateData
00191 {
00192 public:
00193 class PixelMatrix: private QBitArray
00194 {
00195 public:
00196 PixelMatrix(const QRect& rect):
00197 QBitArray(rect.width() * rect.height()),
00198 _rect(rect)
00199 {
00200 fill(false);
00201 }
00202
00203 inline bool testPixel(const QPoint& pos)
00204 {
00205 if ( !_rect.contains(pos) )
00206 return false;
00207
00208 const int idx = _rect.width() * (pos.y() - _rect.y()) +
00209 (pos.x() - _rect.x());
00210
00211 const bool marked = testBit(idx);
00212 if ( !marked )
00213 setBit(idx, true);
00214
00215 return !marked;
00216 }
00217
00218 private:
00219 QRect _rect;
00220 };
00221
00222 PrivateData():
00223 curveType(Yfx),
00224 style(QwtPlotCurve::Lines),
00225 reference(0.0),
00226 attributes(0),
00227 paintAttributes(0)
00228 {
00229 symbol = new QwtSymbol();
00230 pen = QPen(Qt::black);
00231 curveFitter = new QwtSplineCurveFitter;
00232 }
00233
00234 ~PrivateData()
00235 {
00236 delete symbol;
00237 delete curveFitter;
00238 }
00239
00240 QwtPlotCurve::CurveType curveType;
00241 QwtPlotCurve::CurveStyle style;
00242 double reference;
00243
00244 QwtSymbol *symbol;
00245 QwtCurveFitter *curveFitter;
00246
00247 QPen pen;
00248 QBrush brush;
00249
00250 int attributes;
00251 int paintAttributes;
00252
00253 QwtGuardedPainter guardedPainter;
00254 };
00255
00257 QwtPlotCurve::QwtPlotCurve():
00258 QwtPlotItem(QwtText())
00259 {
00260 init();
00261 }
00262
00267 QwtPlotCurve::QwtPlotCurve(const QwtText &title):
00268 QwtPlotItem(title)
00269 {
00270 init();
00271 }
00272
00277 QwtPlotCurve::QwtPlotCurve(const QString &title):
00278 QwtPlotItem(QwtText(title))
00279 {
00280 init();
00281 }
00282
00284 QwtPlotCurve::~QwtPlotCurve()
00285 {
00286 delete d_xy;
00287 delete d_data;
00288 }
00289
00293 void QwtPlotCurve::init()
00294 {
00295 setItemAttribute(QwtPlotItem::Legend);
00296 setItemAttribute(QwtPlotItem::AutoScale);
00297
00298 d_data = new PrivateData;
00299 d_xy = new QwtPolygonFData(QwtArray<QwtDoublePoint>());
00300
00301 setZ(20.0);
00302 }
00303
00305 int QwtPlotCurve::rtti() const
00306 {
00307 return QwtPlotItem::Rtti_PlotCurve;
00308 }
00309
00333 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00334 {
00335 if ( on )
00336 d_data->paintAttributes |= attribute;
00337 else
00338 d_data->paintAttributes &= ~attribute;
00339 }
00340
00345 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00346 {
00347 return (d_data->paintAttributes & attribute);
00348 }
00349
00377 void QwtPlotCurve::setStyle(CurveStyle style)
00378 {
00379 if ( style != d_data->style )
00380 {
00381 d_data->style = style;
00382 itemChanged();
00383 }
00384 }
00385
00390 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00391 {
00392 return d_data->style;
00393 }
00394
00400 void QwtPlotCurve::setSymbol(const QwtSymbol &symbol )
00401 {
00402 delete d_data->symbol;
00403 d_data->symbol = symbol.clone();
00404 itemChanged();
00405 }
00406
00411 const QwtSymbol &QwtPlotCurve::symbol() const
00412 {
00413 return *d_data->symbol;
00414 }
00415
00421 void QwtPlotCurve::setPen(const QPen &pen)
00422 {
00423 if ( pen != d_data->pen )
00424 {
00425 d_data->pen = pen;
00426 itemChanged();
00427 }
00428 }
00429
00434 const QPen& QwtPlotCurve::pen() const
00435 {
00436 return d_data->pen;
00437 }
00438
00451 void QwtPlotCurve::setBrush(const QBrush &brush)
00452 {
00453 if ( brush != d_data->brush )
00454 {
00455 d_data->brush = brush;
00456 itemChanged();
00457 }
00458 }
00459
00464 const QBrush& QwtPlotCurve::brush() const
00465 {
00466 return d_data->brush;
00467 }
00468
00469
00481 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00482 {
00483 delete d_xy;
00484 d_xy = new QwtArrayData(xData, yData, size);
00485 itemChanged();
00486 }
00487
00496 void QwtPlotCurve::setData(const QwtArray<double> &xData,
00497 const QwtArray<double> &yData)
00498 {
00499 delete d_xy;
00500 d_xy = new QwtArrayData(xData, yData);
00501 itemChanged();
00502 }
00503
00510 #if QT_VERSION < 0x040000
00511 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00512 #else
00513 void QwtPlotCurve::setData(const QPolygonF &data)
00514 #endif
00515 {
00516 delete d_xy;
00517 d_xy = new QwtPolygonFData(data);
00518 itemChanged();
00519 }
00520
00527 void QwtPlotCurve::setData(const QwtData &data)
00528 {
00529 delete d_xy;
00530 d_xy = data.copy();
00531 itemChanged();
00532 }
00533
00547 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00548 {
00549 delete d_xy;
00550 d_xy = new QwtCPointerData(xData, yData, size);
00551 itemChanged();
00552 }
00553
00560 QwtDoubleRect QwtPlotCurve::boundingRect() const
00561 {
00562 if ( d_xy == NULL )
00563 return QwtDoubleRect(1.0, 1.0, -2.0, -2.0);
00564
00565 return d_xy->boundingRect();
00566 }
00567
00577 void QwtPlotCurve::draw(QPainter *painter,
00578 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00579 const QRect &) const
00580 {
00581 draw(painter, xMap, yMap, 0, -1);
00582 }
00583
00601 void QwtPlotCurve::draw(int from, int to) const
00602 {
00603 if ( !plot() )
00604 return;
00605
00606 QwtPlotCanvas *canvas = plot()->canvas();
00607
00608 #if QT_VERSION >= 0x040000
00609 #if 0
00610 if ( canvas->paintEngine()->type() == QPaintEngine::OpenGL )
00611 {
00612
00613
00614
00615
00616
00617 canvas->repaint();
00618 return;
00619 }
00620 #endif
00621
00622 if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00623 !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00624 {
00625
00626
00627
00628
00629
00630
00631
00632 QwtPlotCurvePaintHelper helper(this, from, to);
00633 canvas->installEventFilter(&helper);
00634
00635 const bool noSystemBackground =
00636 canvas->testAttribute(Qt::WA_NoSystemBackground);
00637 canvas->setAttribute(Qt::WA_NoSystemBackground, true);
00638 canvas->repaint();
00639 canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground);
00640
00641 return;
00642 }
00643 #endif
00644
00645 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00646 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00647
00648 if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00649 canvas->paintCache() && !canvas->paintCache()->isNull() )
00650 {
00651 QPainter cachePainter((QPixmap *)canvas->paintCache());
00652 cachePainter.translate(-canvas->contentsRect().x(),
00653 -canvas->contentsRect().y());
00654
00655 draw(&cachePainter, xMap, yMap, from, to);
00656 }
00657
00658 #if QT_VERSION >= 0x040000
00659 if ( canvas->testAttribute(Qt::WA_WState_InPaintEvent) )
00660 {
00661 QPainter painter(canvas);
00662
00663 painter.setClipping(true);
00664 painter.setClipRect(canvas->contentsRect());
00665
00666 draw(&painter, xMap, yMap, from, to);
00667 }
00668 else
00669 #endif
00670 {
00671 QPainter *painter = d_data->guardedPainter.begin(canvas);
00672 draw(painter, xMap, yMap, from, to);
00673 }
00674 }
00675
00687 void QwtPlotCurve::draw(QPainter *painter,
00688 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00689 int from, int to) const
00690 {
00691 if ( !painter || dataSize() <= 0 )
00692 return;
00693
00694 if (to < 0)
00695 to = dataSize() - 1;
00696
00697 if ( verifyRange(dataSize(), from, to) > 0 )
00698 {
00699 painter->save();
00700
00701 QPen pen = d_data->pen;
00702
00703 #if SCALE_PEN
00704 if ( pen.width() > 0 )
00705 {
00706 const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
00707 pen.setWidth(metricsMap.screenToLayoutX(pen.width()));
00708 }
00709 #endif
00710
00711 painter->setPen(pen);
00712
00713
00714
00715
00716
00717
00718
00719 drawCurve(painter, d_data->style, xMap, yMap, from, to);
00720 painter->restore();
00721
00722 if (d_data->symbol->style() != QwtSymbol::NoSymbol)
00723 {
00724 painter->save();
00725 drawSymbols(painter, *d_data->symbol, xMap, yMap, from, to);
00726 painter->restore();
00727 }
00728 }
00729 }
00730
00742 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00743 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00744 int from, int to) const
00745 {
00746 switch (style)
00747 {
00748 case Lines:
00749 if ( testCurveAttribute(Fitted) )
00750 {
00751
00752
00753 from = 0;
00754 to = dataSize() - 1;
00755 }
00756 drawLines(painter, xMap, yMap, from, to);
00757 break;
00758 case Sticks:
00759 drawSticks(painter, xMap, yMap, from, to);
00760 break;
00761 case Steps:
00762 drawSteps(painter, xMap, yMap, from, to);
00763 break;
00764 case Dots:
00765 drawDots(painter, xMap, yMap, from, to);
00766 break;
00767 case NoCurve:
00768 default:
00769 break;
00770 }
00771 }
00772
00788 void QwtPlotCurve::drawLines(QPainter *painter,
00789 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00790 int from, int to) const
00791 {
00792 int size = to - from + 1;
00793 if ( size <= 0 )
00794 return;
00795
00796 QwtPolygon polyline;
00797 if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00798 {
00799
00800
00801
00802
00803 #if QT_VERSION < 0x040000
00804 QwtArray<QwtDoublePoint> points(size);
00805 #else
00806 QPolygonF points(size);
00807 #endif
00808 for (int i = from; i <= to; i++)
00809 {
00810 QwtDoublePoint &p = points[i];
00811 p.setX( xMap.xTransform(x(i)) );
00812 p.setY( yMap.xTransform(y(i)) );
00813 }
00814
00815 points = d_data->curveFitter->fitCurve(points);
00816 size = points.size();
00817
00818 if ( size == 0 )
00819 return;
00820
00821
00822
00823
00824
00825
00826 polyline.resize(size);
00827
00828 const QwtDoublePoint *p = points.data();
00829 QPoint *pl = polyline.data();
00830 if ( d_data->paintAttributes & PaintFiltered )
00831 {
00832
00833 QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00834 pl[0] = pp;
00835
00836 int count = 1;
00837 for (int i = 1; i < size; i++)
00838 {
00839 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00840 if ( pi != pp )
00841 {
00842 pl[count++] = pi;
00843 pp = pi;
00844 }
00845 }
00846 if ( count != size )
00847 polyline.resize(count);
00848 }
00849 else
00850 {
00851 for ( int i = 0; i < size; i++ )
00852 {
00853 pl[i].setX( qRound(p[i].x()) );
00854 pl[i].setY( qRound(p[i].y()) );
00855 }
00856 }
00857 }
00858 else
00859 {
00860 polyline.resize(size);
00861
00862 if ( d_data->paintAttributes & PaintFiltered )
00863 {
00864 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00865 polyline.setPoint(0, pp);
00866
00867 int count = 1;
00868 for (int i = from + 1; i <= to; i++)
00869 {
00870 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00871 if ( pi != pp )
00872 {
00873 polyline.setPoint(count, pi);
00874 count++;
00875
00876 pp = pi;
00877 }
00878 }
00879 if ( count != size )
00880 polyline.resize(count);
00881 }
00882 else
00883 {
00884 for (int i = from; i <= to; i++)
00885 {
00886 int xi = xMap.transform(x(i));
00887 int yi = yMap.transform(y(i));
00888
00889 polyline.setPoint(i - from, xi, yi);
00890 }
00891 }
00892 }
00893
00894 polyline = ::clipPolygon(painter, d_data->paintAttributes, polyline);
00895
00896 QwtPainter::drawPolyline(painter, polyline);
00897
00898 if ( d_data->brush.style() != Qt::NoBrush )
00899 fillCurve(painter, xMap, yMap, polyline);
00900 }
00901
00913 void QwtPlotCurve::drawSticks(QPainter *painter,
00914 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00915 int from, int to) const
00916 {
00917 int x0 = xMap.transform(d_data->reference);
00918 int y0 = yMap.transform(d_data->reference);
00919
00920 for (int i = from; i <= to; i++)
00921 {
00922 const int xi = xMap.transform(x(i));
00923 const int yi = yMap.transform(y(i));
00924
00925 if (d_data->curveType == Xfy)
00926 QwtPainter::drawLine(painter, x0, yi, xi, yi);
00927 else
00928 QwtPainter::drawLine(painter, xi, y0, xi, yi);
00929 }
00930 }
00931
00943 void QwtPlotCurve::drawDots(QPainter *painter,
00944 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00945 int from, int to) const
00946 {
00947 const QRect window = painter->window();
00948 if ( window.isEmpty() )
00949 return;
00950
00951 const bool doFill = d_data->brush.style() != Qt::NoBrush;
00952
00953 QwtPolygon polyline;
00954 if ( doFill )
00955 polyline.resize(to - from + 1);
00956
00957 if ( to > from && d_data->paintAttributes & PaintFiltered )
00958 {
00959 if ( doFill )
00960 {
00961 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00962
00963 QwtPainter::drawPoint(painter, pp.x(), pp.y());
00964 polyline.setPoint(0, pp);
00965
00966 int count = 1;
00967 for (int i = from + 1; i <= to; i++)
00968 {
00969 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00970 if ( pi != pp )
00971 {
00972 QwtPainter::drawPoint(painter, pi.x(), pi.y());
00973
00974 polyline.setPoint(count, pi);
00975 count++;
00976
00977 pp = pi;
00978 }
00979 }
00980 if ( int(polyline.size()) != count )
00981 polyline.resize(count);
00982 }
00983 else
00984 {
00985
00986
00987
00988 PrivateData::PixelMatrix pixelMatrix(window);
00989
00990 for (int i = from; i <= to; i++)
00991 {
00992 const QPoint p( xMap.transform(x(i)),
00993 yMap.transform(y(i)) );
00994
00995 if ( pixelMatrix.testPixel(p) )
00996 QwtPainter::drawPoint(painter, p.x(), p.y());
00997 }
00998 }
00999 }
01000 else
01001 {
01002 for (int i = from; i <= to; i++)
01003 {
01004 const int xi = xMap.transform(x(i));
01005 const int yi = yMap.transform(y(i));
01006 QwtPainter::drawPoint(painter, xi, yi);
01007
01008 if ( doFill )
01009 polyline.setPoint(i - from, xi, yi);
01010 }
01011 }
01012
01013 if ( doFill )
01014 {
01015 polyline = ::clipPolygon(painter, d_data->paintAttributes, polyline);
01016 fillCurve(painter, xMap, yMap, polyline);
01017 }
01018 }
01019
01034 void QwtPlotCurve::drawSteps(QPainter *painter,
01035 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01036 int from, int to) const
01037 {
01038 QwtPolygon polyline(2 * (to - from) + 1);
01039
01040 bool inverted = d_data->curveType == Yfx;
01041 if ( d_data->attributes & Inverted )
01042 inverted = !inverted;
01043
01044 int i,ip;
01045 for (i = from, ip = 0; i <= to; i++, ip += 2)
01046 {
01047 const int xi = xMap.transform(x(i));
01048 const int yi = yMap.transform(y(i));
01049
01050 if ( ip > 0 )
01051 {
01052 if (inverted)
01053 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
01054 else
01055 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
01056 }
01057
01058 polyline.setPoint(ip, xi, yi);
01059 }
01060
01061 polyline = ::clipPolygon(painter, d_data->paintAttributes, polyline);
01062
01063 QwtPainter::drawPolyline(painter, polyline);
01064
01065 if ( d_data->brush.style() != Qt::NoBrush )
01066 fillCurve(painter, xMap, yMap, polyline);
01067 }
01068
01069
01092 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
01093 {
01094 if ( bool(d_data->attributes & attribute) == on )
01095 return;
01096
01097 if ( on )
01098 d_data->attributes |= attribute;
01099 else
01100 d_data->attributes &= ~attribute;
01101
01102 itemChanged();
01103 }
01104
01109 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const
01110 {
01111 return d_data->attributes & attribute;
01112 }
01113
01130 void QwtPlotCurve::setCurveType(CurveType curveType)
01131 {
01132 if ( d_data->curveType != curveType )
01133 {
01134 d_data->curveType = curveType;
01135 itemChanged();
01136 }
01137 }
01138
01143 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01144 {
01145 return d_data->curveType;
01146 }
01147
01148 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01149 {
01150 delete d_data->curveFitter;
01151 d_data->curveFitter = curveFitter;
01152
01153 itemChanged();
01154 }
01155
01156 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01157 {
01158 return d_data->curveFitter;
01159 }
01160
01173 void QwtPlotCurve::fillCurve(QPainter *painter,
01174 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01175 QwtPolygon &pa) const
01176 {
01177 if ( d_data->brush.style() == Qt::NoBrush )
01178 return;
01179
01180 closePolyline(xMap, yMap, pa);
01181 if ( pa.count() <= 2 )
01182 return;
01183
01184 QBrush b = d_data->brush;
01185 if ( !b.color().isValid() )
01186 b.setColor(d_data->pen.color());
01187
01188 painter->save();
01189
01190 painter->setPen(QPen(Qt::NoPen));
01191 painter->setBrush(b);
01192
01193 QwtPainter::drawPolygon(painter, pa);
01194
01195 painter->restore();
01196 }
01197
01207 void QwtPlotCurve::closePolyline(
01208 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01209 QwtPolygon &pa) const
01210 {
01211 const int sz = pa.size();
01212 if ( sz < 2 )
01213 return;
01214
01215 pa.resize(sz + 2);
01216
01217 if ( d_data->curveType == QwtPlotCurve::Xfy )
01218 {
01219 pa.setPoint(sz,
01220 xMap.transform(d_data->reference), pa.point(sz - 1).y());
01221 pa.setPoint(sz + 1,
01222 xMap.transform(d_data->reference), pa.point(0).y());
01223 }
01224 else
01225 {
01226 pa.setPoint(sz,
01227 pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01228 pa.setPoint(pa.size() - 1,
01229 pa.point(0).x(), yMap.transform(d_data->reference));
01230 }
01231 }
01232
01244 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01245 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01246 int from, int to) const
01247 {
01248 painter->setBrush(symbol.brush());
01249
01250 const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
01251
01252 QPen pen = symbol.pen();
01253
01254 #if SCALE_PEN
01255 if ( pen.width() > 0 )
01256 pen.setWidth(metricsMap.screenToLayoutX(pen.width()));
01257 #endif
01258
01259 painter->setPen(pen);
01260
01261 QRect rect;
01262 rect.setSize(metricsMap.screenToLayout(symbol.size()));
01263
01264 if ( to > from && d_data->paintAttributes & PaintFiltered )
01265 {
01266 const QRect window = painter->window();
01267 if ( window.isEmpty() )
01268 return;
01269
01270 PrivateData::PixelMatrix pixelMatrix(window);
01271
01272 for (int i = from; i <= to; i++)
01273 {
01274 const QPoint pi( xMap.transform(x(i)),
01275 yMap.transform(y(i)) );
01276
01277 if ( pixelMatrix.testPixel(pi) )
01278 {
01279 rect.moveCenter(pi);
01280 symbol.draw(painter, rect);
01281 }
01282 }
01283 }
01284 else
01285 {
01286 for (int i = from; i <= to; i++)
01287 {
01288 const int xi = xMap.transform(x(i));
01289 const int yi = yMap.transform(y(i));
01290
01291 rect.moveCenter(QPoint(xi, yi));
01292 symbol.draw(painter, rect);
01293 }
01294 }
01295 }
01296
01310 void QwtPlotCurve::setBaseline(double reference)
01311 {
01312 if ( d_data->reference != reference )
01313 {
01314 d_data->reference = reference;
01315 itemChanged();
01316 }
01317 }
01318
01323 double QwtPlotCurve::baseline() const
01324 {
01325 return d_data->reference;
01326 }
01327
01332 int QwtPlotCurve::dataSize() const
01333 {
01334 return d_xy->size();
01335 }
01336
01337 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01338 {
01339 if ( plot() == NULL || dataSize() <= 0 )
01340 return -1;
01341
01342 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01343 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01344
01345 int index = -1;
01346 double dmin = 1.0e10;
01347
01348 for (int i=0; i < dataSize(); i++)
01349 {
01350 const double cx = xMap.xTransform(x(i)) - pos.x();
01351 const double cy = yMap.xTransform(y(i)) - pos.y();
01352
01353 const double f = qwtSqr(cx) + qwtSqr(cy);
01354 if (f < dmin)
01355 {
01356 index = i;
01357 dmin = f;
01358 }
01359 }
01360 if ( dist )
01361 *dist = sqrt(dmin);
01362
01363 return index;
01364 }
01365
01367 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01368 {
01369 if ( !legend )
01370 return;
01371
01372 QwtPlotItem::updateLegend(legend);
01373
01374 QWidget *widget = legend->find(this);
01375 if ( !widget || !widget->inherits("QwtLegendItem") )
01376 return;
01377
01378 QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01379
01380 #if QT_VERSION < 0x040000
01381 const bool doUpdate = legendItem->isUpdatesEnabled();
01382 #else
01383 const bool doUpdate = legendItem->updatesEnabled();
01384 #endif
01385 legendItem->setUpdatesEnabled(false);
01386
01387 const int policy = legend->displayPolicy();
01388
01389 if (policy == QwtLegend::FixedIdentifier)
01390 {
01391 int mode = legend->identifierMode();
01392
01393 if (mode & QwtLegendItem::ShowLine)
01394 legendItem->setCurvePen(pen());
01395
01396 if (mode & QwtLegendItem::ShowSymbol)
01397 legendItem->setSymbol(symbol());
01398
01399 if (mode & QwtLegendItem::ShowText)
01400 legendItem->setText(title());
01401 else
01402 legendItem->setText(QwtText());
01403
01404 legendItem->setIdentifierMode(mode);
01405 }
01406 else if (policy == QwtLegend::AutoIdentifier)
01407 {
01408 int mode = 0;
01409
01410 if (QwtPlotCurve::NoCurve != style())
01411 {
01412 legendItem->setCurvePen(pen());
01413 mode |= QwtLegendItem::ShowLine;
01414 }
01415 if (QwtSymbol::NoSymbol != symbol().style())
01416 {
01417 legendItem->setSymbol(symbol());
01418 mode |= QwtLegendItem::ShowSymbol;
01419 }
01420 if ( !title().isEmpty() )
01421 {
01422 legendItem->setText(title());
01423 mode |= QwtLegendItem::ShowText;
01424 }
01425 else
01426 {
01427 legendItem->setText(QwtText());
01428 }
01429 legendItem->setIdentifierMode(mode);
01430 }
01431
01432 legendItem->setUpdatesEnabled(doUpdate);
01433 legendItem->update();
01434 }