QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsvectorcolorrampv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorcolorrampv2.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
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 
16 #include "qgsvectorcolorrampv2.h"
17 #include "qgscolorbrewerpalette.h"
18 #include "qgscptcityarchive.h"
19 
20 #include "qgssymbollayerv2utils.h"
21 #include "qgsapplication.h"
22 #include "qgslogger.h"
23 
24 #include <stdlib.h> // for random()
25 #include <algorithm>
26 
27 #include <QTime>
28 
30 
31 static QColor _interpolate( const QColor& c1, const QColor& c2, const double value )
32 {
33  if ( qIsNaN( value ) ) return c2;
34  int r = ( int )( c1.red() + value * ( c2.red() - c1.red() ) );
35  int g = ( int )( c1.green() + value * ( c2.green() - c1.green() ) );
36  int b = ( int )( c1.blue() + value * ( c2.blue() - c1.blue() ) );
37  int a = ( int )( c1.alpha() + value * ( c2.alpha() - c1.alpha() ) );
38 
39  return QColor::fromRgb( r, g, b, a );
40 }
41 
43 
45  bool discrete, QgsGradientStopsList stops )
46  : mColor1( color1 ), mColor2( color2 ), mDiscrete( discrete ), mStops( stops )
47 {
48 }
49 
51 {
52  // color1 and color2
55  if ( props.contains( "color1" ) )
56  color1 = QgsSymbolLayerV2Utils::decodeColor( props["color1"] );
57  if ( props.contains( "color2" ) )
58  color2 = QgsSymbolLayerV2Utils::decodeColor( props["color2"] );
59 
60  //stops
62  if ( props.contains( "stops" ) )
63  {
64  foreach ( QString stop, props["stops"].split( ':' ) )
65  {
66  int i = stop.indexOf( ';' );
67  if ( i == -1 )
68  continue;
69 
70  QColor c = QgsSymbolLayerV2Utils::decodeColor( stop.mid( i + 1 ) );
71  stops.append( QgsGradientStop( stop.left( i ).toDouble(), c ) );
72  }
73  }
74 
75  // discrete vs. continuous
76  bool discrete = false;
77  if ( props.contains( "discrete" ) )
78  {
79  if ( props["discrete"] == "1" )
80  discrete = true;
81  }
82 
83  // search for information keys starting with "info_"
85  for ( QgsStringMap::const_iterator it = props.constBegin();
86  it != props.constEnd(); ++it )
87  {
88  if ( it.key().startsWith( "info_" ) )
89  info[ it.key().mid( 5 )] = it.value();
90  }
91 
92  QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( color1, color2, discrete, stops );
93  r->setInfo( info );
94  return r;
95 }
96 
98 {
99  if ( index <= 0 )
100  {
101  return 0;
102  }
103  else if ( index >= mStops.size() + 1 )
104  {
105  return 1;
106  }
107  else
108  {
109  return mStops[index-1].offset;
110  }
111 }
112 
114 {
115  if ( qgsDoubleNear( value, 0.0 ) || value < 0.0 )
116  {
117  return mColor1;
118  }
119  else if ( qgsDoubleNear( value, 1.0 ) || value > 1.0 )
120  {
121  return mColor2;
122  }
123  else if ( mStops.isEmpty() )
124  {
125  if ( mDiscrete )
126  return mColor1;
127 
128  return _interpolate( mColor1, mColor2, value );
129  }
130  else
131  {
132  double lower = 0, upper = 0;
133  QColor c1 = mColor1, c2;
134  for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
135  {
136  if ( it->offset > value )
137  {
138  if ( mDiscrete )
139  return c1;
140 
141  upper = it->offset;
142  c2 = it->color;
143 
144  return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
145  }
146  lower = it->offset;
147  c1 = it->color;
148  }
149 
150  if ( mDiscrete )
151  return c1;
152 
153  upper = 1;
154  c2 = mColor2;
155  return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
156  }
157 }
158 
160 {
162  mDiscrete, mStops );
163  r->setInfo( mInfo );
164  return r;
165 }
166 
168 {
169  QgsStringMap map;
170  map["color1"] = QgsSymbolLayerV2Utils::encodeColor( mColor1 );
171  map["color2"] = QgsSymbolLayerV2Utils::encodeColor( mColor2 );
172  if ( !mStops.isEmpty() )
173  {
174  QStringList lst;
175  for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
176  {
177  lst.append( QString( "%1;%2" ).arg( it->offset ).arg( QgsSymbolLayerV2Utils::encodeColor( it->color ) ) );
178  }
179  map["stops"] = lst.join( ":" );
180  }
181 
182  map["discrete"] = mDiscrete ? "1" : "0";
183 
185  it != mInfo.constEnd(); ++it )
186  {
187  map["info_" + it.key()] = it.value();
188  }
189 
190  return map;
191 }
193 {
194  if ( discrete == mDiscrete )
195  return;
196 
197  // if going to/from Discrete, re-arrange stops
198  // this will only work when stops are equally-spaced
199  QgsGradientStopsList newStops;
200  if ( discrete )
201  {
202  // re-arrange stops offset
203  int numStops = mStops.count() + 2;
204  int i = 1;
205  for ( QgsGradientStopsList::const_iterator it = mStops.begin();
206  it != mStops.end(); ++it )
207  {
208  newStops.append( QgsGradientStop(( double ) i / numStops, it->color ) );
209  if ( i == numStops - 1 )
210  break;
211  i++;
212  }
213  // replicate last color
214  newStops.append( QgsGradientStop(( double ) i / numStops, mColor2 ) );
215  }
216  else
217  {
218  // re-arrange stops offset, remove duplicate last color
219  int numStops = mStops.count() + 2;
220  int i = 1;
221  for ( QgsGradientStopsList::const_iterator it = mStops.begin();
222  it != mStops.end(); ++it )
223  {
224  newStops.append( QgsGradientStop(( double ) i / ( numStops - 2 ), it->color ) );
225  if ( i == numStops - 3 )
226  break;
227  i++;
228  }
229  }
230  mStops = newStops;
231  mDiscrete = discrete;
232 }
233 
235 {
236  //copy color ramp stops to a QGradient
239  if ( alpha < 1 )
240  {
241  color1.setAlpha( color1.alpha() * alpha );
242  color2.setAlpha( color2.alpha() * alpha );
243  }
244  gradient->setColorAt( 0, color1 );
245  gradient->setColorAt( 1, color2 );
246 
247  for ( QgsGradientStopsList::const_iterator it = mStops.begin();
248  it != mStops.end(); ++it )
249  {
250  QColor rampColor = it->color;
251  if ( alpha < 1 )
252  {
253  rampColor.setAlpha( rampColor.alpha() * alpha );
254  }
255  gradient->setColorAt( it->offset, rampColor );
256  }
257 }
258 
259 
261 
262 
264  int satMin, int satMax, int valMin, int valMax )
265  : mCount( count )
266  , mHueMin( hueMin ), mHueMax( hueMax )
267  , mSatMin( satMin ), mSatMax( satMax )
268  , mValMin( valMin ), mValMax( valMax )
269 {
270  updateColors();
271 }
272 
274 {
279 
280  if ( props.contains( "count" ) ) count = props["count"].toInt();
281  if ( props.contains( "hueMin" ) ) hueMin = props["hueMin"].toInt();
282  if ( props.contains( "hueMax" ) ) hueMax = props["hueMax"].toInt();
283  if ( props.contains( "satMin" ) ) satMin = props["satMin"].toInt();
284  if ( props.contains( "satMax" ) ) satMax = props["satMax"].toInt();
285  if ( props.contains( "valMin" ) ) valMin = props["valMin"].toInt();
286  if ( props.contains( "valMax" ) ) valMax = props["valMax"].toInt();
287 
288  return new QgsVectorRandomColorRampV2( count, hueMin, hueMax, satMin, satMax, valMin, valMax );
289 }
290 
292 {
293  if ( mColors.size() < 1 ) return 0;
294  return index / mColors.size() - 1;
295 }
296 
298 {
299  int colorCnt = mColors.count();
300  int colorIdx = ( int )( value * colorCnt );
301 
302  if ( colorIdx >= 0 && colorIdx < colorCnt )
303  return mColors.at( colorIdx );
304 
305  return QColor();
306 }
307 
309 {
311 }
312 
314 {
315  QgsStringMap map;
316  map["count"] = QString::number( mCount );
317  map["hueMin"] = QString::number( mHueMin );
318  map["hueMax"] = QString::number( mHueMax );
319  map["satMin"] = QString::number( mSatMin );
320  map["satMax"] = QString::number( mSatMax );
321  map["valMin"] = QString::number( mValMin );
322  map["valMax"] = QString::number( mValMax );
323  return map;
324 }
325 
327  int hueMax, int hueMin, int satMax, int satMin, int valMax, int valMin )
328 {
329  int h, s, v;
330  QList<QColor> colors;
331 
332  //normalize values
333  int safeHueMax = qMax( hueMin, hueMax );
334  int safeHueMin = qMin( hueMin, hueMax );
335  int safeSatMax = qMax( satMin, satMax );
336  int safeSatMin = qMin( satMin, satMax );
337  int safeValMax = qMax( valMin, valMax );
338  int safeValMin = qMin( valMin, valMax );
339 
340  //start hue at random angle
341  double currentHueAngle = 360.0 * ( double )qrand() / RAND_MAX;
342 
343  for ( int i = 0; i < count; i++ )
344  {
345  //increment hue by golden ratio (approx 137.507 degrees)
346  //as this minimises hue nearness as count increases
347  //see http://basecase.org/env/on-rainbows for more details
348  currentHueAngle += 137.50776;
349  //scale hue to between hueMax and hueMin
350  h = qBound( 0, qRound(( fmod( currentHueAngle, 360.0 ) / 360.0 ) * ( safeHueMax - safeHueMin ) + safeHueMin ), 359 );
351  s = qBound( 0, ( qrand() % ( safeSatMax - safeSatMin + 1 ) ) + safeValMax, 255 );
352  v = qBound( 0, ( qrand() % ( safeValMax - safeValMin + 1 ) ) + safeValMin, 255 );
353  colors.append( QColor::fromHsv( h, s, v ) );
354  }
355  return colors;
356 }
357 
359 {
361 }
362 
364 
366  : mTotalColorCount( 0 )
367 {
368 }
369 
371 {
372 
373 }
374 
376 {
377  return INT_MAX;
378 }
379 
380 double QgsRandomColorsV2::value( int index ) const
381 {
382  Q_UNUSED( index );
383  return 0.0;
384 }
385 
386 QColor QgsRandomColorsV2::color( double value ) const
387 {
388  int minVal = 130;
389  int maxVal = 255;
390 
391  //if value is nan, then use last precalculated color
392  int colorIndex = ( !qIsNaN( value ) ? value : 1 ) * ( mTotalColorCount - 1 );
393  if ( mTotalColorCount >= 1 && mPrecalculatedColors.length() > colorIndex )
394  {
395  //use precalculated hue
396  return mPrecalculatedColors.at( colorIndex );
397  }
398 
399  //can't use precalculated hues, use a totally random hue
400  int h = 1 + ( int )( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
401  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
402  int v = ( qrand() % ( maxVal - minVal + 1 ) ) + minVal;
403  return QColor::fromHsv( h, s, v );
404 }
405 
406 void QgsRandomColorsV2::setTotalColorCount( const int colorCount )
407 {
408  //calculate colors in advance, so that we can ensure they are more visually distinct than pure random colors
410  mTotalColorCount = colorCount;
411 
412  //This works ok for low color counts, but for > 10 or so colors there's still a good chance of
413  //similar colors being picked. TODO - investigate alternative "n-visually distinct color" routines
414 
415  //random offsets
416  double hueOffset = ( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
417 
418  //try to maximise difference between hues. this is not an ideal implementation, as constant steps
419  //through the hue wheel are not visually perceived as constant changes in hue
420  //(for instance, we are much more likely to get green hues than yellow hues)
421  double hueStep = 359.0 / colorCount;
422  double currentHue = hueOffset;
423 
424  //build up a list of colors
425  for ( int idx = 0; idx < colorCount; ++ idx )
426  {
427  int h = qRound( currentHue ) % 360;
428  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
429  int v = ( qrand() % ( DEFAULT_RANDOM_VAL_MAX - DEFAULT_RANDOM_VAL_MIN + 1 ) ) + DEFAULT_RANDOM_VAL_MIN;
431  currentHue += hueStep;
432  }
433 
434  //lastly, shuffle color list
435  std::random_shuffle( mPrecalculatedColors.begin(), mPrecalculatedColors.end() );
436 }
437 
439 {
440  return "randomcolors";
441 }
442 
444 {
445  return new QgsRandomColorsV2();
446 }
447 
449 {
450  return QgsStringMap();
451 }
452 
454 
456  : mSchemeName( schemeName ), mColors( colors )
457 {
458  loadPalette();
459 }
460 
462 {
465 
466  if ( props.contains( "schemeName" ) )
467  schemeName = props["schemeName"];
468  if ( props.contains( "colors" ) )
469  colors = props["colors"].toInt();
470 
471  return new QgsVectorColorBrewerColorRampV2( schemeName, colors );
472 }
473 
475 {
477 }
478 
480 {
482 }
483 
485 {
486  return QgsColorBrewerPalette::listSchemeVariants( schemeName );
487 }
488 
490 {
491  if ( mPalette.size() < 1 ) return 0;
492  return index / mPalette.size() - 1;
493 }
494 
496 {
497  if ( mPalette.isEmpty() || value < 0 || value > 1 )
498  return QColor( 255, 0, 0 ); // red color as a warning :)
499 
500  int paletteEntry = ( int )( value * mPalette.count() );
501  if ( paletteEntry >= mPalette.count() )
502  paletteEntry = mPalette.count() - 1;
503  return mPalette.at( paletteEntry );
504 }
505 
507 {
509 }
510 
512 {
513  QgsStringMap map;
514  map["schemeName"] = mSchemeName;
515  map["colors"] = QString::number( mColors );
516  return map;
517 }
518 
519 
521 
522 
524  bool doLoadFile )
526  , mSchemeName( schemeName ), mVariantName( variantName )
527  , mVariantList( QStringList() ), mFileLoaded( false ), mMultiStops( false )
528 {
529  // TODO replace this with hard-coded data in the default case
530  // don't load file if variant is missing
531  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
532  loadFile();
533 }
534 
536  QString variantName, bool doLoadFile )
538  , mSchemeName( schemeName ), mVariantName( variantName )
539  , mVariantList( variantList ), mFileLoaded( false ), mMultiStops( false )
540 {
542 
543  // TODO replace this with hard-coded data in the default case
544  // don't load file if variant is missing
545  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
546  loadFile();
547 }
548 
550 {
553 
554  if ( props.contains( "schemeName" ) )
555  schemeName = props["schemeName"];
556  if ( props.contains( "variantName" ) )
557  variantName = props["variantName"];
558 
559  return new QgsCptCityColorRampV2( schemeName, variantName );
560 }
561 
563 {
564  QgsCptCityColorRampV2* ramp = new QgsCptCityColorRampV2( "", "", false );
565  ramp->copy( this );
566  return ramp;
567 }
568 
570 {
571  if ( ! other )
572  return;
573  mColor1 = other->color1();
574  mColor2 = other->color2();
575  mDiscrete = other->isDiscrete();
576  mStops = other->stops();
577  mSchemeName = other->mSchemeName;
578  mVariantName = other->mVariantName;
579  mVariantList = other->mVariantList;
580  mFileLoaded = other->mFileLoaded;
581 }
582 
584 {
587  // add author and copyright information
588  // TODO also add COPYING.xml file/link?
590  info["cpt-city-gradient"] = "<cpt-city>/" + mSchemeName + mVariantName + ".svg";
591  QString copyingFilename = copyingFileName();
592  copyingFilename.remove( QgsCptCityArchive::defaultBaseDir() );
593  info["cpt-city-license"] = "<cpt-city>" + copyingFilename;
594  ramp->setInfo( info );
595  return ramp;
596 }
597 
598 
600 {
601  QgsStringMap map;
602  map["schemeName"] = mSchemeName;
603  map["variantName"] = mVariantName;
604  return map;
605 }
606 
607 
609 {
610  if ( mSchemeName == "" )
611  return QString();
612  else
613  {
615  }
616 }
617 
619 {
620  return QgsCptCityArchive::findFileName( "COPYING.xml", QFileInfo( fileName() ).dir().path(),
622 }
623 
625 {
626  return QgsCptCityArchive::findFileName( "DESC.xml", QFileInfo( fileName() ).dir().path(),
628 }
629 
631 {
633 }
634 
636 {
637  if ( mFileLoaded )
638  {
639  QgsDebugMsg( "File already loaded for " + mSchemeName + mVariantName );
640  return true;
641  }
642 
643  // get filename
644  QString filename = fileName();
645  if ( filename.isNull() )
646  {
647  QgsDebugMsg( "Couldn't get fileName() for " + mSchemeName + mVariantName );
648  return false;
649  }
650 
651  QgsDebugMsg( QString( "filename= %1 loaded=%2" ).arg( filename ).arg( mFileLoaded ) );
652 
653  // get color ramp from svg file
656 
657  // add colors to palette
658  mFileLoaded = false;
659  mStops.clear();
660  QMap<double, QPair<QColor, QColor> >::const_iterator it, prev;
661  // first detect if file is gradient is continuous or dicrete
662  // discrete: stop contains 2 colors and first color is identical to previous second
663  // multi: stop contains 2 colors and no relation with previous stop
664  mDiscrete = false;
665  mMultiStops = false;
666  it = prev = colorMap.constBegin();
667  while ( it != colorMap.constEnd() )
668  {
669  // look for stops that contain multiple values
670  if ( it != colorMap.constBegin() && ( it.value().first != it.value().second ) )
671  {
672  if ( it.value().first == prev.value().second )
673  {
674  mDiscrete = true;
675  break;
676  }
677  else
678  {
679  mMultiStops = true;
680  break;
681  }
682  }
683  prev = it;
684  ++it;
685  }
686 
687  // fill all stops
688  it = prev = colorMap.constBegin();
689  while ( it != colorMap.constEnd() )
690  {
691  if ( mDiscrete )
692  {
693  // mPalette << qMakePair( it.key(), it.value().second );
694  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
695  }
696  else
697  {
698  // mPalette << qMakePair( it.key(), it.value().first );
699  mStops.append( QgsGradientStop( it.key(), it.value().first ) );
700  if (( mMultiStops ) &&
701  ( it.key() != 0.0 && it.key() != 1.0 ) )
702  {
703  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
704  }
705  }
706  prev = it;
707  ++it;
708  }
709 
710  // remove first and last items (mColor1 and mColor2)
711  if ( ! mStops.isEmpty() && mStops.first().offset == 0.0 )
712  mColor1 = mStops.takeFirst().color;
713  if ( ! mStops.isEmpty() && mStops.last().offset == 1.0 )
714  mColor2 = mStops.takeLast().color;
715 
716  mFileLoaded = true;
717  return true;
718 }
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual QColor color(double value) const override
void clear()
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
static unsigned index
virtual QgsVectorColorRampV2 * clone() const override
bool contains(const Key &key) const
#define DEFAULT_CPTCITY_VARIANTNAME
QgsVectorGradientColorRampV2(QColor color1=DEFAULT_GRADIENT_COLOR1, QColor color2=DEFAULT_GRADIENT_COLOR2, bool discrete=false, QgsGradientStopsList stops=QgsGradientStopsList())
void copy(const QgsCptCityColorRampV2 *other)
static QList< int > listSchemeVariants(QString schemeName)
int length() const
int count() const override
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setColorAt(qreal position, const QColor &color)
static QString defaultBaseDir()
#define DEFAULT_COLORBREWER_SCHEMENAME
#define DEFAULT_RANDOM_HUE_MIN
const_iterator constBegin() const
const T & at(int i) const
QgsVectorColorRampV2 * clone() const override
void setInfo(const QgsStringMap &info)
static QList< int > listSchemeVariants(QString schemeName)
void setAlpha(int alpha)
virtual void setTotalColorCount(const int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
static QColor decodeColor(QString str)
QString join(const QString &separator) const
QString & remove(int position, int n)
#define DEFAULT_CPTCITY_SCHEMENAME
double toDouble(bool *ok) const
QChar separator()
QMap< QString, QString > QgsStringMap
Definition: qgis.h:441
#define DEFAULT_RANDOM_SAT_MAX
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:350
int size() const
bool isNull() const
static QString encodeColor(QColor color)
QColor fromHsv(int h, int s, int v, int a)
virtual QgsStringMap properties() const override
QColor fromRgb(QRgb rgb)
QString variantName() const
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
QStringList variantList() const
virtual QgsVectorColorRampV2 * clone() const override
#define DEFAULT_GRADIENT_COLOR2
static QList< QColor > listSchemeColors(QString schemeName, int colors)
virtual QgsStringMap properties() const override
QgsVectorRandomColorRampV2(int count=DEFAULT_RANDOM_COUNT, int hueMin=DEFAULT_RANDOM_HUE_MIN, int hueMax=DEFAULT_RANDOM_HUE_MAX, int satMin=DEFAULT_RANDOM_SAT_MIN, int satMax=DEFAULT_RANDOM_SAT_MAX, int valMin=DEFAULT_RANDOM_VAL_MIN, int valMax=DEFAULT_RANDOM_VAL_MAX)
virtual QColor color(double value) const override
int red() const
static QColor _interpolate(const QColor &c1, const QColor &c2, const double value)
bool isEmpty() const
#define DEFAULT_GRADIENT_COLOR1
const_iterator constEnd() const
#define DEFAULT_RANDOM_VAL_MAX
QgsStringMap copyingInfo() const
virtual QgsStringMap properties() const override
static QMap< QString, QString > copyingInfo(const QString &fileName)
static QList< QColor > randomColors(int count, int hueMax=DEFAULT_RANDOM_HUE_MAX, int hueMin=DEFAULT_RANDOM_HUE_MIN, int satMax=DEFAULT_RANDOM_SAT_MAX, int satMin=DEFAULT_RANDOM_SAT_MIN, int valMax=DEFAULT_RANDOM_VAL_MAX, int valMin=DEFAULT_RANDOM_VAL_MIN)
Get a list of random colors.
T & first()
virtual QgsStringMap properties() const override
QString type() const override
int alpha() const
int green() const
iterator end()
#define DEFAULT_RANDOM_SAT_MIN
virtual double value(int index) const override
virtual QgsVectorColorRampV2 * clone() const override
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
QgsStringMap properties() const override
virtual QColor color(double value) const override
const Key key(const T &value) const
QgsVectorGradientColorRampV2 * cloneGradientRamp() const
int blue() const
int ANALYSIS_EXPORT lower(int n, int i)
Lower function.
T takeLast()
QString mid(int position, int n) const
virtual double value(int index) const override
T takeFirst()
#define DEFAULT_COLORBREWER_COLORS
static QStringList listSchemes()
const QgsGradientStopsList & stops() const
QColor color(double value) const override
T & last()
double value(int index) const override
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
QList< QColor > mPrecalculatedColors
#define DEFAULT_RANDOM_HUE_MAX
QString left(int n) const
QgsCptCityColorRampV2(QString schemeName=DEFAULT_CPTCITY_SCHEMENAME, QString variantName=DEFAULT_CPTCITY_VARIANTNAME, bool doLoadFile=true)
virtual QgsVectorColorRampV2 * clone() const override
virtual double value(int index) const override
static QMap< double, QPair< QColor, QColor > > gradientColorMap(const QString &fileName)
note not available in python bindings
QgsVectorColorBrewerColorRampV2(QString schemeName=DEFAULT_COLORBREWER_SCHEMENAME, int colors=DEFAULT_COLORBREWER_COLORS)
#define DEFAULT_RANDOM_VAL_MIN
void addStopsToGradient(QGradient *gradient, double alpha=1)
Copy color ramp stops to a QGradient.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
iterator begin()
QString copyingFileName() const
#define DEFAULT_RANDOM_COUNT
static QString findFileName(const QString &target, const QString &startDir, const QString &baseDir)
const T value(const Key &key) const