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
00030 #include <qevent.h>
00031 #include <qpaintengine.h>
00032
00033 class QwtPlotCurvePaintHelper: public QObject
00034 {
00035 public:
00036 QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00037 _curve(curve),
00038 _from(from),
00039 _to(to)
00040 {
00041 }
00042
00043 virtual bool eventFilter(QObject *, QEvent *event)
00044 {
00045 if ( event->type() == QEvent::Paint )
00046 {
00047 _curve->draw(_from, _to);
00048 return true;
00049 }
00050 return false;
00051 }
00052 private:
00053 const QwtPlotCurve *_curve;
00054 int _from;
00055 int _to;
00056 };
00057
00058 #endif // QT_VERSION >= 0x040000
00059
00060 static int verifyRange(int size, int &i1, int &i2)
00061 {
00062 if (size < 1)
00063 return 0;
00064
00065 i1 = qwtLim(i1, 0, size-1);
00066 i2 = qwtLim(i2, 0, size-1);
00067
00068 if ( i1 > i2 )
00069 qSwap(i1, i2);
00070
00071 return (i2 - i1 + 1);
00072 }
00073
00074 class QwtPlotCurve::PrivateData
00075 {
00076 public:
00077 class PixelMatrix: private QBitArray
00078 {
00079 public:
00080 PixelMatrix(const QRect& rect):
00081 QBitArray(rect.width() * rect.height()),
00082 _rect(rect)
00083 {
00084 fill(false);
00085 }
00086
00087 inline bool testPixel(const QPoint& pos)
00088 {
00089 if ( !_rect.contains(pos) )
00090 return false;
00091
00092 const int idx = _rect.width() * (pos.y() - _rect.y()) +
00093 (pos.x() - _rect.x());
00094
00095 const bool marked = testBit(idx);
00096 if ( !marked )
00097 setBit(idx, true);
00098
00099 return !marked;
00100 }
00101
00102 private:
00103 QRect _rect;
00104 };
00105
00106 PrivateData():
00107 curveType(Yfx),
00108 style(QwtPlotCurve::Lines),
00109 reference(0.0),
00110 attributes(0),
00111 paintAttributes(0)
00112 {
00113 symbol = new QwtSymbol();
00114 pen = QPen(Qt::black);
00115 curveFitter = new QwtSplineCurveFitter;
00116 }
00117
00118 ~PrivateData()
00119 {
00120 delete symbol;
00121 delete curveFitter;
00122 }
00123
00124 QwtPlotCurve::CurveType curveType;
00125 QwtPlotCurve::CurveStyle style;
00126 double reference;
00127
00128 QwtSymbol *symbol;
00129 QwtCurveFitter *curveFitter;
00130
00131 QPen pen;
00132 QBrush brush;
00133
00134 int attributes;
00135 int paintAttributes;
00136 };
00137
00139 QwtPlotCurve::QwtPlotCurve():
00140 QwtPlotItem(QwtText())
00141 {
00142 init();
00143 }
00144
00149 QwtPlotCurve::QwtPlotCurve(const QwtText &title):
00150 QwtPlotItem(title)
00151 {
00152 init();
00153 }
00154
00159 QwtPlotCurve::QwtPlotCurve(const QString &title):
00160 QwtPlotItem(QwtText(title))
00161 {
00162 init();
00163 }
00164
00166 QwtPlotCurve::~QwtPlotCurve()
00167 {
00168 delete d_xy;
00169 delete d_data;
00170 }
00171
00175 void QwtPlotCurve::init()
00176 {
00177 setItemAttribute(QwtPlotItem::Legend);
00178 setItemAttribute(QwtPlotItem::AutoScale);
00179
00180 d_data = new PrivateData;
00181 d_xy = new QwtPolygonFData(QwtArray<QwtDoublePoint>());
00182
00183 setZ(20.0);
00184 }
00185
00187 int QwtPlotCurve::rtti() const
00188 {
00189 return QwtPlotItem::Rtti_PlotCurve;
00190 }
00191
00215 void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on)
00216 {
00217 if ( on )
00218 d_data->paintAttributes |= attribute;
00219 else
00220 d_data->paintAttributes &= ~attribute;
00221 }
00222
00227 bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const
00228 {
00229 return (d_data->paintAttributes & attribute);
00230 }
00231
00259 void QwtPlotCurve::setStyle(CurveStyle style)
00260 {
00261 if ( style != d_data->style )
00262 {
00263 d_data->style = style;
00264 itemChanged();
00265 }
00266 }
00267
00272 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00273 {
00274 return d_data->style;
00275 }
00276
00282 void QwtPlotCurve::setSymbol(const QwtSymbol &symbol )
00283 {
00284 delete d_data->symbol;
00285 d_data->symbol = symbol.clone();
00286 itemChanged();
00287 }
00288
00293 const QwtSymbol &QwtPlotCurve::symbol() const
00294 {
00295 return *d_data->symbol;
00296 }
00297
00303 void QwtPlotCurve::setPen(const QPen &pen)
00304 {
00305 if ( pen != d_data->pen )
00306 {
00307 d_data->pen = pen;
00308 itemChanged();
00309 }
00310 }
00311
00316 const QPen& QwtPlotCurve::pen() const
00317 {
00318 return d_data->pen;
00319 }
00320
00333 void QwtPlotCurve::setBrush(const QBrush &brush)
00334 {
00335 if ( brush != d_data->brush )
00336 {
00337 d_data->brush = brush;
00338 itemChanged();
00339 }
00340 }
00341
00346 const QBrush& QwtPlotCurve::brush() const
00347 {
00348 return d_data->brush;
00349 }
00350
00351
00363 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00364 {
00365 delete d_xy;
00366 d_xy = new QwtArrayData(xData, yData, size);
00367 itemChanged();
00368 }
00369
00378 void QwtPlotCurve::setData(const QwtArray<double> &xData,
00379 const QwtArray<double> &yData)
00380 {
00381 delete d_xy;
00382 d_xy = new QwtArrayData(xData, yData);
00383 itemChanged();
00384 }
00385
00392 #if QT_VERSION < 0x040000
00393 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00394 #else
00395 void QwtPlotCurve::setData(const QPolygonF &data)
00396 #endif
00397 {
00398 delete d_xy;
00399 d_xy = new QwtPolygonFData(data);
00400 itemChanged();
00401 }
00402
00409 void QwtPlotCurve::setData(const QwtData &data)
00410 {
00411 delete d_xy;
00412 d_xy = data.copy();
00413 itemChanged();
00414 }
00415
00429 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00430 {
00431 delete d_xy;
00432 d_xy = new QwtCPointerData(xData, yData, size);
00433 itemChanged();
00434 }
00435
00442 QwtDoubleRect QwtPlotCurve::boundingRect() const
00443 {
00444 if ( d_xy == NULL )
00445 return QwtDoubleRect(1.0, 1.0, -2.0, -2.0);
00446
00447 return d_xy->boundingRect();
00448 }
00449
00459 void QwtPlotCurve::draw(QPainter *painter,
00460 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00461 const QRect &) const
00462 {
00463 draw(painter, xMap, yMap, 0, -1);
00464 }
00465
00483 void QwtPlotCurve::draw(int from, int to) const
00484 {
00485 if ( !plot() )
00486 return;
00487
00488 QwtPlotCanvas *canvas = plot()->canvas();
00489
00490 #if QT_VERSION >= 0x040000
00491 if ( canvas->paintEngine()->type() == QPaintEngine::OpenGL )
00492 {
00493
00494
00495
00496
00497
00498 canvas->repaint();
00499 return;
00500 }
00501
00502 if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00503 !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00504 {
00505
00506
00507
00508
00509
00510
00511
00512 QwtPlotCurvePaintHelper helper(this, from, to);
00513 canvas->installEventFilter(&helper);
00514
00515 const bool noSystemBackground =
00516 canvas->testAttribute(Qt::WA_NoSystemBackground);
00517 canvas->setAttribute(Qt::WA_NoSystemBackground, true);
00518 canvas->repaint();
00519 canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground);
00520
00521 return;
00522 }
00523 #endif
00524
00525 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00526 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00527
00528 if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00529 canvas->paintCache() && !canvas->paintCache()->isNull() )
00530 {
00531 QPainter cachePainter((QPixmap *)canvas->paintCache());
00532 cachePainter.translate(-canvas->contentsRect().x(),
00533 -canvas->contentsRect().y());
00534
00535 draw(&cachePainter, xMap, yMap, from, to);
00536 }
00537
00538 QPainter painter(canvas);
00539
00540 painter.setClipping(true);
00541 painter.setClipRect(canvas->contentsRect());
00542
00543 draw(&painter, xMap, yMap, from, to);
00544 }
00545
00557 void QwtPlotCurve::draw(QPainter *painter,
00558 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00559 int from, int to) const
00560 {
00561 if ( !painter || dataSize() <= 0 )
00562 return;
00563
00564 if (to < 0)
00565 to = dataSize() - 1;
00566
00567 if ( verifyRange(dataSize(), from, to) > 0 )
00568 {
00569 painter->save();
00570 painter->setPen(d_data->pen);
00571
00572
00573
00574
00575
00576
00577
00578 drawCurve(painter, d_data->style, xMap, yMap, from, to);
00579 painter->restore();
00580
00581 if (d_data->symbol->style() != QwtSymbol::NoSymbol)
00582 {
00583 painter->save();
00584 drawSymbols(painter, *d_data->symbol, xMap, yMap, from, to);
00585 painter->restore();
00586 }
00587 }
00588 }
00589
00601 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00602 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00603 int from, int to) const
00604 {
00605 switch (style)
00606 {
00607 case Lines:
00608 if ( testCurveAttribute(Fitted) )
00609 {
00610
00611
00612 from = 0;
00613 to = dataSize() - 1;
00614 }
00615 drawLines(painter, xMap, yMap, from, to);
00616 break;
00617 case Sticks:
00618 drawSticks(painter, xMap, yMap, from, to);
00619 break;
00620 case Steps:
00621 drawSteps(painter, xMap, yMap, from, to);
00622 break;
00623 case Dots:
00624 drawDots(painter, xMap, yMap, from, to);
00625 break;
00626 case NoCurve:
00627 default:
00628 break;
00629 }
00630 }
00631
00647 void QwtPlotCurve::drawLines(QPainter *painter,
00648 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00649 int from, int to) const
00650 {
00651 int size = to - from + 1;
00652 if ( size <= 0 )
00653 return;
00654
00655 QwtPolygon polyline;
00656 if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
00657 {
00658
00659
00660
00661
00662 #if QT_VERSION < 0x040000
00663 QwtArray<QwtDoublePoint> points(size);
00664 #else
00665 QPolygonF points(size);
00666 #endif
00667 for (int i = from; i <= to; i++)
00668 {
00669 QwtDoublePoint &p = points[i];
00670 p.setX( xMap.xTransform(x(i)) );
00671 p.setY( yMap.xTransform(y(i)) );
00672 }
00673
00674 points = d_data->curveFitter->fitCurve(points);
00675 size = points.size();
00676
00677 if ( size == 0 )
00678 return;
00679
00680
00681
00682
00683
00684
00685 polyline.resize(size);
00686
00687 const QwtDoublePoint *p = points.data();
00688 QPoint *pl = polyline.data();
00689 if ( d_data->paintAttributes & PaintFiltered )
00690 {
00691
00692 QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
00693 pl[0] = pp;
00694
00695 int count = 1;
00696 for (int i = 1; i < size; i++)
00697 {
00698 const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
00699 if ( pi != pp )
00700 {
00701 pl[count++] = pi;
00702 pp = pi;
00703 }
00704 }
00705 if ( count != size )
00706 polyline.resize(count);
00707 }
00708 else
00709 {
00710 for ( int i = 0; i < size; i++ )
00711 {
00712 pl[i].setX( qRound(p[i].x()) );
00713 pl[i].setY( qRound(p[i].y()) );
00714 }
00715 }
00716 }
00717 else
00718 {
00719 polyline.resize(size);
00720
00721 if ( d_data->paintAttributes & PaintFiltered )
00722 {
00723 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00724 polyline.setPoint(0, pp);
00725
00726 int count = 1;
00727 for (int i = from + 1; i <= to; i++)
00728 {
00729 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00730 if ( pi != pp )
00731 {
00732 polyline.setPoint(count, pi);
00733 count++;
00734
00735 pp = pi;
00736 }
00737 }
00738 if ( count != size )
00739 polyline.resize(count);
00740 }
00741 else
00742 {
00743 for (int i = from; i <= to; i++)
00744 {
00745 int xi = xMap.transform(x(i));
00746 int yi = yMap.transform(y(i));
00747
00748 polyline.setPoint(i - from, xi, yi);
00749 }
00750 }
00751 }
00752
00753 if ( d_data->paintAttributes & ClipPolygons )
00754 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00755
00756 QwtPainter::drawPolyline(painter, polyline);
00757
00758 if ( d_data->brush.style() != Qt::NoBrush )
00759 fillCurve(painter, xMap, yMap, polyline);
00760 }
00761
00773 void QwtPlotCurve::drawSticks(QPainter *painter,
00774 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00775 int from, int to) const
00776 {
00777 int x0 = xMap.transform(d_data->reference);
00778 int y0 = yMap.transform(d_data->reference);
00779
00780 for (int i = from; i <= to; i++)
00781 {
00782 const int xi = xMap.transform(x(i));
00783 const int yi = yMap.transform(y(i));
00784
00785 if (d_data->curveType == Xfy)
00786 QwtPainter::drawLine(painter, x0, yi, xi, yi);
00787 else
00788 QwtPainter::drawLine(painter, xi, y0, xi, yi);
00789 }
00790 }
00791
00803 void QwtPlotCurve::drawDots(QPainter *painter,
00804 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00805 int from, int to) const
00806 {
00807 const QRect window = painter->window();
00808 if ( window.isEmpty() )
00809 return;
00810
00811 const bool doFill = d_data->brush.style() != Qt::NoBrush;
00812
00813 QwtPolygon polyline;
00814 if ( doFill )
00815 polyline.resize(to - from + 1);
00816
00817 if ( to > from && d_data->paintAttributes & PaintFiltered )
00818 {
00819 if ( doFill )
00820 {
00821 QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
00822
00823 QwtPainter::drawPoint(painter, pp.x(), pp.y());
00824 polyline.setPoint(0, pp);
00825
00826 int count = 1;
00827 for (int i = from + 1; i <= to; i++)
00828 {
00829 const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
00830 if ( pi != pp )
00831 {
00832 QwtPainter::drawPoint(painter, pi.x(), pi.y());
00833
00834 polyline.setPoint(count, pi);
00835 count++;
00836
00837 pp = pi;
00838 }
00839 }
00840 if ( int(polyline.size()) != count )
00841 polyline.resize(count);
00842 }
00843 else
00844 {
00845
00846
00847
00848 PrivateData::PixelMatrix pixelMatrix(window);
00849
00850 for (int i = from; i <= to; i++)
00851 {
00852 const QPoint p( xMap.transform(x(i)),
00853 yMap.transform(y(i)) );
00854
00855 if ( pixelMatrix.testPixel(p) )
00856 QwtPainter::drawPoint(painter, p.x(), p.y());
00857 }
00858 }
00859 }
00860 else
00861 {
00862 for (int i = from; i <= to; i++)
00863 {
00864 const int xi = xMap.transform(x(i));
00865 const int yi = yMap.transform(y(i));
00866 QwtPainter::drawPoint(painter, xi, yi);
00867
00868 if ( doFill )
00869 polyline.setPoint(i - from, xi, yi);
00870 }
00871 }
00872
00873 if ( doFill )
00874 {
00875 if ( d_data->paintAttributes & ClipPolygons )
00876 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00877
00878 fillCurve(painter, xMap, yMap, polyline);
00879 }
00880 }
00881
00896 void QwtPlotCurve::drawSteps(QPainter *painter,
00897 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00898 int from, int to) const
00899 {
00900 QwtPolygon polyline(2 * (to - from) + 1);
00901
00902 bool inverted = d_data->curveType == Yfx;
00903 if ( d_data->attributes & Inverted )
00904 inverted = !inverted;
00905
00906 int i,ip;
00907 for (i = from, ip = 0; i <= to; i++, ip += 2)
00908 {
00909 const int xi = xMap.transform(x(i));
00910 const int yi = yMap.transform(y(i));
00911
00912 if ( ip > 0 )
00913 {
00914 if (inverted)
00915 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00916 else
00917 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00918 }
00919
00920 polyline.setPoint(ip, xi, yi);
00921 }
00922
00923 if ( d_data->paintAttributes & ClipPolygons )
00924 polyline = QwtClipper::clipPolygon(painter->window(), polyline);
00925
00926 QwtPainter::drawPolyline(painter, polyline);
00927
00928 if ( d_data->brush.style() != Qt::NoBrush )
00929 fillCurve(painter, xMap, yMap, polyline);
00930 }
00931
00932
00955 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
00956 {
00957 if ( bool(d_data->attributes & attribute) == on )
00958 return;
00959
00960 if ( on )
00961 d_data->attributes |= attribute;
00962 else
00963 d_data->attributes &= ~attribute;
00964
00965 itemChanged();
00966 }
00967
00972 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const
00973 {
00974 return d_data->attributes & attribute;
00975 }
00976
00993 void QwtPlotCurve::setCurveType(CurveType curveType)
00994 {
00995 if ( d_data->curveType != curveType )
00996 {
00997 d_data->curveType = curveType;
00998 itemChanged();
00999 }
01000 }
01001
01006 QwtPlotCurve::CurveType QwtPlotCurve::curveType() const
01007 {
01008 return d_data->curveType;
01009 }
01010
01011 void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter)
01012 {
01013 delete d_data->curveFitter;
01014 d_data->curveFitter = curveFitter;
01015
01016 itemChanged();
01017 }
01018
01019 QwtCurveFitter *QwtPlotCurve::curveFitter() const
01020 {
01021 return d_data->curveFitter;
01022 }
01023
01036 void QwtPlotCurve::fillCurve(QPainter *painter,
01037 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01038 QwtPolygon &pa) const
01039 {
01040 if ( d_data->brush.style() == Qt::NoBrush )
01041 return;
01042
01043 closePolyline(xMap, yMap, pa);
01044 if ( pa.count() <= 2 )
01045 return;
01046
01047 QBrush b = d_data->brush;
01048 if ( !b.color().isValid() )
01049 b.setColor(d_data->pen.color());
01050
01051 painter->save();
01052
01053 painter->setPen(QPen(Qt::NoPen));
01054 painter->setBrush(b);
01055
01056 QwtPainter::drawPolygon(painter, pa);
01057
01058 painter->restore();
01059 }
01060
01070 void QwtPlotCurve::closePolyline(
01071 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01072 QwtPolygon &pa) const
01073 {
01074 const int sz = pa.size();
01075 if ( sz < 2 )
01076 return;
01077
01078 pa.resize(sz + 2);
01079
01080 if ( d_data->curveType == QwtPlotCurve::Xfy )
01081 {
01082 pa.setPoint(sz,
01083 xMap.transform(d_data->reference), pa.point(sz - 1).y());
01084 pa.setPoint(sz + 1,
01085 xMap.transform(d_data->reference), pa.point(0).y());
01086 }
01087 else
01088 {
01089 pa.setPoint(sz,
01090 pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01091 pa.setPoint(pa.size() - 1,
01092 pa.point(0).x(), yMap.transform(d_data->reference));
01093 }
01094 }
01095
01107 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01108 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01109 int from, int to) const
01110 {
01111 painter->setBrush(symbol.brush());
01112 painter->setPen(symbol.pen());
01113
01114 QRect rect;
01115 rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01116
01117 if ( to > from && d_data->paintAttributes & PaintFiltered )
01118 {
01119 const QRect window = painter->window();
01120 if ( window.isEmpty() )
01121 return;
01122
01123 PrivateData::PixelMatrix pixelMatrix(window);
01124
01125 for (int i = from; i <= to; i++)
01126 {
01127 const QPoint pi( xMap.transform(x(i)),
01128 yMap.transform(y(i)) );
01129
01130 if ( pixelMatrix.testPixel(pi) )
01131 {
01132 rect.moveCenter(pi);
01133 symbol.draw(painter, rect);
01134 }
01135 }
01136 }
01137 else
01138 {
01139 for (int i = from; i <= to; i++)
01140 {
01141 const int xi = xMap.transform(x(i));
01142 const int yi = yMap.transform(y(i));
01143
01144 rect.moveCenter(QPoint(xi, yi));
01145 symbol.draw(painter, rect);
01146 }
01147 }
01148 }
01149
01163 void QwtPlotCurve::setBaseline(double reference)
01164 {
01165 if ( d_data->reference != reference )
01166 {
01167 d_data->reference = reference;
01168 itemChanged();
01169 }
01170 }
01171
01176 double QwtPlotCurve::baseline() const
01177 {
01178 return d_data->reference;
01179 }
01180
01185 int QwtPlotCurve::dataSize() const
01186 {
01187 return d_xy->size();
01188 }
01189
01190 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01191 {
01192 if ( plot() == NULL || dataSize() <= 0 )
01193 return -1;
01194
01195 const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01196 const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01197
01198 int index = -1;
01199 double dmin = 1.0e10;
01200
01201 for (int i=0; i < dataSize(); i++)
01202 {
01203 const double cx = xMap.xTransform(x(i)) - pos.x();
01204 const double cy = yMap.xTransform(y(i)) - pos.y();
01205
01206 const double f = qwtSqr(cx) + qwtSqr(cy);
01207 if (f < dmin)
01208 {
01209 index = i;
01210 dmin = f;
01211 }
01212 }
01213 if ( dist )
01214 *dist = sqrt(dmin);
01215
01216 return index;
01217 }
01218
01220 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01221 {
01222 if ( !legend )
01223 return;
01224
01225 QwtPlotItem::updateLegend(legend);
01226
01227 QWidget *widget = legend->find(this);
01228 if ( !widget || !widget->inherits("QwtLegendItem") )
01229 return;
01230
01231 QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01232
01233 #if QT_VERSION < 0x040000
01234 const bool doUpdate = legendItem->isUpdatesEnabled();
01235 #else
01236 const bool doUpdate = legendItem->updatesEnabled();
01237 #endif
01238 legendItem->setUpdatesEnabled(false);
01239
01240 const int policy = legend->displayPolicy();
01241
01242 if (policy == QwtLegend::FixedIdentifier)
01243 {
01244 int mode = legend->identifierMode();
01245
01246 if (mode & QwtLegendItem::ShowLine)
01247 legendItem->setCurvePen(pen());
01248
01249 if (mode & QwtLegendItem::ShowSymbol)
01250 legendItem->setSymbol(symbol());
01251
01252 if (mode & QwtLegendItem::ShowText)
01253 legendItem->setText(title());
01254 else
01255 legendItem->setText(QwtText());
01256
01257 legendItem->setIdentifierMode(mode);
01258 }
01259 else if (policy == QwtLegend::AutoIdentifier)
01260 {
01261 int mode = 0;
01262
01263 if (QwtPlotCurve::NoCurve != style())
01264 {
01265 legendItem->setCurvePen(pen());
01266 mode |= QwtLegendItem::ShowLine;
01267 }
01268 if (QwtSymbol::NoSymbol != symbol().style())
01269 {
01270 legendItem->setSymbol(symbol());
01271 mode |= QwtLegendItem::ShowSymbol;
01272 }
01273 if ( !title().isEmpty() )
01274 {
01275 legendItem->setText(title());
01276 mode |= QwtLegendItem::ShowText;
01277 }
01278 else
01279 {
01280 legendItem->setText(QwtText());
01281 }
01282 legendItem->setIdentifierMode(mode);
01283 }
01284
01285 legendItem->setUpdatesEnabled(doUpdate);
01286 legendItem->update();
01287 }