QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
qgscolorrampshader.cpp
Go to the documentation of this file.
1/* **************************************************************************
2 qgscolorrampshader.cpp - description
3 -------------------
4begin : Fri Dec 28 2007
5copyright : (C) 2007 by Peter J. Ersts
6email : ersts@amnh.org
7
8This class is based off of code that was originally written by Marco Hugentobler and
9originally part of the larger QgsRasterLayer class
10****************************************************************************/
11
12/* **************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21// Threshold for treating values as exact match.
22// Set to 0.0 to support displaying small values (https://github.com/qgis/QGIS/issues/20706)
23#define DOUBLE_DIFF_THRESHOLD 0.0 // 0.0000001
24
25#include "qgslogger.h"
26#include "qgis.h"
27#include "qgscolorrampimpl.h"
28#include "qgscolorrampshader.h"
29#include "qgsrasterinterface.h"
30#include "qgssymbollayerutils.h"
31#include "qgsreadwritecontext.h"
33
34#include <cmath>
35QgsColorRampShader::QgsColorRampShader( double minimumValue, double maximumValue, QgsColorRamp *colorRamp, Qgis::ShaderInterpolationMethod type, Qgis::ShaderClassificationMethod classificationMode )
36 : QgsRasterShaderFunction( minimumValue, maximumValue )
37 , mColorRampType( type )
38 , mClassificationMode( classificationMode )
39 , mLegendSettings( std::make_unique< QgsColorRampLegendNodeSettings >() )
40{
41 QgsDebugMsgLevel( QStringLiteral( "called." ), 4 );
42
43 setSourceColorRamp( colorRamp );
44}
45
47
50 , mColorRampType( other.mColorRampType )
51 , mClassificationMode( other.mClassificationMode )
52 , mLUT( other.mLUT )
53 , mLUTOffset( other.mLUTOffset )
54 , mLUTFactor( other.mLUTFactor )
55 , mLUTInitialized( other.mLUTInitialized )
56 , mClip( other.mClip )
57 , mLegendSettings( other.legendSettings() ? new QgsColorRampLegendNodeSettings( *other.legendSettings() ) : new QgsColorRampLegendNodeSettings() )
58{
59 if ( auto *lSourceColorRamp = other.sourceColorRamp() )
60 mSourceColorRamp.reset( lSourceColorRamp->clone() );
61 mColorRampItemList = other.mColorRampItemList;
62}
63
65{
66 QgsRasterShaderFunction::operator=( other );
67 if ( auto *lSourceColorRamp = other.sourceColorRamp() )
68 mSourceColorRamp.reset( lSourceColorRamp->clone() );
69 else
70 mSourceColorRamp.reset();
71
72 mColorRampType = other.mColorRampType;
73 mClassificationMode = other.mClassificationMode;
74 mLUT = other.mLUT;
75 mLUTOffset = other.mLUTOffset;
76 mLUTFactor = other.mLUTFactor;
77 mLUTInitialized = other.mLUTInitialized;
78 mClip = other.mClip;
79 mColorRampItemList = other.mColorRampItemList;
80 mLegendSettings.reset( other.legendSettings() ? new QgsColorRampLegendNodeSettings( *other.legendSettings() ) : new QgsColorRampLegendNodeSettings() );
81 return *this;
82}
83
85{
86 switch ( mColorRampType )
87 {
89 return QStringLiteral( "INTERPOLATED" );
91 return QStringLiteral( "DISCRETE" );
93 return QStringLiteral( "EXACT" );
94 }
95 return QStringLiteral( "Unknown" );
96}
97
98void QgsColorRampShader::setColorRampItemList( const QList<QgsColorRampShader::ColorRampItem> &list )
99{
100 mColorRampItemList = list.toVector();
101 // Reset the look up table when the color ramp is changed
102 mLUTInitialized = false;
103 mLUT.clear();
104}
105
107{
108 mColorRampType = colorRampType;
109}
110
112{
113 return mColorRampItemList.isEmpty();
114}
115
116void QgsColorRampShader::setColorRampType( const QString &type )
117{
118 if ( type == QLatin1String( "INTERPOLATED" ) )
119 {
121 }
122 else if ( type == QLatin1String( "DISCRETE" ) )
123 {
125 }
126 else
127 {
129 }
130}
131
136
138{
139 std::unique_ptr<QgsGradientColorRamp> ramp = std::make_unique< QgsGradientColorRamp >();
140 const int count = mColorRampItemList.size();
141 if ( count == 0 )
142 {
143 const QColor none( 0, 0, 0, 0 );
144 ramp->setColor1( none );
145 ramp->setColor2( none );
146 }
147 else if ( count == 1 )
148 {
149 ramp->setColor1( mColorRampItemList[0].color );
150 ramp->setColor2( mColorRampItemList[0].color );
151 }
152 else
153 {
155 // minimum and maximum values can fall outside the range of the item list
156 const double min = minimumValue();
157 const double max = maximumValue();
158 for ( int i = 0; i < count; i++ )
159 {
160 const double offset = ( mColorRampItemList[i].value - min ) / ( max - min );
161 if ( i == 0 )
162 {
163 ramp->setColor1( mColorRampItemList[i].color );
164 if ( offset <= 0.0 )
165 continue;
166 }
167 else if ( i == count - 1 )
168 {
169 ramp->setColor2( mColorRampItemList[i].color );
170 if ( offset >= 1.0 )
171 continue;
172 }
173 stops << QgsGradientStop( offset, mColorRampItemList[i].color );
174 }
175 ramp->setStops( stops );
176 }
177
178 return ramp.release();
179}
180
182{
183 mSourceColorRamp.reset( colorramp );
184}
185
186void QgsColorRampShader::classifyColorRamp( const int classes, const int band, const QgsRectangle &extent, QgsRasterInterface *input )
187{
188 if ( minimumValue() > maximumValue() )
189 return;
190
192
193 QList<double> entryValues;
194 QVector<QColor> entryColors;
195
196 double min = minimumValue();
197 double max = maximumValue();
198
199 if ( minimumValue() == maximumValue() )
200 {
201 if ( sourceColorRamp() && sourceColorRamp()->count() > 1 )
202 {
203 entryValues.push_back( min );
204 if ( discrete )
205 entryValues.push_back( std::numeric_limits<double>::infinity() );
206 for ( int i = 0; i < entryValues.size(); ++i )
207 entryColors.push_back( sourceColorRamp()->color( sourceColorRamp()->value( i ) ) );
208 }
209 }
211 {
212 if ( sourceColorRamp() && sourceColorRamp()->count() > 1 )
213 {
214 int numberOfEntries = sourceColorRamp()->count();
215 entryValues.reserve( numberOfEntries );
216 if ( discrete )
217 {
218 double intervalDiff = max - min;
219
220 // remove last class when ColorRamp is gradient and discrete, as they are implemented with an extra stop
221 QgsGradientColorRamp *colorGradientRamp = dynamic_cast<QgsGradientColorRamp *>( sourceColorRamp() );
222 if ( colorGradientRamp && colorGradientRamp->isDiscrete() )
223 {
224 numberOfEntries--;
225 }
226 else
227 {
228 // if color ramp is continuous scale values to get equally distributed classes.
229 // Doesn't work perfectly when stops are non equally distributed.
230 intervalDiff *= ( numberOfEntries - 1 ) / static_cast<double>( numberOfEntries );
231 }
232
233 // skip first value (always 0.0)
234 for ( int i = 1; i < numberOfEntries; ++i )
235 {
236 const double value = sourceColorRamp()->value( i );
237 entryValues.push_back( min + value * intervalDiff );
238 }
239 entryValues.push_back( std::numeric_limits<double>::infinity() );
240 }
241 else
242 {
243 for ( int i = 0; i < numberOfEntries; ++i )
244 {
245 const double value = sourceColorRamp()->value( i );
246 entryValues.push_back( min + value * ( max - min ) );
247 }
248 }
249 // for continuous mode take original color map colors
250 for ( int i = 0; i < numberOfEntries; ++i )
251 {
252 const int idx = i;
253 entryColors.push_back( sourceColorRamp()->color( sourceColorRamp()->value( idx ) ) );
254 }
255 }
256 }
257 else // for other classification modes interpolate colors linearly
258 {
259 if ( classes < 2 )
260 return; // < 2 classes is not useful, shouldn't happen, but if it happens save it from crashing
261
263 {
264 // Quantile
265 if ( band < 0 || !input )
266 return; // quantile classification requires a valid band, minMaxOrigin, and input
267
268 double cut1 = std::numeric_limits<double>::quiet_NaN();
269 double cut2 = std::numeric_limits<double>::quiet_NaN();
270 // Note: the sample size in other parts of QGIS appears to be 25000, it is ten times here.
271 const int sampleSize = 250000 * 10;
272
273 // set min and max from histogram, used later to calculate number of decimals to display
274 input->cumulativeCut( band, 0.0, 1.0, min, max, extent, sampleSize );
275
276 entryValues.reserve( classes );
277 if ( discrete )
278 {
279 const double intervalDiff = 1.0 / ( classes );
280 for ( int i = 1; i < classes; ++i )
281 {
282 input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
283 entryValues.push_back( cut2 );
284 }
285 entryValues.push_back( std::numeric_limits<double>::infinity() );
286 }
287 else
288 {
289 const double intervalDiff = 1.0 / ( classes - 1 );
290 for ( int i = 0; i < classes; ++i )
291 {
292 input->cumulativeCut( band, 0.0, i * intervalDiff, cut1, cut2, extent, sampleSize );
293 entryValues.push_back( cut2 );
294 }
295 }
296 }
297 else // EqualInterval
298 {
299 entryValues.reserve( classes );
300 if ( discrete )
301 {
302 // in discrete mode the lowest value is not an entry and the highest
303 // value is inf, there are ( numberOfEntries ) of which the first
304 // and last are not used.
305 const double intervalDiff = ( max - min ) / ( classes );
306
307 for ( int i = 1; i < classes; ++i )
308 {
309 entryValues.push_back( min + i * intervalDiff );
310 }
311 entryValues.push_back( std::numeric_limits<double>::infinity() );
312 }
313 else
314 {
315 //because the highest value is also an entry, there are (numberOfEntries - 1) intervals
316 const double intervalDiff = ( max - min ) / ( classes - 1 );
317
318 for ( int i = 0; i < classes; ++i )
319 {
320 entryValues.push_back( min + i * intervalDiff );
321 }
322 }
323 }
324
325 if ( !sourceColorRamp() || sourceColorRamp()->count() == 1 )
326 {
327 //hard code color range from blue -> red (previous default)
328 int colorDiff = 0;
329 if ( classes != 0 )
330 {
331 colorDiff = ( int )( 255 / classes );
332 }
333
334 entryColors.reserve( classes );
335 for ( int i = 0; i < classes; ++i )
336 {
337 QColor currentColor;
338 const int idx = i;
339 currentColor.setRgb( colorDiff * idx, 0, 255 - colorDiff * idx );
340 entryColors.push_back( currentColor );
341 }
342 }
343 else
344 {
345 entryColors.reserve( classes );
346 for ( int i = 0; i < classes; ++i )
347 {
348 const int idx = i;
349 entryColors.push_back( sourceColorRamp()->color( ( ( double ) idx ) / ( classes - 1 ) ) );
350 }
351 }
352 }
353
354 QList<double>::const_iterator value_it = entryValues.constBegin();
355 QVector<QColor>::const_iterator color_it = entryColors.constBegin();
356
357 // calculate a reasonable number of decimals to display
358 const double maxabs = std::log10( std::max( std::fabs( max ), std::fabs( min ) ) );
359 const int nDecimals = std::round( std::max( 3.0 + maxabs - std::log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
360
361 QList<QgsColorRampShader::ColorRampItem> colorRampItems;
362 for ( ; value_it != entryValues.constEnd(); ++value_it, ++color_it )
363 {
364 QgsColorRampShader::ColorRampItem newColorRampItem;
365 newColorRampItem.value = *value_it;
366 newColorRampItem.color = *color_it;
367 newColorRampItem.label = QString::number( *value_it, 'g', nDecimals );
368 colorRampItems.append( newColorRampItem );
369 }
370
371 std::sort( colorRampItems.begin(), colorRampItems.end() );
372 setColorRampItemList( colorRampItems );
373}
374
375void QgsColorRampShader::classifyColorRamp( const int band, const QgsRectangle &extent, QgsRasterInterface *input )
376{
377 classifyColorRamp( colorRampItemList().count(), band, extent, input );
378}
379
380bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue ) const
381{
382 if ( mColorRampItemList.isEmpty() )
383 {
384 return false;
385 }
386 if ( std::isnan( value ) || std::isinf( value ) )
387 return false;
388
389 const int colorRampItemListCount = mColorRampItemList.count();
390 const QgsColorRampShader::ColorRampItem *colorRampItems = mColorRampItemList.constData();
391 int idx;
392 if ( !mLUTInitialized )
393 {
394 // calculate LUT for faster index recovery
395 mLUTFactor = 1.0;
396 const double minimumValue = colorRampItems[0].value;
397 mLUTOffset = minimumValue + DOUBLE_DIFF_THRESHOLD;
398 // Only make lut if at least 3 items, with 2 items the low and high cases handle both
399 if ( colorRampItemListCount >= 3 )
400 {
401 const double rangeValue = colorRampItems[colorRampItemListCount - 2].value - minimumValue;
402 if ( rangeValue > 0 )
403 {
404 const int lutSize = 256; // TODO: test if speed can be increased with a different LUT size
405 mLUTFactor = ( lutSize - 0.0000001 ) / rangeValue; // decrease slightly to make sure last LUT category is correct
406 idx = 0;
407 double val;
408 mLUT.reserve( lutSize );
409 for ( int i = 0; i < lutSize; i++ )
410 {
411 val = ( i / mLUTFactor ) + mLUTOffset;
412 while ( idx < colorRampItemListCount
413 && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
414 {
415 idx++;
416 }
417 mLUT.emplace_back( idx );
418 }
419 }
420 }
421 mLUTInitialized = true;
422 }
423
424 // overflow indicates that value > maximum value + DOUBLE_DIFF_THRESHOLD
425 // that way idx can point to the last valid item
426 bool overflow = false;
427
428 // find index of the first ColorRampItem that is equal or higher to theValue
429 const int lutIndex = ( value - mLUTOffset ) * mLUTFactor;
430 if ( value <= mLUTOffset )
431 {
432 idx = 0;
433 }
434 else if ( static_cast< std::size_t>( lutIndex ) >= mLUT.size() )
435 {
436 idx = colorRampItemListCount - 1;
437 if ( colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
438 {
439 overflow = true;
440 }
441 }
442 else if ( lutIndex < 0 )
443 {
444 return false;
445 }
446 else
447 {
448 // get initial value from LUT
449 idx = mLUT[ lutIndex ];
450
451 // check if it's correct and if not increase until correct
452 // the LUT is made in such a way the index is always correct or too low, never too high
453 while ( idx < colorRampItemListCount && colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
454 {
455 idx++;
456 }
457 if ( idx >= colorRampItemListCount )
458 {
459 idx = colorRampItemListCount - 1;
460 overflow = true;
461 }
462 }
463
464 const QgsColorRampShader::ColorRampItem &currentColorRampItem = colorRampItems[idx];
465
466 switch ( colorRampType() )
467 {
469 {
470 // Interpolate the color between two class breaks linearly.
471 if ( idx < 1 || overflow || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
472 {
473 if ( mClip && ( overflow
474 || currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD > value ) )
475 {
476 return false;
477 }
478 *returnRedValue = currentColorRampItem.color.red();
479 *returnGreenValue = currentColorRampItem.color.green();
480 *returnBlueValue = currentColorRampItem.color.blue();
481 *returnAlphaValue = currentColorRampItem.color.alpha();
482 return true;
483 }
484
485 const QgsColorRampShader::ColorRampItem &previousColorRampItem = colorRampItems[idx - 1];
486
487 const float currentRampRange = currentColorRampItem.value - previousColorRampItem.value;
488 const float offsetInRange = value - previousColorRampItem.value;
489 const float scale = offsetInRange / currentRampRange;
490
491 const QRgb c1 = previousColorRampItem.color.rgba();
492 const QRgb c2 = currentColorRampItem.color.rgba();
493
494 *returnRedValue = qRed( c1 ) + static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
495 *returnGreenValue = qGreen( c1 ) + static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
496 *returnBlueValue = qBlue( c1 ) + static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
497 *returnAlphaValue = qAlpha( c1 ) + static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
498 return true;
499 };
501 {
502 // Assign the color of the higher class for every pixel between two class breaks.
503 // NOTE: The implementation has always been different than the documentation,
504 // which said lower class before, see https://github.com/qgis/QGIS/issues/22009
505 if ( overflow )
506 {
507 return false;
508 }
509 *returnRedValue = currentColorRampItem.color.red();
510 *returnGreenValue = currentColorRampItem.color.green();
511 *returnBlueValue = currentColorRampItem.color.blue();
512 *returnAlphaValue = currentColorRampItem.color.alpha();
513 return true;
514 };
516 {
517 // Assign the color of the exact matching value in the color ramp item list
518 if ( !overflow && currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
519 {
520 *returnRedValue = currentColorRampItem.color.red();
521 *returnGreenValue = currentColorRampItem.color.green();
522 *returnBlueValue = currentColorRampItem.color.blue();
523 *returnAlphaValue = currentColorRampItem.color.alpha();
524 return true;
525 }
526 else
527 {
528 return false;
529 }
530 }
531 }
532 return false;
533}
534
535bool QgsColorRampShader::shade( double redValue, double greenValue,
536 double blueValue, double alphaValue,
537 int *returnRedValue, int *returnGreenValue,
538 int *returnBlueValue, int *returnAlphaValue ) const
539{
540 Q_UNUSED( redValue )
541 Q_UNUSED( greenValue )
542 Q_UNUSED( blueValue )
543 Q_UNUSED( alphaValue )
544
545 *returnRedValue = 0;
546 *returnGreenValue = 0;
547 *returnBlueValue = 0;
548 *returnAlphaValue = 0;
549
550 return false;
551}
552
553void QgsColorRampShader::legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems ) const
554{
555 QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
556 for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
557 {
558 symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
559 }
560}
561
562QDomElement QgsColorRampShader::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
563{
564 QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( "colorrampshader" ) );
565 colorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), colorRampTypeAsQString() );
566 colorRampShaderElem.setAttribute( QStringLiteral( "classificationMode" ), static_cast< int >( classificationMode() ) );
567 colorRampShaderElem.setAttribute( QStringLiteral( "clip" ), clip() );
568 colorRampShaderElem.setAttribute( QStringLiteral( "minimumValue" ), mMinimumValue );
569 colorRampShaderElem.setAttribute( QStringLiteral( "maximumValue" ), mMaximumValue );
570 colorRampShaderElem.setAttribute( QStringLiteral( "labelPrecision" ), mLabelPrecision );
571
572 // save source color ramp
573 if ( sourceColorRamp() )
574 {
575 const QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), sourceColorRamp(), doc );
576 colorRampShaderElem.appendChild( colorRampElem );
577 }
578
579 //items
580 const QList<QgsColorRampShader::ColorRampItem> itemList = colorRampItemList();
581 QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
582 for ( ; itemIt != itemList.constEnd(); ++itemIt )
583 {
584 QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
585 itemElem.setAttribute( QStringLiteral( "label" ), itemIt->label );
586 itemElem.setAttribute( QStringLiteral( "value" ), QgsRasterBlock::printValue( itemIt->value ) );
587 itemElem.setAttribute( QStringLiteral( "color" ), itemIt->color.name() );
588 itemElem.setAttribute( QStringLiteral( "alpha" ), itemIt->color.alpha() );
589 colorRampShaderElem.appendChild( itemElem );
590 }
591
592 if ( mLegendSettings )
593 mLegendSettings->writeXml( doc, colorRampShaderElem, context );
594
595 return colorRampShaderElem;
596}
597
598void QgsColorRampShader::readXml( const QDomElement &colorRampShaderElem, const QgsReadWriteContext &context )
599{
600 // try to load color ramp (optional)
601 QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( "colorramp" ) );
602 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
603 {
605 }
606
607 setColorRampType( colorRampShaderElem.attribute( QStringLiteral( "colorRampType" ), QStringLiteral( "INTERPOLATED" ) ) );
608 setClassificationMode( static_cast< Qgis::ShaderClassificationMethod >( colorRampShaderElem.attribute( QStringLiteral( "classificationMode" ), QStringLiteral( "1" ) ).toInt() ) );
609 setClip( colorRampShaderElem.attribute( QStringLiteral( "clip" ), QStringLiteral( "0" ) ) == QLatin1String( "1" ) );
610 setMinimumValue( colorRampShaderElem.attribute( QStringLiteral( "minimumValue" ) ).toDouble() );
611 setMaximumValue( colorRampShaderElem.attribute( QStringLiteral( "maximumValue" ) ).toDouble() );
612 setLabelPrecision( colorRampShaderElem.attribute( QStringLiteral( "labelPrecision" ), QStringLiteral( "6" ) ).toDouble() );
613
614 QList<QgsColorRampShader::ColorRampItem> itemList;
615 QDomElement itemElem;
616 QString itemLabel;
617 double itemValue;
618 QColor itemColor;
619
620 const QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( "item" ) );
621 itemList.reserve( itemNodeList.size() );
622 for ( int i = 0; i < itemNodeList.size(); ++i )
623 {
624 itemElem = itemNodeList.at( i ).toElement();
625 itemValue = itemElem.attribute( QStringLiteral( "value" ) ).toDouble();
626 itemLabel = itemElem.attribute( QStringLiteral( "label" ) );
627 itemColor.setNamedColor( itemElem.attribute( QStringLiteral( "color" ) ) );
628 itemColor.setAlpha( itemElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt() );
629
630 itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
631 }
632 setColorRampItemList( itemList );
633
634 if ( !mLegendSettings )
635 mLegendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
636
637 mLegendSettings->readXml( colorRampShaderElem, context );
638}
639
641{
642 return mLegendSettings.get();
643}
644
646{
647 if ( settings == mLegendSettings.get() )
648 return;
649 mLegendSettings.reset( settings );
650}
ShaderInterpolationMethod
Color ramp shader interpolation methods.
Definition qgis.h:1335
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
@ Linear
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
ShaderClassificationMethod
Color ramp shader classification methods.
Definition qgis.h:1350
@ Continuous
Uses breaks from color palette.
@ Quantile
Uses quantile (i.e. equal pixel) count.
Settings for a color ramp legend node.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
~QgsColorRampShader() override
void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const override
Returns legend symbology items if provided by renderer.
Qgis::ShaderClassificationMethod classificationMode() const
Returns the classification mode.
Qgis::ShaderInterpolationMethod colorRampType() const
Returns the color ramp interpolation method.
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
bool isEmpty() const
Whether the color ramp contains any items.
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
void setClassificationMode(Qgis::ShaderClassificationMethod classificationMode)
Sets the classification mode.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom color map.
QgsColorRampShader & operator=(const QgsColorRampShader &other)
void setClip(bool clip)
Sets whether the shader should not render values out of range.
bool clip() const
Returns whether the shader will clip values which are out of range.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates an new RGBA value based on one input value.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
QgsColorRamp * createColorRamp() const
Creates a gradient color ramp from shader settings.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
void setColorRampType(Qgis::ShaderInterpolationMethod colorRampType)
Sets the color ramp interpolation method.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom color map.
QString colorRampTypeAsQString() const
Returns the color ramp type as a string.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
QgsColorRampShader(double minimumValue=0.0, double maximumValue=255.0, QgsColorRamp *colorRamp=nullptr, Qgis::ShaderInterpolationMethod type=Qgis::ShaderInterpolationMethod::Linear, Qgis::ShaderClassificationMethod classificationMode=Qgis::ShaderClassificationMethod::Continuous)
Creates a new color ramp shader.
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Source color ramp.
void setLegendSettings(QgsColorRampLegendNodeSettings *settings)
Sets the color ramp shader legend settings.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual int count() const =0
Returns number of defined colors, or -1 if undefined.
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
Represents a color stop within a QgsGradientColorRamp color ramp.
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
double mMinimumValue
User defineable minimum value for the shading function.
double maximumValue() const
Returns the minimum value for the raster shader.
double mMaximumValue
User defineable maximum value for the shading function.
void setLabelPrecision(int labelPrecision)
Sets label precision to labelPrecision.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
int mLabelPrecision
Label precision.
double minimumValue() const
Returns the maximum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
#define DOUBLE_DIFF_THRESHOLD
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39