QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
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#include "qgsrasterlayer.h"
20#include "qgslinesymbol.h"
21#include "qgsfillsymbol.h"
22#include "qgssymbollayerutils.h"
23#include "qgslinesymbollayer.h"
24#include "qgsfillsymbollayer.h"
25#include "qgsapplication.h"
27
30{
32 setDefaultProfileLineSymbol( color );
33 setDefaultProfileFillSymbol( color );
34}
35
37
39{
40 return mEnabled;
41}
42
43QDomElement QgsRasterLayerElevationProperties::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context )
44{
45 QDomElement element = document.createElement( QStringLiteral( "elevation" ) );
46 element.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
47 element.setAttribute( QStringLiteral( "symbology" ), qgsEnumValueToKey( mSymbology ) );
48 if ( !std::isnan( mElevationLimit ) )
49 element.setAttribute( QStringLiteral( "elevationLimit" ), qgsDoubleToString( mElevationLimit ) );
50
51 writeCommonProperties( element, document, context );
52 element.setAttribute( QStringLiteral( "band" ), mBandNumber );
53
54 QDomElement profileLineSymbolElement = document.createElement( QStringLiteral( "profileLineSymbol" ) );
55 profileLineSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileLineSymbol.get(), document, context ) );
56 element.appendChild( profileLineSymbolElement );
57
58 QDomElement profileFillSymbolElement = document.createElement( QStringLiteral( "profileFillSymbol" ) );
59 profileFillSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileFillSymbol.get(), document, context ) );
60 element.appendChild( profileFillSymbolElement );
61
62 parentElement.appendChild( element );
63 return element;
64}
65
66bool QgsRasterLayerElevationProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
67{
68 const QDomElement elevationElement = element.firstChildElement( QStringLiteral( "elevation" ) ).toElement();
69 mEnabled = elevationElement.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt();
70 mSymbology = qgsEnumKeyToValue( elevationElement.attribute( QStringLiteral( "symbology" ) ), Qgis::ProfileSurfaceSymbology::Line );
71 if ( elevationElement.hasAttribute( QStringLiteral( "elevationLimit" ) ) )
72 mElevationLimit = elevationElement.attribute( QStringLiteral( "elevationLimit" ) ).toDouble();
73 else
74 mElevationLimit = std::numeric_limits< double >::quiet_NaN();
75
76 readCommonProperties( elevationElement, context );
77 mBandNumber = elevationElement.attribute( QStringLiteral( "band" ), QStringLiteral( "1" ) ).toInt();
78
79 const QColor defaultColor = QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
80
81 const QDomElement profileLineSymbolElement = elevationElement.firstChildElement( QStringLiteral( "profileLineSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) );
82 mProfileLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsLineSymbol >( profileLineSymbolElement, context ) );
83 if ( !mProfileLineSymbol )
84 setDefaultProfileLineSymbol( defaultColor );
85
86 const QDomElement profileFillSymbolElement = elevationElement.firstChildElement( QStringLiteral( "profileFillSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) );
87 mProfileFillSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( profileFillSymbolElement, context ) );
88 if ( !mProfileFillSymbol )
89 setDefaultProfileFillSymbol( defaultColor );
90
91 return true;
92}
93
95{
96 std::unique_ptr< QgsRasterLayerElevationProperties > res = std::make_unique< QgsRasterLayerElevationProperties >( nullptr );
97 res->setEnabled( mEnabled );
98 res->setProfileLineSymbol( mProfileLineSymbol->clone() );
99 res->setProfileFillSymbol( mProfileFillSymbol->clone() );
100 res->setProfileSymbology( mSymbology );
101 res->setElevationLimit( mElevationLimit );
102 res->setBandNumber( mBandNumber );
103 res->copyCommonProperties( this );
104 return res.release();
105}
106
108{
109 QStringList properties;
110 properties << tr( "Elevation band: %1" ).arg( mBandNumber );
111 properties << tr( "Scale: %1" ).arg( mZScale );
112 properties << tr( "Offset: %1" ).arg( mZOffset );
113 return QStringLiteral( "<li>%1</li>" ).arg( properties.join( QLatin1String( "</li><li>" ) ) );
114}
115
117{
118 // TODO -- test actual raster z range
119 return true;
120}
121
123{
124 // TODO -- determine actual z range from raster statistics
125 return QgsDoubleRange();
126}
127
132
134{
135 if ( enabled == mEnabled )
136 return;
137
138 mEnabled = enabled;
139 emit changed();
141}
142
144{
145 if ( mBandNumber == band )
146 return;
147
148 mBandNumber = band;
149 emit changed();
151}
152
154{
155 return mProfileLineSymbol.get();
156}
157
159{
160 mProfileLineSymbol.reset( symbol );
161 emit changed();
163}
164
166{
167 return mProfileFillSymbol.get();
168}
169
171{
172 mProfileFillSymbol.reset( symbol );
173 emit changed();
175}
176
178{
179 if ( mSymbology == symbology )
180 return;
181
182 mSymbology = symbology;
183 emit changed();
185}
186
188{
189 return mElevationLimit;
190}
191
193{
194 if ( qgsDoubleNear( mElevationLimit, limit ) )
195 return;
196
197 mElevationLimit = limit;
198 emit changed();
200}
201
203{
204 // multiple bands => unlikely to be a DEM
205 if ( layer->bandCount() > 1 )
206 return false;
207
208 // raster attribute table => unlikely to be a DEM
209 if ( layer->attributeTable( 1 ) )
210 return false;
211
212 if ( QgsRasterDataProvider *dataProvider = layer->dataProvider() )
213 {
214 // filter out data types which aren't likely to be DEMs
215 switch ( dataProvider->dataType( 1 ) )
216 {
225 return false;
226
234 break;
235 }
236 }
237
238 // Check the layer's name for DEM-ish hints.
239 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
240 // but adding hardcoded localized variants of the strings is encouraged.
241 static const QStringList sPartialCandidates{ QStringLiteral( "dem" ),
242 QStringLiteral( "dtm" ),
243 QStringLiteral( "dsm" ),
244 QStringLiteral( "height" ),
245 QStringLiteral( "elev" ),
246 QStringLiteral( "srtm" ),
247 // French hints
248 QStringLiteral( "mne" ),
249 QStringLiteral( "mnt" ),
250 QStringLiteral( "mns" ),
251 QStringLiteral( "rge" ),
252 QStringLiteral( "alti" ),
253 // German hints
254 QStringLiteral( "dhm" ),
255 QStringLiteral( "dgm" ),
256 QStringLiteral( "dom" ),
257 QStringLiteral( "Höhe" ),
258 QStringLiteral( "Hoehe" ) };
259 const QString layerName = layer->name();
260 for ( const QString &candidate : sPartialCandidates )
261 {
262 if ( layerName.contains( candidate, Qt::CaseInsensitive ) )
263 return true;
264 }
265
266 // these candidates must occur with word boundaries (we don't want to find "aster" in "raster"!)
267 static const QStringList sWordCandidates{ QStringLiteral( "aster" ) };
268 for ( const QString &candidate : sWordCandidates )
269 {
270 const thread_local QRegularExpression re( QStringLiteral( "\\b%1\\b" ).arg( candidate ) );
271 if ( re.match( layerName, Qt::CaseInsensitive ).hasMatch() )
272 return true;
273 }
274
275 return false;
276}
277
278void QgsRasterLayerElevationProperties::setDefaultProfileLineSymbol( const QColor &color )
279{
280 std::unique_ptr< QgsSimpleLineSymbolLayer > profileLineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( color, 0.6 );
281 mProfileLineSymbol = std::make_unique< QgsLineSymbol>( QgsSymbolLayerList( { profileLineLayer.release() } ) );
282}
283
284void QgsRasterLayerElevationProperties::setDefaultProfileFillSymbol( const QColor &color )
285{
286 std::unique_ptr< QgsSimpleFillSymbolLayer > profileFillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( color );
287 profileFillLayer->setStrokeStyle( Qt::NoPen );
288 mProfileFillSymbol = std::make_unique< QgsFillSymbol>( QgsSymbolLayerList( { profileFillLayer.release() } ) );
289}
@ CInt32
Complex Int32.
@ 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.
@ CInt16
Complex Int16.
@ UInt32
Thirty two bit unsigned integer (quint32)
ProfileSurfaceSymbology
Surface symbology type for elevation profile plots.
Definition qgis.h:2823
@ 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.
Definition qgsrange.h:203
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.
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...
Base class for all map layer types.
Definition qgsmaplayer.h:74
QString name
Definition qgsmaplayer.h:77
Base class for raster data providers.
Raster layer specific subclass of QgsMapLayerElevationProperties.
void setProfileFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used to render the raster profile in elevation profile plots.
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.
bool isVisibleInZRange(const QgsDoubleRange &range) const override
Returns true if the layer should be visible and rendered for the specified z range.
QgsDoubleRange calculateZRange(QgsMapLayer *layer) const override
Attempts to calculate the overall elevation or z range for the specified layer, using the settings de...
void setBandNumber(int band)
Sets the band number from which the elevation should be taken.
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 setProfileSymbology(Qgis::ProfileSurfaceSymbology symbology)
Sets the symbology option used to render the raster profile in elevation profile plots.
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 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.
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:4555
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:4271
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:4536
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:4332
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30