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 Tue Nov 16 21:12:20 2004 for Qwt User's Guide by doxygen 1.3.8