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

qwt_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 "qwt_global.h"
00012 #include "qwt_curve.h"
00013 #include "qwt_data.h"
00014 #include "qwt_dimap.h"
00015 #include "qwt_double_rect.h"
00016 #include "qwt_math.h"
00017 #include "qwt_painter.h"
00018 
00022 void QwtCurve::init(const QString &title)
00023 {
00024     d_pen = QPen(Qt::black, 1);
00025     d_ref = 0.0;
00026     d_splineSize = 250;
00027     d_options = Auto;
00028     d_title = title;
00029     d_style = Lines;
00030     d_data = new QwtDoublePointData(QwtArray<QwtDoublePoint>());
00031 }
00032 
00036 void QwtCurve::copy(const QwtCurve &c)
00037 {
00038     d_ref = c.d_ref;
00039     d_sym = c.d_sym;
00040     d_pen = c.d_pen;
00041     d_title = c.d_title;
00042     d_style = c.d_style;
00043 
00044     d_splineSize = c.d_splineSize;
00045     d_options = c.d_options;
00046 
00047     delete d_data;
00048     d_data = c.d_data->copy();
00049 }
00050 
00052 QwtCurve::~QwtCurve()
00053 {
00054     delete d_data;
00055 }
00056 
00060 QwtCurve::QwtCurve(const QwtCurve &c)
00061 {
00062     init(c.d_title);
00063     copy(c);
00064 }
00065 
00069 const QwtCurve& QwtCurve::operator=(const QwtCurve &c)
00070 {
00071     if (this != &c)
00072     {
00073         copy(c);
00074         curveChanged();
00075     }
00076 
00077     return *this;
00078 }
00079 
00110 void QwtCurve::setStyle(int style, int options)
00111 {
00112     d_options = options;
00113     d_style = style;
00114     curveChanged();
00115 }
00116 
00122 int QwtCurve::style() const 
00123 { 
00124     return d_style; 
00125 }
00126 
00132 void QwtCurve::setSymbol(const QwtSymbol &s )
00133 {
00134     d_sym = s;
00135     curveChanged();
00136 }
00137 
00142 const QwtSymbol &QwtCurve::symbol() const 
00143 { 
00144     return d_sym; 
00145 }
00146 
00147 
00152 void QwtCurve::setPen(const QPen &p)
00153 {
00154     if ( p != d_pen )
00155     {
00156         d_pen = p;
00157         curveChanged();
00158     }
00159 }
00160 
00165 const QPen& QwtCurve::pen() const 
00166 { 
00167     return d_pen; 
00168 }
00169 
00182 void QwtCurve::setBrush(const QBrush &brush)
00183 {
00184     if ( brush != d_brush )
00185     {
00186         d_brush = brush;
00187         curveChanged();
00188     }
00189 }
00190 
00196 const QBrush& QwtCurve::brush() const 
00197 {
00198     return d_brush;
00199 }
00200 
00201 
00213 void QwtCurve::setData(const double *xData, const double *yData, int size)
00214 {
00215     delete d_data;
00216     d_data = new QwtArrayData(xData, yData, size);
00217     curveChanged();
00218 }
00219 
00228 void QwtCurve::setData(const QwtArray<double> &xData, 
00229     const QwtArray<double> &yData)
00230 {
00231     delete d_data;
00232     d_data = new QwtArrayData(xData, yData);
00233     curveChanged();
00234 }
00235 
00243 void QwtCurve::setData(const QwtArray<QwtDoublePoint> &data)
00244 {
00245     delete d_data;
00246     d_data = new QwtDoublePointData(data);
00247     curveChanged();
00248 }
00249 
00257 void QwtCurve::setData(const QwtData &data)
00258 {
00259     delete d_data;
00260     d_data = data.copy();
00261     curveChanged();
00262 }
00263 
00277 void QwtCurve::setRawData(const double *xData, const double *yData, int size)
00278 {
00279     delete d_data;
00280     d_data = new QwtCPointerData(xData, yData, size);
00281     curveChanged();
00282 }
00283 
00288 void QwtCurve::setTitle(const QString &title)
00289 {
00290     d_title = title;
00291     curveChanged();
00292 }
00293 
00298 const QString &QwtCurve::title() const 
00299 { 
00300     return d_title; 
00301 }
00302 
00309 QwtDoubleRect QwtCurve::boundingRect() const
00310 {
00311     if ( d_data == NULL )
00312         return QwtDoubleRect(1.0, -1.0, 1.0, -1.0); // invalid
00313 
00314     return d_data->boundingRect();
00315 }
00316 
00321 QwtCurve::QwtCurve(const QString &title)
00322 {
00323     init(title);
00324 }
00325 
00331 int QwtCurve::verifyRange(int &i1, int &i2)
00332 {
00333     int size = dataSize();
00334 
00335     if (size < 1) return 0;
00336 
00337     i1 = qwtLim(i1, 0, size-1);
00338     i2 = qwtLim(i2, 0, size-1);
00339     qwtSort(i1, i2, i1, i2);
00340 
00341     return (i2 - i1 + 1);
00342 }
00343 
00357 void QwtCurve::draw(QPainter *painter,
00358     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00359 {
00360     if ( !painter || dataSize() <= 0 )
00361         return;
00362 
00363     if (to < 0)
00364         to = dataSize() - 1;
00365 
00366     if ( verifyRange(from, to) > 0 )
00367     {
00368         painter->save();
00369         painter->setPen(d_pen);
00370 
00371         QBrush b = d_brush;
00372         if ( b.style() != Qt::NoBrush && !b.color().isValid() )
00373             b.setColor(d_pen.color());
00374 
00375         painter->setBrush(b);
00376 
00377         drawCurve(painter, d_style, xMap, yMap, from, to);
00378         painter->restore();
00379 
00380         if (d_sym.style() != QwtSymbol::None)
00381         {
00382             painter->save();
00383             drawSymbols(painter, d_sym, xMap, yMap, from, to);
00384             painter->restore();
00385         }
00386     }
00387 }
00388 
00401 void QwtCurve::drawCurve(QPainter *painter, int style,
00402     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00403 {
00404     switch (style)
00405     {
00406         case NoCurve:
00407             break;
00408         case Lines:
00409             drawLines(painter, xMap, yMap, from, to);
00410             break;
00411         case Sticks:
00412             drawSticks(painter, xMap, yMap, from, to);
00413             break;
00414         case Steps:
00415             drawSteps(painter, xMap, yMap, from, to);
00416             break;
00417         case Spline:
00418             if ( from > 0 || to < dataSize() - 1 )
00419                 drawLines(painter, xMap, yMap, from, to);
00420             else
00421                 drawSpline(painter, xMap, yMap);
00422             break;
00423         case Dots:
00424             drawDots(painter, xMap, yMap, from, to);
00425             break;
00426         default:
00427             break;
00428     }
00429 }
00430 
00441 void QwtCurve::drawLines(QPainter *painter,
00442     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00443 {
00444     QPointArray polyline(to - from + 1);
00445     for (int i = from; i <= to; i++)
00446     {
00447         int xi = xMap.transform(x(i));
00448         int yi = yMap.transform(y(i));
00449 
00450         polyline.setPoint(i - from, xi, yi);
00451     }
00452 
00453     QwtPainter::drawPolyline(painter, polyline);
00454 
00455     if ( painter->brush().style() != Qt::NoBrush )
00456     {
00457         closePolyline(xMap, yMap, polyline);
00458         painter->setPen(QPen(Qt::NoPen));
00459         QwtPainter::drawPolygon(painter, polyline);
00460     }
00461 }
00462 
00473 void QwtCurve::drawSticks(QPainter *painter,
00474     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00475 {
00476     int x0 = xMap.transform(d_ref);
00477     int y0 = yMap.transform(d_ref);
00478 
00479     for (int i = from; i <= to; i++)
00480     {
00481         int xi = xMap.transform(x(i));
00482         int yi = yMap.transform(y(i));
00483 
00484         if (d_options & Xfy)
00485             QwtPainter::drawLine(painter, x0, yi, xi, yi);
00486         else
00487             QwtPainter::drawLine(painter, xi, y0, xi, yi);
00488     }
00489 }
00490 
00502 void QwtCurve::drawDots(QPainter *painter,
00503     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00504 {
00505     const bool doFill = painter->brush().style() != Qt::NoBrush;
00506 
00507     QPointArray polyline;
00508     if ( doFill )
00509         polyline.resize(to - from + 1);
00510 
00511     for (int i = from; i <= to; i++)
00512     {
00513         int xi = xMap.transform(x(i));
00514         int yi = yMap.transform(y(i));
00515         QwtPainter::drawPoint(painter, xi, yi);
00516 
00517         if ( doFill )
00518             polyline.setPoint(i - from, xi, yi);
00519     }
00520 
00521     if ( doFill )
00522     {
00523         closePolyline(xMap, yMap, polyline);
00524         painter->setPen(QPen(Qt::NoPen));
00525         QwtPainter::drawPolygon(painter, polyline);
00526     }
00527 }
00528 
00539 void QwtCurve::drawSteps(QPainter *painter,
00540     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00541 {
00542     QPointArray polyline(2 * (to - from) + 1);
00543 
00544     bool inverted = d_options & Yfx;
00545     if ( d_options & Inverted )
00546         inverted = !inverted;
00547 
00548     int i,ip;
00549     for (i = from, ip = 0; i <= to; i++, ip += 2)
00550     {
00551         int xi = xMap.transform(x(i));
00552         int yi = yMap.transform(y(i));
00553 
00554         if ( ip > 0 )
00555         {
00556             if (inverted)
00557                 polyline.setPoint(ip - 1, polyline[ip-2].x(), yi);
00558             else
00559                 polyline.setPoint(ip - 1, xi, polyline[ip-2].y());
00560         }
00561 
00562         polyline.setPoint(ip, xi, yi);
00563     }
00564 
00565     QwtPainter::drawPolyline(painter, polyline);
00566 
00567     if ( painter->brush().style() != Qt::NoBrush )
00568     {
00569         closePolyline(xMap, yMap, polyline);
00570         painter->setPen(QPen(Qt::NoPen));
00571         QwtPainter::drawPolygon(painter, polyline);
00572     }
00573 }
00574 
00583 void QwtCurve::drawSpline(QPainter *painter,
00584     const QwtDiMap &xMap, const QwtDiMap &yMap)
00585 {
00586     register int i;
00587 
00588     int size = dataSize();
00589     double *txval = new double[size];
00590     double *tyval = new double[size];
00591 
00592 
00593     if ( !txval || !tyval )
00594     {
00595         if (txval) delete[] txval;
00596         if (tyval) delete[] tyval;
00597         return;
00598     }
00599 
00600     QPointArray polyline(d_splineSize);
00601 
00602     //
00603     // Transform x and y values to window coordinates
00604     // to avoid a distinction between linear and
00605     // logarithmic scales.
00606     //
00607     for (i=0;i<size;i++)
00608     {
00609         txval[i] = xMap.xTransform(x(i));
00610         tyval[i] = yMap.xTransform(y(i));
00611     }
00612 
00613     int stype;
00614     if (! (d_options & (Yfx|Xfy|Parametric)))
00615     {
00616         if (qwtChkMono(txval, size))
00617         {
00618             stype = Yfx;
00619         }
00620         else
00621         {
00622             if(qwtChkMono(tyval, size))
00623             {
00624                 stype = Xfy;
00625             }
00626             else
00627             {
00628                 stype = Parametric;
00629                 if ( (d_options & Periodic) ||
00630                     ( (x(0) == x(size-1))
00631                     && (y(0) == y(size-1))))
00632                 {
00633                     stype |= Periodic;
00634                 }
00635             }
00636         }
00637     }
00638     else
00639     {
00640         stype = d_options;
00641     }
00642 
00643     if (stype & Parametric)
00644     {
00645         double *param = new double[size];
00646         if (param)
00647         {
00648             //
00649             // setup parameter vector
00650             //
00651             param[0] = 0.0;
00652             for (i=1; i<size; i++)
00653             {
00654                 double delta = sqrt( qwtSqr(txval[i] - txval[i-1])
00655                               + qwtSqr( tyval[i] - tyval[i-1]));
00656                 param[i] = param[i-1] + qwtMax(delta, 1.0);
00657             }
00658 
00659             //
00660             // setup splines
00661             int rc = d_spx.recalc(param, txval, size, stype & Periodic);
00662             if (!rc)
00663                 rc = d_spy.recalc(param, tyval, size, stype & Periodic);
00664 
00665             if (rc)
00666             {
00667                 drawLines(painter, xMap, yMap, 0, size - 1);
00668             }
00669             else
00670             {
00671                 // fill point array
00672                 double delta = param[size - 1] / double(d_splineSize-1);
00673                 for (i=0;i<d_splineSize;i++)
00674                 {
00675                     double dtmp = delta * double(i);
00676                     polyline.setPoint(i, int(floor (d_spx.value(dtmp) + 0.5)),
00677                                   int(floor (d_spy.value(dtmp) + 0.5)));
00678                 }
00679             }
00680 
00681             delete[] param;
00682         }
00683     }
00684     else if (stype & Xfy)
00685     {
00686         if (tyval[size-1] < tyval[0])
00687         {
00688             qwtTwistArray(txval, size);
00689             qwtTwistArray(tyval, size);
00690         }
00691 
00692         // 1. Calculate spline coefficients
00693         int rc = d_spx.recalc(tyval, txval, size, stype & Periodic);
00694         if (rc)                         // an error occurred
00695         {
00696             drawLines(painter, xMap, yMap, 0, size - 1);
00697         }
00698         else                            // Spline OK
00699         {
00700             double ymin = qwtGetMin(tyval, size);
00701             double ymax = qwtGetMax(tyval, size);
00702             double delta = (ymax - ymin) / double(d_splineSize - 1);
00703 
00704             for (i=0;i<d_splineSize;i++)
00705             {
00706                 double dtmp = ymin + delta * double(i);
00707                 polyline.setPoint(i, int(floor(d_spx.value(dtmp) + 0.5)),
00708                               int(floor(dtmp + 0.5)));
00709             }
00710         }
00711     }
00712     else
00713     {
00714         if (txval[size-1] < txval[0])
00715         {
00716             qwtTwistArray(tyval, size);
00717             qwtTwistArray(txval, size);
00718         }
00719 
00720 
00721         // 1. Calculate spline coefficients
00722         int rc = d_spy.recalc(txval, tyval, size, stype & Periodic);
00723         if (rc)                         // error
00724         {
00725             drawLines(painter, xMap, yMap, 0, size - 1);
00726         }
00727         else                            // Spline OK
00728         {
00729             double xmin = qwtGetMin(txval, size);
00730             double xmax = qwtGetMax(txval, size);
00731             double delta = (xmax - xmin) / double(d_splineSize - 1);
00732 
00733             for (i=0;i<d_splineSize;i++)
00734             {
00735                 double dtmp = xmin + delta * double(i);
00736                 polyline.setPoint(i, int(floor (dtmp + 0.5)),
00737                               int(floor(d_spy.value(dtmp) + 0.5)));
00738             }
00739         }
00740     }
00741 
00742     delete[] txval;
00743     delete[] tyval;
00744 
00745     QwtPainter::drawPolyline(painter, polyline);
00746 
00747     if ( painter->brush().style() != Qt::NoBrush )
00748     {
00749         closePolyline(xMap, yMap, polyline);
00750         painter->setPen(QPen(Qt::NoPen));
00751         QwtPainter::drawPolygon(painter, polyline);
00752     }
00753 }
00754 
00785 void QwtCurve::setOptions(int opt)
00786 {
00787     d_options = opt;
00788     curveChanged();
00789 }
00790 
00795 int QwtCurve::options() const 
00796 { 
00797     return d_options; 
00798 }
00799 
00805 void QwtCurve::setSplineSize(int s)
00806 {
00807     d_splineSize = qwtMax(s, 10);
00808     curveChanged();
00809 }
00810 
00817 int QwtCurve::splineSize() const 
00818 { 
00819     return d_splineSize; 
00820 }
00821 
00831 void QwtCurve::closePolyline(const QwtDiMap &xMap, const QwtDiMap &yMap,
00832     QPointArray &pa) const
00833 {
00834     const int sz = pa.size();
00835     if ( sz < 2 )
00836         return;
00837 
00838     pa.resize(sz + 2);
00839 
00840     if ( d_options & QwtCurve::Xfy )
00841     {
00842         pa.setPoint(sz,
00843             xMap.transform(d_ref), pa.point(sz - 1).y());
00844         pa.setPoint(sz + 1,
00845             xMap.transform(d_ref), pa.point(0).y());
00846     }
00847     else
00848     {
00849         pa.setPoint(sz,
00850             pa.point(sz - 1).x(), yMap.transform(d_ref));
00851         pa.setPoint(pa.size() - 1,
00852             pa.point(0).x(), yMap.transform(d_ref));
00853     }
00854 }
00855 
00865 void QwtCurve::drawSymbols(QPainter *painter, QwtSymbol &symbol,
00866     const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to)
00867 {
00868     painter->setBrush(symbol.brush());
00869     painter->setPen(symbol.pen());
00870 
00871     QRect rect;
00872     rect.setSize(QwtPainter::metricsMap().screenToLayout(symbol.size()));
00873 
00874     for (int i = from; i <= to; i++)
00875     {
00876         const int xi = xMap.transform(x(i));
00877         const int yi = yMap.transform(y(i));
00878 
00879         rect.moveCenter(QPoint(xi, yi));
00880         symbol.draw(painter, rect);
00881     }
00882 }
00883 
00897 void QwtCurve::setBaseline(double ref)
00898 {
00899     d_ref = ref;
00900     curveChanged();
00901 }
00902 
00907 double QwtCurve::baseline() const 
00908 { 
00909     return d_ref; 
00910 }
00911 
00915 int QwtCurve::dataSize() const
00916 {
00917     return d_data->size();
00918 }
00919 
00927 void QwtCurve::curveChanged() 
00928 {
00929 }

Generated on Sun Nov 21 11:12:42 2004 for Qwt User's Guide by doxygen 1.3.5