QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsrastercontourrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrastercontourrenderer.cpp
3  --------------------------------------
4  Date : March 2020
5  Copyright : (C) 2020 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgslinesymbollayer.h"
19 #include "qgsreadwritecontext.h"
20 #include "qgssymbollayerutils.h"
21 
22 #include <gdal_alg.h>
23 
25  : QgsRasterRenderer( input, QStringLiteral( "contour" ) )
26 {
27  mContourSymbol.reset( static_cast<QgsLineSymbol *>( QgsLineSymbol::defaultSymbol( QgsWkbTypes::LineGeometry ) ) );
28 }
29 
31 
33 {
34  QgsRasterContourRenderer *renderer = new QgsRasterContourRenderer( nullptr );
35  renderer->copyCommonProperties( this );
36  renderer->mContourSymbol.reset( mContourSymbol ? mContourSymbol->clone() : nullptr );
37  renderer->mContourIndexSymbol.reset( mContourIndexSymbol ? mContourIndexSymbol->clone() : nullptr );
38  renderer->mContourInterval = mContourInterval;
39  renderer->mContourIndexInterval = mContourIndexInterval;
40  renderer->mInputBand = mInputBand;
41  renderer->mDownscale = mDownscale;
42  return renderer;
43 }
44 
46 {
47  if ( elem.isNull() )
48  {
49  return nullptr;
50  }
51 
53  r->readXml( elem );
54 
55  int inputBand = elem.attribute( QStringLiteral( "band" ), QStringLiteral( "-1" ) ).toInt();
56  double contourInterval = elem.attribute( QStringLiteral( "contour-interval" ), QStringLiteral( "100" ) ).toDouble();
57  double contourIndexInterval = elem.attribute( QStringLiteral( "contour-index-interval" ), QStringLiteral( "0" ) ).toDouble();
58  double downscale = elem.attribute( QStringLiteral( "downscale" ), QStringLiteral( "4" ) ).toDouble();
59 
60  r->setInputBand( inputBand );
63  r->setDownscale( downscale );
64 
65  QDomElement symbolsElem = elem.firstChildElement( QStringLiteral( "symbols" ) );
66  if ( !symbolsElem.isNull() )
67  {
69  if ( symbolMap.contains( QStringLiteral( "contour" ) ) )
70  {
71  QgsSymbol *symbol = symbolMap.take( QStringLiteral( "contour" ) );
72  if ( symbol->type() == QgsSymbol::Line )
73  r->setContourSymbol( static_cast<QgsLineSymbol *>( symbol ) );
74  }
75  if ( symbolMap.contains( QStringLiteral( "index-contour" ) ) )
76  {
77  QgsSymbol *symbol = symbolMap.take( QStringLiteral( "index-contour" ) );
78  if ( symbol->type() == QgsSymbol::Line )
79  r->setContourIndexSymbol( static_cast<QgsLineSymbol *>( symbol ) );
80  }
81  }
82  return r;
83 }
84 
85 void QgsRasterContourRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
86 {
87  if ( parentElem.isNull() )
88  {
89  return;
90  }
91 
92  QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
93  _writeXml( doc, rasterRendererElem );
94 
95  rasterRendererElem.setAttribute( QStringLiteral( "band" ), mInputBand );
96  rasterRendererElem.setAttribute( QStringLiteral( "contour-interval" ), mContourInterval );
97  rasterRendererElem.setAttribute( QStringLiteral( "contour-index-interval" ), mContourIndexInterval );
98  rasterRendererElem.setAttribute( QStringLiteral( "downscale" ), mDownscale );
99 
100  QgsSymbolMap symbols;
101  symbols[QStringLiteral( "contour" )] = mContourSymbol.get();
102  if ( mContourIndexSymbol )
103  symbols[QStringLiteral( "index-contour" )] = mContourIndexSymbol.get();
104  QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( symbols, QStringLiteral( "symbols" ), doc, QgsReadWriteContext() );
105  rasterRendererElem.appendChild( symbolsElem );
106 
107  parentElem.appendChild( rasterRendererElem );
108 }
109 
111 {
112  QPainter *painter;
113  double scaleX, scaleY;
118 };
119 
120 CPLErr _rasterContourWriter( double dfLevel, int nPoints, double *padfX, double *padfY, void *ptr )
121 {
122  Q_UNUSED( dfLevel )
123  ContourWriterData *crData = static_cast<ContourWriterData *>( ptr );
124  QPolygonF polygon( nPoints );
125  QPointF *d = polygon.data();
126  for ( int i = 0; i < nPoints; ++i )
127  {
128  d[i] = QPointF( padfX[i] * crData->scaleX, padfY[i] * crData->scaleY );
129  }
130 
131  if ( crData->indexSymbol && !qgsDoubleNear( crData->indexInterval, 0 ) && qgsDoubleNear( fmod( dfLevel, crData->indexInterval ), 0 ) )
132  crData->indexSymbol->renderPolyline( polygon, nullptr, *crData->context );
133  else
134  crData->symbol->renderPolyline( polygon, nullptr, *crData->context );
135  return CE_None;
136 }
137 
138 QgsRasterBlock *QgsRasterContourRenderer::block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback )
139 {
140  Q_UNUSED( bandNo )
141 
142  std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
143  if ( !mInput || !mContourSymbol )
144  {
145  return outputBlock.release();
146  }
147 
148  int inputWidth = static_cast<int>( round( width / mDownscale ) );
149  int inputHeight = static_cast<int>( round( height / mDownscale ) );
150 
151  std::unique_ptr< QgsRasterBlock > inputBlock( mInput->block( mInputBand, extent, inputWidth, inputHeight, feedback ) );
152  if ( !inputBlock || inputBlock->isEmpty() )
153  {
154  QgsDebugMsg( QStringLiteral( "No raster data!" ) );
155  return outputBlock.release();
156  }
157 
158  if ( !inputBlock->convert( Qgis::Float64 ) ) // contouring algorithm requires double
159  return outputBlock.release();
160  double *scanline = reinterpret_cast<double *>( inputBlock->bits() );
161 
162  QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
163  img.fill( Qt::transparent );
164 
165  QPainter p( &img );
166  p.setRenderHint( QPainter::Antialiasing );
167 
169 
170  ContourWriterData crData;
171  crData.painter = &p;
172  crData.scaleX = width / double( inputWidth );
173  crData.scaleY = height / double( inputHeight );
174  crData.symbol = mContourSymbol.get();
175  crData.indexSymbol = mContourIndexSymbol.get();
176  crData.indexInterval = mContourIndexInterval;
177  crData.context = &context;
178 
179  crData.symbol->startRender( context );
180  if ( crData.indexSymbol )
181  crData.indexSymbol->startRender( context );
182 
183  double contourBase = 0.;
184  GDALContourGeneratorH cg = GDAL_CG_Create( inputBlock->width(), inputBlock->height(),
185  inputBlock->hasNoDataValue(), inputBlock->noDataValue(),
186  mContourInterval, contourBase,
187  _rasterContourWriter, static_cast<void *>( &crData ) );
188  for ( int i = 0; i < inputHeight; ++i )
189  {
190  if ( feedback && feedback->isCanceled() )
191  break;
192 
193  GDAL_CG_FeedLine( cg, scanline );
194  scanline += inputWidth;
195  }
196  GDAL_CG_Destroy( cg );
197 
198  crData.symbol->stopRender( context );
199  if ( crData.indexSymbol )
200  crData.indexSymbol->stopRender( context );
201 
202  p.end();
203 
204  outputBlock->setImage( &img );
205  return outputBlock.release();
206 }
207 
209 {
210  QList<int> bandList;
211  if ( mInputBand != -1 )
212  {
213  bandList << mInputBand;
214  }
215  return bandList;
216 }
217 
219 {
220  mContourSymbol.reset( symbol );
221 }
222 
224 {
225  mContourIndexSymbol.reset( symbol );
226 }
QgsRasterContourRenderer::setInputBand
void setInputBand(int band)
Sets the number of the input raster band.
Definition: qgsrastercontourrenderer.h:58
QgsRasterContourRenderer::setDownscale
void setDownscale(double scale)
Sets by how much the renderer will scale down the request to the data provider.
Definition: qgsrastercontourrenderer.h:92
QgsSymbolLayerUtils::loadSymbols
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
Definition: qgssymbollayerutils.cpp:2946
ContourWriterData::symbol
QgsLineSymbol * symbol
Definition: qgsrastercontourrenderer.cpp:114
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:35
QgsSymbol::defaultSymbol
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:320
QgsRasterInterface::mInput
QgsRasterInterface * mInput
Definition: qgsrasterinterface.h:467
ContourWriterData::scaleY
double scaleY
Definition: qgsrastercontourrenderer.cpp:113
QgsRasterContourRenderer::writeXml
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
Definition: qgsrastercontourrenderer.cpp:85
QgsRasterContourRenderer::block
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
Definition: qgsrastercontourrenderer.cpp:138
qgsreadwritecontext.h
QgsSymbolMap
QMap< QString, QgsSymbol * > QgsSymbolMap
Definition: qgsrenderer.h:46
qgssymbollayerutils.h
QgsRasterContourRenderer::setContourSymbol
void setContourSymbol(QgsLineSymbol *symbol)
Sets the symbol used for contour lines. Takes ownership of the passed symbol.
Definition: qgsrastercontourrenderer.cpp:218
QgsRasterContourRenderer::contourInterval
double contourInterval() const
Returns the interval of contour lines generation.
Definition: qgsrastercontourrenderer.h:61
ContourWriterData::scaleX
double scaleX
Definition: qgsrastercontourrenderer.cpp:113
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
_rasterContourWriter
CPLErr _rasterContourWriter(double dfLevel, int nPoints, double *padfX, double *padfY, void *ptr)
Definition: qgsrastercontourrenderer.cpp:120
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:64
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsRasterContourRenderer::create
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
Creates an instance of the renderer based on definition from XML (used by renderer registry)
Definition: qgsrastercontourrenderer.cpp:45
QgsRasterContourRenderer::setContourIndexInterval
void setContourIndexInterval(double interval)
Sets the interval of index contour lines (index contour lines are typical further apart and with a wi...
Definition: qgsrastercontourrenderer.h:73
QgsRasterContourRenderer::inputBand
int inputBand() const
Returns the number of the input raster band.
Definition: qgsrastercontourrenderer.h:56
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsRasterContourRenderer::usesBands
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
Definition: qgsrastercontourrenderer.cpp:208
QgsRasterContourRenderer::~QgsRasterContourRenderer
~QgsRasterContourRenderer() override
QgsRasterContourRenderer::setContourInterval
void setContourInterval(double interval)
Sets the interval of contour lines generation.
Definition: qgsrastercontourrenderer.h:63
ContourWriterData::context
QgsRenderContext * context
Definition: qgsrastercontourrenderer.cpp:117
QgsSymbol::stopRender
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:479
QgsRasterRenderer
Raster renderer pipe that applies colors to a raster.
Definition: qgsrasterrenderer.h:39
QgsRasterContourRenderer
Raster renderer that generates contours on the fly for a source raster band.
Definition: qgsrastercontourrenderer.h:31
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsRasterContourRenderer::setContourIndexSymbol
void setContourIndexSymbol(QgsLineSymbol *symbol)
Sets the symbol of index contour lines.
Definition: qgsrastercontourrenderer.cpp:223
QgsRasterRenderer::readXml
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
Definition: qgsrasterrenderer.cpp:134
QgsRasterRenderer::_writeXml
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
Definition: qgsrasterrenderer.cpp:104
QgsLineSymbol
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:1131
QgsRasterRenderer::copyCommonProperties
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
Definition: qgsrasterrenderer.cpp:162
QgsSymbol::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:454
ContourWriterData::indexInterval
double indexInterval
Definition: qgsrastercontourrenderer.cpp:116
ContourWriterData::painter
QPainter * painter
Definition: qgsrastercontourrenderer.cpp:112
ContourWriterData::indexSymbol
QgsLineSymbol * indexSymbol
Definition: qgsrastercontourrenderer.cpp:115
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
QgsRasterContourRenderer::downscale
double downscale() const
Returns by how much the renderer will scale down the request to the data provider.
Definition: qgsrastercontourrenderer.h:86
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsRasterInterface
Base class for processing filters like renderers, reprojector, resampler etc.
Definition: qgsrasterinterface.h:117
qgslinesymbollayer.h
QgsSymbolLayerUtils::saveSymbols
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
Definition: qgssymbollayerutils.cpp:3024
QgsRenderContext::fromQPainter
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
Definition: qgsrendercontext.cpp:119
QgsRasterInterface::input
virtual QgsRasterInterface * input() const
Current input.
Definition: qgsrasterinterface.h:269
QgsRasterBlockFeedback
Feedback object tailored for raster block reading.
Definition: qgsrasterinterface.h:41
QgsLineSymbol::renderPolyline
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol along the line joining points, using the given render context.
Definition: qgssymbol.cpp:2125
qgsrastercontourrenderer.h
QgsSymbol::Line
@ Line
Line symbol.
Definition: qgssymbol.h:88
ContourWriterData
Definition: qgsrastercontourrenderer.cpp:111
QgsSymbol::type
SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:122
QgsRasterContourRenderer::clone
QgsRasterContourRenderer * clone() const override
Clone itself, create deep copy.
Definition: qgsrastercontourrenderer.cpp:32
QgsRasterContourRenderer::QgsRasterContourRenderer
QgsRasterContourRenderer(QgsRasterInterface *input)
Creates a contour renderer.
Definition: qgsrastercontourrenderer.cpp:24
QgsRasterInterface::block
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.
QgsRasterContourRenderer::contourIndexInterval
double contourIndexInterval() const
Returns the interval of index contour lines (index contour lines are typical further apart and with a...
Definition: qgsrastercontourrenderer.h:71
QgsRasterBlock
Raster data container.
Definition: qgsrasterblock.h:37
QgsRasterInterface::extent
virtual QgsRectangle extent() const
Gets the extent of the interface.
Definition: qgsrasterinterface.h:229
Qgis::Float64
@ Float64
Sixty four bit floating point (double)
Definition: qgis.h:110