QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
17#include "qgsdiagramrenderer.h"
18#include "qgsexpression.h"
19#include "qgsrendercontext.h"
20
21#include <QPainter>
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
26const QString QgsPieDiagram::DIAGRAM_NAME_PIE = u"Pie"_s;
27
29{
30 mCategoryBrush.setStyle( Qt::SolidPattern );
31 mPen.setStyle( Qt::SolidLine );
32}
33
35{
36 return new QgsPieDiagram( *this );
37}
38
40{
41 Q_UNUSED( c )
42
43 QVariant attrVal;
45 {
46 QgsExpressionContext expressionContext = c.expressionContext();
47 if ( !feature.fields().isEmpty() )
48 expressionContext.setFields( feature.fields() );
49 expressionContext.setFeature( feature );
50
51 QgsExpression *expression = getExpression( is.classificationAttributeExpression, expressionContext );
52 attrVal = expression->evaluate( &expressionContext );
53 }
54 else
55 {
56 attrVal = feature.attribute( is.classificationField );
57 }
58
59 bool ok = false;
60 const double value = attrVal.toDouble( &ok );
61 if ( !ok )
62 {
63 return QSizeF(); //zero size if attribute is missing
64 }
65
66 return sizeForValue( value, s, is );
67}
68
69double QgsPieDiagram::legendSize( double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &is ) const
70{
71 const QSizeF size = sizeForValue( value, s, is );
72 return std::max( size.width(), size.height() );
73}
74
79
81{
82 Q_UNUSED( c )
83 Q_UNUSED( attributes )
84 return s.size;
85}
86
87void QgsPieDiagram::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, const QgsDiagramSettings &s, QPointF position )
88{
89 QPainter *p = c.painter();
90 if ( !p )
91 {
92 return;
93 }
94
95 //get sum of values
96 QList<double> values;
97 double currentVal = 0;
98 double valSum = 0;
99 int valCount = 0;
100
101 QgsExpressionContext expressionContext = c.expressionContext();
102 expressionContext.setFeature( feature );
103 if ( !feature.fields().isEmpty() )
104 expressionContext.setFields( feature.fields() );
105
106 QList<QString>::const_iterator catIt = s.categoryAttributes.constBegin();
107 for ( ; catIt != s.categoryAttributes.constEnd(); ++catIt )
108 {
109 QgsExpression *expression = getExpression( *catIt, expressionContext );
110 currentVal = expression->evaluate( &expressionContext ).toDouble();
111 values.push_back( currentVal );
112 valSum += currentVal;
113 if ( currentVal ) valCount++;
114 }
115
116 //draw the slices
117 double totalAngle = 0;
118 double currentAngle;
119
120 //convert from mm / map units to painter units
121 const QSizeF spu = sizePainterUnits( s.size, s, c );
122 const double w = spu.width();
123 const double h = spu.height();
124
125 const double baseX = position.x();
126 const double baseY = position.y() - h;
127
128 mPen.setColor( s.penColor );
129 setPenWidth( mPen, s, c );
130 p->setPen( mPen );
131
132 // there are some values > 0 available
133 if ( valSum > 0 )
134 {
135 QList<double>::const_iterator valIt = values.constBegin();
136 QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
137 for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
138 {
139 if ( *valIt )
140 {
141 currentAngle = ( *valIt / valSum * 360 * 16 ) * ( s.direction() == QgsDiagramSettings::Clockwise ? -1 : 1 );
142 QColor brushColor( *colIt );
143 brushColor.setAlphaF( brushColor.alphaF() * s.opacity );
144 mCategoryBrush.setColor( brushColor );
145 p->setBrush( mCategoryBrush );
146 // if only 1 value is > 0, draw a circle
147 if ( valCount == 1 )
148 {
149 p->drawEllipse( QRectF( baseX, baseY, w, h ) );
150 }
151 else
152 {
153 p->drawPie( QRectF( baseX, baseY, w, h ), totalAngle - s.rotationOffset * 16.0, currentAngle );
154 }
155 totalAngle += currentAngle;
156 }
157 }
158 }
159 else // valSum > 0
160 {
161 // draw empty circle if no values are defined at all
162 mCategoryBrush.setColor( Qt::transparent );
163 p->setBrush( mCategoryBrush );
164 p->drawEllipse( QRectF( baseX, baseY, w, h ) );
165 }
166}
A vector of attributes.
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.
QSizeF sizePainterUnits(QSizeF size, const QgsDiagramSettings &s, const QgsRenderContext &c)
Calculates a size to match the current settings and rendering context.
QgsExpression * getExpression(const QString &expression, const QgsExpressionContext &context)
Returns a prepared expression for the specified context.
QSizeF sizeForValue(double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &interpolationSettings) const
Returns the scaled size of a diagram for a value, respecting the specified diagram interpolation sett...
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.
Handles 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:60
QgsFields fields
Definition qgsfeature.h:70
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
bool isEmpty
Definition qgsfields.h:49
QSizeF diagramSize(const QgsAttributes &attributes, const QgsRenderContext &c, const QgsDiagramSettings &s) override
Returns the size in map units the diagram will use to render.
static const QString DIAGRAM_NAME_PIE
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.
double legendSize(double value, const QgsDiagramSettings &s, const QgsDiagramInterpolationSettings &interpolationSettings) const override
Returns the size of the legend item for the diagram corresponding to a specified value.
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