QGIS API Documentation
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 
35  qreal r = ( c1.redF() + value * ( c2.redF() - c1.redF() ) );
36  qreal g = ( c1.greenF() + value * ( c2.greenF() - c1.greenF() ) );
37  qreal b = ( c1.blueF() + value * ( c2.blueF() - c1.blueF() ) );
38  qreal a = ( c1.alphaF() + value * ( c2.alphaF() - c1.alphaF() ) );
39 
40  return QColor::fromRgbF( r, g, b, a );
41 }
42 
44 
46  bool discrete, const QgsGradientStopsList& stops )
47  : mColor1( color1 )
48  , mColor2( color2 )
49  , mDiscrete( discrete )
50  , mStops( stops )
51 {
52 }
53 
55 {
56  // color1 and color2
59  if ( props.contains( "color1" ) )
60  color1 = QgsSymbolLayerV2Utils::decodeColor( props["color1"] );
61  if ( props.contains( "color2" ) )
62  color2 = QgsSymbolLayerV2Utils::decodeColor( props["color2"] );
63 
64  //stops
66  if ( props.contains( "stops" ) )
67  {
68  Q_FOREACH ( const QString& stop, props["stops"].split( ':' ) )
69  {
70  int i = stop.indexOf( ';' );
71  if ( i == -1 )
72  continue;
73 
74  QColor c = QgsSymbolLayerV2Utils::decodeColor( stop.mid( i + 1 ) );
75  stops.append( QgsGradientStop( stop.left( i ).toDouble(), c ) );
76  }
77  }
78 
79  // discrete vs. continuous
80  bool discrete = false;
81  if ( props.contains( "discrete" ) )
82  {
83  if ( props["discrete"] == "1" )
84  discrete = true;
85  }
86 
87  // search for information keys starting with "info_"
89  for ( QgsStringMap::const_iterator it = props.constBegin();
90  it != props.constEnd(); ++it )
91  {
92  if ( it.key().startsWith( "info_" ) )
93  info[ it.key().mid( 5 )] = it.value();
94  }
95 
96  QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( color1, color2, discrete, stops );
97  r->setInfo( info );
98  return r;
99 }
100 
102 {
103  if ( index <= 0 )
104  {
105  return 0;
106  }
107  else if ( index >= mStops.size() + 1 )
108  {
109  return 1;
110  }
111  else
112  {
113  return mStops[index-1].offset;
114  }
115 }
116 
118 {
119  if ( qgsDoubleNear( value, 0.0 ) || value < 0.0 )
120  {
121  return mColor1;
122  }
123  else if ( qgsDoubleNear( value, 1.0 ) || value > 1.0 )
124  {
125  return mColor2;
126  }
127  else if ( mStops.isEmpty() )
128  {
129  if ( mDiscrete )
130  return mColor1;
131 
132  return _interpolate( mColor1, mColor2, value );
133  }
134  else
135  {
136  double lower = 0, upper = 0;
137  QColor c1 = mColor1, c2;
138  for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
139  {
140  if ( it->offset > value )
141  {
142  if ( mDiscrete )
143  return c1;
144 
145  upper = it->offset;
146  c2 = it->color;
147 
148  return qgsDoubleNear( upper, lower ) ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
149  }
150  lower = it->offset;
151  c1 = it->color;
152  }
153 
154  if ( mDiscrete )
155  return c1;
156 
157  upper = 1;
158  c2 = mColor2;
159  return qgsDoubleNear( upper, lower ) ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
160  }
161 }
162 
164 {
166  mDiscrete, mStops );
167  r->setInfo( mInfo );
168  return r;
169 }
170 
172 {
173  QgsStringMap map;
174  map["color1"] = QgsSymbolLayerV2Utils::encodeColor( mColor1 );
175  map["color2"] = QgsSymbolLayerV2Utils::encodeColor( mColor2 );
176  if ( !mStops.isEmpty() )
177  {
178  QStringList lst;
179  for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
180  {
181  lst.append( QString( "%1;%2" ).arg( it->offset ).arg( QgsSymbolLayerV2Utils::encodeColor( it->color ) ) );
182  }
183  map["stops"] = lst.join( ":" );
184  }
185 
186  map["discrete"] = mDiscrete ? "1" : "0";
187 
189  it != mInfo.constEnd(); ++it )
190  {
191  map["info_" + it.key()] = it.value();
192  }
193 
194  return map;
195 }
197 {
198  if ( discrete == mDiscrete )
199  return;
200 
201  // if going to/from Discrete, re-arrange stops
202  // this will only work when stops are equally-spaced
203  QgsGradientStopsList newStops;
204  if ( discrete )
205  {
206  // re-arrange stops offset
207  int numStops = mStops.count() + 2;
208  int i = 1;
209  for ( QgsGradientStopsList::const_iterator it = mStops.constBegin();
210  it != mStops.constEnd(); ++it )
211  {
212  newStops.append( QgsGradientStop( static_cast< double >( i ) / numStops, it->color ) );
213  if ( i == numStops - 1 )
214  break;
215  i++;
216  }
217  // replicate last color
218  newStops.append( QgsGradientStop( static_cast< double >( i ) / numStops, mColor2 ) );
219  }
220  else
221  {
222  // re-arrange stops offset, remove duplicate last color
223  int numStops = mStops.count() + 2;
224  int i = 1;
225  for ( QgsGradientStopsList::const_iterator it = mStops.constBegin();
226  it != mStops.constEnd(); ++it )
227  {
228  newStops.append( QgsGradientStop( static_cast< double >( i ) / ( numStops - 2 ), it->color ) );
229  if ( i == numStops - 3 )
230  break;
231  i++;
232  }
233  }
234  mStops = newStops;
235  mDiscrete = discrete;
236 }
237 
239 {
240  //copy color ramp stops to a QGradient
243  if ( alpha < 1 )
244  {
245  color1.setAlpha( color1.alpha() * alpha );
246  color2.setAlpha( color2.alpha() * alpha );
247  }
248  gradient->setColorAt( 0, color1 );
249  gradient->setColorAt( 1, color2 );
250 
251  for ( QgsGradientStopsList::const_iterator it = mStops.constBegin();
252  it != mStops.constEnd(); ++it )
253  {
254  QColor rampColor = it->color;
255  if ( alpha < 1 )
256  {
257  rampColor.setAlpha( rampColor.alpha() * alpha );
258  }
259  gradient->setColorAt( it->offset, rampColor );
260  }
261 }
262 
263 
265 
266 
268  int satMin, int satMax, int valMin, int valMax )
269  : mCount( count )
270  , mHueMin( hueMin ), mHueMax( hueMax )
271  , mSatMin( satMin ), mSatMax( satMax )
272  , mValMin( valMin ), mValMax( valMax )
273 {
274  updateColors();
275 }
276 
278 {
283 
284  if ( props.contains( "count" ) ) count = props["count"].toInt();
285  if ( props.contains( "hueMin" ) ) hueMin = props["hueMin"].toInt();
286  if ( props.contains( "hueMax" ) ) hueMax = props["hueMax"].toInt();
287  if ( props.contains( "satMin" ) ) satMin = props["satMin"].toInt();
288  if ( props.contains( "satMax" ) ) satMax = props["satMax"].toInt();
289  if ( props.contains( "valMin" ) ) valMin = props["valMin"].toInt();
290  if ( props.contains( "valMax" ) ) valMax = props["valMax"].toInt();
291 
292  return new QgsVectorRandomColorRampV2( count, hueMin, hueMax, satMin, satMax, valMin, valMax );
293 }
294 
296 {
297  if ( mColors.size() < 1 ) return 0;
298  return static_cast< double >( index ) / ( mColors.size() - 1 );
299 }
300 
302 {
303  int colorCnt = mColors.count();
304  int colorIdx = static_cast< int >( value * ( colorCnt - 1 ) );
305 
306  if ( colorIdx >= 0 && colorIdx < colorCnt )
307  return mColors.at( colorIdx );
308 
309  return QColor();
310 }
311 
313 {
315 }
316 
318 {
319  QgsStringMap map;
320  map["count"] = QString::number( mCount );
321  map["hueMin"] = QString::number( mHueMin );
322  map["hueMax"] = QString::number( mHueMax );
323  map["satMin"] = QString::number( mSatMin );
324  map["satMax"] = QString::number( mSatMax );
325  map["valMin"] = QString::number( mValMin );
326  map["valMax"] = QString::number( mValMax );
327  return map;
328 }
329 
331  int hueMax, int hueMin, int satMax, int satMin, int valMax, int valMin )
332 {
333  int h, s, v;
334  QList<QColor> colors;
335 
336  //normalize values
337  int safeHueMax = qMax( hueMin, hueMax );
338  int safeHueMin = qMin( hueMin, hueMax );
339  int safeSatMax = qMax( satMin, satMax );
340  int safeSatMin = qMin( satMin, satMax );
341  int safeValMax = qMax( valMin, valMax );
342  int safeValMin = qMin( valMin, valMax );
343 
344  //start hue at random angle
345  double currentHueAngle = 360.0 * static_cast< double >( qrand() ) / RAND_MAX;
346 
347  colors.reserve( count );
348  for ( int i = 0; i < count; ++i )
349  {
350  //increment hue by golden ratio (approx 137.507 degrees)
351  //as this minimises hue nearness as count increases
352  //see http://basecase.org/env/on-rainbows for more details
353  currentHueAngle += 137.50776;
354  //scale hue to between hueMax and hueMin
355  h = qBound( 0, qRound(( fmod( currentHueAngle, 360.0 ) / 360.0 ) * ( safeHueMax - safeHueMin ) + safeHueMin ), 359 );
356  s = qBound( 0, ( qrand() % ( safeSatMax - safeSatMin + 1 ) ) + safeSatMin, 255 );
357  v = qBound( 0, ( qrand() % ( safeValMax - safeValMin + 1 ) ) + safeValMin, 255 );
358  colors.append( QColor::fromHsv( h, s, v ) );
359  }
360  return colors;
361 }
362 
364 {
366 }
367 
369 
371  : mTotalColorCount( 0 )
372 {
373 }
374 
376 {
377 
378 }
379 
381 {
382  return -1;
383 }
384 
385 double QgsRandomColorsV2::value( int index ) const
386 {
387  Q_UNUSED( index );
388  return 0.0;
389 }
390 
392 {
393  int minVal = 130;
394  int maxVal = 255;
395 
396  //if value is nan, then use last precalculated color
397  int colorIndex = ( !qIsNaN( value ) ? value : 1 ) * ( mTotalColorCount - 1 );
398  if ( mTotalColorCount >= 1 && mPrecalculatedColors.length() > colorIndex )
399  {
400  //use precalculated hue
401  return mPrecalculatedColors.at( colorIndex );
402  }
403 
404  //can't use precalculated hues, use a totally random hue
405  int h = static_cast< int >( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
406  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
407  int v = ( qrand() % ( maxVal - minVal + 1 ) ) + minVal;
408  return QColor::fromHsv( h, s, v );
409 }
410 
411 void QgsRandomColorsV2::setTotalColorCount( const int colorCount )
412 {
413  //calculate colors in advance, so that we can ensure they are more visually distinct than pure random colors
415  mTotalColorCount = colorCount;
416 
417  //This works ok for low color counts, but for > 10 or so colors there's still a good chance of
418  //similar colors being picked. TODO - investigate alternative "n-visually distinct color" routines
419 
420  //random offsets
421  double hueOffset = ( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
422 
423  //try to maximise difference between hues. this is not an ideal implementation, as constant steps
424  //through the hue wheel are not visually perceived as constant changes in hue
425  //(for instance, we are much more likely to get green hues than yellow hues)
426  double hueStep = 359.0 / colorCount;
427  double currentHue = hueOffset;
428 
429  //build up a list of colors
430  for ( int idx = 0; idx < colorCount; ++ idx )
431  {
432  int h = qRound( currentHue ) % 360;
433  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
434  int v = ( qrand() % ( DEFAULT_RANDOM_VAL_MAX - DEFAULT_RANDOM_VAL_MIN + 1 ) ) + DEFAULT_RANDOM_VAL_MIN;
436  currentHue += hueStep;
437  }
438 
439  //lastly, shuffle color list
440  std::random_shuffle( mPrecalculatedColors.begin(), mPrecalculatedColors.end() );
441 }
442 
444 {
445  return "randomcolors";
446 }
447 
449 {
450  return new QgsRandomColorsV2();
451 }
452 
454 {
455  return QgsStringMap();
456 }
457 
459 
461  : mSchemeName( schemeName )
462  , mColors( colors )
463 {
464  loadPalette();
465 }
466 
468 {
471 
472  if ( props.contains( "schemeName" ) )
473  schemeName = props["schemeName"];
474  if ( props.contains( "colors" ) )
475  colors = props["colors"].toInt();
476 
477  return new QgsVectorColorBrewerColorRampV2( schemeName, colors );
478 }
479 
481 {
483 }
484 
486 {
488 }
489 
491 {
492  return QgsColorBrewerPalette::listSchemeVariants( schemeName );
493 }
494 
496 {
497  if ( mPalette.size() < 1 ) return 0;
498  return static_cast< double >( index ) / ( mPalette.size() - 1 );
499 }
500 
502 {
503  if ( mPalette.isEmpty() || value < 0 || value > 1 )
504  return QColor();
505 
506  int paletteEntry = static_cast< int >( value * mPalette.count() );
507  if ( paletteEntry >= mPalette.count() )
508  paletteEntry = mPalette.count() - 1;
509  return mPalette.at( paletteEntry );
510 }
511 
513 {
515 }
516 
518 {
519  QgsStringMap map;
520  map["schemeName"] = mSchemeName;
521  map["colors"] = QString::number( mColors );
522  return map;
523 }
524 
525 
527 
528 
530  bool doLoadFile )
532  , mSchemeName( schemeName ), mVariantName( variantName )
533  , mVariantList( QStringList() ), mFileLoaded( false ), mMultiStops( false )
534 {
535  // TODO replace this with hard-coded data in the default case
536  // don't load file if variant is missing
537  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
538  loadFile();
539 }
540 
542  const QString& variantName, bool doLoadFile )
544  , mSchemeName( schemeName ), mVariantName( variantName )
545  , mVariantList( variantList ), mFileLoaded( false ), mMultiStops( false )
546 {
548 
549  // TODO replace this with hard-coded data in the default case
550  // don't load file if variant is missing
551  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
552  loadFile();
553 }
554 
556 {
559 
560  if ( props.contains( "schemeName" ) )
561  schemeName = props["schemeName"];
562  if ( props.contains( "variantName" ) )
563  variantName = props["variantName"];
564 
565  return new QgsCptCityColorRampV2( schemeName, variantName );
566 }
567 
569 {
570  QgsCptCityColorRampV2* ramp = new QgsCptCityColorRampV2( "", "", false );
571  ramp->copy( this );
572  return ramp;
573 }
574 
576 {
577  if ( ! other )
578  return;
579  mColor1 = other->color1();
580  mColor2 = other->color2();
581  mDiscrete = other->isDiscrete();
582  mStops = other->stops();
583  mSchemeName = other->mSchemeName;
584  mVariantName = other->mVariantName;
585  mVariantList = other->mVariantList;
586  mFileLoaded = other->mFileLoaded;
587 }
588 
590 {
593  // add author and copyright information
594  // TODO also add COPYING.xml file/link?
596  info["cpt-city-gradient"] = "<cpt-city>/" + mSchemeName + mVariantName + ".svg";
597  QString copyingFilename = copyingFileName();
598  copyingFilename.remove( QgsCptCityArchive::defaultBaseDir() );
599  info["cpt-city-license"] = "<cpt-city>" + copyingFilename;
600  ramp->setInfo( info );
601  return ramp;
602 }
603 
604 
606 {
607  QgsStringMap map;
608  map["schemeName"] = mSchemeName;
609  map["variantName"] = mVariantName;
610  return map;
611 }
612 
613 
615 {
616  if ( mSchemeName == "" )
617  return QString();
618  else
619  {
621  }
622 }
623 
625 {
626  return QgsCptCityArchive::findFileName( "COPYING.xml", QFileInfo( fileName() ).dir().path(),
628 }
629 
631 {
632  return QgsCptCityArchive::findFileName( "DESC.xml", QFileInfo( fileName() ).dir().path(),
634 }
635 
637 {
639 }
640 
642 {
643  if ( mFileLoaded )
644  {
645  QgsDebugMsg( "File already loaded for " + mSchemeName + mVariantName );
646  return true;
647  }
648 
649  // get filename
650  QString filename = fileName();
651  if ( filename.isNull() )
652  {
653  QgsDebugMsg( "Couldn't get fileName() for " + mSchemeName + mVariantName );
654  return false;
655  }
656 
657  QgsDebugMsg( QString( "filename= %1 loaded=%2" ).arg( filename ).arg( mFileLoaded ) );
658 
659  // get color ramp from svg file
662 
663  // add colors to palette
664  mFileLoaded = false;
665  mStops.clear();
666  QMap<double, QPair<QColor, QColor> >::const_iterator it, prev;
667  // first detect if file is gradient is continuous or dicrete
668  // discrete: stop contains 2 colors and first color is identical to previous second
669  // multi: stop contains 2 colors and no relation with previous stop
670  mDiscrete = false;
671  mMultiStops = false;
672  it = prev = colorMap.constBegin();
673  while ( it != colorMap.constEnd() )
674  {
675  // look for stops that contain multiple values
676  if ( it != colorMap.constBegin() && ( it.value().first != it.value().second ) )
677  {
678  if ( it.value().first == prev.value().second )
679  {
680  mDiscrete = true;
681  break;
682  }
683  else
684  {
685  mMultiStops = true;
686  break;
687  }
688  }
689  prev = it;
690  ++it;
691  }
692 
693  // fill all stops
694  it = prev = colorMap.constBegin();
695  while ( it != colorMap.constEnd() )
696  {
697  if ( mDiscrete )
698  {
699  // mPalette << qMakePair( it.key(), it.value().second );
700  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
701  }
702  else
703  {
704  // mPalette << qMakePair( it.key(), it.value().first );
705  mStops.append( QgsGradientStop( it.key(), it.value().first ) );
706  if (( mMultiStops ) &&
707  ( it.key() != 0.0 && it.key() != 1.0 ) )
708  {
709  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
710  }
711  }
712  prev = it;
713  ++it;
714  }
715 
716  // remove first and last items (mColor1 and mColor2)
717  if ( ! mStops.isEmpty() && mStops.at( 0 ).offset == 0.0 )
718  mColor1 = mStops.takeFirst().color;
719  if ( ! mStops.isEmpty() && mStops.last().offset == 1.0 )
720  mColor2 = mStops.takeLast().color;
721 
722  mFileLoaded = true;
723  return true;
724 }
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual QColor color(double value) const override
Returns the color corresponding to a specified value.
void clear()
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
static unsigned index
int count() const override
Returns number of defined colors, or -1 if undefined.
QgsRandomColorsV2 * clone() const override
Creates a clone of the color ramp.
bool contains(const Key &key) const
#define DEFAULT_CPTCITY_VARIANTNAME
virtual QgsVectorRandomColorRampV2 * clone() const override
Creates a clone of the color ramp.
Represents a color stop within a gradient color ramp.
qreal alphaF() const
qreal redF() const
void copy(const QgsCptCityColorRampV2 *other)
int length() const
int count() const override
Returns number of defined colors, or -1 if undefined.
virtual QgsVectorColorBrewerColorRampV2 * clone() const override
Creates a clone of the color ramp.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setColorAt(qreal position, const QColor &color)
void reserve(int alloc)
static QString defaultBaseDir()
static QString encodeColor(const QColor &color)
#define DEFAULT_COLORBREWER_SCHEMENAME
#define DEFAULT_RANDOM_HUE_MIN
qreal blueF() const
const_iterator constBegin() const
const T & at(int i) const
void setInfo(const QgsStringMap &info)
Sets additional info to attach to the gradient ramp (eg authorship notes)
virtual QgsVectorGradientColorRampV2 * clone() const override
Creates a clone of the color ramp.
virtual QgsCptCityColorRampV2 * clone() const override
Creates a clone of the color ramp.
void setAlpha(int alpha)
virtual void setTotalColorCount(const int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
QString join(const QString &separator) const
QString & remove(int position, int n)
#define DEFAULT_CPTCITY_SCHEMENAME
double toDouble(bool *ok) const
static QList< QColor > listSchemeColors(const QString &schemeName, int colors)
QChar separator()
QMap< QString, QString > QgsStringMap
Definition: qgis.h:451
#define DEFAULT_RANDOM_SAT_MAX
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:348
int size() const
QgsStringMap info() const
Returns any additional info attached to the gradient ramp (eg authorship notes)
bool isNull() const
QgsCptCityColorRampV2(const QString &schemeName=DEFAULT_CPTCITY_SCHEMENAME, const QString &variantName=DEFAULT_CPTCITY_VARIANTNAME, bool doLoadFile=true)
QColor fromHsv(int h, int s, int v, int a)
static QList< int > listSchemeVariants(const QString &schemeName)
virtual QgsStringMap properties() const override
Returns a string map containing all the color ramp&#39;s properties.
virtual int count() const override
Returns number of defined colors, or -1 if undefined.
QString variantName() const
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
QStringList variantList() const
#define DEFAULT_GRADIENT_COLOR2
virtual QgsStringMap properties() const override
Returns a string map containing all the color ramp&#39;s properties.
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
Returns the color corresponding to a specified value.
static QColor _interpolate(const QColor &c1, const QColor &c2, const double value)
bool isEmpty() const
#define DEFAULT_GRADIENT_COLOR1
const_iterator constEnd() const
qreal greenF() const
#define DEFAULT_RANDOM_VAL_MAX
QgsStringMap copyingInfo() const
virtual QgsStringMap properties() const override
Returns a string map containing all the color ramp&#39;s properties.
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.
QgsVectorGradientColorRampV2(const QColor &color1=DEFAULT_GRADIENT_COLOR1, const QColor &color2=DEFAULT_GRADIENT_COLOR2, bool discrete=false, const QgsGradientStopsList &stops=QgsGradientStopsList())
Constructor for QgsVectorGradientColorRampV2.
virtual QgsStringMap properties() const override
Returns a string map containing all the color ramp&#39;s properties.
QString type() const override
Returns a string representing the color ramp type.
void convertToDiscrete(bool discrete)
Converts a gradient with existing color stops to or from discrete interpolation.
int alpha() const
iterator end()
QColor fromRgbF(qreal r, qreal g, qreal b, qreal a)
#define DEFAULT_RANDOM_SAT_MIN
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
virtual double value(int index) const override
Returns relative value between [0,1] of color at specified index.
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsVectorColorRampV2 from a map of properties.
QgsStringMap properties() const override
Returns a string map containing all the color ramp&#39;s properties.
virtual QColor color(double value) const override
Returns the color corresponding to a specified value.
const Key key(const T &value) const
QgsVectorGradientColorRampV2 * cloneGradientRamp() const
Random color ramp, which returns random colors based on preset parameters.
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
Returns relative value between [0,1] of color at specified index.
T takeFirst()
#define DEFAULT_COLORBREWER_COLORS
static QStringList listSchemes()
QColor color(double value) const override
Returns the color corresponding to a specified value.
T & last()
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
double value(int index) const override
Returns relative value between [0,1] of color at specified index.
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
QList< QColor > mPrecalculatedColors
#define DEFAULT_RANDOM_HUE_MAX
QString left(int n) const
QgsVectorColorBrewerColorRampV2(const QString &schemeName=DEFAULT_COLORBREWER_SCHEMENAME, int colors=DEFAULT_COLORBREWER_COLORS)
static QColor decodeColor(const QString &str)
static QList< int > listSchemeVariants(const QString &schemeName)
virtual double value(int index) const override
Returns relative value between [0,1] of color at specified index.
static QMap< double, QPair< QColor, QColor > > gradientColorMap(const QString &fileName)
const_iterator constEnd() const
const_iterator constBegin() const
#define DEFAULT_RANDOM_VAL_MIN
void addStopsToGradient(QGradient *gradient, double alpha=1)
Copy color ramp stops to a QGradient.
Abstract base class for color ramps.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QColor color2() const
Returns the gradient end color.
QColor color1() const
Returns the gradient start color.
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