QGIS API Documentation 3.41.0-Master (af5edcb665c)
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
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 const int colorRampItemListCount = mColorRampItemList.count();
383 if ( colorRampItemListCount == 0 )
384 {
385 return false;
386 }
387 if ( std::isnan( value ) || std::isinf( value ) )
388 return false;
389
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 ( mColorRampType )
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 int c1Red = previousColorRampItem.color.red();
492 const int c1Green = previousColorRampItem.color.green();
493 const int c1Blue = previousColorRampItem.color.blue();
494 const int c1Alpha = previousColorRampItem.color.alpha();
495
496 const int c2Red = currentColorRampItem.color.red();
497 const int c2Green = currentColorRampItem.color.green();
498 const int c2Blue = currentColorRampItem.color.blue();
499 const int c2Alpha = currentColorRampItem.color.alpha();
500
501 *returnRedValue = c1Red + static_cast< int >( ( c2Red - c1Red ) * scale );
502 *returnGreenValue = c1Green + static_cast< int >( ( c2Green - c1Green ) * scale );
503 *returnBlueValue = c1Blue + static_cast< int >( ( c2Blue - c1Blue ) * scale );
504 *returnAlphaValue = c1Alpha + static_cast< int >( ( c2Alpha - c1Alpha ) * scale );
505 return true;
506 };
508 {
509 // Assign the color of the higher class for every pixel between two class breaks.
510 // NOTE: The implementation has always been different than the documentation,
511 // which said lower class before, see https://github.com/qgis/QGIS/issues/22009
512 if ( overflow )
513 {
514 return false;
515 }
516 *returnRedValue = currentColorRampItem.color.red();
517 *returnGreenValue = currentColorRampItem.color.green();
518 *returnBlueValue = currentColorRampItem.color.blue();
519 *returnAlphaValue = currentColorRampItem.color.alpha();
520 return true;
521 };
523 {
524 // Assign the color of the exact matching value in the color ramp item list
525 if ( !overflow && currentColorRampItem.value - DOUBLE_DIFF_THRESHOLD <= value )
526 {
527 *returnRedValue = currentColorRampItem.color.red();
528 *returnGreenValue = currentColorRampItem.color.green();
529 *returnBlueValue = currentColorRampItem.color.blue();
530 *returnAlphaValue = currentColorRampItem.color.alpha();
531 return true;
532 }
533 else
534 {
535 return false;
536 }
537 }
538 }
539 return false;
540}
541
542bool QgsColorRampShader::shade( double redValue, double greenValue,
543 double blueValue, double alphaValue,
544 int *returnRedValue, int *returnGreenValue,
545 int *returnBlueValue, int *returnAlphaValue ) const
546{
547 Q_UNUSED( redValue )
548 Q_UNUSED( greenValue )
549 Q_UNUSED( blueValue )
550 Q_UNUSED( alphaValue )
551
552 *returnRedValue = 0;
553 *returnGreenValue = 0;
554 *returnBlueValue = 0;
555 *returnAlphaValue = 0;
556
557 return false;
558}
559
560void QgsColorRampShader::legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems ) const
561{
562 QVector<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
563 for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
564 {
565 symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
566 }
567}
568
569QDomElement QgsColorRampShader::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
570{
571 QDomElement colorRampShaderElem = doc.createElement( QStringLiteral( "colorrampshader" ) );
572 colorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), colorRampTypeAsQString() );
573 colorRampShaderElem.setAttribute( QStringLiteral( "classificationMode" ), static_cast< int >( classificationMode() ) );
574 colorRampShaderElem.setAttribute( QStringLiteral( "clip" ), clip() );
575 colorRampShaderElem.setAttribute( QStringLiteral( "minimumValue" ), mMinimumValue );
576 colorRampShaderElem.setAttribute( QStringLiteral( "maximumValue" ), mMaximumValue );
577 colorRampShaderElem.setAttribute( QStringLiteral( "labelPrecision" ), mLabelPrecision );
578
579 // save source color ramp
580 if ( sourceColorRamp() )
581 {
582 const QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), sourceColorRamp(), doc );
583 colorRampShaderElem.appendChild( colorRampElem );
584 }
585
586 //items
587 const QList<QgsColorRampShader::ColorRampItem> itemList = colorRampItemList();
588 QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
589 for ( ; itemIt != itemList.constEnd(); ++itemIt )
590 {
591 QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
592 itemElem.setAttribute( QStringLiteral( "label" ), itemIt->label );
593 itemElem.setAttribute( QStringLiteral( "value" ), QgsRasterBlock::printValue( itemIt->value ) );
594 itemElem.setAttribute( QStringLiteral( "color" ), itemIt->color.name() );
595 itemElem.setAttribute( QStringLiteral( "alpha" ), itemIt->color.alpha() );
596 colorRampShaderElem.appendChild( itemElem );
597 }
598
599 if ( mLegendSettings )
600 mLegendSettings->writeXml( doc, colorRampShaderElem, context );
601
602 return colorRampShaderElem;
603}
604
605void QgsColorRampShader::readXml( const QDomElement &colorRampShaderElem, const QgsReadWriteContext &context )
606{
607 // try to load color ramp (optional)
608 QDomElement sourceColorRampElem = colorRampShaderElem.firstChildElement( QStringLiteral( "colorramp" ) );
609 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
610 {
612 }
613
614 setColorRampType( colorRampShaderElem.attribute( QStringLiteral( "colorRampType" ), QStringLiteral( "INTERPOLATED" ) ) );
615 setClassificationMode( static_cast< Qgis::ShaderClassificationMethod >( colorRampShaderElem.attribute( QStringLiteral( "classificationMode" ), QStringLiteral( "1" ) ).toInt() ) );
616 setClip( colorRampShaderElem.attribute( QStringLiteral( "clip" ), QStringLiteral( "0" ) ) == QLatin1String( "1" ) );
617 setMinimumValue( colorRampShaderElem.attribute( QStringLiteral( "minimumValue" ) ).toDouble() );
618 setMaximumValue( colorRampShaderElem.attribute( QStringLiteral( "maximumValue" ) ).toDouble() );
619 setLabelPrecision( colorRampShaderElem.attribute( QStringLiteral( "labelPrecision" ), QStringLiteral( "6" ) ).toDouble() );
620
621 QList<QgsColorRampShader::ColorRampItem> itemList;
622 QDomElement itemElem;
623 QString itemLabel;
624 double itemValue;
625 QColor itemColor;
626
627 const QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( QStringLiteral( "item" ) );
628 itemList.reserve( itemNodeList.size() );
629 for ( int i = 0; i < itemNodeList.size(); ++i )
630 {
631 itemElem = itemNodeList.at( i ).toElement();
632 itemValue = itemElem.attribute( QStringLiteral( "value" ) ).toDouble();
633 itemLabel = itemElem.attribute( QStringLiteral( "label" ) );
634 itemColor.setNamedColor( itemElem.attribute( QStringLiteral( "color" ) ) );
635 itemColor.setAlpha( itemElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt() );
636
637 itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
638 }
639 setColorRampItemList( itemList );
640
641 if ( !mLegendSettings )
642 mLegendSettings = std::make_unique< QgsColorRampLegendNodeSettings >();
643
644 mLegendSettings->readXml( colorRampShaderElem, context );
645}
646
648{
649 return mLegendSettings.get();
650}
651
653{
654 if ( settings == mLegendSettings.get() )
655 return;
656 mLegendSettings.reset( settings );
657}
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