31 #include "qgssettings.h" 
   41   , mLightAngle( lightAngle )
 
   42   , mLightAzimuth( lightAzimuth )
 
   43   , mMultiDirectional( false )
 
   65   int band = elem.attribute( QStringLiteral( 
"band" ), QStringLiteral( 
"0" ) ).toInt();
 
   66   double azimuth = elem.attribute( QStringLiteral( 
"azimuth" ), QStringLiteral( 
"315" ) ).toDouble();
 
   67   double angle = elem.attribute( QStringLiteral( 
"angle" ), QStringLiteral( 
"45" ) ).toDouble();
 
   68   double zFactor = elem.attribute( QStringLiteral( 
"zfactor" ), QStringLiteral( 
"1" ) ).toDouble();
 
   69   bool multiDirectional = elem.attribute( QStringLiteral( 
"multidirection" ), QStringLiteral( 
"0" ) ).toInt();
 
   80   if ( parentElem.isNull() )
 
   85   QDomElement rasterRendererElem = doc.createElement( QStringLiteral( 
"rasterrenderer" ) );
 
   88   rasterRendererElem.setAttribute( QStringLiteral( 
"band" ), mBand );
 
   89   rasterRendererElem.setAttribute( QStringLiteral( 
"azimuth" ), QString::number( mLightAzimuth ) );
 
   90   rasterRendererElem.setAttribute( QStringLiteral( 
"angle" ), QString::number( mLightAngle ) );
 
   91   rasterRendererElem.setAttribute( QStringLiteral( 
"zfactor" ), QString::number( mZFactor ) );
 
   92   rasterRendererElem.setAttribute( QStringLiteral( 
"multidirection" ), QString::number( mMultiDirectional ) );
 
   93   parentElem.appendChild( rasterRendererElem );
 
   99   std::unique_ptr< QgsRasterBlock > outputBlock( 
new QgsRasterBlock() );
 
  102     QgsDebugMsg( QStringLiteral( 
"No input raster!" ) );
 
  103     return outputBlock.release();
 
  106   std::shared_ptr< QgsRasterBlock > inputBlock( 
mInput->
block( mBand, 
extent, width, height, feedback ) );
 
  108   if ( !inputBlock || inputBlock->isEmpty() )
 
  110     QgsDebugMsg( QStringLiteral( 
"No raster data!" ) );
 
  111     return outputBlock.release();
 
  114   std::shared_ptr< QgsRasterBlock > alphaBlock;
 
  119     if ( !alphaBlock || alphaBlock->isEmpty() )
 
  122       return outputBlock.release();
 
  127     alphaBlock = inputBlock;
 
  132     return outputBlock.release();
 
  138   float cellXSize = 
static_cast<float>( 
extent.
width() ) / width;
 
  139   float cellYSize = 
static_cast<float>( 
extent.
height() ) / height;
 
  140   float zenithRad = 
static_cast<float>( std::max( 0.0, 90 - mLightAngle ) * M_PI / 180.0 );
 
  141   float azimuthRad = 
static_cast<float>( -1 * mLightAzimuth * M_PI / 180.0 );
 
  142   float cosZenithRad = std::cos( zenithRad );
 
  143   float sinZenithRad = std::sin( zenithRad );
 
  146   float cos_alt_mul_z = cosZenithRad * 
static_cast<float>( mZFactor );
 
  147   float cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
 
  148   float sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
 
  149   float cos_az_mul_cos_alt_mul_z_mul_254 = 254.0f * cos_az_mul_cos_alt_mul_z;
 
  150   float sin_az_mul_cos_alt_mul_z_mul_254 = 254.0f * sin_az_mul_cos_alt_mul_z;
 
  151   float square_z = 
