Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_plot_shapeitem.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_plot_shapeitem.h"
11#include "qwt_scale_map.h"
12#include "qwt_text.h"
13#include "qwt_graphic.h"
14#include "qwt_painter.h"
15#include "qwt_weeding_curve_fitter.h"
16#include "qwt_clipper.h"
17#include "qwt_math.h"
18
19#include <qpainter.h>
20#include <qpainterpath.h>
21
22static QPainterPath qwtTransformPath( const QwtScaleMap& xMap,
23 const QwtScaleMap& yMap, const QPainterPath& path, bool doAlign )
24{
25 QPainterPath shape;
26 shape.setFillRule( path.fillRule() );
27
28 for ( int i = 0; i < path.elementCount(); i++ )
29 {
30 const QPainterPath::Element element = path.elementAt( i );
31
32 double x = xMap.transform( element.x );
33 double y = yMap.transform( element.y );
34
35 switch( element.type )
36 {
37 case QPainterPath::MoveToElement:
38 {
39 if ( doAlign )
40 {
41 x = qRound( x );
42 y = qRound( y );
43 }
44
45 shape.moveTo( x, y );
46 break;
47 }
48 case QPainterPath::LineToElement:
49 {
50 if ( doAlign )
51 {
52 x = qRound( x );
53 y = qRound( y );
54 }
55
56 shape.lineTo( x, y );
57 break;
58 }
59 case QPainterPath::CurveToElement:
60 {
61 const QPainterPath::Element element1 = path.elementAt( ++i );
62 const double x1 = xMap.transform( element1.x );
63 const double y1 = yMap.transform( element1.y );
64
65 const QPainterPath::Element element2 = path.elementAt( ++i );
66 const double x2 = xMap.transform( element2.x );
67 const double y2 = yMap.transform( element2.y );
68
69 shape.cubicTo( x, y, x1, y1, x2, y2 );
70 break;
71 }
72 case QPainterPath::CurveToDataElement:
73 {
74 break;
75 }
76 }
77 }
78
79 return shape;
80}
81
82
83class QwtPlotShapeItem::PrivateData
84{
85 public:
86 PrivateData()
87 : legendMode( QwtPlotShapeItem::LegendColor )
88 , renderTolerance( 0.0 )
89 {
90 }
91
94
95 double renderTolerance;
96 QRectF boundingRect;
97
98 QPen pen;
99 QBrush brush;
100 QPainterPath shape;
101};
102
113 : QwtPlotItem( QwtText( title ) )
114{
115 init();
116}
117
128 : QwtPlotItem( title )
129{
130 init();
131}
132
135{
136 delete m_data;
137}
138
139void QwtPlotShapeItem::init()
140{
141 m_data = new PrivateData();
142 m_data->boundingRect = QwtPlotItem::boundingRect();
143
146
147 setZ( 8.0 );
148}
149
152{
154}
155
164{
165 if ( on )
166 m_data->paintAttributes |= attribute;
167 else
168 m_data->paintAttributes &= ~attribute;
169}
170
176{
177 return ( m_data->paintAttributes & attribute );
178}
179
187{
188 if ( mode != m_data->legendMode )
189 {
190 m_data->legendMode = mode;
192 }
193}
194
200{
201 return m_data->legendMode;
202}
203
206{
207 return m_data->boundingRect;
208}
209
216void QwtPlotShapeItem::setRect( const QRectF& rect )
217{
218 QPainterPath path;
219 path.addRect( rect );
220
221 setShape( path );
222}
223
230void QwtPlotShapeItem::setPolygon( const QPolygonF& polygon )
231{
232 QPainterPath shape;
233 shape.addPolygon( polygon );
234
235 setShape( shape );
236}
237
244void QwtPlotShapeItem::setShape( const QPainterPath& shape )
245{
246 if ( shape != m_data->shape )
247 {
248 m_data->shape = shape;
249 if ( shape.isEmpty() )
250 {
251 m_data->boundingRect = QwtPlotItem::boundingRect();
252 }
253 else
254 {
255 m_data->boundingRect = shape.boundingRect();
256 }
257
258 itemChanged();
259 }
260}
261
266QPainterPath QwtPlotShapeItem::shape() const
267{
268 return m_data->shape;
269}
270
284void QwtPlotShapeItem::setPen( const QColor& color, qreal width, Qt::PenStyle style )
285{
286 setPen( QPen( color, width, style ) );
287}
288
297void QwtPlotShapeItem::setPen( const QPen& pen )
298{
299 if ( pen != m_data->pen )
300 {
301 m_data->pen = pen;
302 itemChanged();
303 }
304}
305
311{
312 return m_data->pen;
313}
314
323void QwtPlotShapeItem::setBrush( const QBrush& brush )
324{
325 if ( brush != m_data->brush )
326 {
327 m_data->brush = brush;
328 itemChanged();
329 }
330}
331
337{
338 return m_data->brush;
339}
340
358{
359 tolerance = qwtMaxF( tolerance, 0.0 );
360
361 if ( tolerance != m_data->renderTolerance )
362 {
363 m_data->renderTolerance = tolerance;
364 itemChanged();
365 }
366}
367
373{
374 return m_data->renderTolerance;
375}
376
385void QwtPlotShapeItem::draw( QPainter* painter,
386 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
387 const QRectF& canvasRect ) const
388{
389 if ( m_data->shape.isEmpty() )
390 return;
391
392 if ( m_data->pen.style() == Qt::NoPen
393 && m_data->brush.style() == Qt::NoBrush )
394 {
395 return;
396 }
397
398 const QRectF cr = QwtScaleMap::invTransform(
399 xMap, yMap, canvasRect.toRect() );
400
401 const QRectF& br = m_data->boundingRect;
402
403 if ( ( br.left() > cr.right() ) || ( br.right() < cr.left() )
404 || ( br.top() > cr.bottom() ) || ( br.bottom() < cr.top() ) )
405 {
406 // outside the visible area
407 return;
408 }
409
410 const bool doAlign = QwtPainter::roundingAlignment( painter );
411
412 QPainterPath path = qwtTransformPath( xMap, yMap,
413 m_data->shape, doAlign );
414
416 {
417 const qreal pw = QwtPainter::effectivePenWidth( painter->pen() );
418 const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );
419
420 QPainterPath clippedPath;
421 clippedPath.setFillRule( path.fillRule() );
422
423 QList< QPolygonF > polygons = path.toSubpathPolygons();
424 for ( int i = 0; i < polygons.size(); i++ )
425 {
426 QwtClipper::clipPolygonF( clipRect, polygons[i], true );
427 clippedPath.addPolygon( polygons[i] );
428
429 }
430
431 path = clippedPath;
432 }
433
434 if ( m_data->renderTolerance > 0.0 )
435 {
436 QwtWeedingCurveFitter fitter( m_data->renderTolerance );
437
438 QPainterPath fittedPath;
439 fittedPath.setFillRule( path.fillRule() );
440
441 const QList< QPolygonF > polygons = path.toSubpathPolygons();
442 for ( int i = 0; i < polygons.size(); i++ )
443 fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) );
444
445 path = fittedPath;
446 }
447
448 painter->setPen( m_data->pen );
449 painter->setBrush( m_data->brush );
450
451 painter->drawPath( path );
452}
453
464 const QSizeF& size ) const
465{
466 Q_UNUSED( index );
467
468 QwtGraphic icon;
469 icon.setDefaultSize( size );
470
471 if ( size.isEmpty() )
472 return icon;
473
474 if ( m_data->legendMode == QwtPlotShapeItem::LegendShape )
475 {
476 const QRectF& br = m_data->boundingRect;
477
478 QPainter painter( &icon );
479 painter.setRenderHint( QPainter::Antialiasing,
481
482 painter.translate( -br.topLeft() );
483
484 painter.setPen( m_data->pen );
485 painter.setBrush( m_data->brush );
486 painter.drawPath( m_data->shape );
487 }
488 else
489 {
490 QColor iconColor;
491 if ( m_data->brush.style() != Qt::NoBrush )
492 iconColor = m_data->brush.color();
493 else
494 iconColor = m_data->pen.color();
495
496 icon = defaultIcon( iconColor, size );
497 }
498
499 return icon;
500}
501
A paint device for scalable graphics.
Definition qwt_graphic.h:76
void setDefaultSize(const QSizeF &)
Set a default size.
static qreal effectivePenWidth(const QPen &)
static bool roundingAlignment()
Base class for items on the plot canvas.
virtual void legendChanged()
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
QwtGraphic defaultIcon(const QBrush &, const QSizeF &) const
Return a default icon from a brush.
@ Rtti_PlotShape
For QwtPlotShapeItem.
@ RenderAntialiased
Enable antialiasing.
bool testRenderHint(RenderHint) const
virtual void itemChanged()
@ Legend
The item is represented on the legend.
virtual QRectF boundingRect() const
A plot item, which displays any graphical shape, that can be defined by a QPainterPath.
bool testPaintAttribute(PaintAttribute) const
virtual QRectF boundingRect() const override
Bounding rectangle of the shape.
void setRect(const QRectF &)
Set a path built from a rectangle.
void setShape(const QPainterPath &)
Set the shape to be displayed.
LegendMode
Mode how to display the item on the legend.
@ LegendColor
Display a filled rectangle.
@ LegendShape
Display a scaled down version of the shape.
void setLegendMode(LegendMode)
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const override
virtual int rtti() const override
LegendMode legendMode() const
QwtPlotShapeItem(const QString &title=QString())
Constructor.
void setPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
void setRenderTolerance(double)
Set the tolerance for the weeding optimization.
void setPolygon(const QPolygonF &)
Set a path built from a polygon.
double renderTolerance() const
void setBrush(const QBrush &)
virtual ~QwtPlotShapeItem()
Destructor.
void setPaintAttribute(PaintAttribute, bool on=true)
QFlags< PaintAttribute > PaintAttributes
QPainterPath shape() const
A scale map.
double transform(double s) const
double invTransform(double p) const
A class representing a text.
Definition qwt_text.h:52
A curve fitter implementing Douglas and Peucker algorithm.
virtual QPolygonF fitCurve(const QPolygonF &) const override
QWT_EXPORT void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)