QGIS API Documentation 4.3.0-Master (90cb4ecf9ef)
Loading...
Searching...
No Matches
qgsrasterlayerelevationproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayerelevationproperties.cpp
3 ---------------
4 begin : February 2022
5 copyright : (C) 2022 by Nyall Dawson
6 email : nyall dot dawson dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include "qgsapplication.h"
23#include "qgsfillsymbol.h"
24#include "qgsfillsymbollayer.h"
25#include "qgslinesymbol.h"
26#include "qgslinesymbollayer.h"
27#include "qgsrasterlayer.h"
28#include "qgssymbollayerutils.h"
29
30#include <QString>
31
32#include "moc_qgsrasterlayerelevationproperties.cpp"
33
34using namespace Qt::StringLiterals;
35
38{
40 setDefaultProfileLineSymbol( color );
41 setDefaultProfileFillSymbol( color );
42}
43
45
47{
48 return mEnabled;
49}
50
51QDomElement QgsRasterLayerElevationProperties::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context )
52{
53 QDomElement element = document.createElement( u"elevation"_s );
54 element.setAttribute( u"enabled"_s, mEnabled ? u"1"_s : u"0"_s );
55 element.setAttribute( u"mode"_s, qgsEnumValueToKey( mMode ) );
56 element.setAttribute( u"symbology"_s, qgsEnumValueToKey( mSymbology ) );
57 if ( !std::isnan( mElevationLimit ) )
58 element.setAttribute( u"elevationLimit"_s, qgsDoubleToString( mElevationLimit ) );
59
60 writeCommonProperties( element, document, context );
61
62 switch ( mMode )
63 {
65 element.setAttribute( u"lower"_s, qgsDoubleToString( mFixedRange.lower() ) );
66 element.setAttribute( u"upper"_s, qgsDoubleToString( mFixedRange.upper() ) );
67 element.setAttribute( u"includeLower"_s, mFixedRange.includeLower() ? "1" : "0" );
68 element.setAttribute( u"includeUpper"_s, mFixedRange.includeUpper() ? "1" : "0" );
69 break;
70
72 {
73 QDomElement ranges = document.createElement( u"ranges"_s );
74 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
75 {
76 QDomElement range = document.createElement( u"range"_s );
77 range.setAttribute( u"band"_s, it.key() );
78 range.setAttribute( u"lower"_s, qgsDoubleToString( it.value().lower() ) );
79 range.setAttribute( u"upper"_s, qgsDoubleToString( it.value().upper() ) );
80 range.setAttribute( u"includeLower"_s, it.value().includeLower() ? "1" : "0" );
81 range.setAttribute( u"includeUpper"_s, it.value().includeUpper() ? "1" : "0" );
82 ranges.appendChild( range );
83 }
84 element.appendChild( ranges );
85 break;
86 }
87
89 break;
90
92 element.setAttribute( u"band"_s, mBandNumber );
93 break;
94 }
95
96 QDomElement profileLineSymbolElement = document.createElement( u"profileLineSymbol"_s );
97 profileLineSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileLineSymbol.get(), document, context ) );
98 element.appendChild( profileLineSymbolElement );
99
100 QDomElement profileFillSymbolElement = document.createElement( u"profileFillSymbol"_s );
101 profileFillSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileFillSymbol.get(), document, context ) );
102 element.appendChild( profileFillSymbolElement );
103
104 parentElement.appendChild( element );
105 return element;
106}
107
108bool QgsRasterLayerElevationProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
109{
110 const QDomElement elevationElement = element.firstChildElement( u"elevation"_s ).toElement();
111 mEnabled = elevationElement.attribute( u"enabled"_s, u"0"_s ).toInt();
112 mMode = qgsEnumKeyToValue( elevationElement.attribute( u"mode"_s ), Qgis::RasterElevationMode::RepresentsElevationSurface );
113 mSymbology = qgsEnumKeyToValue( elevationElement.attribute( u"symbology"_s ), Qgis::ProfileSurfaceSymbology::Line );
114 if ( elevationElement.hasAttribute( u"elevationLimit"_s ) )
115 mElevationLimit = elevationElement.attribute( u"elevationLimit"_s ).toDouble();
116 else
117 mElevationLimit = std::numeric_limits< double >::quiet_NaN();
118
119 readCommonProperties( elevationElement, context );
120
121 switch ( mMode )
122 {
124 {
125 const double lower = elevationElement.attribute( u"lower"_s ).toDouble();
126 const double upper = elevationElement.attribute( u"upper"_s ).toDouble();
127 const bool includeLower = elevationElement.attribute( u"includeLower"_s ).toInt();
128 const bool includeUpper = elevationElement.attribute( u"includeUpper"_s ).toInt();
129 mFixedRange = QgsDoubleRange( lower, upper, includeLower, includeUpper );
130 break;
131 }
132
134 {
135 mRangePerBand.clear();
136
137 const QDomNodeList ranges = elevationElement.firstChildElement( u"ranges"_s ).childNodes();
138 for ( int i = 0; i < ranges.size(); ++i )
139 {
140 const QDomElement rangeElement = ranges.at( i ).toElement();
141 const int band = rangeElement.attribute( u"band"_s ).toInt();
142 const double lower = rangeElement.attribute( u"lower"_s ).toDouble();
143 const double upper = rangeElement.attribute( u"upper"_s ).toDouble();
144 const bool includeLower = rangeElement.attribute( u"includeLower"_s ).toInt();
145 const bool includeUpper = rangeElement.attribute( u"includeUpper"_s ).toInt();
146 mRangePerBand.insert( band, QgsDoubleRange( lower, upper, includeLower, includeUpper ) );
147 }
148 break;
149 }
150
152 break;
153
155 mBandNumber = elevationElement.attribute( u"band"_s, u"1"_s ).toInt();
156 break;
157 }
158
159 const QColor defaultColor = QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
160
161 const QDomElement profileLineSymbolElement = elevationElement.firstChildElement( u"profileLineSymbol"_s ).firstChildElement( u"symbol"_s );
162 mProfileLineSymbol = QgsSymbolLayerUtils::loadSymbol< QgsLineSymbol >( profileLineSymbolElement, context );
163 if ( !mProfileLineSymbol )
164 setDefaultProfileLineSymbol( defaultColor );
165
166 const QDomElement profileFillSymbolElement = elevationElement.firstChildElement( u"profileFillSymbol"_s ).firstChildElement( u"symbol"_s );
167 mProfileFillSymbol = QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( profileFillSymbolElement, context );
168 if ( !mProfileFillSymbol )
169 setDefaultProfileFillSymbol( defaultColor );
170
171 return true;
172}
173
175{
176 auto res = std::make_unique< QgsRasterLayerElevationProperties >( nullptr );
177 res->setEnabled( mEnabled );
178 res->setMode( mMode );
179 res->setProfileLineSymbol( mProfileLineSymbol->clone() );
180 res->setProfileFillSymbol( mProfileFillSymbol->clone() );
181 res->setProfileSymbology( mSymbology );
182 res->setElevationLimit( mElevationLimit );
183 res->setBandNumber( mBandNumber );
184 res->setFixedRange( mFixedRange );
185 res->setFixedRangePerBand( mRangePerBand );
186 res->copyCommonProperties( this );
187 return res.release();
188}
189
191{
192 QStringList properties;
193 switch ( mMode )
194 {
196 properties << tr( "Elevation range: %1 to %2" ).arg( mFixedRange.lower() ).arg( mFixedRange.upper() );
197 break;
198
200 {
201 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
202 {
203 properties << tr( "Elevation for band %1: %2 to %3" ).arg( it.key() ).arg( it.value().lower() ).arg( it.value().upper() );
204 }
205 break;
206 }
207
209 break;
210
212 properties << tr( "Elevation band: %1" ).arg( mBandNumber );
213 properties << tr( "Scale: %1" ).arg( mZScale );
214 properties << tr( "Offset: %1" ).arg( mZOffset );
215 break;
216 }
217
218 return u"<li>%1</li>"_s.arg( properties.join( "</li><li>"_L1 ) );
219}
220
222{
223 switch ( mMode )
224 {
226 return mFixedRange.overlaps( range );
227
229 {
230 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
231 {
232 if ( it.value().overlaps( range ) )
233 return true;
234 }
235 return false;
236 }
237
239 {
240 if ( QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
241 {
242 QgsExpressionContext context;
245 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band"_s, 1, true, false, tr( "Band number" ) ) );
246 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_name"_s, rl->dataProvider()->displayBandName( 1 ), true, false, tr( "Band name" ) ) );
247 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_description"_s, rl->dataProvider()->bandDescription( 1 ), true, false, tr( "Band description" ) ) );
248 context.appendScope( bandScope );
249
252 lowerProperty.prepare( context );
253 upperProperty.prepare( context );
254 for ( int band = 1; band <= rl->bandCount(); ++band )
255 {
256 bandScope->setVariable( u"band"_s, band );
257 bandScope->setVariable( u"band_name"_s, rl->dataProvider()->displayBandName( band ) );
258 bandScope->setVariable( u"band_description"_s, rl->dataProvider()->bandDescription( band ) );
259
260 bool ok = false;
261 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
262 if ( !ok )
263 continue;
264 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
265 if ( !ok )
266 continue;
267
268 if ( QgsDoubleRange( lower, upper ).overlaps( range ) )
269 return true;
270 }
271 }
272 return false;
273 }
274
276 // TODO -- test actual raster z range
277 return true;
278 }
280}
281
283{
284 switch ( mMode )
285 {
287 return mFixedRange;
288
290 {
291 double lower = std::numeric_limits< double >::max();
292 double upper = std::numeric_limits< double >::min();
293 bool includeLower = true;
294 bool includeUpper = true;
295 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
296 {
297 if ( it.value().lower() < lower )
298 {
299 lower = it.value().lower();
300 includeLower = it.value().includeLower();
301 }
302 else if ( !includeLower && it.value().lower() == lower && it.value().includeLower() )
303 {
304 includeLower = true;
305 }
306 if ( it.value().upper() > upper )
307 {
308 upper = it.value().upper();
309 includeUpper = it.value().includeUpper();
310 }
311 else if ( !includeUpper && it.value().upper() == upper && it.value().includeUpper() )
312 {
313 includeUpper = true;
314 }
315 }
316 return QgsDoubleRange( lower, upper, includeLower, includeUpper );
317 }
318
320 {
321 if ( QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
322 {
323 QgsExpressionContext context;
326 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band"_s, 1, true, false, tr( "Band number" ) ) );
327 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_name"_s, rl->dataProvider()->displayBandName( 1 ), true, false, tr( "Band name" ) ) );
328 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_description"_s, rl->dataProvider()->bandDescription( 1 ), true, false, tr( "Band description" ) ) );
329 context.appendScope( bandScope );
330
333 lowerProperty.prepare( context );
334 upperProperty.prepare( context );
335 double minLower = std::numeric_limits<double>::max();
336 double maxUpper = std::numeric_limits<double>::lowest();
337 for ( int band = 1; band <= rl->bandCount(); ++band )
338 {
339 bandScope->setVariable( u"band"_s, band );
340 bandScope->setVariable( u"band_name"_s, rl->dataProvider()->displayBandName( band ) );
341 bandScope->setVariable( u"band_description"_s, rl->dataProvider()->bandDescription( band ) );
342
343 bool ok = false;
344 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
345 if ( !ok )
346 continue;
347 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
348 if ( !ok )
349 continue;
350
351 minLower = std::min( minLower, lower );
352 maxUpper = std::max( maxUpper, upper );
353 }
354 return ( minLower == std::numeric_limits<double>::max() && maxUpper == std::numeric_limits<double>::lowest() ) ? QgsDoubleRange() : QgsDoubleRange( minLower, maxUpper );
355 }
356 return QgsDoubleRange();
357 }
358
360 {
361 if ( QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
362 {
363 if ( QgsRasterDataProvider *provider = rl->dataProvider() )
364 {
365 if ( mBandNumber > 0 && mBandNumber <= provider->bandCount() )
366 {
367 const QgsRasterBandStats stats
368 = provider->bandStatistics( mBandNumber, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast< int >( QgsRasterLayer::SAMPLE_SIZE ) );
370 {
372 }
373 }
374 }
375 }
376 return QgsDoubleRange();
377 }
378 }
380}
381
383{
384 switch ( mMode )
385 {
387 {
388 if ( !mFixedRange.isInfinite() && mFixedRange.lower() != mFixedRange.upper() )
389 return { mFixedRange.lower(), mFixedRange.upper() };
390 else if ( !mFixedRange.isInfinite() )
391 return { mFixedRange.lower() };
392
393 return {};
394 }
395
397 {
398 QList< double > res;
399 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
400 {
401 if ( it.value().isInfinite() )
402 continue;
403
404 if ( !res.contains( it.value().lower() ) )
405 res.append( it.value().lower() );
406 if ( !res.contains( it.value().upper() ) )
407 res.append( it.value().upper() );
408 }
409 std::sort( res.begin(), res.end() );
410 return res;
411 }
412
414 {
415 QList< double > res;
416 if ( QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
417 {
418 QgsExpressionContext context;
421 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band"_s, 1, true, false, tr( "Band number" ) ) );
422 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_name"_s, rl->dataProvider()->displayBandName( 1 ), true, false, tr( "Band name" ) ) );
423 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_description"_s, rl->dataProvider()->bandDescription( 1 ), true, false, tr( "Band description" ) ) );
424 context.appendScope( bandScope );
425
428 lowerProperty.prepare( context );
429 upperProperty.prepare( context );
430 for ( int band = 1; band <= rl->bandCount(); ++band )
431 {
432 bandScope->setVariable( u"band"_s, band );
433 bandScope->setVariable( u"band_name"_s, rl->dataProvider()->displayBandName( band ) );
434 bandScope->setVariable( u"band_description"_s, rl->dataProvider()->bandDescription( band ) );
435
436 bool ok = false;
437 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
438 if ( ok && !res.contains( lower ) )
439 res.append( lower );
440 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
441 if ( ok && !res.contains( upper ) )
442 res.append( upper );
443 }
444 }
445 return res;
446 }
447
449 return {};
450 }
452}
453
458
476
478{
479 if ( enabled == mEnabled )
480 return;
481
482 mEnabled = enabled;
483 emit changed();
485}
486
491
493{
494 if ( mMode == mode )
495 return;
496
497 mMode = mode;
498 emit changed();
499}
500
502{
503 if ( mBandNumber == band )
504 return;
505
506 mBandNumber = band;
507 emit changed();
509}
510
512{
513 if ( !mEnabled || std::isnan( pixelValue ) )
514 return QgsDoubleRange();
515
516 switch ( mMode )
517 {
519 return mFixedRange;
520
522 {
523 auto it = mRangePerBand.constFind( band );
524 if ( it != mRangePerBand.constEnd() )
525 return it.value();
526 return QgsDoubleRange();
527 }
528
530 {
531 if ( layer && band > 0 && band <= layer->bandCount() )
532 {
533 QgsExpressionContext context;
536 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band"_s, band, true, false, tr( "Band number" ) ) );
537 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_name"_s, layer->dataProvider()->displayBandName( band ), true, false, tr( "Band name" ) ) );
538 bandScope->addVariable( QgsExpressionContextScope::StaticVariable( u"band_description"_s, layer->dataProvider()->bandDescription( band ), true, false, tr( "Band description" ) ) );
539 context.appendScope( bandScope );
540
543 lowerProperty.prepare( context );
544 upperProperty.prepare( context );
545
546 bool ok = false;
547 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
548 if ( !ok )
549 return QgsDoubleRange();
550 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
551 if ( !ok )
552 return QgsDoubleRange();
553
554 return QgsDoubleRange( lower, upper );
555 }
556
557 return QgsDoubleRange();
558 }
559
561 {
562 if ( band != mBandNumber )
563 return QgsDoubleRange();
564
565 const double z = pixelValue * mZScale + mZOffset;
566 return QgsDoubleRange( z, z );
567 }
568 }
570}
571
573{
574 switch ( mMode )
575 {
578 return -1;
579
581 {
582 // find the top-most band which matches the map range
583 int currentMatchingBand = -1;
584 QgsDoubleRange currentMatchingRange;
585 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
586 {
587 if ( it.value().overlaps( range ) )
588 {
589 if ( currentMatchingRange.isInfinite()
590 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingRange.upper() )
591 || ( !currentMatchingRange.includeUpper() && it.value().upper() >= currentMatchingRange.upper() ) )
592 {
593 currentMatchingBand = it.key();
594 currentMatchingRange = it.value();
595 }
596 }
597 }
598 return currentMatchingBand;
599 }
600
602 {
603 if ( layer )
604 {
605 QgsExpressionContext context;
608 context.appendScope( bandScope );
609
612 lowerProperty.prepare( context );
613 upperProperty.prepare( context );
614
615 int currentMatchingBand = -1;
616 QgsDoubleRange currentMatchingRange;
617
618 for ( int band = 1; band <= layer->bandCount(); ++band )
619 {
620 bandScope->setVariable( u"band"_s, band );
621 bandScope->setVariable( u"band_name"_s, layer->dataProvider()->displayBandName( band ) );
622 bandScope->setVariable( u"band_description"_s, layer->dataProvider()->bandDescription( band ) );
623
624 bool ok = false;
625 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
626 if ( !ok )
627 continue;
628 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
629 if ( !ok )
630 continue;
631
632 const QgsDoubleRange bandRange = QgsDoubleRange( lower, upper );
633 if ( bandRange.overlaps( range ) )
634 {
635 if ( currentMatchingRange.isInfinite()
636 || ( bandRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() )
637 || ( !currentMatchingRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() ) )
638 {
639 currentMatchingBand = band;
640 currentMatchingRange = bandRange;
641 }
642 }
643 }
644 return currentMatchingBand;
645 }
646 return -1;
647 }
648 }
650}
651
653{
654 return mProfileLineSymbol.get();
655}
656
658{
659 mProfileLineSymbol.reset( symbol );
660 emit changed();
662}
663
665{
666 return mProfileFillSymbol.get();
667}
668
670{
671 mProfileFillSymbol.reset( symbol );
672 emit changed();
674}
675
677{
678 if ( mSymbology == symbology )
679 return;
680
681 mSymbology = symbology;
682 emit changed();
684}
685
687{
688 return mElevationLimit;
689}
690
692{
693 if ( qgsDoubleNear( mElevationLimit, limit ) )
694 return;
695
696 mElevationLimit = limit;
697 emit changed();
699}
700
702{
703 // multiple bands => unlikely to be a DEM
704 if ( layer->bandCount() > 1 )
705 return false;
706
707 // raster attribute table => unlikely to be a DEM
708 if ( layer->attributeTable( 1 ) )
709 return false;
710
711 if ( QgsRasterDataProvider *dataProvider = layer->dataProvider() )
712 {
713 // filter out data types which aren't likely to be DEMs
714 switch ( dataProvider->dataType( 1 ) )
715 {
724 return false;
725
733 break;
734 }
735 }
736
737 // Check the layer's name for DEM-ish hints.
738 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
739 // but adding hardcoded localized variants of the strings is encouraged.
740 static const QStringList sPartialCandidates {
741 u"dem"_s,
742 u"dtm"_s,
743 u"dsm"_s,
744 u"height"_s,
745 u"elev"_s,
746 u"srtm"_s,
747 u"dted"_s,
748 // French hints
749 u"mne"_s,
750 u"mnt"_s,
751 u"mns"_s,
752 u"rge"_s,
753 u"alti"_s,
754 // German hints
755 u"dhm"_s,
756 u"dgm"_s,
757 u"dom"_s,
758 u"Höhe"_s,
759 u"Hoehe"_s
760 };
761 const QString layerName = layer->name();
762 for ( const QString &candidate : sPartialCandidates )
763 {
764 if ( layerName.contains( candidate, Qt::CaseInsensitive ) )
765 return true;
766 }
767
768 // these candidates must occur with word boundaries (we don't want to find "aster" in "raster"!)
769 static const QStringList sWordCandidates { u"aster"_s };
770 for ( const QString &candidate : sWordCandidates )
771 {
772 const thread_local QRegularExpression re( u"\\b%1\\b"_s.arg( candidate ) );
773 if ( re.match( layerName, Qt::CaseInsensitive ).hasMatch() )
774 return true;
775 }
776
777 return false;
778}
779
780void QgsRasterLayerElevationProperties::setDefaultProfileLineSymbol( const QColor &color )
781{
782 auto profileLineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( color, 0.6 );
783 mProfileLineSymbol = std::make_unique< QgsLineSymbol>( QgsSymbolLayerList( { profileLineLayer.release() } ) );
784}
785
786void QgsRasterLayerElevationProperties::setDefaultProfileFillSymbol( const QColor &color )
787{
788 auto profileFillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( color );
789 profileFillLayer->setStrokeStyle( Qt::NoPen );
790 mProfileFillSymbol = std::make_unique< QgsFillSymbol>( QgsSymbolLayerList( { profileFillLayer.release() } ) );
791}
792
794{
795 return mRangePerBand;
796}
797
798void QgsRasterLayerElevationProperties::setFixedRangePerBand( const QMap<int, QgsDoubleRange> &ranges )
799{
800 if ( ranges == mRangePerBand )
801 return;
802
803 mRangePerBand = ranges;
804 emit changed();
805}
806
808{
809 return mFixedRange;
810}
811
813{
814 if ( range == mFixedRange )
815 return;
816
817 mFixedRange = range;
818 emit changed();
819}
RasterElevationMode
Raster layer elevation modes.
Definition qgis.h:4240
@ FixedRangePerBand
Layer has a fixed (manually specified) elevation range per band.
Definition qgis.h:4243
@ FixedElevationRange
Layer has a fixed elevation range.
Definition qgis.h:4241
@ RepresentsElevationSurface
Pixel values represent an elevation surface.
Definition qgis.h:4242
@ DynamicRangePerBand
Layer has a elevation range per band, calculated dynamically from an expression.
Definition qgis.h:4244
@ CInt32
Complex Int32.
Definition qgis.h:404
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:401
@ CFloat64
Complex Float64.
Definition qgis.h:406
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:398
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition qgis.h:408
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:396
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:397
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:395
@ UnknownDataType
Unknown or unspecified type.
Definition qgis.h:394
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition qgis.h:407
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:400
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:402
@ CFloat32
Complex Float32.
Definition qgis.h:405
@ CInt16
Complex Int16.
Definition qgis.h:403
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:399
ProfileSurfaceSymbology
Surface symbology type for elevation profile plots.
Definition qgis.h:4594
@ Line
The elevation surface will be rendered using a line symbol.
Definition qgis.h:4595
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
QColor fetchRandomStyleColor() const
Returns a random color for use with a new symbol style (e.g.
QgsRange which stores a range of double values.
Definition qgsrange.h:217
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:266
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsPropertyCollection mDataDefinedProperties
Property collection for data defined elevation settings.
void writeCommonProperties(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context)
Writes common class properties to a DOM element, to be used later with readXml().
void profileGenerationPropertyChanged()
Emitted when any of the elevation properties which relate solely to generation of elevation profiles ...
QgsMapLayerElevationProperties(QObject *parent)
Constructor for QgsMapLayerElevationProperties, with the specified parent object.
void readCommonProperties(const QDomElement &element, const QgsReadWriteContext &context)
Reads common class properties from a DOM element previously written by writeXml().
void changed()
Emitted when any of the elevation properties have changed.
void profileRenderingPropertyChanged()
Emitted when any of the elevation properties which relate solely to presentation of elevation results...
@ RasterPerBandUpperElevation
Upper elevation for each raster band.
@ RasterPerBandLowerElevation
Lower elevation for each raster band.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when z range context is modified.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString name
Definition qgsmaplayer.h:87
A store for object properties.
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const
Prepares the property against a specified expression context.
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
Definition qgsrange.h:102
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:171
T upper() const
Returns the upper bound of the range.
Definition qgsrange.h:86
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
Qgis::RasterBandStatistics statsGathered
Collected statistics.
double maximumValue
The maximum cell value in the raster band.
Base class for raster data providers.
virtual QString bandDescription(int bandNumber)
Returns the description for band bandNumber, or an empty string if the band is not valid or has not d...
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
QgsDoubleRange fixedRange() const
Returns the fixed elevation range for the raster.
void setProfileFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used to render the raster profile in elevation profile plots.
void setFixedRange(const QgsDoubleRange &range)
Sets the fixed elevation range for the raster.
QgsDoubleRange elevationRangeForPixelValue(QgsRasterLayer *layer, int band, double pixelValue) const
Returns the elevation range corresponding to a raw pixel value from the specified band.
QList< double > significantZValues(QgsMapLayer *layer) const override
Returns a list of significant elevation/z-values for the specified layer, using the settings defined ...
Qgis::RasterElevationMode mode() const
Returns the elevation mode.
QgsLineSymbol * profileLineSymbol() const
Returns the line symbol used to render the raster profile in elevation profile plots.
bool hasElevation() const override
Returns true if the layer has an elevation or z component.
QgsRasterLayerElevationProperties * clone() const override
Creates a clone of the properties.
QgsDoubleRange calculateZRange(QgsMapLayer *layer) const override
Attempts to calculate the overall elevation or z range for the specified layer, using the settings de...
QgsMapLayerElevationProperties::Flags flags() const override
Returns flags associated to the elevation properties.
void setBandNumber(int band)
Sets the band number from which the elevation should be taken.
int bandForElevationRange(QgsRasterLayer *layer, const QgsDoubleRange &range) const
Returns the band corresponding to the specified range.
QString htmlSummary() const override
Returns a HTML formatted summary of the properties.
void setElevationLimit(double limit)
Sets the elevation limit, which is used when profileSymbology() is Qgis::ProfileSurfaceSymbology::Fil...
void setFixedRangePerBand(const QMap< int, QgsDoubleRange > &ranges)
Sets the fixed elevation range for each band.
bool isVisibleInZRange(const QgsDoubleRange &range, QgsMapLayer *layer=nullptr) const override
Returns true if the layer should be visible and rendered for the specified z range.
void setProfileSymbology(Qgis::ProfileSurfaceSymbology symbology)
Sets the symbology option used to render the raster profile in elevation profile plots.
QMap< int, QgsDoubleRange > fixedRangePerBand() const
Returns the fixed elevation range for each band.
static bool layerLooksLikeDem(QgsRasterLayer *layer)
Returns true if a raster layer looks like a DEM.
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
QgsFillSymbol * profileFillSymbol() const
Returns the fill symbol used to render the raster profile in elevation profile plots.
double elevationLimit() const
Returns the elevation limit, which is used when profileSymbology() is Qgis::ProfileSurfaceSymbology::...
void setProfileLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used to render the raster profile in elevation profile plots.
void setMode(Qgis::RasterElevationMode mode)
Sets the elevation mode.
void setEnabled(bool enabled)
Sets whether the elevation properties are enabled, i.e.
QgsRasterLayerElevationProperties(QObject *parent)
Constructor for QgsRasterLayerElevationProperties, with the specified parent object.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the elevation properties from a DOM element previously written by writeXml().
bool showByDefaultInElevationProfilePlots() const override
Returns true if the layer should be visible by default in newly created elevation profile plots.
Represents a raster layer.
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly NULL) raster attribute table for the given band bandNumber.
int bandCount() const
Returns the number of bands in this layer.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
A container for the context for various read/write operations on objects.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7812
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:7464
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7793
#define BUILTIN_UNREACHABLE
Definition qgis.h:8191
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7557
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
Single variable definition for use within a QgsExpressionContextScope.