QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
qgsvectorlayerplotdatagatherer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectorlayerplotdatagatherer.cpp
3 -----------------
4 begin : August 2025
5 copyright : (C) 2025 by Mathieu
6 email : mathieu at opengis dot ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include "qgsexpression.h"
21
22#include "moc_qgsvectorlayerplotdatagatherer.cpp"
23
27
28void QgsVectorLayerXyPlotDataGatherer::setSeriesDetails( const QList<QgsVectorLayerXyPlotDataGatherer::XySeriesDetails> &seriesDetails )
29{
30 mSeriesDetails = seriesDetails;
31}
32
33void QgsVectorLayerXyPlotDataGatherer::setPredefinedCategories( const QStringList &predefinedCategories )
34{
35 mPredefinedCategories = predefinedCategories;
36}
37
39{
40 QStringList gatheredCategories;
41 QList<QMap<QString, double>> gatheredSeriesCategoriesSum;
42 gatheredSeriesCategoriesSum.reserve( mSeriesDetails.size() );
43 std::vector<std::unique_ptr<QgsXyPlotSeries>> gatheredSeries;
44 gatheredSeries.reserve( mSeriesDetails.size() );
45 for ( int i = 0; i < mSeriesDetails.size(); i++ )
46 {
47 auto series = std::make_unique<QgsXyPlotSeries>();
48 gatheredSeries.emplace_back( std::move( series ) );
49 gatheredSeriesCategoriesSum << QMap<QString, double>();
50 }
51
52 QMap<QString, QgsExpression> preparedExpressions;
53 QgsFeature feature;
54 while ( mIterator.nextFeature( feature ) )
55 {
56 mExpressionContext.setFeature( feature );
57
58 int seriesIndex = -1;
59 for ( const XySeriesDetails &seriesDetails : mSeriesDetails )
60 {
61 seriesIndex++;
62 if ( !seriesDetails.filterExpression.isEmpty() )
63 {
64 auto filterExpressionIt = preparedExpressions.find( seriesDetails.filterExpression );
65 if ( filterExpressionIt == preparedExpressions.end() )
66 {
67 filterExpressionIt = preparedExpressions.insert( seriesDetails.filterExpression, QgsExpression( seriesDetails.filterExpression ) );
68 filterExpressionIt->prepare( &mExpressionContext );
69 }
70
71 if ( !filterExpressionIt->evaluate( &mExpressionContext ).toBool() )
72 {
73 continue;
74 }
75 }
76
77 auto xExpressionIt = preparedExpressions.find( seriesDetails.xExpression );
78 if ( xExpressionIt == preparedExpressions.end() )
79 {
80 xExpressionIt = preparedExpressions.insert( seriesDetails.xExpression, QgsExpression( seriesDetails.xExpression ) );
81 xExpressionIt->prepare( &mExpressionContext );
82 }
83
84 auto yExpressionIt = preparedExpressions.find( seriesDetails.yExpression );
85 if ( yExpressionIt == preparedExpressions.end() )
86 {
87 yExpressionIt = preparedExpressions.insert( seriesDetails.yExpression, QgsExpression( seriesDetails.yExpression ) );
88 yExpressionIt->prepare( &mExpressionContext );
89 }
90
91 bool ok = false;
92 const double y = yExpressionIt->evaluate( &mExpressionContext ).toDouble( &ok );
93 if ( !ok )
94 {
95 continue;
96 }
97 switch ( mXAxisType )
98 {
100 {
101 const double x = xExpressionIt->evaluate( &mExpressionContext ).toDouble( &ok );
102 if ( !ok )
103 {
104 continue;
105 }
106
107 gatheredSeries[seriesIndex]->append( x, y );
108 break;
109 }
110
112 {
113 const QString category = xExpressionIt->evaluate( &mExpressionContext ).toString();
114 if ( category.isEmpty() )
115 {
116 continue;
117 }
118
119 double x = -1;
120 if ( !mPredefinedCategories.isEmpty() )
121 {
122 x = mPredefinedCategories.indexOf( category );
123 }
124 else
125 {
126 if ( !gatheredCategories.contains( category ) )
127 {
128 gatheredCategories << category;
129 }
130 x = gatheredCategories.indexOf( category );
131 }
132
133 if ( x == -1 )
134 {
135 continue;
136 }
137
138 auto gatheredSeriesCategoriesSumIt = gatheredSeriesCategoriesSum[seriesIndex].find( category );
139 if ( gatheredSeriesCategoriesSumIt == gatheredSeriesCategoriesSum[seriesIndex].end() )
140 {
141 gatheredSeriesCategoriesSumIt = gatheredSeriesCategoriesSum[seriesIndex].insert( category, y );
142 *gatheredSeriesCategoriesSumIt = y;
143 }
144 else
145 {
146 *gatheredSeriesCategoriesSumIt += y;
147 }
148 }
149 }
150
151 if ( isCanceled() )
152 return false;
153 }
154 }
155
156 switch ( mXAxisType )
157 {
159 {
160 int seriesIndex = -1;
161 for ( QMap<QString, double> &gatheredCategoriesSum : gatheredSeriesCategoriesSum )
162 {
163 seriesIndex++;
164 if ( !mPredefinedCategories.isEmpty() )
165 {
166 for ( int i = 0; i < mPredefinedCategories.size(); i++ )
167 {
168 auto gatheredCategoriesSumIt = gatheredCategoriesSum.find( mPredefinedCategories[i] );
169 if ( gatheredCategoriesSumIt != gatheredCategoriesSum.end() )
170 {
171 gatheredSeries[seriesIndex]->append( i, *gatheredCategoriesSumIt );
172 }
173 }
174 }
175 else if ( !gatheredCategories.isEmpty() )
176 {
177 for ( int i = 0; i < gatheredCategories.size(); i++ )
178 {
179 auto gatheredCategoriesSumIt = gatheredCategoriesSum.find( gatheredCategories[i] );
180 if ( gatheredCategoriesSumIt != gatheredCategoriesSum.end() )
181 {
182 gatheredSeries[seriesIndex]->append( i, *gatheredCategoriesSumIt );
183 }
184 }
185 }
186 }
187
188 mData.setCategories( !mPredefinedCategories.isEmpty() ? mPredefinedCategories : gatheredCategories );
189 break;
190 }
191
193 break;
194 }
195
196 int seriesIndex = 0;
197 for ( std::unique_ptr<QgsXyPlotSeries> &series : gatheredSeries )
198 {
199 series->setName( mSeriesDetails[seriesIndex++].name );
200 mData.addSeries( series.release() );
201 }
202
203 return true;
204}
205
PlotAxisType
Plots axis types.
Definition qgis.h:3448
@ Categorical
The axis represents categories.
Definition qgis.h:3450
@ Interval
The axis represents a range of values.
Definition qgis.h:3449
Handles parsing and evaluation of expressions (formerly called "search strings").
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
Encapsulates one or more plot series.
Definition qgsplot.h:303
bool isCanceled() const
Will return true if task should terminate ASAP.
QgsPlotData data() const override
Returns the plot data.
void setPredefinedCategories(const QStringList &categories)
Sets the predefined categories list that will be used to restrict the categories used when gathering ...
bool run() override
Performs the task's operation.
void setSeriesDetails(const QList< QgsVectorLayerXyPlotDataGatherer::XySeriesDetails > &details)
Sets the series details list that will be used to prepare the data being gathered.
QgsVectorLayerXyPlotDataGatherer(Qgis::PlotAxisType xAxisType=Qgis::PlotAxisType::Interval)
The vector layer XY plot data gatherer constructor.