QGIS API Documentation  2.15.0-Master (972fc9f)
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 
238 bool stopLessThan( const QgsGradientStop &s1, const QgsGradientStop &s2 )
239 {
240  return s1.offset < s2.offset;
241 }
242 
244 {
245  mStops = stops;
246 
247  //sort stops by offset
248  qSort( mStops.begin(), mStops.end(), stopLessThan );
249 }
250 
252 {
253  //copy color ramp stops to a QGradient
256  if ( alpha < 1 )
257  {
258  color1.setAlpha( color1.alpha() * alpha );
259  color2.setAlpha( color2.alpha() * alpha );
260  }
261  gradient->setColorAt( 0, color1 );
262  gradient->setColorAt( 1, color2 );
263 
264  for ( QgsGradientStopsList::const_iterator it = mStops.constBegin();
265  it != mStops.constEnd(); ++it )
266  {
267  QColor rampColor = it->color;
268  if ( alpha < 1 )
269  {
270  rampColor.setAlpha( rampColor.alpha() * alpha );
271  }
272  gradient->setColorAt( it->offset, rampColor );
273  }
274 }
275 
276 
278 
279 
281  int satMin, int satMax, int valMin, int valMax )
282  : mCount( count )
283  , mHueMin( hueMin ), mHueMax( hueMax )
284  , mSatMin( satMin ), mSatMax( satMax )
285  , mValMin( valMin ), mValMax( valMax )
286 {
287  updateColors();
288 }
289 
291 {
296 
297  if ( props.contains( "count" ) ) count = props["count"].toInt();
298  if ( props.contains( "hueMin" ) ) hueMin = props["hueMin"].toInt();
299  if ( props.contains( "hueMax" ) ) hueMax = props["hueMax"].toInt();
300  if ( props.contains( "satMin" ) ) satMin = props["satMin"].toInt();
301  if ( props.contains( "satMax" ) ) satMax = props["satMax"].toInt();
302  if ( props.contains( "valMin" ) ) valMin = props["valMin"].toInt();
303  if ( props.contains( "valMax" ) ) valMax = props["valMax"].toInt();
304 
305  return new QgsVectorRandomColorRampV2( count, hueMin, hueMax, satMin, satMax, valMin, valMax );
306 }
307 
309 {
310  if ( mColors.size() < 1 ) return 0;
311  return static_cast< double >( index ) / ( mColors.size() - 1 );
312 }
313 
315 {
316  int colorCnt = mColors.count();
317  int colorIdx = static_cast< int >( value * ( colorCnt - 1 ) );
318 
319  if ( colorIdx >= 0 && colorIdx < colorCnt )
320  return mColors.at( colorIdx );
321 
322  return QColor();
323 }
324 
326 {
328 }
329 
331 {
332  QgsStringMap map;
333  map["count"] = QString::number( mCount );
334  map["hueMin"] = QString::number( mHueMin );
335  map["hueMax"] = QString::number( mHueMax );
336  map["satMin"] = QString::number( mSatMin );
337  map["satMax"] = QString::number( mSatMax );
338  map["valMin"] = QString::number( mValMin );
339  map["valMax"] = QString::number( mValMax );
340  return map;
341 }
342 
344  int hueMax, int hueMin, int satMax, int satMin, int valMax, int valMin )
345 {
346  int h, s, v;
347  QList<QColor> colors;
348 
349  //normalize values
350  int safeHueMax = qMax( hueMin, hueMax );
351  int safeHueMin = qMin( hueMin, hueMax );
352  int safeSatMax = qMax( satMin, satMax );
353  int safeSatMin = qMin( satMin, satMax );
354  int safeValMax = qMax( valMin, valMax );
355  int safeValMin = qMin( valMin, valMax );
356 
357  //start hue at random angle
358  double currentHueAngle = 360.0 * static_cast< double >( qrand() ) / RAND_MAX;
359 
360  colors.reserve( count );
361  for ( int i = 0; i < count; ++i )
362  {
363  //increment hue by golden ratio (approx 137.507 degrees)
364  //as this minimises hue nearness as count increases
365  //see http://basecase.org/env/on-rainbows for more details
366  currentHueAngle += 137.50776;
367  //scale hue to between hueMax and hueMin
368  h = qBound( 0, qRound(( fmod( currentHueAngle, 360.0 ) / 360.0 ) * ( safeHueMax - safeHueMin ) + safeHueMin ), 359 );
369  s = qBound( 0, ( qrand() % ( safeSatMax - safeSatMin + 1 ) ) + safeSatMin, 255 );
370  v = qBound( 0, ( qrand() % ( safeValMax - safeValMin + 1 ) ) + safeValMin, 255 );
371  colors.append( QColor::fromHsv( h, s, v ) );
372  }
373  return colors;
374 }
375 
377 {
379 }
380 
382 
384  : mTotalColorCount( 0 )
385 {
386 }
387 
389 {
390 
391 }
392 
394 {
395  return -1;
396 }
397 
398 double QgsRandomColorsV2::value( int index ) const
399 {
400  Q_UNUSED( index );
401  return 0.0;
402 }
403 
405 {
406  int minVal = 130;
407  int maxVal = 255;
408 
409  //if value is nan, then use last precalculated color
410  int colorIndex = ( !qIsNaN( value ) ? value : 1 ) * ( mTotalColorCount - 1 );
411  if ( mTotalColorCount >= 1 && mPrecalculatedColors.length() > colorIndex )
412  {
413  //use precalculated hue
414  return mPrecalculatedColors.at( colorIndex );
415  }
416 
417  //can't use precalculated hues, use a totally random hue
418  int h = static_cast< int >( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
419  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
420  int v = ( qrand() % ( maxVal - minVal + 1 ) ) + minVal;
421  return QColor::fromHsv( h, s, v );
422 }
423 
424 void QgsRandomColorsV2::setTotalColorCount( const int colorCount )
425 {
426  //calculate colors in advance, so that we can ensure they are more visually distinct than pure random colors
428  mTotalColorCount = colorCount;
429 
430  //This works ok for low color counts, but for > 10 or so colors there's still a good chance of
431  //similar colors being picked. TODO - investigate alternative "n-visually distinct color" routines
432 
433  //random offsets
434  double hueOffset = ( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
435 
436  //try to maximise difference between hues. this is not an ideal implementation, as constant steps
437  //through the hue wheel are not visually perceived as constant changes in hue
438  //(for instance, we are much more likely to get green hues than yellow hues)
439  double hueStep = 359.0 / colorCount;
440  double currentHue = hueOffset;
441 
442  //build up a list of colors
443  for ( int idx = 0; idx < colorCount; ++ idx )
444  {
445  int h = qRound( currentHue ) % 360;
446  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
447  int v = ( qrand() % ( DEFAULT_RANDOM_VAL_MAX - DEFAULT_RANDOM_VAL_MIN + 1 ) ) + DEFAULT_RANDOM_VAL_MIN;
449  currentHue += hueStep;
450  }
451 
452  //lastly, shuffle color list
453  std::random_shuffle( mPrecalculatedColors.begin(), mPrecalculatedColors.end() );
454 }
455 
457 {
458  return "randomcolors";
459 }
460 
462 {
463  return new QgsRandomColorsV2();
464 }
465 
467 {
468  return QgsStringMap();
469 }
470 
472 
474  : mSchemeName( schemeName )
475  , mColors( colors )
476 {
477  loadPalette();
478 }
479 
481 {
484 
485  if ( props.contains( "schemeName" ) )
486  schemeName = props["schemeName"];
487  if ( props.contains( "colors" ) )
488  colors = props["colors"].toInt();
489 
490  return new QgsVectorColorBrewerColorRampV2( schemeName, colors );
491 }
492 
494 {
496 }
497 
499 {
501 }
502 
504 {
505  return QgsColorBrewerPalette::listSchemeVariants( schemeName );
506 }
507 
509 {
510  if ( mPalette.size() < 1 ) return 0;
511  return static_cast< double >( index ) / ( mPalette.size() - 1 );
512 }
513 
515 {
516  if ( mPalette.isEmpty() || value < 0 || value > 1 )
517  return QColor();
518 
519  int paletteEntry = static_cast< int >( value * mPalette.count() );
520  if ( paletteEntry >= mPalette.count() )
521  paletteEntry = mPalette.count() - 1;
522  return mPalette.at( paletteEntry );
523 }
524 
526 {
528 }
529 
531 {
532  QgsStringMap map;
533  map["schemeName"] = mSchemeName;
534  map["colors"] = QString::number( mColors );
535  return map;
536 }
537 
538 
540 
541 
543  bool doLoadFile )
545  , mSchemeName( schemeName ), mVariantName( variantName )
546  , mVariantList( QStringList() ), mFileLoaded( false ), mMultiStops( false )
547 {
548  // TODO replace this with hard-coded data in the default case
549  // don't load file if variant is missing
550  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
551  loadFile();
552 }
553 
555  const QString& variantName, bool doLoadFile )
557  , mSchemeName( schemeName ), mVariantName( variantName )
558  , mVariantList( variantList ), mFileLoaded( false ), mMultiStops( false )
559 {
561 
562  // TODO replace this with hard-coded data in the default case
563  // don't load file if variant is missing
564  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
565  loadFile();
566 }
567 
569 {
572 
573  if ( props.contains( "schemeName" ) )
574  schemeName = props["schemeName"];
575  if ( props.contains( "variantName" ) )
576  variantName = props["variantName"];
577 
578  return new QgsCptCityColorRampV2( schemeName, variantName );
579 }
580 
582 {
583  QgsCptCityColorRampV2* ramp = new QgsCptCityColorRampV2( "", "", false );
584  ramp->copy( this );
585  return ramp;
586 }
587 
589 {
590  if ( ! other )
591  return;
592  mColor1 = other->color1();
593  mColor2 = other->color2();
594  mDiscrete = other->isDiscrete();
595  mStops = other->stops();
596  mSchemeName = other->mSchemeName;
597  mVariantName = other->mVariantName;
598  mVariantList = other->mVariantList;
599  mFileLoaded = other->mFileLoaded;
600 }
601 
603 {
606  // add author and copyright information
607  // TODO also add COPYING.xml file/link?
609  info["cpt-city-gradient"] = "<cpt-city>/" + mSchemeName + mVariantName + ".svg";
610  QString copyingFilename = copyingFileName();
611  copyingFilename.remove( QgsCptCityArchive::defaultBaseDir() );
612  info["cpt-city-license"] = "<cpt-city>" + copyingFilename;
613  ramp->setInfo( info );
614  return ramp;
615 }
616 
617 
619 {
620  QgsStringMap map;
621  map["schemeName"] = mSchemeName;
622  map["variantName"] = mVariantName;
623  return map;
624 }
625 
626 
628 {
629  if ( mSchemeName == "" )
630  return QString();
631  else
632  {
634  }
635 }
636 
638 {
639  return QgsCptCityArchive::findFileName( "COPYING.xml", QFileInfo( fileName() ).dir().path(),
641 }
642 
644 {
645  return QgsCptCityArchive::findFileName( "DESC.xml", QFileInfo( fileName() ).dir().path(),
647 }
648 
650 {
652 }
653 
655 {
656  if ( mFileLoaded )
657  {
658  QgsDebugMsg( "File already loaded for " + mSchemeName + mVariantName );
659  return true;
660  }
661 
662  // get filename
663  QString filename = fileName();
664  if ( filename.isNull() )
665  {
666  QgsDebugMsg( "Couldn't get fileName() for " + mSchemeName + mVariantName );
667  return false;
668  }
669 
670  QgsDebugMsg( QString( "filename= %1 loaded=%2" ).arg( filename ).arg( mFileLoaded ) );
671 
672  // get color ramp from svg file
675 
676  // add colors to palette
677  mFileLoaded = false;
678  mStops.clear();
679  QMap<double, QPair<QColor, QColor> >::const_iterator it, prev;
680  // first detect if file is gradient is continuous or dicrete
681  // discrete: stop contains 2 colors and first color is identical to previous second
682  // multi: stop contains 2 colors and no relation with previous stop
683  mDiscrete = false;
684  mMultiStops = false;
685  it = prev = colorMap.constBegin();
686  while ( it != colorMap.constEnd() )
687  {
688  // look for stops that contain multiple values
689  if ( it != colorMap.constBegin() && ( it.value().first != it.value().second ) )
690  {
691  if ( it.value().first == prev.value().second )
692  {
693  mDiscrete = true;
694  break;
695  }
696  else
697  {
698  mMultiStops = true;
699  break;
700  }
701  }
702  prev = it;
703  ++it;
704  }
705 
706  // fill all stops
707  it = prev = colorMap.constBegin();
708  while ( it != colorMap.constEnd() )
709  {
710  if ( mDiscrete )
711  {
712  // mPalette << qMakePair( it.key(), it.value().second );
713  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
714  }
715  else
716  {
717  // mPalette << qMakePair( it.key(), it.value().first );
718  mStops.append( QgsGradientStop( it.key(), it.value().first ) );
719  if (( mMultiStops ) &&
720  ( it.key() != 0.0 && it.key() != 1.0 ) )
721  {
722  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
723  }
724  }
725  prev = it;
726  ++it;
727  }
728 
729  // remove first and last items (mColor1 and mColor2)
730  if ( ! mStops.isEmpty() && mStops.at( 0 ).offset == 0.0 )
731  mColor1 = mStops.takeFirst().color;
732  if ( ! mStops.isEmpty() && mStops.last().offset == 1.0 )
733  mColor2 = mStops.takeLast().color;
734 
735  mFileLoaded = true;
736  return true;
737 }
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)
bool stopLessThan(const QgsGradientStop &s1, const QgsGradientStop &s2)
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:491
#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:352
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)
double offset
Relative positional offset, between 0 and 1.
bool isEmpty() const
#define DEFAULT_GRADIENT_COLOR1
const_iterator constEnd() const
void setStops(const QgsGradientStopsList &stops)
Sets the list of intermediate gradient stops for the ramp.
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