00001
00002
00003
00004
00005
00006
00007
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);
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
00604
00605
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
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
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
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
00693
int rc = d_spx.
recalc(tyval, txval, size, stype & Periodic);
00694
if (rc)
00695 {
00696
drawLines(painter, xMap, yMap, 0, size - 1);
00697 }
00698
else
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
00722
int rc = d_spy.
recalc(txval, tyval, size, stype & Periodic);
00723
if (rc)
00724 {
00725
drawLines(painter, xMap, yMap, 0, size - 1);
00726 }
00727
else
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 }