QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgspiediagram.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspiediagram.cpp
3 ---------------------
4 begin : March 2011
5 copyright : (C) 2011 by Marco Hugentobler
6 email : marco dot hugentobler at sourcepole dot ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgspiediagram.h"
16#include "qgsdiagramrenderer.h"
17#include "qgsrendercontext.h"
18#include "qgsexpression.h"
19
20#include <QPainter>
21
22
24{
25 mCategoryBrush.setStyle( Qt::SolidPattern );
26 mPen.setStyle( Qt::SolidLine );
27}
28
30{
31 return new QgsPieDiagram( *this );
32}
33
35{
36 Q_UNUSED( c )
37
38 QVariant attrVal;
40 {
41 QgsExpressionContext expressionContext = c.expressionContext();
42 if ( !feature.fields().isEmpty() )
43 expressionContext.setFields( feature.fields() );
44 expressionContext.setFeature( feature );
45
46 QgsExpression *expression = getExpression( is.classificationAttributeExpression, expressionContext );
47 attrVal = expression->evaluate( &expressionContext );
48 }
49 else
50 {
51 attrVal = feature.attribute( is.classificationField );
52 }
53
54 bool ok = false;
55 const double value = attrVal.toDouble( &ok );
56 if ( !ok )
57 {
58 return QSizeF(); //zero size if attribute is missing
59 }
60
61 return sizeForValue( value, s, is );
62}
63
64double QgsPieDiagram::legendSize( double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) const
65{
66 const QSizeF size = sizeForValue( value, s, is );
67 return std::max( size.width(), size.height() );
68}
69
71{
72 return DIAGRAM_NAME_PIE;
73}
74
76{
77 Q_UNUSED( c )
78 Q_UNUSED( attributes )
79 return s.size;
80}
81
82void QgsPieDiagram::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position )
83{
84 QPainter *p = c.painter();
85 if ( !p )
86 {
87 return;
88 }
89
90 //get sum of values
91 QList<double> values;
92 double currentVal = 0;
93 double valSum = 0;
94 int valCount = 0;
95
96 QgsExpressionContext expressionContext = c.expressionContext();
97 expressionContext.setFeature( feature );
98 if ( !feature.fields().isEmpty() )
99 expressionContext.setFields( feature.fields() );
100
101 QList<QString>::const_iterator catIt = s.categoryAttributes.constBegin();
102 for ( ; catIt != s.categoryAttributes.constEnd(); ++catIt )
103 {
104 QgsExpression *expression = getExpression( *catIt, expressionContext );
105 currentVal = expression->evaluate( &expressionContext ).toDouble();
106 values.push_back( currentVal );
107 valSum += currentVal;
108 if ( currentVal ) valCount++;
109 }
110
111 //draw the slices
112 double totalAngle = 0;
113 double currentAngle;
114
115 //convert from mm / map units to painter units
116 const QSizeF spu = sizePainterUnits( s.size, s, c );
117 const double w = spu.width();
118 const double h = spu.height();
119
120 const double baseX = position.x();
121 const double baseY = position.y() - h;
122
123 mPen.setColor( s.penColor );
124 setPenWidth( mPen, s, c );
125 p->setPen( mPen );
126
127 // there are some values > 0 available
128 if ( valSum > 0 )
129 {
130 QList<double>::const_iterator valIt = values.constBegin();
131 QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
132 for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
133 {
134 if ( *valIt )
135 {
136 currentAngle = ( *valIt / valSum * 360 * 16 ) * ( s.direction() == QgsDiagramSettings::Clockwise ? -1 : 1 );
137 QColor brushColor( *colIt );
138 brushColor.setAlphaF( brushColor.alphaF() * s.opacity );
139 mCategoryBrush.setColor( brushColor );
140 p->setBrush( mCategoryBrush );
141 // if only 1 value is > 0, draw a circle
142 if ( valCount == 1 )
143 {
144 p->drawEllipse( QRectF( baseX, baseY, w, h ) );
145 }
146 else
147 {
148 p->drawPie( QRectF( baseX, baseY, w, h ), totalAngle - s.rotationOffset * 16.0, currentAngle );
149 }
150 totalAngle += currentAngle;
151 }
152 }
153 }
154 else // valSum > 0
155 {
156 // draw empty circle if no values are defined at all
157 mCategoryBrush.setColor( Qt::transparent );
158 p->setBrush( mCategoryBrush );
159 p->drawEllipse( QRectF( baseX, baseY, w, h ) );
160 }
161}
A vector of attributes.
Definition: qgsattributes.h:59
Additional diagram settings for interpolated size rendering.
QString classificationField
Name of the field for classification.
Stores the settings for rendering a single diagram.
Direction direction() const
Returns the chart's angular direction.
double opacity
Opacity, from 0 (transparent) to 1.0 (opaque)
QList< QString > categoryAttributes
QList< QColor > categoryColors
double rotationOffset
Rotation offset, in degrees clockwise from horizontal.
@ Clockwise
Clockwise orientation.
void setPenWidth(QPen &pen, const QgsDiagramSettings &s, const QgsRenderContext &c)
Changes the pen width to match the current settings and rendering context.
Definition: qgsdiagram.cpp:49
QSizeF sizePainterUnits(QSizeF size, const QgsDiagramSettings &s, const QgsRenderContext &c)
Calculates a size to match the current settings and rendering context.
Definition: qgsdiagram.cpp:55
QgsExpression * getExpression(const QString &expression, const QgsExpressionContext &context)
Returns a prepared expression for the specified context.
Definition: qgsdiagram.cpp:38
QSizeF sizeForValue(double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is) const
Returns the scaled size of a diagram for a value, respecting the specified diagram interpolation sett...
Definition: qgsdiagram.cpp:81
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
QVariant evaluate()
Evaluate the feature and return the result.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsFields fields
Definition: qgsfeature.h:66
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:335
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
A pie chart diagram.
Definition: qgspiediagram.h:39
QSizeF diagramSize(const QgsAttributes &attributes, const QgsRenderContext &c, const QgsDiagramSettings &s) override
Returns the size in map units the diagram will use to render.
double legendSize(double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is) const override
Returns the size of the legend item for the diagram corresponding to a specified value.
QgsPieDiagram * clone() const override
Returns an instance that is equivalent to this one.
void renderDiagram(const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position) override
Draws the diagram at the given position (in pixel coordinates)
QString diagramName() const override
Gets a descriptive name for this diagram type.
Contains information about the context of a rendering operation.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define DIAGRAM_NAME_PIE
Definition: qgspiediagram.h:18