1 /***************************************************************************
2                          qgshillshaderenderer.cpp
3                          ---------------------------------
4     begin                : May 2016
5     copyright            : (C) 2016 by Nathan Woodrow
6     email                : woodrow dot nathan at gmail 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 
18 #ifndef QGSHILLSHADERENDERER_H
19 #define QGSHILLSHADERENDERER_H
20 
21 
22 #include "qgis_core.h"
23 #include "qgis_sip.h"
24 #include "qgsrasterrenderer.h"
25 
26 class QgsRasterBlock;
27 class QgsRectangle;
28 class QgsRasterInterface;
29 
30 
31 /**
32  * \ingroup core
33  * \brief A renderer for generating live hillshade models.
34  * \since QGIS 2.16
35  */
36 class CORE_EXPORT QgsHillshadeRenderer : public QgsRasterRenderer
37 {
38   public:
39 
40     /**
41      * \brief A renderer for generating live hillshade models.
42      * \param input The input raster interface
43      * \param band The band in the raster to use
44      * \param lightAzimuth The azimuth of the light source
45      * \param lightAltitude The altitude of the light source
46      */
47     QgsHillshadeRenderer( QgsRasterInterface *input, int band, double lightAzimuth, double lightAltitude );
48 
49     QgsHillshadeRenderer *clone() const override SIP_FACTORY;
50 
51     /**
52      * \brief Factory method to create a new renderer
53      * \param elem A DOM element to create the renderer from.
54      * \param input The raster input interface.
55      * \returns A new QgsHillshadeRenderer.
56      */
57     static QgsRasterRenderer *create( const QDomElement &elem, QgsRasterInterface *input ) SIP_FACTORY;
58 
59     void writeXml( QDomDocument &doc, QDomElement &parentElem ) const override;
60 
61     QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback = nullptr ) override SIP_FACTORY;
62 
63     QList<int> usesBands() const override;
64 
65     void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props = QVariantMap() ) const override;
66 
67     /**
68      * Returns the band used by the renderer
69      */
band()70     int band() const { return mBand; }
71 
72     /**
73      * Sets the band used by the renderer.
74      * \see band
75      */
76     void setBand( int bandNo );
77 
78     /**
79      * Returns the direction of the light over the raster between 0-360.
80      * \see setAzimuth()
81      */
azimuth()82     double azimuth() const { return mLightAzimuth; }
83 
84     /**
85      * Returns the angle of the light source over the raster.
86      * \see setAltitude()
87      */
altitude()88     double altitude()  const { return mLightAngle; }
89 
90     /**
91      * Returns the Z scaling factor.
92      * \see setZFactor()
93      */
zFactor()94     double zFactor()  const { return mZFactor; }
95 
96     /**
97      * Returns TRUE if the renderer is using multi-directional hillshading.
98      * \see setMultiDirectional()
99      */
multiDirectional()100     bool multiDirectional() const { return mMultiDirectional; }
101 
102     /**
103      * \brief Set the azimuth of the light source.
104      * \param azimuth The azimuth of the light source, between 0 and 360.0
105      * \see azimuth()
106      */
setAzimuth(double azimuth)107     void setAzimuth( double azimuth ) { mLightAzimuth = azimuth; }
108 
109     /**
110      * \brief Set the altitude of the light source
111      * \param altitude the altitude
112      * \see altitude()
113      */
setAltitude(double altitude)114     void setAltitude( double altitude ) { mLightAngle = altitude; }
115 
116     /**
117      * \brief Set the Z scaling factor of the result image.
118      * \param zfactor The z factor
119      * \see zFactor()
120      */
setZFactor(double zfactor)121     void setZFactor( double zfactor ) { mZFactor = zfactor; }
122 
123     /**
124      * Sets whether to render using a multi-directional hillshade algorithm.
125      * \param isMultiDirectional set to TRUE to use multi directional rendering
126      * \see multiDirectional()
127      */
setMultiDirectional(bool isMultiDirectional)128     void setMultiDirectional( bool isMultiDirectional ) { mMultiDirectional = isMultiDirectional; }
129 
130   private:
131     int mBand;
132     double mZFactor;
133     double mLightAngle;
134     double mLightAzimuth;
135     bool mMultiDirectional;
136 
137     //! Calculates the first order derivative in x-direction according to Horn (1981)
138     double calcFirstDerX( double x11, double x21, double x31, double x12, double x22, double x32, double x13, double x23, double x33, double cellsize );
139 
140     //! Calculates the first order derivative in y-direction according to Horn (1981)
141     double calcFirstDerY( double x11, double x21, double x31, double x12, double x22, double x32, double x13, double x23, double x33, double cellsize );
142 };
143 
144 #endif // QGSHILLSHADERENDERER_H
145