QGIS API Documentation  2.17.0-Master (0497e4a)
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  if ( value < 0 || value > 1 )
317  return QColor();
318 
319  int colorCnt = mColors.count();
320  int colorIdx = qMin( static_cast< int >( value * colorCnt ), colorCnt - 1 );
321 
322  if ( colorIdx >= 0 && colorIdx < colorCnt )
323  return mColors.at( colorIdx );
324 
325  return QColor();
326 }
327 
329 {
331 }
332 
334 {
335  QgsStringMap map;
336  map["count"] = QString::number( mCount );
337  map["hueMin"] = QString::number( mHueMin );
338  map["hueMax"] = QString::number( mHueMax );
339  map["satMin"] = QString::number( mSatMin );
340  map["satMax"] = QString::number( mSatMax );
341  map["valMin"] = QString::number( mValMin );
342  map["valMax"] = QString::number( mValMax );
343  return map;
344 }
345 
347  int hueMax, int hueMin, int satMax, int satMin, int valMax, int valMin )
348 {
349  int h, s, v;
350  QList<QColor> colors;
351 
352  //normalize values
353  int safeHueMax = qMax( hueMin, hueMax );
354  int safeHueMin = qMin( hueMin, hueMax );
355  int safeSatMax = qMax( satMin, satMax );
356  int safeSatMin = qMin( satMin, satMax );
357  int safeValMax = qMax( valMin, valMax );
358  int safeValMin = qMin( valMin, valMax );
359 
360  //start hue at random angle
361  double currentHueAngle = 360.0 * static_cast< double >( qrand() ) / RAND_MAX;
362 
363  colors.reserve( count );
364  for ( int i = 0; i < count; ++i )
365  {
366  //increment hue by golden ratio (approx 137.507 degrees)
367  //as this minimises hue nearness as count increases
368  //see http://basecase.org/env/on-rainbows for more details
369  currentHueAngle += 137.50776;
370  //scale hue to between hueMax and hueMin
371  h = qBound( 0, qRound(( fmod( currentHueAngle, 360.0 ) / 360.0 ) * ( safeHueMax - safeHueMin ) + safeHueMin ), 359 );
372  s = qBound( 0, ( qrand() % ( safeSatMax - safeSatMin + 1 ) ) + safeSatMin, 255 );
373  v = qBound( 0, ( qrand() % ( safeValMax - safeValMin + 1 ) ) + safeValMin, 255 );
374  colors.append( QColor::fromHsv( h, s, v ) );
375  }
376  return colors;
377 }
378 
380 {
382 }
383 
385 
387  : mTotalColorCount( 0 )
388 {
389 }
390 
392 {
393 
394 }
395 
397 {
398  return -1;
399 }
400 
401 double QgsRandomColorsV2::value( int index ) const
402 {
403  Q_UNUSED( index );
404  return 0.0;
405 }
406 
408 {
409  int minVal = 130;
410  int maxVal = 255;
411 
412  //if value is nan, then use last precalculated color
413  int colorIndex = ( !qIsNaN( value ) ? value : 1 ) * ( mTotalColorCount - 1 );
414  if ( mTotalColorCount >= 1 && mPrecalculatedColors.length() > colorIndex )
415  {
416  //use precalculated hue
417  return mPrecalculatedColors.at( colorIndex );
418  }
419 
420  //can't use precalculated hues, use a totally random hue
421  int h = static_cast< int >( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
422  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
423  int v = ( qrand() % ( maxVal - minVal + 1 ) ) + minVal;
424  return QColor::fromHsv( h, s, v );
425 }
426 
427 void QgsRandomColorsV2::setTotalColorCount( const int colorCount )
428 {
429  //calculate colors in advance, so that we can ensure they are more visually distinct than pure random colors
431  mTotalColorCount = colorCount;
432 
433  //This works ok for low color counts, but for > 10 or so colors there's still a good chance of
434  //similar colors being picked. TODO - investigate alternative "n-visually distinct color" routines
435 
436  //random offsets
437  double hueOffset = ( 360.0 * qrand() / ( RAND_MAX + 1.0 ) );
438 
439  //try to maximise difference between hues. this is not an ideal implementation, as constant steps
440  //through the hue wheel are not visually perceived as constant changes in hue
441  //(for instance, we are much more likely to get green hues than yellow hues)
442  double hueStep = 359.0 / colorCount;
443  double currentHue = hueOffset;
444 
445  //build up a list of colors
446  for ( int idx = 0; idx < colorCount; ++ idx )
447  {
448  int h = qRound( currentHue ) % 360;
449  int s = ( qrand() % ( DEFAULT_RANDOM_SAT_MAX - DEFAULT_RANDOM_SAT_MIN + 1 ) ) + DEFAULT_RANDOM_SAT_MIN;
450  int v = ( qrand() % ( DEFAULT_RANDOM_VAL_MAX - DEFAULT_RANDOM_VAL_MIN + 1 ) ) + DEFAULT_RANDOM_VAL_MIN;
452  currentHue += hueStep;
453  }
454 
455  //lastly, shuffle color list
456  std::random_shuffle( mPrecalculatedColors.begin(), mPrecalculatedColors.end() );
457 }
458 
460 {
461  return "randomcolors";
462 }
463 
465 {
466  return new QgsRandomColorsV2();
467 }
468 
470 {
471  return QgsStringMap();
472 }
473 
475 
477  : mSchemeName( schemeName )
478  , mColors( colors )
479 {
480  loadPalette();
481 }
482 
484 {
487 
488  if ( props.contains( "schemeName" ) )
489  schemeName = props["schemeName"];
490  if ( props.contains( "colors" ) )
491  colors = props["colors"].toInt();
492 
493  return new QgsVectorColorBrewerColorRampV2( schemeName, colors );
494 }
495 
497 {
499 }
500 
502 {
504 }
505 
507 {
508  return QgsColorBrewerPalette::listSchemeVariants( schemeName );
509 }
510 
512 {
513  if ( mPalette.size() < 1 ) return 0;
514  return static_cast< double >( index ) / ( mPalette.size() - 1 );
515 }
516 
518 {
519  if ( mPalette.isEmpty() || value < 0 || value > 1 )
520  return QColor();
521 
522  int paletteEntry = static_cast< int >( value * mPalette.count() );
523  if ( paletteEntry >= mPalette.count() )
524  paletteEntry = mPalette.count() - 1;
525  return mPalette.at( paletteEntry );
526 }
527 
529 {
531 }
532 
534 {
535  QgsStringMap map;
536  map["schemeName"] = mSchemeName;
537  map["colors"] = QString::number( mColors );
538  return map;
539 }
540 
541 
543 
544 
546  bool doLoadFile )
548  , mSchemeName( schemeName ), mVariantName( variantName )
549  , mVariantList( QStringList() ), mFileLoaded( false ), mMultiStops( false )
550 {
551  // TODO replace this with hard-coded data in the default case
552  // don't load file if variant is missing
553  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
554  loadFile();
555 }
556 
558  const QString& variantName, bool doLoadFile )
560  , mSchemeName( schemeName ), mVariantName( variantName )
561  , mVariantList( variantList ), mFileLoaded( false ), mMultiStops( false )
562 {
564 
565  // TODO replace this with hard-coded data in the default case
566  // don't load file if variant is missing
567  if ( doLoadFile && ( variantName != QString() || mVariantList.isEmpty() ) )
568  loadFile();
569 }
570 
572 {
575 
576  if ( props.contains( "schemeName" ) )
577  schemeName = props["schemeName"];
578  if ( props.contains( "variantName" ) )
579  variantName = props["variantName"];
580 
581  return new QgsCptCityColorRampV2( schemeName, variantName );
582 }
583 
585 {
586  QgsCptCityColorRampV2* ramp = new QgsCptCityColorRampV2( "", "", false );
587  ramp->copy( this );
588  return ramp;
589 }
590 
592 {
593  if ( ! other )
594  return;
595  mColor1 = other->color1();
596  mColor2 = other->color2();
597  mDiscrete = other->isDiscrete();
598  mStops = other->stops();
599  mSchemeName = other->mSchemeName;
600  mVariantName = other->mVariantName;
601  mVariantList = other->mVariantList;
602  mFileLoaded = other->mFileLoaded;
603 }
604 
606 {
609  // add author and copyright information
610  // TODO also add COPYING.xml file/link?
612  info["cpt-city-gradient"] = "<cpt-city>/" + mSchemeName + mVariantName + ".svg";
613  QString copyingFilename = copyingFileName();
614  copyingFilename.remove( QgsCptCityArchive::defaultBaseDir() );
615  info["cpt-city-license"] = "<cpt-city>" + copyingFilename;
616  ramp->setInfo( info );
617  return ramp;
618 }
619 
620 
622 {
623  QgsStringMap map;
624  map["schemeName"] = mSchemeName;
625  map["variantName"] = mVariantName;
626  return map;
627 }
628 
629 
631 {
632  if ( mSchemeName == "" )
633  return QString();
634  else
635  {
637  }
638 }
639 
641 {
642  return QgsCptCityArchive::findFileName( "COPYING.xml", QFileInfo( fileName() ).dir().path(),
644 }
645 
647 {
648  return QgsCptCityArchive::findFileName( "DESC.xml", QFileInfo( fileName() ).dir().path(),
650 }
651 
653 {
655 }
656 
658 {
659  if ( mFileLoaded )
660  {
661  QgsDebugMsg( "File already loaded for " + mSchemeName + mVariantName );
662  return true;
663  }
664 
665  // get filename
666  QString filename = fileName();
667  if ( filename.isNull() )
668  {
669  QgsDebugMsg( "Couldn't get fileName() for " + mSchemeName + mVariantName );
670  return false;
671  }
672 
673  QgsDebugMsg( QString( "filename= %1 loaded=%2" ).arg( filename ).arg( mFileLoaded ) );
674 
675  // get color ramp from svg file
678 
679  // add colors to palette
680  mFileLoaded = false;
681  mStops.clear();
682  QMap<double, QPair<QColor, QColor> >::const_iterator it, prev;
683  // first detect if file is gradient is continuous or dicrete
684  // discrete: stop contains 2 colors and first color is identical to previous second
685  // multi: stop contains 2 colors and no relation with previous stop
686  mDiscrete = false;
687  mMultiStops = false;
688  it = prev = colorMap.constBegin();
689  while ( it != colorMap.constEnd() )
690  {
691  // look for stops that contain multiple values
692  if ( it != colorMap.constBegin() && ( it.value().first != it.value().second ) )
693  {
694  if ( it.value().first == prev.value().second )
695  {
696  mDiscrete = true;
697  break;
698  }
699  else
700  {
701  mMultiStops = true;
702  break;
703  }
704  }
705  prev = it;
706  ++it;
707  }
708 
709  // fill all stops
710  it = prev = colorMap.constBegin();
711  while ( it != colorMap.constEnd() )
712  {
713  if ( mDiscrete )
714  {
715  // mPalette << qMakePair( it.key(), it.value().second );
716  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
717  }
718  else
719  {
720  // mPalette << qMakePair( it.key(), it.value().first );
721  mStops.append( QgsGradientStop( it.key(), it.value().first ) );
722  if (( mMultiStops ) &&
723  ( it.key() != 0.0 && it.key() != 1.0 ) )
724  {
725  mStops.append( QgsGradientStop( it.key(), it.value().second ) );
726  }
727  }
728  prev = it;
729  ++it;
730  }
731 
732  // remove first and last items (mColor1 and mColor2)
733  if ( ! mStops.isEmpty() && mStops.at( 0 ).offset == 0.0 )
734  mColor1 = mStops.takeFirst().color;
735  if ( ! mStops.isEmpty() && mStops.last().offset == 1.0 )
736  mColor2 = mStops.takeLast().color;
737 
738  mFileLoaded = true;
739  return true;
740 }
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()
QgsStringMap copyingInfo() const
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
QColor color2() const
Returns the gradient end color.
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)
QColor color1() const
Returns the gradient start color.
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)
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
virtual void setTotalColorCount(const int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
QgsVectorGradientColorRampV2 * cloneGradientRamp() const
QString join(const QString &separator) const
QString & remove(int position, int n)
#define DEFAULT_CPTCITY_SCHEMENAME
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
double toDouble(bool *ok) const
static QList< QColor > listSchemeColors(const QString &schemeName, int colors)
QChar separator()
QMap< QString, QString > QgsStringMap
Definition: qgis.h:492
#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:353
int size() const
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 number(int n, int base)
int count(const T &value) const
void append(const T &value)
QgsStringMap info() const
Returns any additional info attached to the gradient ramp (eg authorship notes)
#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
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
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
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()
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 ...
iterator begin()
#define DEFAULT_RANDOM_COUNT
static QString findFileName(const QString &target, const QString &startDir, const QString &baseDir)
QStringList variantList() const
const T value(const Key &key) const