static_cast<float>( mZFactor * mZFactor );
 
  152   float sin_altRadians_mul_254 = 254.0f * sinZenithRad;
 
  155   float sin_altRadians_mul_127 = 127.0f * sinZenithRad;
 
  157   float cos225_az_mul_cos_alt_mul_z_mul_127 = -32.87001872802012f * cos_alt_mul_z;
 
  158   float cos_alt_mul_z_mul_127 = 127.0f * cos_alt_mul_z;
 
  169                   && inputBlock->dataTypeSize() <= 4 );
 
  175     if ( source.isEmpty() )
 
  183   std::chrono::time_point<std::chrono::system_clock> startTime( std::chrono::system_clock::now() );
 
  191       std::size_t inputDataTypeSize = inputBlock->dataTypeSize();
 
  192       std::size_t outputDataTypeSize = outputBlock->dataTypeSize();
 
  195       switch ( inputBlock->dataType() )
 
  198           typeName = QStringLiteral( 
"unsigned char" );
 
  201           typeName = QStringLiteral( 
"unsigned int" );
 
  204           typeName = QStringLiteral( 
"short" );
 
  207           typeName = QStringLiteral( 
"unsigned int" );
 
  213           typeName = QStringLiteral( 
"float" );
 
  216           throw QgsException( QStringLiteral( 
"Unsupported data type for OpenCL processing." ) );
 
  221         source.replace( QLatin1String( 
"__global float *scanLine" ), QStringLiteral( 
"__global %1 *scanLine" ).arg( 
typeName ) );
 
  225       std::size_t scanLineWidth( inputBlock->width() + 2 );
 
  226       std::size_t inputSize( inputDataTypeSize * inputBlock->width() );
 
  229       std::size_t bufferWidth( width + 2 );
 
  230       std::size_t bufferSize( inputDataTypeSize * bufferWidth );
 
  235       std::unique_ptr<QgsRasterBlock> scanLine = std::make_unique<QgsRasterBlock>( inputBlock->dataType(), scanLineWidth, 1 );
 
  242       std::vector<float> rasterParams;
 
  243       rasterParams.push_back( inputBlock->noDataValue() );
 
  244       rasterParams.push_back( outputBlock->noDataValue() );
 
  245       rasterParams.push_back( mZFactor );
 
  246       rasterParams.push_back( cellXSize );
 
  247       rasterParams.push_back( cellYSize );
 
  248       rasterParams.push_back( 
static_cast<float>( 
mOpacity ) ); 
 
  251       rasterParams.push_back( cos_az_mul_cos_alt_mul_z_mul_254 ); 
 
  252       rasterParams.push_back( sin_az_mul_cos_alt_mul_z_mul_254 ); 
 
  253       rasterParams.push_back( square_z ); 
 
  254       rasterParams.push_back( sin_altRadians_mul_254 ); 
 
  257       rasterParams.push_back( sin_altRadians_mul_127 ); 
 
  258       rasterParams.push_back( cos225_az_mul_cos_alt_mul_z_mul_127 ); 
 
  259       rasterParams.push_back( cos_alt_mul_z_mul_127 ); 
 
  262       rasterParams.push_back( 
static_cast<float>( qBlue( defaultNodataColor ) ) ); 
 
  263       rasterParams.push_back( 
static_cast<float>( qGreen( defaultNodataColor ) ) ); 
 
  264       rasterParams.push_back( 
static_cast<float>( qRed( defaultNodataColor ) ) ); 
 
  265       rasterParams.push_back( 
static_cast<float>( qAlpha( defaultNodataColor ) ) / 255.0f ); 
 
  268       rasterParams.push_back( 
static_cast<float>( mMultiDirectional ) ); 
 
  270       cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(), 
true, 
false, 
nullptr );
 
  271       cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  272       cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  273       cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  274       cl::Buffer *scanLineBuffer[3] = {&scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer};
 
  276       cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, outputDataTypeSize * width, 
nullptr, 
nullptr );
 
  278       static std::map<Qgis::DataType, cl::Program> programCache;
 
  279       cl::Program program = programCache[inputBlock->dataType()];
 
  280       if ( ! program.get() )
 
  284         program = programCache[inputBlock->dataType()];
 
  291       auto kernel =  cl::KernelFunctor <
 
  297                      > ( program, 
"processNineCellWindow" );
 
  301       std::vector<int> rowIndex = {0, 1, 2};
 
  303       for ( 
int i = 0; i < height; i++ )
 
  312           feedback->
