00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_curve.h"
00011 #include "qwt_point_data.h"
00012 #include "qwt_math.h"
00013 #include "qwt_clipper.h"
00014 #include "qwt_painter.h"
00015 #include "qwt_scale_map.h"
00016 #include "qwt_plot.h"
00017 #include "qwt_spline_curve_fitter.h"
00018 #include "qwt_symbol.h"
00019 #include "qwt_point_mapper.h"
00020 #include <qpainter.h>
00021 #include <qpixmap.h>
00022 #include <qalgorithms.h>
00023 #include <qmath.h>
00024
00025 static inline QRectF qwtIntersectedClipRect( const QRectF &rect, QPainter *painter )
00026 {
00027 QRectF clipRect = rect;
00028 if ( painter->hasClipping() )
00029 {
00030 #if QT_VERSION >= 0x040800
00031 const QRectF r = painter->clipBoundingRect();
00032 #else
00033 const QRectF r = painter->clipRegion().boundingRect();
00034 #endif
00035 clipRect &= r;
00036 }
00037
00038 return clipRect;
00039 }
00040
00041 static void qwtUpdateLegendIconSize( QwtPlotCurve *curve )
00042 {
00043 if ( curve->symbol() &&
00044 curve->testLegendAttribute( QwtPlotCurve::LegendShowSymbol ) )
00045 {
00046 QSize sz = curve->symbol()->boundingRect().size();
00047 sz += QSize( 2, 2 );
00048
00049 if ( curve->testLegendAttribute( QwtPlotCurve::LegendShowLine ) )
00050 {
00051
00052
00053 int w = qCeil( 1.5 * sz.width() );
00054 if ( w % 2 )
00055 w++;
00056
00057 sz.setWidth( qMax( 8, w ) );
00058 }
00059
00060 curve->setLegendIconSize( sz );
00061 }
00062 }
00063
00064 static int qwtVerifyRange( int size, int &i1, int &i2 )
00065 {
00066 if ( size < 1 )
00067 return 0;
00068
00069 i1 = qBound( 0, i1, size - 1 );
00070 i2 = qBound( 0, i2, size - 1 );
00071
00072 if ( i1 > i2 )
00073 qSwap( i1, i2 );
00074
00075 return ( i2 - i1 + 1 );
00076 }
00077
00078 class QwtPlotCurve::PrivateData
00079 {
00080 public:
00081 PrivateData():
00082 style( QwtPlotCurve::Lines ),
00083 baseline( 0.0 ),
00084 symbol( NULL ),
00085 pen( Qt::black ),
00086 attributes( 0 ),
00087 paintAttributes(
00088 QwtPlotCurve::ClipPolygons | QwtPlotCurve::FilterPoints ),
00089 legendAttributes( 0 )
00090 {
00091 curveFitter = new QwtSplineCurveFitter;
00092 }
00093
00094 ~PrivateData()
00095 {
00096 delete symbol;
00097 delete curveFitter;
00098 }
00099
00100 QwtPlotCurve::CurveStyle style;
00101 double baseline;
00102
00103 const QwtSymbol *symbol;
00104 QwtCurveFitter *curveFitter;
00105
00106 QPen pen;
00107 QBrush brush;
00108
00109 QwtPlotCurve::CurveAttributes attributes;
00110 QwtPlotCurve::PaintAttributes paintAttributes;
00111
00112 QwtPlotCurve::LegendAttributes legendAttributes;
00113 };
00114
00119 QwtPlotCurve::QwtPlotCurve( const QwtText &title ):
00120 QwtPlotSeriesItem( title )
00121 {
00122 init();
00123 }
00124
00129 QwtPlotCurve::QwtPlotCurve( const QString &title ):
00130 QwtPlotSeriesItem( QwtText( title ) )
00131 {
00132 init();
00133 }
00134
00136 QwtPlotCurve::~QwtPlotCurve()
00137 {
00138 delete d_data;
00139 }
00140
00142 void QwtPlotCurve::init()
00143 {
00144 setItemAttribute( QwtPlotItem::Legend );
00145 setItemAttribute( QwtPlotItem::AutoScale );
00146
00147 d_data = new PrivateData;
00148 setData( new QwtPointSeriesData() );
00149
00150 setZ( 20.0 );
00151 }
00152
00154 int QwtPlotCurve::rtti() const
00155 {
00156 return QwtPlotItem::Rtti_PlotCurve;
00157 }
00158
00166 void QwtPlotCurve::setPaintAttribute( PaintAttribute attribute, bool on )
00167 {
00168 if ( on )
00169 d_data->paintAttributes |= attribute;
00170 else
00171 d_data->paintAttributes &= ~attribute;
00172 }
00173
00178 bool QwtPlotCurve::testPaintAttribute( PaintAttribute attribute ) const
00179 {
00180 return ( d_data->paintAttributes & attribute );
00181 }
00182
00190 void QwtPlotCurve::setLegendAttribute( LegendAttribute attribute, bool on )
00191 {
00192 if ( on != testLegendAttribute( attribute ) )
00193 {
00194 if ( on )
00195 d_data->legendAttributes |= attribute;
00196 else
00197 d_data->legendAttributes &= ~attribute;
00198
00199 qwtUpdateLegendIconSize( this );
00200 legendChanged();
00201 }
00202 }
00203
00208 bool QwtPlotCurve::testLegendAttribute( LegendAttribute attribute ) const
00209 {
00210 return ( d_data->legendAttributes & attribute );
00211 }
00212
00219 void QwtPlotCurve::setStyle( CurveStyle style )
00220 {
00221 if ( style != d_data->style )
00222 {
00223 d_data->style = style;
00224
00225 legendChanged();
00226 itemChanged();
00227 }
00228 }
00229
00234 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00235 {
00236 return d_data->style;
00237 }
00238
00249 void QwtPlotCurve::setSymbol( QwtSymbol *symbol )
00250 {
00251 if ( symbol != d_data->symbol )
00252 {
00253 delete d_data->symbol;
00254 d_data->symbol = symbol;
00255
00256 qwtUpdateLegendIconSize( this );
00257
00258 legendChanged();
00259 itemChanged();
00260 }
00261 }
00262
00267 const QwtSymbol *QwtPlotCurve::symbol() const
00268 {
00269 return d_data->symbol;
00270 }
00271
00285 void QwtPlotCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style )
00286 {
00287 setPen( QPen( color, width, style ) );
00288 }
00289
00296 void QwtPlotCurve::setPen( const QPen &pen )
00297 {
00298 if ( pen != d_data->pen )
00299 {
00300 d_data->pen = pen;
00301
00302 legendChanged();
00303 itemChanged();
00304 }
00305 }
00306
00311 const QPen& QwtPlotCurve::pen() const
00312 {
00313 return d_data->pen;
00314 }
00315
00331 void QwtPlotCurve::setBrush( const QBrush &brush )
00332 {
00333 if ( brush != d_data->brush )
00334 {
00335 d_data->brush = brush;
00336
00337 legendChanged();
00338 itemChanged();
00339 }
00340 }
00341
00346 const QBrush& QwtPlotCurve::brush() const
00347 {
00348 return d_data->brush;
00349 }
00350
00364 void QwtPlotCurve::drawSeries( QPainter *painter,
00365 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00366 const QRectF &canvasRect, int from, int to ) const
00367 {
00368 const size_t numSamples = dataSize();
00369
00370 if ( !painter || numSamples <= 0 )
00371 return;
00372
00373 if ( to < 0 )
00374 to = numSamples - 1;
00375
00376 if ( qwtVerifyRange( numSamples, from, to ) > 0 )
00377 {
00378 painter->save();
00379 painter->setPen( d_data->pen );
00380
00381
00382
00383
00384
00385
00386
00387 drawCurve( painter, d_data->style, xMap, yMap, canvasRect, from, to );
00388 painter->restore();
00389
00390 if ( d_data->symbol &&
00391 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
00392 {
00393 painter->save();
00394 drawSymbols( painter, *d_data->symbol,
00395 xMap, yMap, canvasRect, from, to );
00396 painter->restore();
00397 }
00398 }
00399 }
00400
00412 void QwtPlotCurve::drawCurve( QPainter *painter, int style,
00413 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00414 const QRectF &canvasRect, int from, int to ) const
00415 {
00416 switch ( style )
00417 {
00418 case Lines:
00419 if ( testCurveAttribute( Fitted ) )
00420 {
00421
00422
00423 from = 0;
00424 to = dataSize() - 1;
00425 }
00426 drawLines( painter, xMap, yMap, canvasRect, from, to );
00427 break;
00428 case Sticks:
00429 drawSticks( painter, xMap, yMap, canvasRect, from, to );
00430 break;
00431 case Steps:
00432 drawSteps( painter, xMap, yMap, canvasRect, from, to );
00433 break;
00434 case Dots:
00435 drawDots( painter, xMap, yMap, canvasRect, from, to );
00436 break;
00437 case LinesAndDots:
00438 {
00439 if ( testCurveAttribute( Fitted ) )
00440 {
00441 from = 0;
00442 to = dataSize() - 1;
00443 }
00444 drawLines( painter, xMap, yMap, canvasRect, from, to );
00445
00446 QPen prev_pen = painter->pen();
00447 QPen new_pen = prev_pen;
00448 new_pen.setWidth( prev_pen.width() * 3);
00449
00450 painter->setPen( new_pen );
00451 drawDots( painter, xMap, yMap, canvasRect, from, to );
00452 painter->setPen( prev_pen );
00453 }
00454 break;
00455 case NoCurve:
00456 default:
00457 break;
00458 }
00459 }
00460
00477 void QwtPlotCurve::drawLines( QPainter *painter,
00478 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00479 const QRectF &canvasRect, int from, int to ) const
00480 {
00481 if ( from > to )
00482 return;
00483
00484 const bool doFit = ( d_data->attributes & Fitted ) && d_data->curveFitter;
00485 const bool doAlign = !doFit && QwtPainter::roundingAlignment( painter );
00486 const bool doFill = ( d_data->brush.style() != Qt::NoBrush )
00487 && ( d_data->brush.color().alpha() > 0 );
00488
00489 QRectF clipRect;
00490 if ( d_data->paintAttributes & ClipPolygons )
00491 {
00492 clipRect = qwtIntersectedClipRect( canvasRect, painter );
00493
00494 const qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
00495 clipRect = clipRect.adjusted(-pw, -pw, pw, pw);
00496 }
00497
00498 bool doIntegers = false;
00499
00500 #if QT_VERSION < 0x040800
00501 if ( painter->paintEngine()->type() == QPaintEngine::Raster )
00502 {
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 if ( !doFit && !doFill )
00513 doIntegers = true;
00514 }
00515 #endif
00516
00517 QwtPointMapper mapper;
00518
00519 if ( doAlign )
00520 {
00521 mapper.setFlag( QwtPointMapper::RoundPoints, true );
00522 mapper.setFlag( QwtPointMapper::WeedOutIntermediatePoints,
00523 testPaintAttribute( FilterPointsAggressive ) );
00524 }
00525
00526 mapper.setFlag( QwtPointMapper::WeedOutPoints,
00527 testPaintAttribute( FilterPoints ) ||
00528 testPaintAttribute( FilterPointsAggressive ) );
00529
00530 mapper.setBoundingRect( canvasRect );
00531
00532 if ( doIntegers )
00533 {
00534 QPolygon polyline = mapper.toPolygon(
00535 xMap, yMap, data(), from, to );
00536
00537 if ( testPaintAttribute( ClipPolygons ) )
00538 {
00539 QwtClipper::clipPolygon( clipRect, polyline, false );
00540 }
00541
00542 QwtPainter::drawPolyline( painter, polyline );
00543 }
00544 else
00545 {
00546 QPolygonF polyline = mapper.toPolygonF( xMap, yMap, data(), from, to );
00547
00548 if ( doFill )
00549 {
00550 if ( doFit )
00551 {
00552
00553
00554
00555
00556 polyline = d_data->curveFitter->fitCurve( polyline );
00557 }
00558
00559 if ( painter->pen().style() != Qt::NoPen )
00560 {
00561
00562
00563
00564 QPolygonF filled = polyline;
00565 fillCurve( painter, xMap, yMap, canvasRect, filled );
00566 filled.clear();
00567
00568 if ( d_data->paintAttributes & ClipPolygons )
00569 QwtClipper::clipPolygonF( clipRect, polyline, false );
00570
00571 QwtPainter::drawPolyline( painter, polyline );
00572 }
00573 else
00574 {
00575 fillCurve( painter, xMap, yMap, canvasRect, polyline );
00576 }
00577 }
00578 else
00579 {
00580 if ( testPaintAttribute( ClipPolygons ) )
00581 {
00582 QwtClipper::clipPolygonF( clipRect, polyline, false );
00583 }
00584
00585 if ( doFit )
00586 {
00587 if ( d_data->curveFitter->mode() == QwtCurveFitter::Path )
00588 {
00589 const QPainterPath curvePath =
00590 d_data->curveFitter->fitCurvePath( polyline );
00591
00592 painter->drawPath( curvePath );
00593 }
00594 else
00595 {
00596 polyline = d_data->curveFitter->fitCurve( polyline );
00597 QwtPainter::drawPolyline( painter, polyline );
00598 }
00599 }
00600 else
00601 {
00602 QwtPainter::drawPolyline( painter, polyline );
00603 }
00604 }
00605 }
00606 }
00607
00620 void QwtPlotCurve::drawSticks( QPainter *painter,
00621 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00622 const QRectF &, int from, int to ) const
00623 {
00624 painter->save();
00625 painter->setRenderHint( QPainter::Antialiasing, false );
00626
00627 const bool doAlign = QwtPainter::roundingAlignment( painter );
00628
00629 double x0 = xMap.transform( d_data->baseline );
00630 double y0 = yMap.transform( d_data->baseline );
00631 if ( doAlign )
00632 {
00633 x0 = qRound( x0 );
00634 y0 = qRound( y0 );
00635 }
00636
00637 const Qt::Orientation o = orientation();
00638
00639 const QwtSeriesData<QPointF> *series = data();
00640
00641 for ( int i = from; i <= to; i++ )
00642 {
00643 const QPointF sample = series->sample( i );
00644 double xi = xMap.transform( sample.x() );
00645 double yi = yMap.transform( sample.y() );
00646 if ( doAlign )
00647 {
00648 xi = qRound( xi );
00649 yi = qRound( yi );
00650 }
00651
00652 if ( o == Qt::Horizontal )
00653 QwtPainter::drawLine( painter, x0, yi, xi, yi );
00654 else
00655 QwtPainter::drawLine( painter, xi, y0, xi, yi );
00656 }
00657
00658 painter->restore();
00659 }
00660
00673 void QwtPlotCurve::drawDots( QPainter *painter,
00674 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00675 const QRectF &canvasRect, int from, int to ) const
00676 {
00677 const QColor color = painter->pen().color();
00678
00679 if ( painter->pen().style() == Qt::NoPen || color.alpha() == 0 )
00680 {
00681 return;
00682 }
00683
00684 const bool doFill = ( d_data->brush.style() != Qt::NoBrush )
00685 && ( d_data->brush.color().alpha() > 0 );
00686 const bool doAlign = QwtPainter::roundingAlignment( painter );
00687
00688 QwtPointMapper mapper;
00689 mapper.setBoundingRect( canvasRect );
00690 mapper.setFlag( QwtPointMapper::RoundPoints, doAlign );
00691
00692 if ( d_data->paintAttributes & FilterPoints )
00693 {
00694 if ( ( color.alpha() == 255 )
00695 && !( painter->renderHints() & QPainter::Antialiasing ) )
00696 {
00697 mapper.setFlag( QwtPointMapper::WeedOutPoints, true );
00698 }
00699 }
00700
00701 if ( doFill )
00702 {
00703 mapper.setFlag( QwtPointMapper::WeedOutPoints, false );
00704
00705 QPolygonF points = mapper.toPointsF(
00706 xMap, yMap, data(), from, to );
00707
00708 QwtPainter::drawPoints( painter, points );
00709 fillCurve( painter, xMap, yMap, canvasRect, points );
00710 }
00711 else if ( d_data->paintAttributes & ImageBuffer )
00712 {
00713 const QImage image = mapper.toImage( xMap, yMap,
00714 data(), from, to, d_data->pen,
00715 painter->testRenderHint( QPainter::Antialiasing ),
00716 renderThreadCount() );
00717
00718 painter->drawImage( canvasRect.toAlignedRect(), image );
00719 }
00720 else if ( d_data->paintAttributes & MinimizeMemory )
00721 {
00722 const QwtSeriesData<QPointF> *series = data();
00723
00724 for ( int i = from; i <= to; i++ )
00725 {
00726 const QPointF sample = series->sample( i );
00727
00728 double xi = xMap.transform( sample.x() );
00729 double yi = yMap.transform( sample.y() );
00730
00731 if ( doAlign )
00732 {
00733 xi = qRound( xi );
00734 yi = qRound( yi );
00735 }
00736
00737 QwtPainter::drawPoint( painter, QPointF( xi, yi ) );
00738 }
00739 }
00740 else
00741 {
00742 if ( doAlign )
00743 {
00744 const QPolygon points = mapper.toPoints(
00745 xMap, yMap, data(), from, to );
00746
00747 QwtPainter::drawPoints( painter, points );
00748 }
00749 else
00750 {
00751 const QPolygonF points = mapper.toPointsF(
00752 xMap, yMap, data(), from, to );
00753
00754 QwtPainter::drawPoints( painter, points );
00755 }
00756 }
00757 }
00758
00774 void QwtPlotCurve::drawSteps( QPainter *painter,
00775 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00776 const QRectF &canvasRect, int from, int to ) const
00777 {
00778 const bool doAlign = QwtPainter::roundingAlignment( painter );
00779
00780 QPolygonF polygon( 2 * ( to - from ) + 1 );
00781 QPointF *points = polygon.data();
00782
00783 bool inverted = orientation() == Qt::Vertical;
00784 if ( d_data->attributes & Inverted )
00785 inverted = !inverted;
00786
00787 const QwtSeriesData<QPointF> *series = data();
00788
00789 int i, ip;
00790 for ( i = from, ip = 0; i <= to; i++, ip += 2 )
00791 {
00792 const QPointF sample = series->sample( i );
00793 double xi = xMap.transform( sample.x() );
00794 double yi = yMap.transform( sample.y() );
00795 if ( doAlign )
00796 {
00797 xi = qRound( xi );
00798 yi = qRound( yi );
00799 }
00800
00801 if ( ip > 0 )
00802 {
00803 const QPointF &p0 = points[ip - 2];
00804 QPointF &p = points[ip - 1];
00805
00806 if ( inverted )
00807 {
00808 p.rx() = p0.x();
00809 p.ry() = yi;
00810 }
00811 else
00812 {
00813 p.rx() = xi;
00814 p.ry() = p0.y();
00815 }
00816 }
00817
00818 points[ip].rx() = xi;
00819 points[ip].ry() = yi;
00820 }
00821
00822 if ( d_data->paintAttributes & ClipPolygons )
00823 {
00824 QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
00825
00826 const qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
00827 clipRect = clipRect.adjusted(-pw, -pw, pw, pw);
00828
00829 const QPolygonF clipped = QwtClipper::clippedPolygonF(
00830 clipRect, polygon, false );
00831
00832 QwtPainter::drawPolyline( painter, clipped );
00833 }
00834 else
00835 {
00836 QwtPainter::drawPolyline( painter, polygon );
00837 }
00838
00839 if ( d_data->brush.style() != Qt::NoBrush )
00840 fillCurve( painter, xMap, yMap, canvasRect, polygon );
00841 }
00842
00843
00852 void QwtPlotCurve::setCurveAttribute( CurveAttribute attribute, bool on )
00853 {
00854 if ( bool( d_data->attributes & attribute ) == on )
00855 return;
00856
00857 if ( on )
00858 d_data->attributes |= attribute;
00859 else
00860 d_data->attributes &= ~attribute;
00861
00862 itemChanged();
00863 }
00864
00869 bool QwtPlotCurve::testCurveAttribute( CurveAttribute attribute ) const
00870 {
00871 return d_data->attributes & attribute;
00872 }
00873
00891 void QwtPlotCurve::setCurveFitter( QwtCurveFitter *curveFitter )
00892 {
00893 delete d_data->curveFitter;
00894 d_data->curveFitter = curveFitter;
00895
00896 itemChanged();
00897 }
00898
00905 QwtCurveFitter *QwtPlotCurve::curveFitter() const
00906 {
00907 return d_data->curveFitter;
00908 }
00909
00922 void QwtPlotCurve::fillCurve( QPainter *painter,
00923 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00924 const QRectF &canvasRect, QPolygonF &polygon ) const
00925 {
00926 if ( d_data->brush.style() == Qt::NoBrush )
00927 return;
00928
00929 closePolyline( painter, xMap, yMap, polygon );
00930 if ( polygon.count() <= 2 )
00931 return;
00932
00933 QBrush brush = d_data->brush;
00934 if ( !brush.color().isValid() )
00935 brush.setColor( d_data->pen.color() );
00936
00937 if ( d_data->paintAttributes & ClipPolygons )
00938 {
00939 const QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
00940 QwtClipper::clipPolygonF( clipRect, polygon, true );
00941 }
00942
00943 painter->save();
00944
00945 painter->setPen( Qt::NoPen );
00946 painter->setBrush( brush );
00947
00948 QwtPainter::drawPolygon( painter, polygon );
00949
00950 painter->restore();
00951 }
00952
00962 void QwtPlotCurve::closePolyline( QPainter *painter,
00963 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00964 QPolygonF &polygon ) const
00965 {
00966 if ( polygon.size() < 2 )
00967 return;
00968
00969 const bool doAlign = QwtPainter::roundingAlignment( painter );
00970
00971 double baseline = d_data->baseline;
00972
00973 if ( orientation() == Qt::Vertical )
00974 {
00975 if ( yMap.transformation() )
00976 baseline = yMap.transformation()->bounded( baseline );
00977
00978 double refY = yMap.transform( baseline );
00979 if ( doAlign )
00980 refY = qRound( refY );
00981
00982 polygon += QPointF( polygon.last().x(), refY );
00983 polygon += QPointF( polygon.first().x(), refY );
00984 }
00985 else
00986 {
00987 if ( xMap.transformation() )
00988 baseline = xMap.transformation()->bounded( baseline );
00989
00990 double refX = xMap.transform( baseline );
00991 if ( doAlign )
00992 refX = qRound( refX );
00993
00994 polygon += QPointF( refX, polygon.last().y() );
00995 polygon += QPointF( refX, polygon.first().y() );
00996 }
00997 }
00998
01012 void QwtPlotCurve::drawSymbols( QPainter *painter, const QwtSymbol &symbol,
01013 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01014 const QRectF &canvasRect, int from, int to ) const
01015 {
01016 QwtPointMapper mapper;
01017 mapper.setFlag( QwtPointMapper::RoundPoints,
01018 QwtPainter::roundingAlignment( painter ) );
01019 mapper.setFlag( QwtPointMapper::WeedOutPoints,
01020 testPaintAttribute( QwtPlotCurve::FilterPoints ) );
01021
01022 const QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
01023 mapper.setBoundingRect( clipRect );
01024
01025 const int chunkSize = 500;
01026
01027 for ( int i = from; i <= to; i += chunkSize )
01028 {
01029 const int n = qMin( chunkSize, to - i + 1 );
01030
01031 const QPolygonF points = mapper.toPointsF( xMap, yMap,
01032 data(), i, i + n - 1 );
01033
01034 if ( points.size() > 0 )
01035 symbol.drawSymbols( painter, points );
01036 }
01037 }
01038
01055 void QwtPlotCurve::setBaseline( double value )
01056 {
01057 if ( d_data->baseline != value )
01058 {
01059 d_data->baseline = value;
01060 itemChanged();
01061 }
01062 }
01063
01068 double QwtPlotCurve::baseline() const
01069 {
01070 return d_data->baseline;
01071 }
01072
01084 int QwtPlotCurve::closestPoint( const QPoint &pos, double *dist ) const
01085 {
01086 const size_t numSamples = dataSize();
01087
01088 if ( plot() == NULL || numSamples <= 0 )
01089 return -1;
01090
01091 const QwtSeriesData<QPointF> *series = data();
01092
01093 const QwtScaleMap xMap = plot()->canvasMap( xAxis() );
01094 const QwtScaleMap yMap = plot()->canvasMap( yAxis() );
01095
01096 int index = -1;
01097 double dmin = 1.0e10;
01098
01099 for ( uint i = 0; i < numSamples; i++ )
01100 {
01101 const QPointF sample = series->sample( i );
01102
01103 const double cx = xMap.transform( sample.x() ) - pos.x();
01104 const double cy = yMap.transform( sample.y() ) - pos.y();
01105
01106 const double f = qwtSqr( cx ) + qwtSqr( cy );
01107 if ( f < dmin )
01108 {
01109 index = i;
01110 dmin = f;
01111 }
01112 }
01113 if ( dist )
01114 *dist = qSqrt( dmin );
01115
01116 return index;
01117 }
01118
01128 QwtGraphic QwtPlotCurve::legendIcon( int index,
01129 const QSizeF &size ) const
01130 {
01131 Q_UNUSED( index );
01132
01133 if ( size.isEmpty() )
01134 return QwtGraphic();
01135
01136 QwtGraphic graphic;
01137 graphic.setDefaultSize( size );
01138 graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
01139
01140 QPainter painter( &graphic );
01141 painter.setRenderHint( QPainter::Antialiasing,
01142 testRenderHint( QwtPlotItem::RenderAntialiased ) );
01143
01144 if ( d_data->legendAttributes == 0 ||
01145 d_data->legendAttributes & QwtPlotCurve::LegendShowBrush )
01146 {
01147 QBrush brush = d_data->brush;
01148
01149 if ( brush.style() == Qt::NoBrush &&
01150 d_data->legendAttributes == 0 )
01151 {
01152 if ( style() != QwtPlotCurve::NoCurve )
01153 {
01154 brush = QBrush( pen().color() );
01155 }
01156 else if ( d_data->symbol &&
01157 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
01158 {
01159 brush = QBrush( d_data->symbol->pen().color() );
01160 }
01161 }
01162
01163 if ( brush.style() != Qt::NoBrush )
01164 {
01165 QRectF r( 0, 0, size.width(), size.height() );
01166 painter.fillRect( r, brush );
01167 }
01168 }
01169
01170 if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine )
01171 {
01172 if ( pen() != Qt::NoPen )
01173 {
01174 QPen pn = pen();
01175 pn.setCapStyle( Qt::FlatCap );
01176
01177 painter.setPen( pn );
01178
01179 const double y = 0.5 * size.height();
01180 QwtPainter::drawLine( &painter, 0.0, y, size.width(), y );
01181 }
01182 }
01183
01184 if ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol )
01185 {
01186 if ( d_data->symbol )
01187 {
01188 QRectF r( 0, 0, size.width(), size.height() );
01189 d_data->symbol->drawSymbol( &painter, r );
01190 }
01191 }
01192
01193 return graphic;
01194 }
01195
01203 void QwtPlotCurve::setSamples( const QVector<QPointF> &samples )
01204 {
01205 setData( new QwtPointSeriesData( samples ) );
01206 }
01207
01218 void QwtPlotCurve::setSamples( QwtSeriesData<QPointF> *data )
01219 {
01220 setData( data );
01221 }
01222
01223 #ifndef QWT_NO_COMPAT
01224
01239 void QwtPlotCurve::setRawSamples(
01240 const double *xData, const double *yData, int size )
01241 {
01242 setData( new QwtCPointerData( xData, yData, size ) );
01243 }
01244
01256 void QwtPlotCurve::setSamples(
01257 const double *xData, const double *yData, int size )
01258 {
01259 setData( new QwtPointArrayData( xData, yData, size ) );
01260 }
01261
01270 void QwtPlotCurve::setSamples( const QVector<double> &xData,
01271 const QVector<double> &yData )
01272 {
01273 setData( new QwtPointArrayData( xData, yData ) );
01274 }
01275
01276 #endif // !QWT_NO_COMPAT
01277