10#include "qwt_plot_intervalcurve.h"
11#include "qwt_interval_symbol.h"
12#include "qwt_scale_map.h"
13#include "qwt_clipper.h"
14#include "qwt_painter.h"
15#include "qwt_graphic.h"
23 double xMin,
double xMax,
double yMin,
double yMax )
25 const double y = sample.
value;
29 const bool isOffScreen = ( y < yMin ) || ( y > yMax )
30 || ( x1 < xMin && x2 < xMin ) || ( x1 > xMax && x2 > xMax );
36 double xMin,
double xMax,
double yMin,
double yMax )
38 const double x = sample.
value;
42 const bool isOffScreen = ( x < xMin ) || ( x > xMax )
43 || ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax );
48static inline int qwtInterpolated(
int from,
int to,
double ratio )
50 return qRound( from + ratio * ( to - from ) );
53static int qwtStartIndex(
int from,
double min,
double max,
64 inline bool operator()(
const double value,
67 return value < sample.
value;
73 inline bool operator()(
const double value,
76 return value > sample.
value;
84 idx = qwtUpperSampleIndex< QwtIntervalSample >(
85 *samples, min, lessThan() );
89 idx = qwtUpperSampleIndex< QwtIntervalSample >(
90 *samples, max, greaterThan() );
95 idx = qMax( from, idx );
111 LinesRenderer( Qt::Orientation,
123 bool append(
int value,
int min,
int max );
125 void addFillLineAt(
int value,
int min,
int max );
126 void addFillLines(
int value,
int min,
int max );
128 void addBorderLineAt(
int value,
int min,
int max );
129 void addBorderLine(
int,
int,
int,
int );
131 const bool m_vertical;
136 const bool m_inverting;
141 int m_intvMin, m_intvMax;
142 int m_valueMin, m_valueMax;
148 inline void reset(
int value )
150 min = max = last = value;
153 inline void extend(
int value )
157 else if ( value > max )
168 LinesRenderer::LinesRenderer( Qt::Orientation orientation,
170 : m_vertical( orientation == Qt::Vertical )
171 , m_valueMap( m_vertical ? xMap : yMap )
172 , m_intervalMap( m_vertical ? yMap : xMap )
173 , m_inverting( m_intervalMap.isInverting() )
179 r.setSize( QSizeF( r.height(), r.width() ) );
181 m_intvMin = qFloor( r.top() );
182 m_intvMax = qCeil( r.bottom() );
184 m_valueMin = qFloor( r.left() );
185 m_valueMax = qCeil( r.right() );
187 const int steps = m_valueMax - m_valueMin + 1;
190 fillLines.reserve( steps );
197 borderLines.reserve( 4 * steps );
200 void LinesRenderer::addSamples(
203 const double v1 = m_valueMap.
invTransform( m_valueMin );
204 const double v2 = m_valueMap.
invTransform( m_valueMax );
206 from = qwtStartIndex( from, qMin( v1, v2 ), qMax( v1, v2 ), samples );
210 for (
int i = from; i <= to; i++ )
212 if ( addSample( samples->
sample( i ) ) )
222 const double value = qRound( m_valueMap.
transform( sample.
value ) );
227 return m_inverting ? append( value, max, min ) : append( value, max, min );
230 inline bool LinesRenderer::append(
231 const int value,
const int lower,
const int upper )
236 m_lower.reset( lower );
237 m_upper.reset( upper );
244 if ( value != m_value )
246 addFillLines( value, lower, upper );
247 addBorderLineAt( m_value, m_lower.min, m_lower.max );
248 addBorderLineAt( m_value, m_upper.min, m_upper.max );
250 addBorderLine( m_value, m_lower.last, value, lower );
251 addBorderLine( m_value, m_upper.last, value, upper );
253 if ( ( value > m_value ) ? ( value > m_valueMax ) : ( value < m_valueMin ) )
261 m_lower.reset( lower );
262 m_upper.reset( upper );
266 m_lower.extend( lower );
267 m_upper.extend( upper );
273 inline void LinesRenderer::flush()
277 addFillLineAt( m_value, m_lower.min, m_upper.max );
278 addBorderLineAt( m_value, m_lower.min, m_lower.max );
279 addBorderLineAt( m_value, m_upper.min, m_upper.max );
283 inline void LinesRenderer::addFillLines(
284 const int value,
const int lower,
const int upper )
286 addFillLineAt( m_value, m_lower.min, m_upper.max );
288 const double delta = value - m_value;
290 if ( value > m_value )
292 for (
int v = m_value + 1; v < value; v++ )
294 const double ratio = ( v - m_value ) / delta;
297 qwtInterpolated( m_lower.last, lower, ratio ),
298 qwtInterpolated( m_upper.last, upper, ratio ) );
303 for (
int v = m_value - 1; v > value; v-- )
305 const double ratio = ( v - m_value ) / delta;
308 qwtInterpolated( m_lower.last, lower, ratio ),
309 qwtInterpolated( m_upper.last, upper, ratio ) );
314 inline void LinesRenderer::addFillLineAt(
int value,
int min,
int max )
316 if ( ( min != max ) && ( max > m_intvMin ) && ( min < m_intvMax ) )
318 min = qMax( min, m_intvMin );
319 max = qMin( max, m_intvMax );
322 fillLines += QLine( value, min, value, max );
324 fillLines += QLine( min, value, max, value );
328 inline void LinesRenderer::addBorderLineAt(
int value,
int min,
int max )
331 addBorderLine( value, min, value, max );
334 inline void LinesRenderer::addBorderLine(
int x1,
int y1,
int x2,
int y2 )
337 borderLines += QLine( x1, y1, x2, y2 );
339 borderLines += QLine( y1, x1, y2, x2 );
343static void qwtDrawTubeLines(
346 const QRectF& canvasRect,
int from,
int to)
348 LinesRenderer renderer( curve->
orientation(), xMap, yMap, canvasRect );
349 renderer.addSamples( curve->
data(), from, to );
351 if ( curve->
brush().style() != Qt::NoBrush )
355 painter->setPen( curve->
brush().color() );
356 painter->setRenderHint( QPainter::Antialiasing,
false );
357 painter->drawLines( renderer.fillLines );
362 if ( curve->
pen().style() != Qt::NoPen )
366 painter->setPen( curve->
pen() );
367 painter->drawLines( renderer.borderLines );
373static void qwtDrawTube(
376 const QRectF& canvasRect,
int from,
int to )
382 const size_t size = to - from + 1;
383 QPolygonF polygon( 2 * size );
384 QPointF* points = polygon.data();
386 for ( uint i = 0; i < size; i++ )
388 QPointF& minValue = points[i];
389 QPointF& maxValue = points[2 * size - 1 - i];
432 if ( curve->
brush().style() != Qt::NoBrush )
434 painter->setPen( QPen( Qt::NoPen ) );
435 painter->setBrush( curve->
brush() );
441 canvasRect.adjusted( -m, -m, m, m ), polygon,
true );
451 if ( curve->
pen().style() != Qt::NoPen )
453 painter->setPen( curve->
pen() );
454 painter->setBrush( Qt::NoBrush );
459 const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );
463 std::memcpy( p.data(), points, size *
sizeof( QPointF ) );
467 std::memcpy( p.data(), points + size, size *
sizeof( QPointF ) );
481class QwtPlotIntervalCurve::PrivateData
493 pen.setCapStyle( Qt::FlatCap );
542 m_data =
new PrivateData;
565 m_data->paintAttributes |= attribute;
567 m_data->paintAttributes &= ~attribute;
577 return ( m_data->paintAttributes & attribute );
614 if (
style != m_data->style )
616 m_data->style =
style;
629 return m_data->style;
640 if (
symbol != m_data->symbol )
642 delete m_data->symbol;
656 return m_data->symbol;
684 if (
pen != m_data->pen )
712 if (
brush != m_data->brush )
714 m_data->brush =
brush;
727 return m_data->brush;
738 rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
758 const QRectF& canvasRect,
int from,
int to )
const
769 if ( m_data->style ==
Tube )
770 drawTube( painter, xMap, yMap, canvasRect, from, to );
772 if ( m_data->symbol &&
776 xMap, yMap, canvasRect, from, to );
799 const QwtScaleMap& yMap,
const QRectF& canvasRect,
int from,
int to)
const
801 if ( ( m_data->pen.style() == Qt::NoPen ) &&
802 ( m_data->brush.style() == Qt::NoBrush ) )
811 qwtDrawTubeLines(
this, painter, xMap, yMap, canvasRect, from, to );
813 qwtDrawTube(
this, painter, xMap, yMap, canvasRect, from, to );
832 const QRectF& canvasRect,
int from,
int to )
const
837 pen.setCapStyle( Qt::FlatCap );
839 painter->setPen(
pen );
844 const double xMin = tr.left();
845 const double xMax = tr.right();
846 const double yMin = tr.top();
847 const double yMax = tr.bottom();
849 const bool doClip = m_data->paintAttributes &
ClipSymbol;
851 for (
int i = from; i <= to; i++ )
857 if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) )
864 QPointF( x, y1 ), QPointF( x, y2 ) );
869 if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) )
876 QPointF( x1, y ), QPointF( x2, y ) );
897 int index,
const QSizeF& size )
const
901 if ( size.isEmpty() )
908 QPainter painter( &icon );
909 painter.setRenderHint( QPainter::Antialiasing,
912 if ( m_data->style ==
Tube )
914 QRectF r( 0, 0, size.width(), size.height() );
915 painter.fillRect( r, m_data->brush );
918 if ( m_data->symbol &&
921 QPen
pen = m_data->symbol->
pen();
922 pen.setWidthF(
pen.widthF() );
923 pen.setCapStyle( Qt::FlatCap );
925 painter.setPen(
pen );
926 painter.setBrush( m_data->symbol->
brush() );
930 const double x = 0.5 * size.width();
933 QPointF( x, 0 ), QPointF( x, size.height() - 1.0 ) );
937 const double y = 0.5 * size.height();
940 QPointF( 0.0, y ), QPointF( size.width() - 1.0, y ) );
Template class for data, that is organized as QVector.
A paint device for scalable graphics.
void setRenderHint(RenderHint, bool on=true)
void setDefaultSize(const QSizeF &)
Set a default size.
A sample of the types (x1-x2, y) or (x, y1-y2)
QwtInterval interval
Interval.
A drawing primitive for displaying an interval like an error bar.
virtual void draw(QPainter *, Qt::Orientation, const QPointF &from, const QPointF &to) const
@ NoSymbol
No Style. The symbol cannot be drawn.
const QBrush & brush() const
static void drawPolygon(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolygon()
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
static qreal effectivePenWidth(const QPen &)
static bool roundingAlignment()
QwtPlotIntervalCurve represents a series of samples, where each value is associated with an interval ...
virtual int rtti() const override
virtual ~QwtPlotIntervalCurve()
Destructor.
QFlags< PaintAttribute > PaintAttributes
void setBrush(const QBrush &)
QwtPlotIntervalCurve(const QString &title=QString())
@ ClipSymbol
Check if a symbol is on the plot canvas before painting it.
void setPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
virtual QRectF boundingRect() const override
void setSymbol(const QwtIntervalSymbol *)
void setStyle(CurveStyle style)
void init()
Initialize internal members.
const QBrush & brush() const
virtual void drawSymbols(QPainter *, const QwtIntervalSymbol &, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
CurveStyle
Curve styles. The default setting is QwtPlotIntervalCurve::Tube.
const QwtIntervalSymbol * symbol() const
void setPaintAttribute(PaintAttribute, bool on=true)
void setSamples(const QVector< QwtIntervalSample > &)
virtual void drawTube(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const override
bool testPaintAttribute(PaintAttribute) const
virtual void legendChanged()
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
@ Rtti_PlotIntervalCurve
For QwtPlotIntervalCurve.
@ RenderAntialiased
Enable antialiasing.
bool testRenderHint(RenderHint) const
virtual void itemChanged()
@ Legend
The item is represented on the legend.
Base class for plot items representing a series of samples.
Qt::Orientation orientation() const
virtual QRectF boundingRect() const override
double transform(double s) const
double invTransform(double p) const
virtual T sample(size_t i) const =0
T sample(int index) const
virtual size_t dataSize() const override
QwtSeriesData< T > * data()
void setData(QwtSeriesData< QwtIntervalSample > *series)
A class representing a text.
QWT_EXPORT QPolygonF clippedPolygonF(const QRectF &, const QPolygonF &, bool closePolygon=false)