📄 qwt_plot_curve.cpp
字号:
QwtDoubleRect QwtPlotCurve::boundingRect() const
{
if ( d_xy == NULL )
return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid
return d_xy->boundingRect();
}
/*!
\brief Draw the complete curve
\param painter Painter
\param xMap Maps x-values into pixel coordinates.
\param yMap Maps y-values into pixel coordinates.
\sa drawCurve(), drawSymbols()
*/
void QwtPlotCurve::draw(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRect &) const
{
draw(painter, xMap, yMap, 0, -1);
}
/*!
\brief Draw a set of points of a curve.
When observing an measurement while it is running, new points have to be
added to an existing curve. drawCurve can be used to display them avoiding
a complete redraw of the canvas.
Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);
will result in faster painting, if the paint engine of the canvas widget
supports this feature.
\param from Index of the first point to be painted
\param to Index of the last point to be painted. If to < 0 the
curve will be painted to its last point.
\sa drawCurve(), drawSymbols()
*/
void QwtPlotCurve::draw(int from, int to) const
{
if ( !plot() )
return;
QwtPlotCanvas *canvas = plot()->canvas();
bool directPaint = true;
#if QT_VERSION >= 0x040000
if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) &&
!canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) )
{
/*
We save curve and range in helper and call repaint.
The helper filters the Paint event, to repeat
the QwtPlotCurve::draw, but now from inside the paint
event.
*/
QwtPlotCurvePaintHelper helper(this, from, to);
canvas->installEventFilter(&helper);
canvas->repaint();
return;
}
#endif
const QwtScaleMap xMap = plot()->canvasMap(xAxis());
const QwtScaleMap yMap = plot()->canvasMap(yAxis());
if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
canvas->paintCache() && !canvas->paintCache()->isNull() )
{
QPainter cachePainter((QPixmap *)canvas->paintCache());
cachePainter.translate(-canvas->contentsRect().x(),
-canvas->contentsRect().y());
draw(&cachePainter, xMap, yMap, from, to);
}
if ( directPaint )
{
QPainter painter(canvas);
painter.setClipping(true);
painter.setClipRect(canvas->contentsRect());
draw(&painter, xMap, yMap, from, to);
return;
}
#if QT_VERSION >= 0x040000
if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) &&
canvas->paintCache() )
{
/*
The cache is up to date. We flush it via repaint to the
canvas. This works flicker free but is much ( > 10x )
slower than direct painting.
*/
const bool noBG = canvas->testAttribute(Qt::WA_NoBackground);
if ( !noBG )
canvas->setAttribute(Qt::WA_NoBackground, true);
canvas->repaint(canvas->contentsRect());
if ( !noBG )
canvas->setAttribute(Qt::WA_NoBackground, false);
return;
}
#endif
// Ok, we give up
canvas->repaint(canvas->contentsRect());
}
/*!
\brief Draw an interval of the curve
\param painter Painter
\param xMap maps x-values into pixel coordinates.
\param yMap maps y-values into pixel coordinates.
\param from index of the first point to be painted
\param to index of the last point to be painted. If to < 0 the
curve will be painted to its last point.
\sa drawCurve(), draSymbols(),
*/
void QwtPlotCurve::draw(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
int from, int to) const
{
if ( !painter || dataSize() <= 0 )
return;
if (to < 0)
to = dataSize() - 1;
if ( verifyRange(dataSize(), from, to) > 0 )
{
painter->save();
painter->setPen(d_data->pen);
/*
Qt 4.0.0 is slow when drawing lines, but it´s even
slower when the painter has a brush. So we don't
set the brush before we really need it.
*/
drawCurve(painter, d_data->style, xMap, yMap, from, to);
painter->restore();
if (d_data->sym.style() != QwtSymbol::NoSymbol)
{
painter->save();
drawSymbols(painter, d_data->sym, xMap, yMap, from, to);
painter->restore();
}
}
}
/*!
\brief Draw the line part (without symbols) of a curve interval.
\param painter Painter
\param style curve style, see QwtPlotCurve::CurveStyle
\param xMap x map
\param yMap y map
\param from index of the first point to be painted
\param to index of the last point to be painted
\sa draw(), drawDots(), drawLines(), drawSteps(), drawSticks()
*/
void QwtPlotCurve::drawCurve(QPainter *painter, int style,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
int from, int to) const
{
switch (style)
{
case Lines:
if ( testCurveAttribute(Fitted) )
{
// we always need the complete
// curve for fitting
from = 0;
to = dataSize() - 1;
}
drawLines(painter, xMap, yMap, from, to);
break;
case Sticks:
drawSticks(painter, xMap, yMap, from, to);
break;
case Steps:
drawSteps(painter, xMap, yMap, from, to);
break;
case Dots:
drawDots(painter, xMap, yMap, from, to);
break;
case NoCurve:
default:
break;
}
}
/*!
\brief Draw lines
If the CurveAttribute Fitted is enabled a QwtCurveFitter tries
to interpolate/smooth the curve, before it is painted.
\param painter Painter
\param xMap x map
\param yMap y map
\param from index of the first point to be painted
\param to index of the last point to be painted
\sa setCurveAttribute(), setCurveFitter(), draw(),
drawLines(), drawDots(), drawSteps(), drawSticks()
*/
void QwtPlotCurve::drawLines(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
int from, int to) const
{
int size = to - from + 1;
if ( size <= 0 )
return;
QwtPolygon polyline;
if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
{
// Transform x and y values to window coordinates
// to avoid a distinction between linear and
// logarithmic scales.
#if QT_VERSION < 0x040000
QwtArray<QwtDoublePoint> points(size);
#else
QPolygonF points(size);
#endif
for (int i = from; i <= to; i++)
{
QwtDoublePoint &p = points[i];
p.setX( xMap.xTransform(x(i)) );
p.setY( yMap.xTransform(y(i)) );
}
points = d_data->curveFitter->fitCurve(points);
size = points.size();
if ( size == 0 )
return;
// Round QwtDoublePoints to QPoints
// When Qwt support for Qt3 has been dropped (Qwt 6.x)
// we will use a doubles for painting and the following
// step will be obsolete.
polyline.resize(size);
const QwtDoublePoint *p = points.data();
QPoint *pl = polyline.data();
if ( d_data->paintAttributes & PaintFiltered )
{
QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
pl[0] = pp;
int count = 1;
for (int i = 1; i < size; i++)
{
const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
if ( pi != pp )
{
pl[count++] = pi;
pp = pi;
}
}
if ( count != size )
polyline.resize(count);
}
else
{
for ( int i = 0; i < size; i++ )
{
pl[i].setX( qRound(p[i].x()) );
pl[i].setY( qRound(p[i].y()) );
}
}
}
else
{
polyline.resize(size);
if ( d_data->paintAttributes & PaintFiltered )
{
QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
polyline.setPoint(0, pp);
int count = 1;
for (int i = from + 1; i <= to; i++)
{
const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
if ( pi != pp )
{
polyline.setPoint(count, pi);
count++;
pp = pi;
}
}
if ( count != size )
polyline.resize(count);
}
else
{
for (int i = from; i <= to; i++)
{
int xi = xMap.transform(x(i));
int yi = yMap.transform(y(i));
polyline.setPoint(i - from, xi, yi);
}
}
}
if ( d_data->paintAttributes & ClipPolygons )
{
QwtRect r = painter->window();
polyline = r.clip(polyline);
}
QwtPainter::drawPolyline(painter, polyline);
if ( d_data->brush.style() != Qt::NoBrush )
fillCurve(painter, xMap, yMap, polyline);
}
/*!
Draw sticks
\param painter Painter
\param xMap x map
\param yMap y map
\param from index of the first point to be painted
\param to index of the last point to be painted
\sa draw(), drawCurve(), drawDots(), drawLines(), drawSteps()
*/
void QwtPlotCurve::drawSticks(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
int from, int to) const
{
int x0 = xMap.transform(d_data->reference);
int y0 = yMap.transform(d_data->reference);
for (int i = from; i <= to; i++)
{
const int xi = xMap.transform(x(i));
const int yi = yMap.transform(y(i));
if (d_data->attributes & Xfy)
QwtPainter::drawLine(painter, x0, yi, xi, yi);
else
QwtPainter::drawLine(painter, xi, y0, xi, yi);
}
}
/*!
Draw dots
\param painter Painter
\param xMap x map
\param yMap y map
\param from index of the first point to be painted
\param to index of the last point to be painted
\sa draw(), drawCurve(), drawSticks(), drawLines(), drawSteps()
*/
void QwtPlotCurve::drawDots(QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
int from, int to) const
{
const QRect window = painter->window();
if ( window.isEmpty() )
return;
const bool doFill = d_data->brush.style() != Qt::NoBrush;
QwtPolygon polyline;
if ( doFill )
polyline.resize(to - from + 1);
if ( to > from && d_data->paintAttributes & PaintFiltered )
{
if ( doFill )
{
QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
QwtPainter::drawPoint(painter, pp.x(), pp.y());
polyline.setPoint(0, pp);
int count = 1;
for (int i = from + 1; i <= to; i++)
{
const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
if ( pi != pp )
{
QwtPainter::drawPoint(painter, pi.x(), pi.y());
polyline.setPoint(count, pi);
count++;
pp = pi;
}
}
if ( int(polyline.size()) != count )
polyline.resize(count);
}
else
{
// if we don't need to fill, we can sort out
// duplicates independent from the order
PrivateData::PixelMatrix pixelMatrix(window);
for (int i = from; i <= to; i++)
{
const QPoint p( xMap.transform(x(i)),
yMap.transform(y(i)) );
if ( pixelMatrix.testPixel(p) )
QwtPainter::drawPoint(painter, p.x(), p.y());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -