@@ -60,8 +60,9 @@ static QColor _interpolate( QColor c1, QColor c2, double value )
6060 int r = ( int )( c1.red () + value * ( c2.red () - c1.red () ) );
6161 int g = ( int )( c1.green () + value * ( c2.green () - c1.green () ) );
6262 int b = ( int )( c1.blue () + value * ( c2.blue () - c1.blue () ) );
63+ int a = ( int )( c1.alpha () + value * ( c2.alpha () - c1.alpha () ) );
6364
64- return QColor::fromRgb ( r, g, b );
65+ return QColor::fromRgb ( r, g, b, a );
6566}
6667
6768QColor QgsVectorGradientColorRampV2::color ( double value ) const
@@ -269,7 +270,7 @@ QMap< QString, QString > QgsCptCityColorRampV2::mCollectionNames;
269270QMap< QString, QStringList > QgsCptCityColorRampV2::mCollectionSelections ;
270271
271272QgsCptCityColorRampV2::QgsCptCityColorRampV2 ( QString schemeName, QString variantName )
272- : mSchemeName( schemeName ), mVariantName( variantName ), mContinuous( false )
273+ : mSchemeName( schemeName ), mVariantName( variantName ), mGradientType( Continuous )
273274{
274275 // TODO replace this with hard-coded data in the default case
275276 loadFile ();
@@ -289,7 +290,7 @@ QgsVectorColorRampV2* QgsCptCityColorRampV2::create( const QgsStringMap& props )
289290}
290291
291292
292-
293+ # if 0
293294QColor QgsCptCityColorRampV2::color( double value ) const
294295{
295296 if ( mPalette.isEmpty() || value < 0 || value > 1 )
@@ -333,6 +334,45 @@ QColor QgsCptCityColorRampV2::color( double value ) const
333334 return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
334335 }
335336}
337+ #endif
338+
339+ QColor QgsCptCityColorRampV2::color ( double value ) const
340+ {
341+ if ( mPalette .isEmpty () || value < 0 || value > 1 )
342+ return QColor ( 255 , 0 , 0 ); // red color as a warning :)
343+
344+ int numStops = mPalette .count ();
345+ if ( numStops < 2 )
346+ return QColor ( 255 , 0 , 0 ); // red color as a warning :)
347+
348+ double lower = 0 , upper = 0 ;
349+ QColor c1, c2;
350+ c1 = mPalette [0 ].second ;
351+ for ( int i = 0 ; i < numStops; i++ )
352+ {
353+ if ( mPalette [i].first >= value )
354+ {
355+ if ( mGradientType == Discrete )
356+ return c1;
357+
358+ upper = mPalette [i].first ;
359+ c2 = mPalette [i].second ;
360+
361+ return upper == lower ? c1 : _interpolate ( c1, c2, ( value - lower ) / ( upper - lower ) );
362+ }
363+
364+ lower = mPalette [i].first ;
365+ c1 = mPalette [i].second ;
366+ }
367+
368+ if ( mGradientType == Discrete )
369+ return c1;
370+
371+ upper = 1 ;
372+ c2 = mPalette [ numStops - 1 ].second ;
373+
374+ return upper == lower ? c1 : _interpolate ( c1, c2, ( value - lower ) / ( upper - lower ) );
375+ }
336376
337377QgsVectorColorRampV2* QgsCptCityColorRampV2::clone () const
338378{
@@ -390,23 +430,6 @@ QStringList QgsCptCityColorRampV2::listSchemeNames( QString collectionName )
390430 return entries;
391431}
392432
393- QList<int > QgsCptCityColorRampV2::listSchemeVariants ( QString schemeName )
394- {
395- QList<int > variants;
396-
397- QString palette ( brewerString );
398- QStringList list = palette.split ( QChar ( ' \n ' ) );
399- foreach ( QString entry, list )
400- {
401- QStringList items = entry.split ( QChar ( ' -' ) );
402- if ( items.count () != 3 || items[0 ] != schemeName )
403- continue ;
404- variants << items[1 ].toInt ();
405- }
406-
407- return variants;
408- }
409-
410433QString QgsCptCityColorRampV2::getBaseDir ()
411434{
412435 // currently hard-coded, but could be also in QGis install path and/or configurable
@@ -436,7 +459,6 @@ bool QgsCptCityColorRampV2::loadFile( QString filename )
436459 // QgsDebugMsg("filename= "+filename);
437460
438461 mPalette .clear ();
439- mPaletteStops .clear ();
440462
441463 QString mErrorString = QString ();
442464
@@ -478,40 +500,38 @@ bool QgsCptCityColorRampV2::loadFile( QString filename )
478500 return false ;
479501 }
480502
481- // initialize self
482- mContinuous = true ; // we will detect later if there are overlapping stops
483- mPalette .clear ();
484- mPaletteStops .clear ();
485-
486503 // loop for all stop tags
487504 QDomElement e = rampsElement.firstChildElement ();
488- // int i = 0;
489- QMap< double , QColor > map;
505+ QMap< double , QPair<QColor, QColor> > map;
506+
507+ QColor prevColor;
490508 while ( !e.isNull () )
491509 {
492- // QgsDebugMsg("read "+e.tagName());
493510 if ( e.tagName () == " stop" )
494511 {
495512 // todo integrate this into symbollayerutils, keep here for now...
496513 double offset;
497514 QString offsetStr = e.attribute ( " offset" ); // offset="50.00%" | offset="0.5"
515+ QString colorStr = e.attribute ( " stop-color" , " " ); // stop-color="rgb(222,235,247)"
516+ QString opacityStr = e.attribute ( " stop-opacity" , " 1.0" ); // stop-opacity="1.0000"
498517 if ( offsetStr.endsWith ( " %" ) )
499518 offset = offsetStr.remove ( offsetStr.size () - 1 , 1 ).toDouble () / 100.0 ;
500519 else
501520 offset = offsetStr.toDouble ();
502521
503- QString colorStr = e.attribute ( " stop-color" , " " ); // stop-color="rgb(222,235,247)"
504- QString opacityStr = e.attribute ( " stop-opacity" , " 1.0" ); // stop-opacity="1.0000"
505522 // QColor color( 255, 0, 0 ); // red color as a warning :)
506523 QColor color = QgsSymbolLayerV2Utils::parseColor ( colorStr );
507524 if ( color != QColor () )
508525 {
509526 int alpha = opacityStr.toDouble () * 255 ; // test
510527 color.setAlpha ( alpha );
511528 if ( map.contains ( offset ) )
512- mContinuous = false ; // assume discrete if at least one stop is repeated
513- map[offset] = color;
529+ map[offset].second = color;
530+ else
531+ map[offset] = qMakePair ( color, color );
514532 }
533+ else
534+ QgsDebugMsg ( QString ( " at offset=%1 invalid color" ).arg ( offset ) );
515535 }
516536 else
517537 {
@@ -521,18 +541,51 @@ bool QgsCptCityColorRampV2::loadFile( QString filename )
521541 e = e.nextSiblingElement ();
522542 }
523543
524- // if this is a discrete gradient, remove last stop
525- if ( ! mContinuous )
544+ // add colors to palette
545+ mPalette .clear ();
546+ QMap<double , QPair<QColor, QColor> >::const_iterator it, prev;
547+ // first detect if file is gradient is continuous or dicrete
548+ // discrete: stop contains 2 colors and first color is identical to previous second
549+ // multi: stop contains 2 colors and no relation with previous stop
550+ mGradientType = Continuous;
551+ it = prev = map.constBegin ();
552+ while ( it != map.constEnd () )
526553 {
527- if ( map.contains ( 1 ) )
528- map.remove ( 1 );
554+ // look for stops that contain multiple values
555+ if ( it != map.constBegin () && ( it.value ().first != it.value ().second ) )
556+ {
557+ if ( it.value ().first == prev.value ().second )
558+ {
559+ mGradientType = Discrete;
560+ break ;
561+ }
562+ else
563+ {
564+ mGradientType = ContinuousMulti;
565+ break ;
566+ }
567+ }
568+ prev = it;
569+ ++it;
529570 }
530- // add colors to palette
531- QMap< double , QColor>::const_iterator it = map.constBegin ();
571+
572+ it = prev = map.constBegin ();
532573 while ( it != map.constEnd () )
533574 {
534- mPaletteStops << it.key ();
535- mPalette << it.value ();
575+ if ( mGradientType == Discrete )
576+ {
577+ mPalette << qMakePair ( it.key (), it.value ().second );
578+ }
579+ else
580+ {
581+ mPalette << qMakePair ( it.key (), it.value ().first );
582+ if (( mGradientType == ContinuousMulti ) &&
583+ ( it.key () != 0.0 && it.key () != 1.0 ) )
584+ {
585+ mPalette << qMakePair ( it.key (), it.value ().second );
586+ }
587+ }
588+ prev = it;
536589 ++it;
537590 }
538591
@@ -782,7 +835,3 @@ bool QgsCptCityColorRampV2::loadSchemes( QString rootDir, bool reset )
782835 return ( ! mCollections .isEmpty () );
783836}
784837
785- void QgsCptCityColorRampV2::loadPalette ()
786- {
787- // TODO: IMPLEMENT ME
788- }
0 commit comments