QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgselevationshadingrenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgselevationshadingrenderer.cpp - QgsElevationShadingRenderer
3
4 ---------------------
5 begin : 4.12.2022
6 copyright : (C) 2022 by Vincent Cloarec
7 email : vcloarec at gmail dot com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
17
18#include <QImage>
19
20#include "qgselevationmap.h"
21#include "qgsrendercontext.h"
22#include "qgsunittypes.h"
23
25{
26}
27
28void QgsElevationShadingRenderer::renderShading( const QgsElevationMap &elevation, QImage &image, const QgsRenderContext &context ) const
29{
30 if ( elevation.rawElevationImage().size() != image.size() )
31 return;
32
33 if ( mRenderEdl )
34 renderEdl( elevation, image, context );
35
36 if ( mRenderHillshading )
37 renderHillshading( elevation, image, context );
38}
39
41{
42 mIsActive = active;
43}
44
46{
47 return mIsActive;
48}
49
51{
52 mRenderEdl = active;
53}
54
56{
57 return mRenderEdl;
58}
59
61{
62 mRenderHillshading = active;
63}
64
66{
67 return mRenderHillshading;
68}
69
71{
72 return mHillshadingZFactor;
73}
74
76{
77 mHillshadingZFactor = zFactor;
78}
79
81{
82 return mHillshadingMultiDir;
83}
84
86{
87 mHillshadingMultiDir = multiDirectional;
88}
89
91{
92 return mLightAltitude;
93}
94
96{
97 mLightAltitude = lightAltitude;
98}
99
101{
102 return mLightAzimuth;
103}
104
106{
107 mLightAzimuth = lightAzimuth;
108}
109
110void QgsElevationShadingRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext & ) const
111{
112 elem.setAttribute( QStringLiteral( "is-active" ), mIsActive ? 1 : 0 );
113
114 elem.setAttribute( QStringLiteral( "combined-method" ), static_cast<int>( mCombinedElevationMethod ) );
115
116 elem.setAttribute( QStringLiteral( "edl-is-active" ), mRenderEdl ? 1 : 0 );
117 elem.setAttribute( QStringLiteral( "edl-strength" ), qgsDoubleToString( mEyeDomeLightingStrength ) );
118 elem.setAttribute( QStringLiteral( "edl-distance" ), qgsDoubleToString( mEyeDomeLightingDistance ) );
119 elem.setAttribute( QStringLiteral( "edl-distance-unit" ), static_cast<int>( mEyeDomeLightingDistanceUnit ) );
120
121 elem.setAttribute( QStringLiteral( "hillshading-is-active" ), mRenderHillshading ? 1 : 0 );
122 elem.setAttribute( QStringLiteral( "hillshading-z-factor" ), qgsDoubleToString( mHillshadingZFactor ) );
123 elem.setAttribute( QStringLiteral( "hillshading-is-multidirectional" ), mHillshadingMultiDir ? 1 : 0 );
124
125 elem.setAttribute( QStringLiteral( "light-altitude" ), qgsDoubleToString( mLightAltitude ) );
126 elem.setAttribute( QStringLiteral( "light-azimuth" ), qgsDoubleToString( mLightAzimuth ) );
127}
128
129void QgsElevationShadingRenderer::readXml( const QDomElement &element, const QgsReadWriteContext & )
130{
131 if ( element.hasAttribute( QStringLiteral( "is-active" ) ) )
132 mIsActive = element.attribute( QStringLiteral( "is-active" ) ).toInt() == 1;
133
134 if ( element.hasAttribute( QStringLiteral( "combined-method" ) ) )
135 mCombinedElevationMethod = static_cast<Qgis::ElevationMapCombineMethod>( element.attribute( QStringLiteral( "combined-method" ) ).toInt() );
136
137 if ( element.hasAttribute( QStringLiteral( "edl-is-active" ) ) )
138 mRenderEdl = element.attribute( QStringLiteral( "edl-is-active" ) ).toInt() == 1;
139
140 if ( element.hasAttribute( QStringLiteral( "edl-strength" ) ) )
141 mEyeDomeLightingStrength = element.attribute( QStringLiteral( "edl-strength" ) ).toDouble();
142
143 if ( element.hasAttribute( QStringLiteral( "edl-distance" ) ) )
144 mEyeDomeLightingDistance = element.attribute( QStringLiteral( "edl-distance" ) ).toDouble();
145
146 if ( element.hasAttribute( QStringLiteral( "edl-distance-unit" ) ) )
147 mEyeDomeLightingDistanceUnit = static_cast<Qgis::RenderUnit>( element.attribute( QStringLiteral( "edl-distance-unit" ) ).toInt() );
148
149 if ( element.hasAttribute( QStringLiteral( "hillshading-is-active" ) ) )
150 mRenderHillshading = element.attribute( QStringLiteral( "hillshading-is-active" ) ).toInt() == 1;
151
152 if ( element.hasAttribute( QStringLiteral( "hillshading-z-factor" ) ) )
153 mHillshadingZFactor = element.attribute( QStringLiteral( "hillshading-z-factor" ) ).toDouble();
154
155 if ( element.hasAttribute( QStringLiteral( "hillshading-is-multidirectional" ) ) )
156 mHillshadingMultiDir = element.attribute( QStringLiteral( "hillshading-is-multidirectional" ) ).toInt() == 1;
157
158 if ( element.hasAttribute( QStringLiteral( "light-altitude" ) ) )
159 mLightAltitude = element.attribute( QStringLiteral( "light-altitude" ) ).toDouble();
160
161 if ( element.hasAttribute( QStringLiteral( "light-azimuth" ) ) )
162 mLightAzimuth = element.attribute( QStringLiteral( "light-azimuth" ) ).toDouble();
163}
164
166{
167 return mCombinedElevationMethod;
168}
169
171{
172 mCombinedElevationMethod = newCombinedElevationMethod;
173}
174
176{
177 return mEyeDomeLightingDistanceUnit;
178}
179
181{
182 mEyeDomeLightingDistanceUnit = newEyeDomeLightingDistanceUnit;
183}
184
186{
187 return mEyeDomeLightingDistance;
188}
189
191{
192 mEyeDomeLightingDistance = distance;
193}
194
196{
197 return mEyeDomeLightingStrength;
198}
199
201{
202 mEyeDomeLightingStrength = strength;
203}
204
205void QgsElevationShadingRenderer::renderEdl( const QgsElevationMap &elevation, QImage &image, const QgsRenderContext &context ) const
206{
207 double strength = mEyeDomeLightingStrength;
208 double distanceDouble = context.convertToPainterUnits( mEyeDomeLightingDistance, mEyeDomeLightingDistanceUnit );
209 int distance = static_cast<int>( std::round( distanceDouble ) );
210
211 elevation.applyEyeDomeLighting( image, distance, static_cast<float>( strength ), static_cast<float>( context.rendererScale() ) );
212}
213
214void QgsElevationShadingRenderer::renderHillshading( const QgsElevationMap &elevation, QImage &image, const QgsRenderContext &context ) const
215{
216 double pixelSize = context.mapToPixel().mapUnitsPerPixel();
217
218 // We suppose that the elevation are in meter, so we need to use meter for pixel size if possible
219 Qgis::DistanceUnit destinationUnit = context.distanceArea().lengthUnits();
220 double effPixelSize;
221 if ( destinationUnit != Qgis::DistanceUnit::Unknown )
222 effPixelSize = QgsUnitTypes::fromUnitToUnitFactor( destinationUnit, Qgis::DistanceUnit::Meters ) * pixelSize;
223 else
224 effPixelSize = pixelSize;
225
226 elevation.applyHillshading( image, mHillshadingMultiDir, mLightAltitude, mLightAzimuth, mHillshadingZFactor, effPixelSize, effPixelSize );
227}
DistanceUnit
Units of distance.
Definition: qgis.h:4124
@ Unknown
Unknown distance unit.
ElevationMapCombineMethod
Methods used to select the elevation when two elevation maps are combined.
Definition: qgis.h:4026
RenderUnit
Rendering size units.
Definition: qgis.h:4255
Qgis::DistanceUnit lengthUnits() const
Returns the units of distance for length calculations made by this object.
Stores digital elevation model in a raster image which may get updated as a part of map layer renderi...
void applyEyeDomeLighting(QImage &image, int distance, float strength, float rendererScale) const
Applies eye dome lighting effect to the given image.
QImage rawElevationImage() const
Returns raw elevation image with elevations encoded as color values.
void applyHillshading(QImage &image, bool multiDirectional, double altitude, double azimuth, double zFactor, double cellSizeX, double cellSizeY) const
Applies hill shading effect to the given image.
Qgis::ElevationMapCombineMethod combinedElevationMethod() const
Returns the method used when conbining different elevation sources.
bool isActiveHillshading() const
Returns whether the hillshading is active.
void setCombinedElevationMethod(Qgis::ElevationMapCombineMethod method)
Sets the method used when conbining different elevation sources.
bool isActive() const
Returns whether this shading renderer is active.
void setActive(bool active)
Sets whether this shading renderer is active.
double hillshadingZFactor() const
Returns the z factor used by the hill shading method.
double eyeDomeLightingStrength() const
Returns the strength of the eye dome lighting method.
void setLightAzimuth(double lightAzimuth)
Sets the azimuth of the light (degree) that can be used by some methods (e.g.
double lightAltitude() const
Returns the altitude of the light (degree) that can be used by some methods (e.g.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes configuration on a DOM element.
void setHillshadingMultidirectional(bool multiDirectional)
Sets whether the hill shading method is multidirectional.
double eyeDomeLightingDistance() const
Returns the distance of the eye dome lighting method, that is the distance where the effect is apply ...
void setLightAltitude(double lightAltitude)
Sets the altitude of the light (degree) that can be used by some methods (e.g.
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads configuration from a DOM element.
void renderShading(const QgsElevationMap &elevation, QImage &image, const QgsRenderContext &context) const
Render shading on image condidering the elevation map elevation and the renderer context context If e...
void setEyeDomeLightingStrength(double strength)
Sets the strength of the eye dome lighting method.
void setEyeDomeLightingDistanceUnit(Qgis::RenderUnit unit)
Sets the unit of the distance of the eye dome lighting method set by setEyeDomeLightingDistance().
void setActiveHillshading(bool active)
Sets active the hillshading.
bool isHillshadingMultidirectional() const
Returns whether the hill shading method is multidirectional.
void setHillshadingZFactor(double zFactor)
Sets the z factor used by the hill shading method.
bool isActiveEyeDomeLighting() const
Returns whether eye-dome lighting shading method is active.
void setEyeDomeLightingDistance(double distance)
Sets the distance of the eye dome lighting method, that is the distance where the effect is apply fro...
void setActiveEyeDomeLighting(bool active)
Sets active the eye-dome lighting shading method.
double lightAzimuth() const
Returns the azimuth of the light (degree) that can be used by some methods (e.g.
Qgis::RenderUnit eyeDomeLightingDistanceUnit() const
Returns the unit of the distance of the eye dome lighting method returned by eyeDomeLightingDistance(...
double mapUnitsPerPixel() const
Returns the current map units per pixel.
The class is used as a container of context for various read/write operations on other objects.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
const QgsDistanceArea & distanceArea() const
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double rendererScale() const
Returns the renderer map scale.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:5124