33 setDefaultProfileLineSymbol( color );
34 setDefaultProfileFillSymbol( color );
46 QDomElement element = document.createElement( QStringLiteral(
"elevation" ) );
47 element.setAttribute( QStringLiteral(
"enabled" ), mEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
49 element.setAttribute( QStringLiteral(
"symbology" ),
qgsEnumValueToKey( mSymbology ) );
50 if ( !std::isnan( mElevationLimit ) )
51 element.setAttribute( QStringLiteral(
"elevationLimit" ),
qgsDoubleToString( mElevationLimit ) );
60 element.setAttribute( QStringLiteral(
"includeLower" ), mFixedRange.
includeLower() ?
"1" :
"0" );
61 element.setAttribute( QStringLiteral(
"includeUpper" ), mFixedRange.
includeUpper() ?
"1" :
"0" );
66 QDomElement ranges = document.createElement( QStringLiteral(
"ranges" ) );
67 for (
auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
69 QDomElement range = document.createElement( QStringLiteral(
"range" ) );
70 range.setAttribute( QStringLiteral(
"band" ), it.key() );
71 range.setAttribute( QStringLiteral(
"lower" ),
qgsDoubleToString( it.value().lower() ) );
72 range.setAttribute( QStringLiteral(
"upper" ),
qgsDoubleToString( it.value().upper() ) );
73 range.setAttribute( QStringLiteral(
"includeLower" ), it.value().includeLower() ?
"1" :
"0" );
74 range.setAttribute( QStringLiteral(
"includeUpper" ), it.value().includeUpper() ?
"1" :
"0" );
75 ranges.appendChild( range );
77 element.appendChild( ranges );
85 element.setAttribute( QStringLiteral(
"band" ), mBandNumber );
89 QDomElement profileLineSymbolElement = document.createElement( QStringLiteral(
"profileLineSymbol" ) );
91 element.appendChild( profileLineSymbolElement );
93 QDomElement profileFillSymbolElement = document.createElement( QStringLiteral(
"profileFillSymbol" ) );
95 element.appendChild( profileFillSymbolElement );
97 parentElement.appendChild( element );
103 const QDomElement elevationElement = element.firstChildElement( QStringLiteral(
"elevation" ) ).toElement();
104 mEnabled = elevationElement.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt();
107 if ( elevationElement.hasAttribute( QStringLiteral(
"elevationLimit" ) ) )
108 mElevationLimit = elevationElement.attribute( QStringLiteral(
"elevationLimit" ) ).toDouble();
110 mElevationLimit = std::numeric_limits< double >::quiet_NaN();
118 const double lower = elevationElement.attribute( QStringLiteral(
"lower" ) ).toDouble();
119 const double upper = elevationElement.attribute( QStringLiteral(
"upper" ) ).toDouble();
120 const bool includeLower = elevationElement.attribute( QStringLiteral(
"includeLower" ) ).toInt();
121 const bool includeUpper = elevationElement.attribute( QStringLiteral(
"includeUpper" ) ).toInt();
128 mRangePerBand.clear();
130 const QDomNodeList ranges = elevationElement.firstChildElement( QStringLiteral(
"ranges" ) ).childNodes();
131 for (
int i = 0; i < ranges.size(); ++i )
133 const QDomElement rangeElement = ranges.at( i ).toElement();
134 const int band = rangeElement.attribute( QStringLiteral(
"band" ) ).toInt();
135 const double lower = rangeElement.attribute( QStringLiteral(
"lower" ) ).toDouble();
136 const double upper = rangeElement.attribute( QStringLiteral(
"upper" ) ).toDouble();
137 const bool includeLower = rangeElement.attribute( QStringLiteral(
"includeLower" ) ).toInt();
138 const bool includeUpper = rangeElement.attribute( QStringLiteral(
"includeUpper" ) ).toInt();
148 mBandNumber = elevationElement.attribute( QStringLiteral(
"band" ), QStringLiteral(
"1" ) ).toInt();
154 const QDomElement profileLineSymbolElement = elevationElement.firstChildElement( QStringLiteral(
"profileLineSymbol" ) ).firstChildElement( QStringLiteral(
"symbol" ) );
155 mProfileLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsLineSymbol >( profileLineSymbolElement, context ) );
156 if ( !mProfileLineSymbol )
157 setDefaultProfileLineSymbol( defaultColor );
159 const QDomElement profileFillSymbolElement = elevationElement.firstChildElement( QStringLiteral(
"profileFillSymbol" ) ).firstChildElement( QStringLiteral(
"symbol" ) );
160 mProfileFillSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( profileFillSymbolElement, context ) );
161 if ( !mProfileFillSymbol )
162 setDefaultProfileFillSymbol( defaultColor );
169 std::unique_ptr< QgsRasterLayerElevationProperties > res = std::make_unique< QgsRasterLayerElevationProperties >(
nullptr );
170 res->setEnabled( mEnabled );
171 res->setMode( mMode );
172 res->setProfileLineSymbol( mProfileLineSymbol->clone() );
173 res->setProfileFillSymbol( mProfileFillSymbol->clone() );
174 res->setProfileSymbology( mSymbology );
175 res->setElevationLimit( mElevationLimit );
176 res->setBandNumber( mBandNumber );
177 res->setFixedRange( mFixedRange );
178 res->setFixedRangePerBand( mRangePerBand );
179 res->copyCommonProperties(
this );
180 return res.release();
185 QStringList properties;
189 properties << tr(
"Elevation range: %1 to %2" ).arg( mFixedRange.
lower() ).arg( mFixedRange.
upper() );
194 for (
auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
196 properties << tr(
"Elevation for band %1: %2 to %3" ).arg( it.key() ).arg( it.value().lower() ).arg( it.value().upper() );
205 properties << tr(
"Elevation band: %1" ).arg( mBandNumber );
206 properties << tr(
"Scale: %1" ).arg(
mZScale );
207 properties << tr(
"Offset: %1" ).arg(
mZOffset );
211 return QStringLiteral(
"<li>%1</li>" ).arg( properties.join( QLatin1String(
"</li><li>" ) ) );
219 return mFixedRange.
overlaps( range );
223 for (
auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
225 if ( it.value().overlaps( range ) )
233 if (
QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
245 lowerProperty.
prepare( context );
246 upperProperty.
prepare( context );
247 for (
int band = 1; band <= rl->bandCount(); ++band )
249 bandScope->
setVariable( QStringLiteral(
"band" ), band );
250 bandScope->
setVariable( QStringLiteral(
"band_name" ), rl->dataProvider()->displayBandName( band ) );
251 bandScope->
setVariable( QStringLiteral(
"band_description" ), rl->dataProvider()->bandDescription( band ) );
257 const double upper = upperProperty.
valueAsDouble( context, 0, &ok );
284 double lower = std::numeric_limits< double >::max();
285 double upper = std::numeric_limits< double >::min();
286 bool includeLower =
true;
287 bool includeUpper =
true;
288 for (
auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
290 if ( it.value().lower() <
lower )
292 lower = it.value().lower();
293 includeLower = it.value().includeLower();
295 else if ( !includeLower && it.value().lower() ==
lower && it.value().includeLower() )
299 if ( it.value().upper() > upper )
301 upper = it.value().upper();
302 includeUpper = it.value().includeUpper();
304 else if ( !includeUpper && it.value().upper() == upper && it.value().includeUpper() )
314 if (
QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer ) )
326 lowerProperty.
prepare( context );
327 upperProperty.
prepare( context );
328 double minLower = std::numeric_limits<double>::max();
329 double maxUpper = std::numeric_limits<double>::lowest();
330 for (
int band = 1; band <= rl->bandCount(); ++band )
332 bandScope->
setVariable( QStringLiteral(
"band" ), band );
333 bandScope->
setVariable( QStringLiteral(
"band_name" ), rl->dataProvider()->displayBandName( band ) );
334 bandScope->
setVariable( QStringLiteral(
"band_description" ), rl->dataProvider()->bandDescription( band ) );
340 const double upper = upperProperty.
valueAsDouble( context, 0, &ok );
344 minLower = std::min( minLower,
lower );
345 maxUpper = std::max( maxUpper, upper );
347 return ( minLower == std::numeric_limits<double>::max() && maxUpper == std::numeric_limits<double>::lowest() ) ?
QgsDoubleRange() :
QgsDoubleRange( minLower, maxUpper );
371 return QgsMapLayerElevationProperties::Flag::FlagDontInvalidateCachedRendersWhenRangeChanges;
384 if ( enabled == mEnabled )
408 if ( mBandNumber == band )
418 if ( !mEnabled || std::isnan( pixelValue ) )
428 auto it = mRangePerBand.constFind( band );
429 if ( it != mRangePerBand.constEnd() )
436 if ( layer && band > 0 && band <= layer->bandCount() )
448 lowerProperty.
prepare( context );
449 upperProperty.
prepare( context );
455 const double upper = upperProperty.
valueAsDouble( context, 0, &ok );
467 if ( band != mBandNumber )
488 int currentMatchingBand = -1;
490 for (
auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
492 if ( it.value().overlaps( range ) )
495 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingRange.
upper() )
496 || ( !currentMatchingRange.
includeUpper() && it.value().upper() >= currentMatchingRange.
upper() ) )
498 currentMatchingBand = it.key();
499 currentMatchingRange = it.value();
503 return currentMatchingBand;
517 lowerProperty.
prepare( context );
518 upperProperty.
prepare( context );
520 int currentMatchingBand = -1;
523 for (
int band = 1; band <= layer->
bandCount(); ++band )
525 bandScope->
setVariable( QStringLiteral(
"band" ), band );
533 const double upper = upperProperty.
valueAsDouble( context, 0, &ok );
544 currentMatchingBand = band;
545 currentMatchingRange = bandRange;
549 return currentMatchingBand;
559 return mProfileLineSymbol.get();
564 mProfileLineSymbol.reset( symbol );
571 return mProfileFillSymbol.get();
576 mProfileFillSymbol.reset( symbol );
583 if ( mSymbology == symbology )
586 mSymbology = symbology;
593 return mElevationLimit;
601 mElevationLimit = limit;
619 switch ( dataProvider->dataType( 1 ) )
645 static const QStringList sPartialCandidates{ QStringLiteral(
"dem" ),
646 QStringLiteral(
"dtm" ),
647 QStringLiteral(
"dsm" ),
648 QStringLiteral(
"height" ),
649 QStringLiteral(
"elev" ),
650 QStringLiteral(
"srtm" ),
652 QStringLiteral(
"mne" ),
653 QStringLiteral(
"mnt" ),
654 QStringLiteral(
"mns" ),
655 QStringLiteral(
"rge" ),
656 QStringLiteral(
"alti" ),
658 QStringLiteral(
"dhm" ),
659 QStringLiteral(
"dgm" ),
660 QStringLiteral(
"dom" ),
661 QStringLiteral(
"Höhe" ),
662 QStringLiteral(
"Hoehe" ) };
663 const QString layerName = layer->
name();
664 for (
const QString &candidate : sPartialCandidates )
666 if ( layerName.contains( candidate, Qt::CaseInsensitive ) )
671 static const QStringList sWordCandidates{ QStringLiteral(
"aster" ) };
672 for (
const QString &candidate : sWordCandidates )
674 const thread_local QRegularExpression re( QStringLiteral(
"\\b%1\\b" ).arg( candidate ) );
675 if ( re.match( layerName, Qt::CaseInsensitive ).hasMatch() )
682void QgsRasterLayerElevationProperties::setDefaultProfileLineSymbol(
const QColor &color )
684 std::unique_ptr< QgsSimpleLineSymbolLayer > profileLineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( color, 0.6 );
685 mProfileLineSymbol = std::make_unique< QgsLineSymbol>(
QgsSymbolLayerList( { profileLineLayer.release() } ) );
688void QgsRasterLayerElevationProperties::setDefaultProfileFillSymbol(
const QColor &color )
690 std::unique_ptr< QgsSimpleFillSymbolLayer > profileFillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( color );
691 profileFillLayer->setStrokeStyle( Qt::NoPen );
692 mProfileFillSymbol = std::make_unique< QgsFillSymbol>(
QgsSymbolLayerList( { profileFillLayer.release() } ) );
697 return mRangePerBand;
702 if ( ranges == mRangePerBand )
705 mRangePerBand = ranges;
716 if ( range == mFixedRange )
RasterElevationMode
Raster layer elevation modes.
@ FixedRangePerBand
Layer has a fixed (manually specified) elevation range per band.
@ FixedElevationRange
Layer has a fixed elevation range.
@ RepresentsElevationSurface
Pixel values represent an elevation surface.
@ DynamicRangePerBand
Layer has a elevation range per band, calculated dynamically from an expression.
@ Float32
Thirty two bit floating point (float)
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32)
@ Float64
Sixty four bit floating point (double)
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32)
ProfileSurfaceSymbology
Surface symbology type for elevation profile plots.
@ Line
The elevation surface will be rendered using a line symbol.
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.
bool isInfinite() const
Returns true if the range consists of all possible values.
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.
Base class for storage of map layer elevation properties.
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 ...
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 (since QGIS 3.38)
@ RasterPerBandLowerElevation
Lower elevation for each raster band (since QGIS 3.38)
Base class for all map layer types.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
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.
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
T lower() const
Returns the lower bound of the range.
bool includeLower() const
Returns true if the lower bound is inclusive, or false if the lower bound is exclusive.
T upper() const
Returns the upper bound of the range.
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.
Raster layer specific subclass of QgsMapLayerElevationProperties.
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.
~QgsRasterLayerElevationProperties() override
QgsDoubleRange elevationRangeForPixelValue(QgsRasterLayer *layer, int band, double pixelValue) const
Returns the elevation range corresponding to a raw pixel value from the specified band.
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.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
The class is used as a container of context for various read/write operations on other objects.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
int ANALYSIS_EXPORT lower(int n, int i)
Lower function.
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.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
#define BUILTIN_UNREACHABLE
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsSymbolLayer * > QgsSymbolLayerList
Single variable definition for use within a QgsExpressionContextScope.