setProgress( 100.0 * 
static_cast< double >( i ) / height );
 
  318           scanLine->resetNoDataValue();
 
  319           queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine->bits( ) );
 
  321           memcpy( scanLine->bits( 0, 1 ), inputBlock->bits( i, 0 ), inputSize );
 
  322           queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine->bits( ) ); 
 
  324           memcpy( scanLine->bits( 0, 1 ), inputBlock->bits( i + 1, 0 ), inputSize );
 
  325           queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine->bits( ) ); 
 
  331           if ( i == inputBlock->height() - 1 )
 
  333             scanLine->resetNoDataValue();
 
  334             queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine->bits( ) );
 
  338             queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, inputDataTypeSize * 1 , inputSize, inputBlock->bits( i + 1, 0 ) );
 
  342         kernel( cl::EnqueueArgs(
 
  346                 *scanLineBuffer[rowIndex[0]],
 
  347                 *scanLineBuffer[rowIndex[1]],
 
  348                 *scanLineBuffer[rowIndex[2]],
 
  353         queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, outputDataTypeSize * outputBlock->width( ), outputBlock->bits( i, 0 ) );
 
  354         std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
 
  357     catch ( cl::Error &e )
 
  372     for ( 
qgssize i = 0; i < static_cast<qgssize>( height ); i++ )
 
  375       for ( 
qgssize j = 0; j < static_cast<qgssize>( width ); j++ )
 
  378         if ( inputBlock->isNoData( i,  j ) )
 
  380           outputBlock->setColor( 
static_cast<int>( i ), 
static_cast<int>( j ), defaultNodataColor );
 
  384         qgssize iUp, iDown, jLeft, jRight;
 
  390         else if ( i < 
static_cast<qgssize>( height ) - 1 )
 
  406         else if ( j <  
static_cast<qgssize>( width ) - 1 )
 
  428         x22 = inputBlock->value( i, j );
 
  430         x11 = inputBlock->isNoData( iUp, jLeft )  ? x22 : inputBlock->value( iUp, jLeft );
 
  431         x21 = inputBlock->isNoData( i, jLeft )     ? x22 : inputBlock->value( i, jLeft );
 
  432         x31 = inputBlock->isNoData( iDown, jLeft ) ? x22 : inputBlock->value( iDown, jLeft );
 
  434         x12 = inputBlock->isNoData( iUp, j )       ? x22 : inputBlock->value( iUp, j );
 
  436         x32 = inputBlock->isNoData( iDown, j )     ? x22 : inputBlock->value( iDown, j );
 
  438         x13 = inputBlock->isNoData( iUp, jRight )   ? x22 : inputBlock->value( iUp, jRight );
 
  439         x23 = inputBlock->isNoData( i, jRight )     ? x22 : inputBlock->value( i, jRight );
 
  440         x33 = inputBlock->isNoData( iDown, jRight ) ? x22 : inputBlock->value( iDown, jRight );
 
  442         double derX = calcFirstDerX( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellXSize );
 
  443         double derY = calcFirstDerY( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellYSize );
 
  448         if ( !mMultiDirectional )
 
  451           grayValue = std::clamp( ( sin_altRadians_mul_254 -
 
  452                                     ( derY * cos_az_mul_cos_alt_mul_z_mul_254 -
 
  453                                       derX * sin_az_mul_cos_alt_mul_z_mul_254 ) ) /
 
  454                                   std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ),
 
  461           const float xx = derX * derX;
 
  462           const float yy = derY * derY;
 
  463           const float xx_plus_yy = xx + yy;
 
  465           if ( xx_plus_yy == 0.0 )
 
  467             grayValue = std::clamp( 
static_cast<float>( 1.0 + sin_altRadians_mul_254 ), 0.0f, 255.0f );
 
  472             float val225_mul_127 = sin_altRadians_mul_127 +
 
  473                                    ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_127;
 
  474             val225_mul_127 = ( val225_mul_127 <= 0.0 ) ? 0.0 : val225_mul_127;
 
  475             float val270_mul_127 = sin_altRadians_mul_127 -
 
  476                                    derX * cos_alt_mul_z_mul_127;
 
  477             val270_mul_127 = ( val270_mul_127 <= 0.0 ) ? 0.0 : val270_mul_127;
 
  478             float val315_mul_127 = sin_altRadians_mul_127 +
 
  479                                    ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_127;
 
  480             val315_mul_127 = ( val315_mul_127 <= 0.0 ) ? 0.0 : val315_mul_127;
 
  481             float val360_mul_127 = sin_altRadians_mul_127 -
 
  482                                    derY * cos_alt_mul_z_mul_127;
 
  483             val360_mul_127 = ( val360_mul_127 <= 0.0 ) ? 0.0 : val360_mul_127;
 
  486             const float weight_225 = 0.5 * xx_plus_yy - derX * derY;
 
  487             const float weight_270 = xx;
 
  488             const float weight_315 = xx_plus_yy - weight_225;
 
  489             const float weight_360 = yy;
 
  490             const float cang_mul_127 = (
 
  491                                          ( weight_225 * val225_mul_127 +
 
  492                                            weight_270 * val270_mul_127 +
 
  493                                            weight_315 * val315_mul_127 +
 
  494                                            weight_360 * val360_mul_127 ) / xx_plus_yy ) /
 
  495                                        ( 1 + square_z * xx_plus_yy );
 
  497             grayValue = std::clamp( 1.0f + cang_mul_127, 0.0f, 255.0f );
 
  508           currentAlpha *= alphaBlock->value( i ) / 255.0;
 
  513           outputBlock->setColor( i, j, qRgba( grayValue, grayValue, grayValue, 255 ) );
 
  517           outputBlock->setColor( i, j, qRgba( currentAlpha * grayValue, currentAlpha * grayValue, currentAlpha * grayValue, currentAlpha * 255 ) );
 
  526   if ( QgsSettings().value( QStringLiteral( 
"Map/logCanvasRefreshEvent" ), 
false ).toBool() )
 
  529                                .arg( useOpenCL ? QStringLiteral( 
"OpenCL" ) : QStringLiteral( 
"CPU" ) )
 
  532                                .arg( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now() - startTime ).count() ),
 
  538   return outputBlock.release();
 
  561 double QgsHillshadeRenderer::calcFirstDerX( 
double x11, 
double x21, 
double x31, 
double x12, 
double x22, 
double x32, 
double x13, 
double x23, 
double x33, 
double cellsize )
 
  566   return ( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellsize );
 
  569 double QgsHillshadeRenderer::calcFirstDerY( 
double x11, 
double x21, 
double x31, 
double x12, 
double x22, 
double x32, 
double x13, 
double x23, 
double x33, 
double cellsize )
 
  574   return ( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellsize );
 
  583   QDomNodeList elements = element.elementsByTagName( QStringLiteral( 
"sld:RasterSymbolizer" ) );
 
  584   if ( elements.size() == 0 )
 
  588   QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
 
  595     QDomElement channelSelectionElem = doc.createElement( QStringLiteral( 
"sld:ChannelSelection" ) );
 
  596     elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( 
"sld:Opacity" ) );
 
  597     if ( elements.size() != 0 )
 
  599       rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
 
  603       elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( 
"sld:Geometry" ) );
 
  604       if ( elements.size() != 0 )
 
  606         rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
 
  610         rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
 
  615     QDomElement channelElem = doc.createElement( QStringLiteral( 
"sld:GrayChannel" ) );
 
  616     channelSelectionElem.appendChild( channelElem );
 
  619     QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( 
"sld:SourceChannelName" ) );
 
  620     sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( 
band() ) ) );
 
  621     channelElem.appendChild( sourceChannelNameElem );
 
  625   QDomElement shadedReliefElem = doc.createElement( QStringLiteral( 
"sld:ShadedRelief" ) );
 
  626   rasterSymbolizerElem.appendChild( shadedReliefElem );
 
  629   QDomElement brightnessOnlyElem = doc.createElement( QStringLiteral( 
"sld:BrightnessOnly" ) );
 
  630   brightnessOnlyElem.appendChild( doc.createTextNode( QStringLiteral( 
"true" ) ) );
 
  631   shadedReliefElem.appendChild( brightnessOnlyElem );
 
  634   QDomElement reliefFactorElem = doc.createElement( QStringLiteral( 
"sld:ReliefFactor" ) );
 
  635   reliefFactorElem.appendChild( doc.createTextNode( QString::number( 
zFactor() ) ) );
 
  636   shadedReliefElem.appendChild( reliefFactorElem );
 
  639   QDomElement altitudeVendorOptionElem = doc.createElement( QStringLiteral( 
"sld:VendorOption" ) );
 
  640   altitudeVendorOptionElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"altitude" ) );
 
  641   altitudeVendorOptionElem.appendChild( doc.createTextNode( QString::number( 
altitude() ) ) );
 
  642   shadedReliefElem.appendChild( altitudeVendorOptionElem );
 
  645   QDomElement azimutVendorOptionElem = doc.createElement( QStringLiteral( 
"sld:VendorOption" ) );
 
  646   azimutVendorOptionElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"azimuth" ) );
 
  647   azimutVendorOptionElem.appendChild( doc.createTextNode( QString::number( 
azimuth() ) ) );
 
  648   shadedReliefElem.appendChild( azimutVendorOptionElem );
 
  651   QDomElement multidirectionalVendorOptionElem = doc.createElement( QStringLiteral( 
"sld:VendorOption" ) );
 
  652   multidirectionalVendorOptionElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"multidirectional" ) );
 
  653   multidirectionalVendorOptionElem.appendChild( doc.createTextNode( QString::number( 
multiDirectional() ) ) );
 
  654   shadedReliefElem.appendChild( multidirectionalVendorOptionElem );
 
