|
25 | 25 | #include "qgsvectorlayer.h" |
26 | 26 | #include "qgsvectordataprovider.h" |
27 | 27 | #include "qgsattributeeditor.h" |
| 28 | +#include "qgsstatisticalsummary.h" |
28 | 29 |
|
29 | 30 | #include <limits> |
30 | 31 | #include <QComboBox> |
31 | 32 | #include <QSettings> |
32 | 33 |
|
| 34 | +QList< QgsStatisticalSummary::Statistic > QgsMergeAttributesDialog::mDisplayStats = |
| 35 | + QList< QgsStatisticalSummary::Statistic > () << QgsStatisticalSummary::Count |
| 36 | + << QgsStatisticalSummary::Sum |
| 37 | + << QgsStatisticalSummary::Mean |
| 38 | + << QgsStatisticalSummary::Median |
| 39 | + << QgsStatisticalSummary::StDev |
| 40 | + << QgsStatisticalSummary::StDevSample |
| 41 | + << QgsStatisticalSummary::Min |
| 42 | + << QgsStatisticalSummary::Max |
| 43 | + << QgsStatisticalSummary::Range |
| 44 | + << QgsStatisticalSummary::Minority |
| 45 | + << QgsStatisticalSummary::Majority |
| 46 | + << QgsStatisticalSummary::Variety |
| 47 | + << QgsStatisticalSummary::FirstQuartile |
| 48 | + << QgsStatisticalSummary::ThirdQuartile |
| 49 | + << QgsStatisticalSummary::InterQuartileRange; |
| 50 | + |
33 | 51 | QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList &features, QgsVectorLayer *vl, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags f ) |
34 | 52 | : QDialog( parent, f ) |
35 | 53 | , mFeatureList( features ) |
@@ -152,16 +170,15 @@ QComboBox *QgsMergeAttributesDialog::createMergeComboBox( QVariant::Type columnT |
152 | 170 | QgsFeatureList::const_iterator f_it = mFeatureList.constBegin(); |
153 | 171 | for ( ; f_it != mFeatureList.constEnd(); ++f_it ) |
154 | 172 | { |
155 | | - newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString::number( f_it->id() ) ); |
| 173 | + newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString( "f%1" ).arg( f_it->id() ) ); |
156 | 174 | } |
157 | 175 |
|
158 | 176 | if ( columnType == QVariant::Double || columnType == QVariant::Int ) |
159 | 177 | { |
160 | | - newComboBox->addItem( tr( "Minimum" ), "minimum" ); |
161 | | - newComboBox->addItem( tr( "Maximum" ), "maximum" ); |
162 | | - newComboBox->addItem( tr( "Median" ), "median" ); |
163 | | - newComboBox->addItem( tr( "Sum" ), "sum" ); |
164 | | - newComboBox->addItem( tr( "Mean" ), "mean" ); |
| 178 | + Q_FOREACH ( QgsStatisticalSummary::Statistic stat, mDisplayStats ) |
| 179 | + { |
| 180 | + newComboBox->addItem( QgsStatisticalSummary::displayName( stat ) , stat ); |
| 181 | + } |
165 | 182 | } |
166 | 183 | else if ( columnType == QVariant::String ) |
167 | 184 | { |
@@ -250,39 +267,26 @@ void QgsMergeAttributesDialog::refreshMergedValue( int col ) |
250 | 267 | //evaluate behaviour (feature value or min / max / mean ) |
251 | 268 | QString mergeBehaviourString = comboBox->itemData( comboBox->currentIndex() ).toString(); |
252 | 269 | QVariant mergeResult; // result to show in the merge result field |
253 | | - if ( mergeBehaviourString == "minimum" ) |
254 | | - { |
255 | | - mergeResult = minimumAttribute( col ); |
256 | | - } |
257 | | - else if ( mergeBehaviourString == "maximum" ) |
258 | | - { |
259 | | - mergeResult = maximumAttribute( col ); |
260 | | - } |
261 | | - else if ( mergeBehaviourString == "mean" ) |
262 | | - { |
263 | | - mergeResult = meanAttribute( col ); |
264 | | - } |
265 | | - else if ( mergeBehaviourString == "median" ) |
266 | | - { |
267 | | - mergeResult = medianAttribute( col ); |
268 | | - } |
269 | | - else if ( mergeBehaviourString == "sum" ) |
270 | | - { |
271 | | - mergeResult = sumAttribute( col ); |
272 | | - } |
273 | | - else if ( mergeBehaviourString == "concat" ) |
| 270 | + if ( mergeBehaviourString == "concat" ) |
274 | 271 | { |
275 | 272 | mergeResult = concatenationAttribute( col ); |
276 | 273 | } |
277 | 274 | else if ( mergeBehaviourString == "skip" ) |
278 | 275 | { |
279 | 276 | mergeResult = tr( "Skipped" ); |
280 | 277 | } |
281 | | - else //an existing feature value |
| 278 | + else if ( mergeBehaviourString.startsWith( "f" ) ) |
282 | 279 | { |
283 | | - int featureId = mergeBehaviourString.toInt(); |
| 280 | + //an existing feature value - TODO should be QgsFeatureId, not int |
| 281 | + int featureId = mergeBehaviourString.mid( 1 ).toInt(); |
284 | 282 | mergeResult = featureAttribute( featureId, col ); |
285 | 283 | } |
| 284 | + else |
| 285 | + { |
| 286 | + //numerical statistic |
| 287 | + QgsStatisticalSummary::Statistic stat = ( QgsStatisticalSummary::Statistic )( comboBox->itemData( comboBox->currentIndex() ).toInt() ); |
| 288 | + mergeResult = calcStatistic( col, stat ); |
| 289 | + } |
286 | 290 |
|
287 | 291 | //insert string into table widget |
288 | 292 | QTableWidgetItem* newTotalItem = new QTableWidgetItem(); |
@@ -311,141 +315,30 @@ QVariant QgsMergeAttributesDialog::featureAttribute( int featureId, int col ) |
311 | 315 | } |
312 | 316 | } |
313 | 317 |
|
314 | | -QVariant QgsMergeAttributesDialog::minimumAttribute( int col ) |
315 | | -{ |
316 | | - double minimumValue = std::numeric_limits<double>::max(); |
317 | | - double currentValue; |
318 | | - bool conversion = false; |
319 | | - int numberOfConsideredFeatures = 0; |
320 | 318 |
|
321 | | - for ( int i = 0; i < mFeatureList.size(); ++i ) |
322 | | - { |
323 | | - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
324 | | - if ( conversion ) |
325 | | - { |
326 | | - if ( currentValue < minimumValue ) |
327 | | - { |
328 | | - minimumValue = currentValue; |
329 | | - ++numberOfConsideredFeatures; |
330 | | - } |
331 | | - } |
332 | | - } |
333 | | - |
334 | | - if ( numberOfConsideredFeatures < 1 ) |
335 | | - { |
336 | | - return QVariant( mVectorLayer->fields().at( col ).type() ); |
337 | | - } |
338 | | - |
339 | | - return QVariant( minimumValue ); |
340 | | -} |
341 | | - |
342 | | -QVariant QgsMergeAttributesDialog::maximumAttribute( int col ) |
| 319 | +QVariant QgsMergeAttributesDialog::calcStatistic( int col, QgsStatisticalSummary::Statistic stat ) |
343 | 320 | { |
344 | | - double maximumValue = -std::numeric_limits<double>::max(); |
345 | | - double currentValue; |
346 | | - bool conversion = false; |
347 | | - int numberOfConsideredFeatures = 0; |
348 | | - |
349 | | - for ( int i = 0; i < mFeatureList.size(); ++i ) |
350 | | - { |
351 | | - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
352 | | - if ( conversion ) |
353 | | - { |
354 | | - if ( currentValue > maximumValue ) |
355 | | - { |
356 | | - maximumValue = currentValue; |
357 | | - ++numberOfConsideredFeatures; |
358 | | - } |
359 | | - } |
360 | | - } |
361 | | - |
362 | | - if ( numberOfConsideredFeatures < 1 ) |
363 | | - { |
364 | | - return QVariant( mVectorLayer->fields().at( col ).type() ); |
365 | | - } |
366 | | - |
367 | | - return QVariant( maximumValue ); |
368 | | -} |
| 321 | + QgsStatisticalSummary summary( stat ); |
369 | 322 |
|
370 | | -QVariant QgsMergeAttributesDialog::meanAttribute( int col ) |
371 | | -{ |
372 | | - int numberOfConsideredFeatures = 0; |
373 | | - double currentValue; |
374 | | - double sum = 0; |
375 | 323 | bool conversion = false; |
376 | | - |
| 324 | + QList<double> values; |
377 | 325 | for ( int i = 0; i < mFeatureList.size(); ++i ) |
378 | 326 | { |
379 | | - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
| 327 | + double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
380 | 328 | if ( conversion ) |
381 | 329 | { |
382 | | - sum += currentValue; |
383 | | - ++numberOfConsideredFeatures; |
| 330 | + values << currentValue; |
384 | 331 | } |
385 | 332 | } |
386 | 333 |
|
387 | | - if ( numberOfConsideredFeatures < 1 ) |
| 334 | + if ( values.isEmpty() ) |
388 | 335 | { |
389 | | - return QVariant( mVectorLayer->fields().at( col ).type() ); |
| 336 | + return QVariant( mVectorLayer->fields()[col].type() ); |
390 | 337 | } |
391 | 338 |
|
392 | | - double mean = sum / numberOfConsideredFeatures; |
393 | | - return QVariant( mean ); |
394 | | -} |
395 | | - |
396 | | -QVariant QgsMergeAttributesDialog::medianAttribute( int col ) |
397 | | -{ |
398 | | - //bring all values into a list and sort |
399 | | - QList<double> valueList; |
400 | | - double currentValue; |
401 | | - bool conversionSuccess; |
402 | | - |
403 | | - for ( int i = 0; i < mFeatureList.size(); ++i ) |
404 | | - { |
405 | | - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversionSuccess ); |
406 | | - if ( !conversionSuccess ) |
407 | | - { |
408 | | - continue; |
409 | | - } |
410 | | - valueList.push_back( currentValue ); |
411 | | - } |
412 | | - qSort( valueList ); |
413 | | - |
414 | | - double medianValue; |
415 | | - int size = valueList.size(); |
416 | | - |
| 339 | + summary.calculate( values ); |
417 | 340 |
|
418 | | - if ( size < 1 ) |
419 | | - { |
420 | | - return QVariant( mVectorLayer->fields().at( col ).type() ); |
421 | | - } |
422 | | - |
423 | | - bool even = ( size % 2 ) < 1; |
424 | | - if ( even ) |
425 | | - { |
426 | | - medianValue = ( valueList[size / 2 - 1] + valueList[size / 2] ) / 2; |
427 | | - } |
428 | | - else //odd |
429 | | - { |
430 | | - medianValue = valueList[( size + 1 ) / 2 - 1]; |
431 | | - } |
432 | | - return QVariant( medianValue ); |
433 | | -} |
434 | | - |
435 | | -QVariant QgsMergeAttributesDialog::sumAttribute( int col ) |
436 | | -{ |
437 | | - double sum = 0.0; |
438 | | - bool conversion = false; |
439 | | - |
440 | | - for ( int i = 0; i < mFeatureList.size(); ++i ) |
441 | | - { |
442 | | - double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
443 | | - if ( conversion ) |
444 | | - { |
445 | | - sum += currentValue; |
446 | | - } |
447 | | - } |
448 | | - return QVariant( sum ); |
| 341 | + return QVariant::fromValue( summary.statistic( stat ) ); |
449 | 342 | } |
450 | 343 |
|
451 | 344 | QVariant QgsMergeAttributesDialog::concatenationAttribute( int col ) |
|
0 commit comments