Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

qwt_plot_curve.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include <qpainter.h>
00011 #include <qpixmap.h>
00012 #include "qwt_global.h"
00013 #include "qwt_legend.h"
00014 #include "qwt_legend_item.h"
00015 #include "qwt_data.h"
00016 #include "qwt_scale_map.h"
00017 #include "qwt_double_rect.h"
00018 #include "qwt_math.h"
00019 #include "qwt_painter.h"
00020 #include "qwt_plot.h"
00021 #include "qwt_plot_canvas.h"
00022 #include "qwt_spline.h"
00023 #include "qwt_symbol.h"
00024 #include "qwt_plot_curve.h"
00025 
00026 #if QT_VERSION < 0x040000
00027 #define QwtPointArray QPointArray
00028 #else
00029 #define QwtPointArray QPolygon
00030 #endif
00031 
00032 #if 0
00033 #if QT_VERSION >= 0x040000
00034 #if !defined(Q_WS_MAC)
00035 
00036 #include <qevent.h>
00037 
00038 class QwtPlotCurvePaintHelper: public QObject
00039 {
00040 public:
00041     QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to):
00042         _curve(curve),
00043         _from(from),
00044         _to(to)
00045     {
00046     }
00047 
00048     virtual bool eventFilter(QObject *, QEvent *event)
00049     {
00050         if ( event->type() == QEvent::Paint )
00051         {
00052             _curve->draw(_from, _to);
00053             return true;
00054         }
00055         return false;
00056     }
00057 private:
00058     const QwtPlotCurve *_curve;
00059     int _from;
00060     int _to;
00061 };
00062 #endif // !defined(Q_WS_MAC)
00063 #endif // QT_VERSION >= 0x040000
00064 #endif
00065 
00066 class QwtPlotCurve::PrivateData
00067 {
00068 public:
00069     PrivateData()
00070     {
00071         pen = QPen(Qt::black, 0);
00072         reference = 0.0;
00073         splineSize = 250;
00074         attributes = Auto;
00075         title = title;
00076         style = QwtPlotCurve::Lines;
00077     }
00078 
00079     QwtPlotCurve::CurveStyle style;
00080     double reference;
00081 
00082     QwtSymbol sym;
00083 
00084     QPen pen;
00085     QBrush brush;
00086     QString title;
00087 
00088     int attributes;
00089     int splineSize;
00090 };
00091 
00092 static int qwtChkMono(const double *array, int size)
00093 {
00094     if (size < 2)
00095         return 0;
00096 
00097     int rv = qwtSign(array[1] - array[0]);
00098     for (int i = 1; i < size - 1; i++)
00099     {
00100         if ( qwtSign(array[i+1] - array[i]) != rv )
00101         {
00102             rv = 0;
00103             break;
00104         }
00105     }
00106     return rv;
00107 }
00108 
00109 static void qwtTwistArray(double *array, int size)
00110 {
00111     const int s2 = size / 2;
00112 
00113     for (int i=0; i < s2; i++)
00114     {
00115         const int itmp = size - 1 - i;
00116         const double dtmp = array[i];
00117         array[i] = array[itmp];
00118         array[itmp] = dtmp;
00119     }
00120 }
00121 
00126 QwtPlotCurve::QwtPlotCurve(const QString &title)
00127 {
00128     init(title);
00129 }
00130 
00134 QwtPlotCurve::QwtPlotCurve(const QwtPlotCurve &c):
00135     QwtPlotItem(c)
00136 {
00137     init(c.d_data->title);
00138     copy(c);
00139 }
00140 
00142 QwtPlotCurve::~QwtPlotCurve()
00143 {
00144     delete d_xy;
00145     delete d_data;
00146 }
00147 
00151 void QwtPlotCurve::init(const QString &title)
00152 {
00153     setItemAttribute(QwtPlotItem::Legend);
00154     setItemAttribute(QwtPlotItem::AutoScale);
00155 
00156     d_data = new PrivateData;
00157     d_data->title = title;
00158 
00159     d_xy = new QwtDoublePointData(QwtArray<QwtDoublePoint>());
00160 
00161     setZ(20.0);
00162 }
00163 
00167 void QwtPlotCurve::copy(const QwtPlotCurve &c)
00168 {
00169     if (this != &c)
00170     {
00171         *d_data = *c.d_data;
00172 
00173         delete d_xy;
00174         d_xy = c.d_xy->copy();
00175 
00176         itemChanged();
00177     }
00178 }
00179 
00180 
00184 const QwtPlotCurve& QwtPlotCurve::operator=(const QwtPlotCurve &c)
00185 {
00186     copy(c);
00187     return *this;
00188 }
00189 
00190 int QwtPlotCurve::rtti() const
00191 {
00192     return QwtPlotItem::Rtti_PlotCurve;
00193 }
00194 
00225 void QwtPlotCurve::setStyle(CurveStyle style)
00226 {
00227     if ( style != d_data->style )
00228     {
00229         d_data->style = style;
00230         itemChanged();
00231     }
00232 }
00233 
00239 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const 
00240 { 
00241     return d_data->style; 
00242 }
00243 
00249 void QwtPlotCurve::setSymbol(const QwtSymbol &s )
00250 {
00251     d_data->sym = s;
00252     itemChanged();
00253 }
00254 
00259 const QwtSymbol &QwtPlotCurve::symbol() const 
00260 { 
00261     return d_data->sym; 
00262 }
00263 
00268 void QwtPlotCurve::setPen(const QPen &p)
00269 {
00270     if ( p != d_data->pen )
00271     {
00272         d_data->pen = p;
00273         itemChanged();
00274     }
00275 }
00276 
00281 const QPen& QwtPlotCurve::pen() const 
00282 { 
00283     return d_data->pen; 
00284 }
00285 
00298 void QwtPlotCurve::setBrush(const QBrush &brush)
00299 {
00300     if ( brush != d_data->brush )
00301     {
00302         d_data->brush = brush;
00303         itemChanged();
00304     }
00305 }
00306 
00312 const QBrush& QwtPlotCurve::brush() const 
00313 {
00314     return d_data->brush;
00315 }
00316 
00317 
00329 void QwtPlotCurve::setData(const double *xData, const double *yData, int size)
00330 {
00331     delete d_xy;
00332     d_xy = new QwtArrayData(xData, yData, size);
00333     itemChanged();
00334 }
00335 
00344 void QwtPlotCurve::setData(const QwtArray<double> &xData, 
00345     const QwtArray<double> &yData)
00346 {
00347     delete d_xy;
00348     d_xy = new QwtArrayData(xData, yData);
00349     itemChanged();
00350 }
00351 
00359 void QwtPlotCurve::setData(const QwtArray<QwtDoublePoint> &data)
00360 {
00361     delete d_xy;
00362     d_xy = new QwtDoublePointData(data);
00363     itemChanged();
00364 }
00365 
00373 void QwtPlotCurve::setData(const QwtData &data)
00374 {
00375     delete d_xy;
00376     d_xy = data.copy();
00377     itemChanged();
00378 }
00379 
00393 void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size)
00394 {
00395     delete d_xy;
00396     d_xy = new QwtCPointerData(xData, yData, size);
00397     itemChanged();
00398 }
00399 
00404 void QwtPlotCurve::setTitle(const QString &title)
00405 {
00406     d_data->title = title;
00407     itemChanged();
00408 }
00409 
00414 const QString &QwtPlotCurve::title() const 
00415 { 
00416     return d_data->title; 
00417 }
00418 
00425 QwtDoubleRect QwtPlotCurve::boundingRect() const
00426 {
00427     if ( d_xy == NULL )
00428         return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid
00429 
00430     return d_xy->boundingRect();
00431 }
00432 
00433 
00439 int QwtPlotCurve::verifyRange(int &i1, int &i2) const
00440 {
00441     int size = dataSize();
00442 
00443     if (size < 1) return 0;
00444 
00445     i1 = qwtLim(i1, 0, size-1);
00446     i2 = qwtLim(i2, 0, size-1);
00447 
00448     if ( i1 > i2 )
00449         qSwap(i1, i2);
00450 
00451     return (i2 - i1 + 1);
00452 }
00453 
00454 void QwtPlotCurve::draw(QPainter *painter,
00455     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00456     const QRect &) const
00457 {
00458     draw(painter, xMap, yMap, 0, -1);
00459 }
00460 
00473 void QwtPlotCurve::draw(int from, int to) const
00474 {
00475     if ( !plot() )
00476         return;
00477 
00478     QwtPlotCanvas *canvas = plot()->canvas();
00479 
00480     bool directPaint = true;
00481 
00482 #if QT_VERSION >= 0x040000
00483     if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
00484         !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
00485     {
00486         // We are outside a paint event and are not
00487         // allowed to paint here.
00488 
00489         directPaint = false;
00490     }
00491 
00492 #if 0
00493 #if !defined(Q_WS_MAC)
00494     if ( !directPaint )
00495     {
00496         /*
00497           We save curve and range in helper and call repaint.
00498           The helper filters the Paint event, to repeat
00499           the QwtPlotCurve::draw, but now from inside the paint
00500           event. TT support told me, that this is not possible
00501           on the Mac, because you always have to repaint the
00502           complete widget. ( Is this really true ? )
00503          */
00504 
00505         QwtPlotCurvePaintHelper helper(this, from, to);
00506         canvas->installEventFilter(&helper);
00507         canvas->repaint();
00508 
00509         return;
00510     }
00511 #endif
00512 #endif
00513 
00514 #endif
00515 
00516     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
00517     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
00518 
00519     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00520         canvas->cache() )
00521     {
00522         QPainter cachePainter((QPixmap *)canvas->cache());
00523         cachePainter.translate(-canvas->contentsRect().x(),
00524             -canvas->contentsRect().y());
00525 
00526         draw(&cachePainter, xMap, yMap, from, to);
00527     }
00528 
00529     if ( directPaint )
00530     {
00531         QPainter painter(canvas);
00532 
00533         painter.setClipping(true);
00534         painter.setClipRect(canvas->contentsRect());
00535 
00536         draw(&painter, xMap, yMap, from, to);
00537 
00538         return;
00539     }
00540 
00541 #if QT_VERSION >= 0x040000
00542     if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
00543         canvas->cache() )
00544     {
00545         /*
00546           The cache is up to date. We flush it via repaint to the
00547           canvas. This works flicker free but is much ( > 10x )
00548           slower than direct painting.
00549          */
00550 
00551         const bool noBG = canvas->testAttribute(Qt::WA_NoBackground);
00552         if ( !noBG )
00553             canvas->setAttribute(Qt::WA_NoBackground, true);
00554 
00555         canvas->repaint(canvas->contentsRect());
00556 
00557         if ( !noBG )
00558             canvas->setAttribute(Qt::WA_NoBackground, false);
00559 
00560         return;
00561     }
00562 #endif
00563 
00564     // Ok, we give up 
00565     canvas->repaint(canvas->contentsRect());
00566 }
00567 
00581 void QwtPlotCurve::draw(QPainter *painter,
00582     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00583     int from, int to) const
00584 {
00585     if ( !painter || dataSize() <= 0 )
00586         return;
00587 
00588     if (to < 0)
00589         to = dataSize() - 1;
00590 
00591     if ( verifyRange(from, to) > 0 )
00592     {
00593         painter->save();
00594         painter->setPen(d_data->pen);
00595 
00596         /*
00597           Qt 4.0.0 is slow when drawing lines, but it´s even 
00598           slower when the painter has a brush. So we don't
00599           set the brush before we need it.
00600          */
00601 
00602         drawCurve(painter, d_data->style, xMap, yMap, from, to);
00603         painter->restore();
00604 
00605         if (d_data->sym.style() != QwtSymbol::None)
00606         {
00607             painter->save();
00608             drawSymbols(painter, d_data->sym, xMap, yMap, from, to);
00609             painter->restore();
00610         }
00611     }
00612 }
00613 
00626 void QwtPlotCurve::drawCurve(QPainter *painter, int style,
00627     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00628     int from, int to) const
00629 {
00630     switch (style)
00631     {
00632         case Lines:
00633             drawLines(painter, xMap, yMap, from, to);
00634             break;
00635         case Sticks:
00636             drawSticks(painter, xMap, yMap, from, to);
00637             break;
00638         case Steps:
00639             drawSteps(painter, xMap, yMap, from, to);
00640             break;
00641         case Spline:
00642             if ( from > 0 || to < dataSize() - 1 )
00643                 drawLines(painter, xMap, yMap, from, to);
00644             else
00645                 drawSpline(painter, xMap, yMap);
00646             break;
00647         case Dots:
00648             drawDots(painter, xMap, yMap, from, to);
00649             break;
00650         case NoCurve:
00651         default:
00652             break;
00653     }
00654 }
00655 
00666 void QwtPlotCurve::drawLines(QPainter *painter,
00667     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00668     int from, int to) const
00669 {
00670     QwtPointArray polyline(to - from + 1);
00671     for (int i = from; i <= to; i++)
00672     {
00673         int xi = xMap.transform(x(i));
00674         int yi = yMap.transform(y(i));
00675 
00676         polyline.setPoint(i - from, xi, yi);
00677     }
00678 
00679     QwtPainter::drawPolyline(painter, polyline);
00680 
00681     if ( d_data->brush.style() != Qt::NoBrush )
00682         fillCurve(painter, xMap, yMap, polyline);
00683 }
00684 
00695 void QwtPlotCurve::drawSticks(QPainter *painter,
00696     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00697     int from, int to) const
00698 {
00699     int x0 = xMap.transform(d_data->reference);
00700     int y0 = yMap.transform(d_data->reference);
00701 
00702     for (int i = from; i <= to; i++)
00703     {
00704         const int xi = xMap.transform(x(i));
00705         const int yi = yMap.transform(y(i));
00706 
00707         if (d_data->attributes & Xfy)
00708             QwtPainter::drawLine(painter, x0, yi, xi, yi);
00709         else
00710             QwtPainter::drawLine(painter, xi, y0, xi, yi);
00711     }
00712 }
00713 
00725 void QwtPlotCurve::drawDots(QPainter *painter,
00726     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00727     int from, int to) const
00728 {
00729     const bool doFill = d_data->brush.style() != Qt::NoBrush;
00730 
00731     QwtPointArray polyline;
00732     if ( doFill )
00733         polyline.resize(to - from + 1);
00734 
00735     for (int i = from; i <= to; i++)
00736     {
00737         const int xi = xMap.transform(x(i));
00738         const int yi = yMap.transform(y(i));
00739         QwtPainter::drawPoint(painter, xi, yi);
00740 
00741         if ( doFill )
00742             polyline.setPoint(i - from, xi, yi);
00743     }
00744 
00745     if ( doFill )
00746         fillCurve(painter, xMap, yMap, polyline);
00747 }
00748 
00759 void QwtPlotCurve::drawSteps(QPainter *painter,
00760     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
00761     int from, int to) const
00762 {
00763     QwtPointArray polyline(2 * (to - from) + 1);
00764 
00765     bool inverted = d_data->attributes & Yfx;
00766     if ( d_data->attributes & Inverted )
00767         inverted = !inverted;
00768 
00769     int i,ip;
00770     for (i = from, ip = 0; i <= to; i++, ip += 2)
00771     {
00772         const int xi = xMap.transform(x(i));
00773         const int yi = yMap.transform(y(i));
00774 
00775         if ( ip > 0 )
00776         {
00777             if (inverted)
00778                 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00779             else
00780                 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00781         }
00782 
00783         polyline.setPoint(ip, xi, yi);
00784     }
00785 
00786     QwtPainter::drawPolyline(painter, polyline);
00787 
00788     if ( d_data->brush.style() != Qt::NoBrush )
00789         fillCurve(painter, xMap, yMap, polyline);
00790 }
00791 
00800 void QwtPlotCurve::drawSpline(QPainter *painter,
00801     const QwtScaleMap &xMap, const QwtScaleMap &yMap) const
00802 {
00803     int i;
00804 
00805     const int size = dataSize();
00806     double *txval = new double[size];
00807     double *tyval = new double[size];
00808 
00809     //
00810     // Transform x and y values to window coordinates
00811     // to avoid a distinction between linear and
00812     // logarithmic scales.
00813     //
00814     for (i=0;i<size;i++)
00815     {
00816         txval[i] = xMap.xTransform(x(i));
00817         tyval[i] = yMap.xTransform(y(i));
00818     }
00819 
00820     int stype;
00821     if (! (d_data->attributes & (Yfx|Xfy|Parametric)))
00822     {
00823         if (qwtChkMono(txval, size))
00824         {
00825             stype = Yfx;
00826         }
00827         else
00828         {
00829             if(qwtChkMono(tyval, size))
00830             {
00831                 stype = Xfy;
00832             }
00833             else
00834             {
00835                 stype = Parametric;
00836                 if ( (d_data->attributes & Periodic) ||
00837                     ( (x(0) == x(size-1))
00838                     && (y(0) == y(size-1))))
00839                 {
00840                     stype |= Periodic;
00841                 }
00842             }
00843         }
00844     }
00845     else
00846     {
00847         stype = d_data->attributes;
00848     }
00849 
00850     bool ok = false;
00851     QwtPointArray polyline(d_data->splineSize);
00852 
00853     if (stype & Parametric)
00854     {
00855         //
00856         // setup parameter vector
00857         //
00858         double *param = new double[size];
00859         param[0] = 0.0;
00860         for (i=1; i<size; i++)
00861         {
00862             const double delta = sqrt( qwtSqr(txval[i] - txval[i-1])
00863                           + qwtSqr( tyval[i] - tyval[i-1]));
00864             param[i] = param[i-1] + qwtMax(delta, 1.0);
00865         }
00866 
00867         //
00868         // setup splines
00869         QwtSpline spx, spy;
00870         ok = spx.recalc(param, txval, size, stype & Periodic);
00871         if (ok)
00872             ok = spy.recalc(param, tyval, size, stype & Periodic);
00873 
00874         if ( ok )
00875         {
00876             // fill point array
00877             const double delta = 
00878                 param[size - 1] / double(d_data->splineSize-1);
00879             for (i = 0; i < d_data->splineSize; i++)
00880             {
00881                 const double dtmp = delta * double(i);
00882                 polyline.setPoint(i, qRound(spx.value(dtmp)), 
00883                     qRound(spy.value(dtmp)) );
00884             }
00885         }
00886         delete[] param;
00887     }
00888     else if (stype & Xfy)
00889     {
00890         if (tyval[size-1] < tyval[0])
00891         {
00892             qwtTwistArray(txval, size);
00893             qwtTwistArray(tyval, size);
00894         }
00895 
00896         // 1. Calculate spline coefficients
00897         QwtSpline spx;
00898         ok = spx.recalc(tyval, txval, size, stype & Periodic);
00899         if ( ok )
00900         {
00901             const double ymin = qwtGetMin(tyval, size);
00902             const double ymax = qwtGetMax(tyval, size);
00903             const double delta = (ymax - ymin) / double(d_data->splineSize - 1);
00904 
00905             for (i = 0; i < d_data->splineSize; i++)
00906             {
00907                 const double dtmp = ymin + delta * double(i);
00908                 polyline.setPoint(i, 
00909                     qRound(spx.value(dtmp)), qRound(dtmp + 0.5));
00910             }
00911         }
00912     }
00913     else
00914     {
00915         if (txval[size-1] < txval[0])
00916         {
00917             qwtTwistArray(tyval, size);
00918             qwtTwistArray(txval, size);
00919         }
00920 
00921         // 1. Calculate spline coefficients
00922         QwtSpline spy;
00923         ok = spy.recalc(txval, tyval, size, stype & Periodic);
00924         if ( ok )
00925         {
00926             const double xmin = qwtGetMin(txval, size);
00927             const double xmax = qwtGetMax(txval, size);
00928             const double delta = (xmax - xmin) / double(d_data->splineSize - 1);
00929 
00930             for (i = 0; i < d_data->splineSize; i++)
00931             {
00932                 double dtmp = xmin + delta * double(i);
00933                 polyline.setPoint(i, 
00934                     qRound(dtmp), qRound(spy.value(dtmp)));
00935             }
00936         }
00937     }
00938 
00939     delete[] txval;
00940     delete[] tyval;
00941 
00942     if ( ok )
00943     {
00944         QwtPainter::drawPolyline(painter, polyline);
00945 
00946         if ( d_data->brush.style() != Qt::NoBrush )
00947             fillCurve(painter, xMap, yMap, polyline);
00948     }
00949     else
00950         drawLines(painter, xMap, yMap, 0, size - 1);
00951 }
00952 
00983 void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on)
00984 {
00985     if ( bool(d_data->attributes & attribute) == on )
00986         return;
00987 
00988     if ( on )
00989         d_data->attributes |= attribute;
00990     else
00991         d_data->attributes &= ~attribute;
00992 
00993     itemChanged();
00994 }
00995 
01000 bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const 
01001 { 
01002     return d_data->attributes & attribute;
01003 }
01004 
01010 void QwtPlotCurve::setSplineSize(int s)
01011 {
01012     d_data->splineSize = qwtMax(s, 10);
01013     itemChanged();
01014 }
01015 
01022 int QwtPlotCurve::splineSize() const 
01023 { 
01024     return d_data->splineSize; 
01025 }
01026 
01027 void QwtPlotCurve::fillCurve(QPainter *painter,
01028     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01029     QwtPointArray &pa) const
01030 {
01031     if ( d_data->brush.style() == Qt::NoBrush )
01032         return;
01033 
01034     closePolyline(xMap, yMap, pa);
01035     if ( pa.count() <= 2 ) // a line can't be filled
01036         return;
01037 
01038     QBrush b = d_data->brush;
01039     if ( !b.color().isValid() )
01040         b.setColor(d_data->pen.color());
01041 
01042     painter->save();
01043 
01044     painter->setPen(QPen(Qt::NoPen));
01045     painter->setBrush(b);
01046 
01047     QwtPainter::drawPolygon(painter, pa);
01048 
01049     painter->restore();
01050 }
01051 
01061 void QwtPlotCurve::closePolyline(
01062     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01063     QwtPointArray &pa) const
01064 {
01065     const int sz = pa.size();
01066     if ( sz < 2 )
01067         return;
01068 
01069     pa.resize(sz + 2);
01070 
01071     if ( d_data->attributes & QwtPlotCurve::Xfy )
01072     {
01073         pa.setPoint(sz,
01074             xMap.transform(d_data->reference), pa.point(sz - 1).y());
01075         pa.setPoint(sz + 1,
01076             xMap.transform(d_data->reference), pa.point(0).y());
01077     }
01078     else
01079     {
01080         pa.setPoint(sz,
01081             pa.point(sz - 1).x(), yMap.transform(d_data->reference));
01082         pa.setPoint(pa.size() - 1,
01083             pa.point(0).x(), yMap.transform(d_data->reference));
01084     }
01085 }
01086 
01096 void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
01097     const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
01098     int from, int to) const
01099 {
01100     painter->setBrush(symbol.brush());
01101     painter->setPen(symbol.pen());
01102 
01103     QRect rect;
01104     rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
01105 
01106     for (int i = from; i <= to; i++)
01107     {
01108         const int xi = xMap.transform(x(i));
01109         const int yi = yMap.transform(y(i));
01110 
01111         rect.moveCenter(QPoint(xi, yi));
01112         symbol.draw(painter, rect);
01113     }
01114 }
01115 
01129 void QwtPlotCurve::setBaseline(double reference)
01130 {
01131     if ( d_data->reference != reference )
01132     {
01133         d_data->reference = reference;
01134         itemChanged();
01135     }
01136 }
01137 
01142 double QwtPlotCurve::baseline() const 
01143 { 
01144     return d_data->reference; 
01145 }
01146 
01150 int QwtPlotCurve::dataSize() const
01151 {
01152     return d_xy->size();
01153 }
01154 
01155 int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const
01156 {
01157     if ( plot() == NULL || dataSize() <= 0 )
01158         return -1;
01159 
01160     const QwtScaleMap xMap = plot()->canvasMap(xAxis());
01161     const QwtScaleMap yMap = plot()->canvasMap(yAxis());
01162 
01163     int index = -1;
01164     double dmin = 1.0e10;
01165 
01166     for (int i=0; i < dataSize(); i++)
01167     {
01168         const double cx = xMap.xTransform(x(i)) - pos.x();
01169         const double cy = yMap.xTransform(y(i)) - pos.y();
01170 
01171         const double f = qwtSqr(cx) + qwtSqr(cy);
01172         if (f < dmin)
01173         {
01174             index = i;
01175             dmin = f;
01176         }
01177     }
01178     if ( dist )
01179         *dist = sqrt(dmin);
01180 
01181     return index;
01182 }
01183 
01184 void QwtPlotCurve::updateLegend(QwtLegend *legend) const
01185 {
01186     if ( !legend )
01187         return;
01188 
01189     QwtPlotItem::updateLegend(legend);
01190 
01191     QWidget *widget = legend->find(this);
01192     if ( !widget || !widget->inherits("QwtLegendItem") )
01193         return;
01194 
01195     QwtLegendItem *legendItem = (QwtLegendItem *)widget;
01196 
01197 #if QT_VERSION < 0x040000
01198     const bool doUpdate = legendItem->isUpdatesEnabled();
01199 #else
01200     const bool doUpdate = legendItem->updatesEnabled();
01201 #endif
01202     legendItem->setUpdatesEnabled(false);
01203 
01204     const int policy = legend->displayPolicy();
01205 
01206     if (policy == QwtLegend::Fixed)
01207     {
01208         int mode = legend->identifierMode();
01209 
01210         if (mode & QwtLegendItem::ShowLine)
01211             legendItem->setCurvePen(pen());
01212 
01213         if (mode & QwtLegendItem::ShowSymbol)
01214             legendItem->setSymbol(symbol());
01215 
01216         if (mode & QwtLegendItem::ShowText)
01217             legendItem->setTitle(title());
01218         else
01219             legendItem->setTitle(QString::null);
01220 
01221         legendItem->setIdentifierMode(mode);
01222     }
01223     else if (policy == QwtLegend::Auto)
01224     {
01225         int mode = 0;
01226 
01227         if (QwtPlotCurve::NoCurve != style())
01228         {
01229             legendItem->setCurvePen(pen());
01230             mode |= QwtLegendItem::ShowLine;
01231         }
01232         if (QwtSymbol::None != symbol().style())
01233         {
01234             legendItem->setSymbol(symbol());
01235             mode |= QwtLegendItem::ShowSymbol;
01236         }
01237         if ( !title().isEmpty() )
01238         {
01239             legendItem->setTitle(title());
01240             mode |= QwtLegendItem::ShowText;
01241         }
01242         else
01243         {
01244             legendItem->setTitle(QString::null);
01245         }
01246         legendItem->setIdentifierMode(mode);
01247     }
01248 
01249     legendItem->setUpdatesEnabled(doUpdate);
01250     legendItem->update();
01251 }

Generated on Wed Aug 31 23:02:29 2005 for Qwt User's Guide by  doxygen 1.4.1