@ Float32
Thirty two bit floating point (float)
@ Int16
Sixteen bit signed integer (qint16)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ Int32
Thirty two bit signed integer (qint32)
@ UInt32
Thirty two bit unsigned integer (quint32)
Defines a QGIS exception class.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
A renderer for generating live hillshade models.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
Factory method to create a new renderer.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
QgsHillshadeRenderer(QgsRasterInterface *input, int band, double lightAzimuth, double lightAltitude)
A renderer for generating live hillshade models.
bool multiDirectional() const
Returns true if the renderer is using multi-directional hillshading.
void setZFactor(double zfactor)
Set the Z scaling factor of the result image.
double azimuth() const
Returns the direction of the light over the raster between 0-360.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
int band() const
Returns the band used by the renderer.
void setBand(int bandNo)
Sets the band used by the renderer.
void setMultiDirectional(bool isMultiDirectional)
Sets whether to render using a multi-directional hillshade algorithm.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
double altitude() const
Returns the angle of the light source over the raster.
double zFactor() const
Returns the Z scaling factor.
QgsHillshadeRenderer * clone() const override
Clone itself, create deep copy.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static Q_DECL_DEPRECATED cl::Program buildProgram(const cl::Context &context, const QString &source, ExceptionBehavior exceptionBehavior=Catch)
Build the program from source in the given context and depending on exceptionBehavior can throw or ca...
static QString sourcePath()
Returns the base path to OpenCL program directory.
static cl::Context context()
Context factory.
static bool enabled()
Returns true if OpenCL is enabled in the user settings.
static bool available()
Checks whether a suitable OpenCL platform and device is available on this system and initialize the Q...
static void setEnabled(bool enabled)
Set the OpenCL user setting to enabled.
static QString errorText(const int errorCode)
Returns a string representation from an OpenCL errorCode.
static cl::CommandQueue commandQueue()
Create an OpenCL command queue from the default context.
static QString sourceFromBaseName(const QString &baseName)
Returns the full path to a an OpenCL source file from the baseName ('.cl' extension is automatically ...
static QLatin1String LOGMESSAGE_TAG
OpenCL string for message logs.
Feedback object tailored for raster block reading.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
virtual QgsRasterInterface * input() const
Current input.
virtual int bandCount() const =0
Gets number of bands.
QgsRasterInterface * mInput
virtual QgsRectangle extent() const
Gets the extent of the interface.
Raster renderer pipe that applies colors to a raster.
double mOpacity
Global alpha value (0-1)
int mAlphaBand
Read alpha value from band.
QRgb renderColorForNodataPixel() const
Returns the color for the renderer to use to represent nodata pixels.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
virtual void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
int alphaValue(double value, int globalTransparency=255) const
Returns the transparency value for a single value pixel.
bool isEmpty() const
True if there are no entries in the pixel lists except the nodata value.
A rectangle specified with double values.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)