00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "qgsgraduatedsymbolrendererv2.h"
00015
00016 #include "qgssymbolv2.h"
00017 #include "qgssymbollayerv2utils.h"
00018 #include "qgsvectorcolorrampv2.h"
00019
00020 #include "qgsfeature.h"
00021 #include "qgsvectorlayer.h"
00022 #include "qgslogger.h"
00023
00024 #include <QDomDocument>
00025 #include <QDomElement>
00026 #include <QSettings>
00027 #include <limits>
00028 #include "math.h"
00029
00030 QgsRendererRangeV2::QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol, QString label )
00031 : mLowerValue( lowerValue ), mUpperValue( upperValue ), mSymbol( symbol ), mLabel( label )
00032 {
00033 }
00034
00035 QgsRendererRangeV2::QgsRendererRangeV2( const QgsRendererRangeV2& range )
00036 : mLowerValue( range.mLowerValue ), mUpperValue( range.mUpperValue ), mLabel( range.mLabel )
00037 {
00038 mSymbol = range.mSymbol->clone();
00039 }
00040
00041 QgsRendererRangeV2::~QgsRendererRangeV2()
00042 {
00043 delete mSymbol;
00044 }
00045
00046 double QgsRendererRangeV2::lowerValue() const
00047 {
00048 return mLowerValue;
00049 }
00050
00051 double QgsRendererRangeV2::upperValue() const
00052 {
00053 return mUpperValue;
00054 }
00055
00056 QgsSymbolV2* QgsRendererRangeV2::symbol() const
00057 {
00058 return mSymbol;
00059 }
00060
00061 QString QgsRendererRangeV2::label() const
00062 {
00063 return mLabel;
00064 }
00065
00066 void QgsRendererRangeV2::setSymbol( QgsSymbolV2* s )
00067 {
00068 if ( mSymbol == s )
00069 return;
00070 delete mSymbol;
00071 mSymbol = s;
00072 }
00073
00074 void QgsRendererRangeV2::setLabel( QString label )
00075 {
00076 mLabel = label;
00077 }
00078
00079 void QgsRendererRangeV2::setUpperValue( double upperValue )
00080 {
00081 mUpperValue = upperValue;
00082 }
00083
00084 void QgsRendererRangeV2::setLowerValue( double lowerValue )
00085 {
00086 mLowerValue = lowerValue;
00087 }
00088
00089 QString QgsRendererRangeV2::dump()
00090 {
00091 return QString( "%1 - %2::%3::%4\n" ).arg( mLowerValue ).arg( mUpperValue ).arg( mLabel ).arg( mSymbol->dump() );
00092 }
00093
00095
00096
00097 QgsGraduatedSymbolRendererV2::QgsGraduatedSymbolRendererV2( QString attrName, QgsRangeList ranges )
00098 : QgsFeatureRendererV2( "graduatedSymbol" ),
00099 mAttrName( attrName ),
00100 mRanges( ranges ),
00101 mMode( Custom ),
00102 mSourceSymbol( NULL ),
00103 mSourceColorRamp( NULL )
00104 {
00105
00106 }
00107
00108 QgsGraduatedSymbolRendererV2::~QgsGraduatedSymbolRendererV2()
00109 {
00110 mRanges.clear();
00111 delete mSourceSymbol;
00112 delete mSourceColorRamp;
00113 }
00114
00115 QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForValue( double value )
00116 {
00117 for ( QgsRangeList::iterator it = mRanges.begin(); it != mRanges.end(); ++it )
00118 {
00119 if ( it->lowerValue() <= value && it->upperValue() >= value )
00120 return it->symbol();
00121 }
00122
00123 return NULL;
00124 }
00125
00126 QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature )
00127 {
00128 const QgsAttributeMap& attrMap = feature.attributeMap();
00129 QgsAttributeMap::const_iterator ita = attrMap.find( mAttrNum );
00130 if ( ita == attrMap.end() )
00131 {
00132 QgsDebugMsg( "attribute required by renderer not found: " + mAttrName + "(index " + QString::number( mAttrNum ) + ")" );
00133 return NULL;
00134 }
00135
00136
00137 QgsSymbolV2* symbol = symbolForValue( ita->toDouble() );
00138
00139
00140 if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 )
00141 return symbol;
00142
00143
00144 double rotation = 0;
00145 double sizeScale = 1;
00146 if ( mRotationFieldIdx != -1 )
00147 rotation = attrMap[mRotationFieldIdx].toDouble();
00148 if ( mSizeScaleFieldIdx != -1 )
00149 sizeScale = attrMap[mSizeScaleFieldIdx].toDouble();
00150
00151
00152 QgsSymbolV2* tempSymbol = mTempSymbols[symbol];
00153
00154
00155 if ( tempSymbol->type() == QgsSymbolV2::Marker )
00156 {
00157 QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( tempSymbol );
00158 if ( mRotationFieldIdx != -1 )
00159 markerSymbol->setAngle( rotation );
00160 if ( mSizeScaleFieldIdx != -1 )
00161 markerSymbol->setSize( sizeScale * static_cast<QgsMarkerSymbolV2*>( symbol )->size() );
00162 }
00163 else if ( tempSymbol->type() == QgsSymbolV2::Line )
00164 {
00165 QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( tempSymbol );
00166 if ( mSizeScaleFieldIdx != -1 )
00167 lineSymbol->setWidth( sizeScale * static_cast<QgsLineSymbolV2*>( symbol )->width() );
00168 }
00169 return tempSymbol;
00170 }
00171
00172 void QgsGraduatedSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
00173 {
00174
00175 mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1;
00176
00177 mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
00178 mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );
00179
00180 QgsRangeList::iterator it = mRanges.begin();
00181 for ( ; it != mRanges.end(); ++it )
00182 {
00183 it->symbol()->startRender( context );
00184
00185 if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
00186 {
00187 QgsSymbolV2* tempSymbol = it->symbol()->clone();
00188 tempSymbol->setRenderHints(( mRotationFieldIdx != -1 ? QgsSymbolV2::DataDefinedRotation : 0 ) |
00189 ( mSizeScaleFieldIdx != -1 ? QgsSymbolV2::DataDefinedSizeScale : 0 ) );
00190 tempSymbol->startRender( context );
00191 mTempSymbols[ it->symbol()] = tempSymbol;
00192 }
00193 }
00194 }
00195
00196 void QgsGraduatedSymbolRendererV2::stopRender( QgsRenderContext& context )
00197 {
00198 QgsRangeList::iterator it = mRanges.begin();
00199 for ( ; it != mRanges.end(); ++it )
00200 it->symbol()->startRender( context );
00201
00202
00203 #if QT_VERSION < 0x40600
00204 QMap<QgsSymbolV2*, QgsSymbolV2*>::iterator it2 = mTempSymbols.begin();
00205 #else
00206 QHash<QgsSymbolV2*, QgsSymbolV2*>::iterator it2 = mTempSymbols.begin();
00207 #endif
00208 for ( ; it2 != mTempSymbols.end(); ++it2 )
00209 {
00210 it2.value()->stopRender( context );
00211 delete it2.value();
00212 }
00213 mTempSymbols.clear();
00214 }
00215
00216 QList<QString> QgsGraduatedSymbolRendererV2::usedAttributes()
00217 {
00218 QList<QString> lst;
00219 lst.append( mAttrName );
00220 if ( !mRotationField.isEmpty() )
00221 lst.append( mRotationField );
00222 if ( !mSizeScaleField.isEmpty() )
00223 lst.append( mSizeScaleField );
00224 return lst;
00225 }
00226
00227 bool QgsGraduatedSymbolRendererV2::updateRangeSymbol( int rangeIndex, QgsSymbolV2* symbol )
00228 {
00229 if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
00230 return false;
00231 mRanges[rangeIndex].setSymbol( symbol );
00232 return true;
00233 }
00234
00235 bool QgsGraduatedSymbolRendererV2::updateRangeLabel( int rangeIndex, QString label )
00236 {
00237 if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
00238 return false;
00239 mRanges[rangeIndex].setLabel( label );
00240 return true;
00241 }
00242
00243 bool QgsGraduatedSymbolRendererV2::updateRangeUpperValue( int rangeIndex, double value )
00244 {
00245 if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
00246 return false;
00247 mRanges[rangeIndex].setUpperValue( value );
00248 return true;
00249 }
00250
00251 bool QgsGraduatedSymbolRendererV2::updateRangeLowerValue( int rangeIndex, double value )
00252 {
00253 if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
00254 return false;
00255 mRanges[rangeIndex].setLowerValue( value );
00256 return true;
00257 }
00258
00259 QString QgsGraduatedSymbolRendererV2::dump()
00260 {
00261 QString s = QString( "GRADUATED: attr %1\n" ).arg( mAttrName );
00262 for ( int i = 0; i < mRanges.count(); i++ )
00263 s += mRanges[i].dump();
00264 return s;
00265 }
00266
00267 QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::clone()
00268 {
00269 QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( mAttrName, mRanges );
00270 r->setMode( mMode );
00271 if ( mSourceSymbol )
00272 r->setSourceSymbol( mSourceSymbol->clone() );
00273 if ( mSourceColorRamp )
00274 r->setSourceColorRamp( mSourceColorRamp->clone() );
00275 r->setUsingSymbolLevels( usingSymbolLevels() );
00276 r->setRotationField( rotationField() );
00277 r->setSizeScaleField( sizeScaleField() );
00278 return r;
00279 }
00280
00281 QgsSymbolV2List QgsGraduatedSymbolRendererV2::symbols()
00282 {
00283 QgsSymbolV2List lst;
00284 for ( int i = 0; i < mRanges.count(); i++ )
00285 lst.append( mRanges[i].symbol() );
00286 return lst;
00287 }
00288
00289 static QList<double> _calcEqualIntervalBreaks( double minimum, double maximum, int classes )
00290 {
00291
00292
00293
00294
00295
00296
00297 double step = ( maximum - minimum ) / classes;
00298
00299 QList<double> breaks;
00300 double value = minimum;
00301 for ( int i = 0; i < classes; i++ )
00302 {
00303 value += step;
00304 breaks.append( value );
00305 }
00306 return breaks;
00307 }
00308
00309 static QList<double> _calcQuantileBreaks( QList<double> values, int classes )
00310 {
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 qSort( values );
00322
00323 QList<double> breaks;
00324
00325 int n = values.count();
00326 double Xq = n > 0 ? values[0] : 0.0;
00327
00328 for ( int i = 1; i < classes; i++ )
00329 {
00330 if ( n > 1 )
00331 {
00332 double q = i / ( double ) classes;
00333 double a = q * ( n - 1 );
00334 int aa = ( int )( a );
00335
00336 double r = a - aa;
00337 Xq = ( 1 - r ) * values[aa] + r * values[aa+1];
00338 }
00339 breaks.append( Xq );
00340 }
00341
00342 breaks.append( values[ n-1 ] );
00343
00344 return breaks;
00345 }
00346
00347 static QList<double> _calcPrettyBreaks( double minimum, double maximum, int classes )
00348 {
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 QList<double> breaks;
00360 if ( classes < 1 )
00361 {
00362 breaks.append( maximum );
00363 return breaks;
00364 }
00365
00366 int minimumCount = ( int ) classes / 3;
00367 double shrink = 0.75;
00368 double highBias = 1.5;
00369 double adjustBias = 0.5 + 1.5 * highBias;
00370 int divisions = classes;
00371 double h = highBias;
00372 double cell;
00373 int U;
00374 bool small = false;
00375 double dx = maximum - minimum;
00376
00377 if ( dx == 0 && maximum == 0 )
00378 {
00379 cell = 1.0;
00380 small = true;
00381 U = 1;
00382 }
00383 else
00384 {
00385 cell = qMax( qAbs( minimum ), qAbs( maximum ) );
00386 if ( adjustBias >= 1.5 * h + 0.5 )
00387 {
00388 U = 1 + ( 1.0 / ( 1 + h ) );
00389 }
00390 else
00391 {
00392 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
00393 }
00394 small = dx < ( cell * U * qMax( 1, divisions ) * 1e-07 * 3.0 );
00395 }
00396
00397 if ( small )
00398 {
00399 if ( cell > 10 )
00400 {
00401 cell = 9 + cell / 10;
00402 cell = cell * shrink;
00403 }
00404 if ( minimumCount > 1 )
00405 {
00406 cell = cell / minimumCount;
00407 }
00408 }
00409 else
00410 {
00411 cell = dx;
00412 if ( divisions > 1 )
00413 {
00414 cell = cell / divisions;
00415 }
00416 }
00417 if ( cell < 20 * 1e-07 )
00418 {
00419 cell = 20 * 1e-07;
00420 }
00421
00422 double base = pow( 10.0, floor( log10( cell ) ) );
00423 double unit = base;
00424 if (( 2 * base ) - cell < h * ( cell - unit ) )
00425 {
00426 unit = 2.0 * base;
00427 if (( 5 * base ) - cell < adjustBias * ( cell - unit ) )
00428 {
00429 unit = 5.0 * base;
00430 if (( 10.0 * base ) - cell < h * ( cell - unit ) )
00431 {
00432 unit = 10.0 * base;
00433 }
00434 }
00435 }
00436
00437 int start = floor( minimum / unit + 1e-07 );
00438 int end = ceil( maximum / unit - 1e-07 );
00439
00440
00441 while ( start * unit > minimum + ( 1e-07 * unit ) )
00442 {
00443 start = start - 1;
00444 }
00445 while ( end * unit < maximum - ( 1e-07 * unit ) )
00446 {
00447 end = end + 1;
00448 }
00449 QgsDebugMsg( QString( "pretty classes: %1" ).arg( end ) );
00450
00451
00452
00453 int k = floor( 0.5 + end - start );
00454 if ( k < minimumCount )
00455 {
00456 k = minimumCount - k;
00457 if ( start >= 0 )
00458 {
00459 end = end + k / 2;
00460 start = start - k / 2 + k % 2;
00461 }
00462 else
00463 {
00464 start = start - k / 2;
00465 end = end + k / 2 + k % 2;
00466 }
00467 divisions = minimumCount;
00468 }
00469 else
00470 {
00471 divisions = k;
00472 }
00473 double minimumBreak = start * unit;
00474 double maximumBreak = end * unit;
00475 int count = ceil( maximumBreak - minimumBreak ) / unit;
00476
00477 for ( int i = 1; i < count + 1; i++ )
00478 {
00479 breaks.append( minimumBreak + i * unit );
00480 }
00481
00482 if ( breaks.first() < minimum )
00483 {
00484 breaks[0] = minimum;
00485 }
00486 if ( breaks.last() > maximum )
00487 {
00488 breaks[breaks.count()-1] = maximum;
00489 }
00490 return breaks;
00491 }
00492
00493
00494 static QList<double> _calcStdDevBreaks( QList<double> values, int classes, QList<int> &labels )
00495 {
00496
00497
00498
00499
00500
00501
00502
00503
00504 double mean = 0.0;
00505 double stdDev = 0.0;
00506 int n = values.count();
00507 double minimum = values[0];
00508 double maximum = values[0];
00509
00510 for ( int i = 0; i < n; i++ )
00511 {
00512 mean += values[i];
00513 minimum = qMin( values[i], minimum );
00514 maximum = qMax( values[i], maximum );
00515 }
00516 mean = mean / ( double ) n;
00517
00518 double sd = 0.0;
00519 for ( int i = 0; i < n; i++ )
00520 {
00521 sd = values[i] - mean;
00522 stdDev += sd * sd;
00523 }
00524 stdDev = sqrt( stdDev / n );
00525
00526 QList<double> breaks = _calcPrettyBreaks(( minimum - mean ) / stdDev, ( maximum - mean ) / stdDev, classes );
00527 for ( int i = 0; i < breaks.count(); i++ )
00528 {
00529 labels.append(( int ) breaks[i] );
00530 breaks[i] = ( breaks[i] * stdDev ) + mean;
00531 }
00532
00533 return breaks;
00534 }
00535
00536 static QList<double> _calcJenksBreaks( QList<double> values, int classes,
00537 double minimum, double maximum,
00538 int maximumSize = 1000 )
00539 {
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 QList<double> breaks;
00552 if ( classes < 1 )
00553 {
00554 breaks.append( maximum );
00555 return breaks;
00556 }
00557
00558 int n = values.count();
00559 QList<double> sample;
00560
00561
00562 if ( n > maximumSize )
00563 {
00564
00565
00566
00567 n = qMax( maximumSize, ( int )(( double ) n * 0.10 ) );
00568 QgsDebugMsg( QString( "natural breaks (jenks) sample size: %1" ).arg( n ) );
00569 sample.append( minimum );
00570 sample.append( maximum );
00571 for ( int i = 0; i < n - 2; i++ )
00572 {
00573
00574 int c = ( int )(( double ) rand() / (( double ) RAND_MAX + 1 ) * n - 1 );
00575 sample.append( values[i+c] );
00576 }
00577 }
00578 else
00579 {
00580 sample = values;
00581 }
00582
00583 qSort( sample );
00584
00585 QList< QList<double> > matrixOne;
00586 QList< QList<double> > matrixTwo;
00587
00588 double v, s1, s2, w, i3, i4, val;
00589
00590 for ( int i = 0; i < n + 1; i++ )
00591 {
00592 QList<double > tempOne;
00593 QList<double > tempTwo;
00594 for ( int j = 0; j < classes + 1; j++ )
00595 {
00596 tempOne.append( 0.0 );
00597 tempTwo.append( 0.0 );
00598 }
00599 matrixOne.append( tempOne );
00600 matrixTwo.append( tempTwo );
00601 }
00602
00603 for ( int i = 1; i < classes + 1; i++ )
00604 {
00605 matrixOne[1][i] = 1.0;
00606 matrixTwo[1][i] = 0.0;
00607 for ( int j = 2; j < n + 1; j++ )
00608 {
00609 matrixTwo[j][i] = std::numeric_limits<qreal>::max();
00610 }
00611 }
00612
00613 v = 0.0;
00614 for ( int l = 2; l < n + 1; l++ )
00615 {
00616 s1 = 0.0;
00617 s2 = 0.0;
00618 w = 0.0;
00619 for ( int m = 1; m < l + 1; m++ )
00620 {
00621 i3 = l - m + 1;
00622
00623 val = sample[ i3 - 1 ];
00624
00625 s2 += val * val;
00626 s1 += val;
00627
00628 w += 1.0;
00629 v = s2 - ( s1 * s1 ) / w;
00630 i4 = i3 - 1;
00631
00632 if ( i4 != 0.0 )
00633 {
00634 for ( int j = 2; j < classes + 1; j++ )
00635 {
00636 if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
00637 {
00638 matrixOne[l][j] = i3;
00639 matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
00640 }
00641 }
00642 }
00643 }
00644 matrixOne[l][1] = 1.0;
00645 matrixTwo[l][1] = v;
00646 }
00647
00648 for ( int i = 0; i < classes; i++ )
00649 {
00650 breaks.append( 0.0 );
00651 }
00652
00653 breaks[classes - 1] = sample[sample.size() - 1];
00654
00655
00656 int k = n;
00657 int count = classes;
00658 while ( count >= 2 )
00659 {
00660 int id = matrixOne[k][count] - 2;
00661 breaks[count - 2] = sample[id];
00662 k = matrixOne[k][count] - 1;
00663 count -= 1;
00664 }
00665
00666 return breaks;
00667 }
00668
00669 #include "qgsvectordataprovider.h"
00670 #include "qgsvectorcolorrampv2.h"
00671
00672 QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
00673 QgsVectorLayer* vlayer,
00674 QString attrName,
00675 int classes,
00676 Mode mode,
00677 QgsSymbolV2* symbol,
00678 QgsVectorColorRampV2* ramp )
00679 {
00680 QgsVectorDataProvider* provider = vlayer->dataProvider();
00681
00682 int attrNum = vlayer->fieldNameIndex( attrName );
00683
00684 double minimum = provider->minimumValue( attrNum ).toDouble();
00685 double maximum = provider->maximumValue( attrNum ).toDouble();
00686 QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );
00687
00688 QList<double> breaks;
00689 QList<int> labels;
00690 if ( mode == EqualInterval )
00691 {
00692 breaks = _calcEqualIntervalBreaks( minimum, maximum, classes );
00693 }
00694 else if ( mode == Pretty )
00695 {
00696 breaks = _calcPrettyBreaks( minimum, maximum, classes );
00697 }
00698 else if ( mode == Quantile || mode == Jenks || mode == StdDev )
00699 {
00700
00701 QList<double> values;
00702 QgsFeature f;
00703 QgsAttributeList lst;
00704 lst.append( attrNum );
00705 provider->select( lst, QgsRectangle(), false );
00706 while ( provider->nextFeature( f ) )
00707 values.append( f.attributeMap()[attrNum].toDouble() );
00708
00709 if ( mode == Quantile )
00710 {
00711 breaks = _calcQuantileBreaks( values, classes );
00712 }
00713 else if ( mode == Jenks )
00714 {
00715 breaks = _calcJenksBreaks( values, classes, minimum, maximum );
00716 }
00717 else if ( mode == StdDev )
00718 {
00719 breaks = _calcStdDevBreaks( values, classes, labels );
00720 }
00721 }
00722 else
00723 {
00724 Q_ASSERT( false );
00725 }
00726
00727 QgsRangeList ranges;
00728 double lower, upper = minimum;
00729 QString label;
00730
00731
00732 int i = 0;
00733 for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
00734 {
00735 lower = upper;
00736 upper = *it;
00737 if ( mode == StdDev )
00738 {
00739 if ( i == 0 )
00740 {
00741 label = "< " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
00742 }
00743 else if ( i == labels.count() - 1 )
00744 {
00745 label = ">= " + QString::number( labels[i-1], 'i', 0 ) + " Std Dev";
00746 }
00747 else
00748 {
00749 label = QString::number( labels[i-1], 'i', 0 ) + " Std Dev" + " - " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
00750 }
00751 }
00752 else
00753 {
00754 label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 );
00755 }
00756
00757 QgsSymbolV2* newSymbol = symbol->clone();
00758 newSymbol->setColor( ramp->color(( double ) i / ( breaks.count() - 1 ) ) );
00759
00760 ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
00761 }
00762
00763 QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
00764 r->setSourceSymbol( symbol->clone() );
00765 r->setSourceColorRamp( ramp->clone() );
00766 r->setMode( mode );
00767 return r;
00768 }
00769
00770
00771
00772 QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create( QDomElement& element )
00773 {
00774 QDomElement symbolsElem = element.firstChildElement( "symbols" );
00775 if ( symbolsElem.isNull() )
00776 return NULL;
00777
00778 QDomElement rangesElem = element.firstChildElement( "ranges" );
00779 if ( rangesElem.isNull() )
00780 return NULL;
00781
00782 QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
00783 QgsRangeList ranges;
00784
00785 QDomElement rangeElem = rangesElem.firstChildElement();
00786 while ( !rangeElem.isNull() )
00787 {
00788 if ( rangeElem.tagName() == "range" )
00789 {
00790 double lowerValue = rangeElem.attribute( "lower" ).toDouble();
00791 double upperValue = rangeElem.attribute( "upper" ).toDouble();
00792 QString symbolName = rangeElem.attribute( "symbol" );
00793 QString label = rangeElem.attribute( "label" );
00794 if ( symbolMap.contains( symbolName ) )
00795 {
00796 QgsSymbolV2* symbol = symbolMap.take( symbolName );
00797 ranges.append( QgsRendererRangeV2( lowerValue, upperValue, symbol, label ) );
00798 }
00799 }
00800 rangeElem = rangeElem.nextSiblingElement();
00801 }
00802
00803 QString attrName = element.attribute( "attr" );
00804
00805 QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
00806
00807
00808 QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
00809
00810
00811 QDomElement sourceSymbolElem = element.firstChildElement( "source-symbol" );
00812 if ( !sourceSymbolElem.isNull() )
00813 {
00814 QgsSymbolV2Map sourceSymbolMap = QgsSymbolLayerV2Utils::loadSymbols( sourceSymbolElem );
00815 if ( sourceSymbolMap.contains( "0" ) )
00816 {
00817 r->setSourceSymbol( sourceSymbolMap.take( "0" ) );
00818 }
00819 QgsSymbolLayerV2Utils::clearSymbolMap( sourceSymbolMap );
00820 }
00821
00822
00823 QDomElement sourceColorRampElem = element.firstChildElement( "colorramp" );
00824 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( "name" ) == "[source]" )
00825 {
00826 r->setSourceColorRamp( QgsSymbolLayerV2Utils::loadColorRamp( sourceColorRampElem ) );
00827 }
00828
00829
00830 QDomElement modeElem = element.firstChildElement( "mode" );
00831 if ( !modeElem.isNull() )
00832 {
00833 QString modeString = modeElem.attribute( "name" );
00834 if ( modeString == "equal" )
00835 r->setMode( EqualInterval );
00836 else if ( modeString == "quantile" )
00837 r->setMode( Quantile );
00838 else if ( modeString == "jenks" )
00839 r->setMode( Jenks );
00840 else if ( modeString == "stddev" )
00841 r->setMode( StdDev );
00842 else if ( modeString == "pretty" )
00843 r->setMode( Pretty );
00844 }
00845
00846 QDomElement rotationElem = element.firstChildElement( "rotation" );
00847 if ( !rotationElem.isNull() )
00848 r->setRotationField( rotationElem.attribute( "field" ) );
00849
00850 QDomElement sizeScaleElem = element.firstChildElement( "sizescale" );
00851 if ( !sizeScaleElem.isNull() )
00852 r->setSizeScaleField( sizeScaleElem.attribute( "field" ) );
00853
00854
00855 return r;
00856 }
00857
00858 QDomElement QgsGraduatedSymbolRendererV2::save( QDomDocument& doc )
00859 {
00860 QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
00861 rendererElem.setAttribute( "type", "graduatedSymbol" );
00862 rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
00863 rendererElem.setAttribute( "attr", mAttrName );
00864
00865
00866 int i = 0;
00867 QgsSymbolV2Map symbols;
00868 QDomElement rangesElem = doc.createElement( "ranges" );
00869 QgsRangeList::const_iterator it = mRanges.constBegin();
00870 for ( ; it != mRanges.end(); it++ )
00871 {
00872 const QgsRendererRangeV2& range = *it;
00873 QString symbolName = QString::number( i );
00874 symbols.insert( symbolName, range.symbol() );
00875
00876 QDomElement rangeElem = doc.createElement( "range" );
00877 rangeElem.setAttribute( "lower", range.lowerValue() );
00878 rangeElem.setAttribute( "upper", range.upperValue() );
00879 rangeElem.setAttribute( "symbol", symbolName );
00880 rangeElem.setAttribute( "label", range.label() );
00881 rangesElem.appendChild( rangeElem );
00882 i++;
00883 }
00884
00885 rendererElem.appendChild( rangesElem );
00886
00887
00888 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
00889 rendererElem.appendChild( symbolsElem );
00890
00891
00892 if ( mSourceSymbol )
00893 {
00894 QgsSymbolV2Map sourceSymbols;
00895 sourceSymbols.insert( "0", mSourceSymbol );
00896 QDomElement sourceSymbolElem = QgsSymbolLayerV2Utils::saveSymbols( sourceSymbols, "source-symbol", doc );
00897 rendererElem.appendChild( sourceSymbolElem );
00898 }
00899
00900
00901 if ( mSourceColorRamp )
00902 {
00903 QDomElement colorRampElem = QgsSymbolLayerV2Utils::saveColorRamp( "[source]", mSourceColorRamp, doc );
00904 rendererElem.appendChild( colorRampElem );
00905 }
00906
00907
00908 QString modeString;
00909 if ( mMode == EqualInterval )
00910 modeString = "equal";
00911 else if ( mMode == Quantile )
00912 modeString = "quantile";
00913 else if ( mMode == Jenks )
00914 modeString = "jenks";
00915 else if ( mMode == StdDev )
00916 modeString = "stddev";
00917 else if ( mMode == Pretty )
00918 modeString = "pretty";
00919 if ( !modeString.isEmpty() )
00920 {
00921 QDomElement modeElem = doc.createElement( "mode" );
00922 modeElem.setAttribute( "name", modeString );
00923 rendererElem.appendChild( modeElem );
00924 }
00925
00926 QDomElement rotationElem = doc.createElement( "rotation" );
00927 rotationElem.setAttribute( "field", mRotationField );
00928 rendererElem.appendChild( rotationElem );
00929
00930 QDomElement sizeScaleElem = doc.createElement( "sizescale" );
00931 sizeScaleElem.setAttribute( "field", mSizeScaleField );
00932 rendererElem.appendChild( sizeScaleElem );
00933
00934 return rendererElem;
00935 }
00936
00937 QgsLegendSymbologyList QgsGraduatedSymbolRendererV2::legendSymbologyItems( QSize iconSize )
00938 {
00939 QSettings settings;
00940 bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool();
00941
00942 QgsLegendSymbologyList lst;
00943 if ( showClassifiers )
00944 {
00945 lst << qMakePair( classAttribute(), QPixmap() );
00946 }
00947
00948 int count = ranges().count();
00949 for ( int i = 0; i < count; i++ )
00950 {
00951 const QgsRendererRangeV2& range = ranges()[i];
00952 QPixmap pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( range.symbol(), iconSize );
00953 lst << qMakePair( range.label(), pix );
00954 }
00955 return lst;
00956 }
00957
00958 QgsLegendSymbolList QgsGraduatedSymbolRendererV2::legendSymbolItems()
00959 {
00960 QSettings settings;
00961 bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool();
00962
00963 QgsLegendSymbolList lst;
00964 if ( showClassifiers )
00965 {
00966 lst << qMakePair( classAttribute(), ( QgsSymbolV2* )0 );
00967 }
00968
00969 QgsRangeList::const_iterator rangeIt = mRanges.constBegin();
00970 for ( ; rangeIt != mRanges.constEnd(); ++rangeIt )
00971 {
00972 lst << qMakePair( rangeIt->label(), rangeIt->symbol() );
00973 }
00974 return lst;
00975 }
00976
00977 QgsSymbolV2* QgsGraduatedSymbolRendererV2::sourceSymbol()
00978 {
00979 return mSourceSymbol;
00980 }
00981 void QgsGraduatedSymbolRendererV2::setSourceSymbol( QgsSymbolV2* sym )
00982 {
00983 delete mSourceSymbol;
00984 mSourceSymbol = sym;
00985 }
00986
00987 QgsVectorColorRampV2* QgsGraduatedSymbolRendererV2::sourceColorRamp()
00988 {
00989 return mSourceColorRamp;
00990 }
00991 void QgsGraduatedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ramp )
00992 {
00993 delete mSourceColorRamp;
00994 mSourceColorRamp = ramp;
00995 }
00996
00997 void QgsGraduatedSymbolRendererV2::addClass( QgsSymbolV2* symbol )
00998 {
00999 QgsSymbolV2* newSymbol = symbol->clone();
01000 QString label = "0.0 - 0.0";
01001 mRanges.insert( 0, QgsRendererRangeV2( 0.0, 0.0, newSymbol, label ) );
01002
01003 }
01004
01005 void QgsGraduatedSymbolRendererV2::deleteClass( int idx )
01006 {
01007 mRanges.removeAt( idx );
01008 }