QGIS API Documentation  2.99.0-Master (dcec6bb)
qgsrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrenderer.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 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 
16 #include "qgsrenderer.h"
17 #include "qgssymbol.h"
18 #include "qgssymbollayerutils.h"
19 #include "qgsrulebasedrenderer.h"
20 
21 #include "qgssinglesymbolrenderer.h" // for default renderer
22 
23 #include "qgsrendererregistry.h"
24 
25 #include "qgsrendercontext.h"
26 #include "qgsclipper.h"
27 #include "qgsgeometry.h"
28 #include "qgsgeometrycollection.h"
29 #include "qgsfeature.h"
30 #include "qgslogger.h"
31 #include "qgsvectorlayer.h"
32 #include "qgspainteffect.h"
33 #include "qgseffectstack.h"
34 #include "qgspainteffectregistry.h"
35 #include "qgswkbptr.h"
36 #include "qgspoint.h"
37 #include "qgsproperty.h"
38 
39 #include <QDomElement>
40 #include <QDomDocument>
41 #include <QPolygonF>
42 
43 QPointF QgsFeatureRenderer::_getPoint( QgsRenderContext &context, const QgsPoint &point )
44 {
45  return QgsSymbol::_getPoint( context, point );
46 }
47 
49 {
50  if ( !destRenderer || !mPaintEffect )
51  return;
52 
53  destRenderer->setPaintEffect( mPaintEffect->clone() );
54  destRenderer->mOrderBy = mOrderBy;
55  destRenderer->mOrderByEnabled = mOrderByEnabled;
56 }
57 
59  : mType( type )
60  , mUsingSymbolLevels( false )
63  , mPaintEffect( nullptr )
64  , mForceRaster( false )
65  , mOrderByEnabled( false )
66 {
68  mPaintEffect->setEnabled( false );
69 }
70 
72 {
73  delete mPaintEffect;
74 }
75 
77 {
78  return new QgsSingleSymbolRenderer( QgsSymbol::defaultSymbol( geomType ) );
79 }
80 
82 {
83  return symbolForFeature( feature, context );
84 }
85 
87 {
88  Q_UNUSED( feature );
89  Q_UNUSED( context );
90  return QSet< QString >();
91 }
92 
94 {
95  return false;
96 }
97 
98 bool QgsFeatureRenderer::renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
99 {
100  QgsSymbol *symbol = symbolForFeature( feature, context );
101  if ( !symbol )
102  return false;
103 
104  renderFeatureWithSymbol( feature, symbol, context, layer, selected, drawVertexMarker );
105  return true;
106 }
107 
108 void QgsFeatureRenderer::renderFeatureWithSymbol( QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
109 {
110  symbol->renderFeature( feature, context, layer, selected, drawVertexMarker, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
111 }
112 
114 {
115  return QStringLiteral( "UNKNOWN RENDERER\n" );
116 }
117 
118 QgsFeatureRenderer *QgsFeatureRenderer::load( QDomElement &element, const QgsReadWriteContext &context )
119 {
120  // <renderer-v2 type=""> ... </renderer-v2>
121 
122  if ( element.isNull() )
123  return nullptr;
124 
125  // load renderer
126  QString rendererType = element.attribute( QStringLiteral( "type" ) );
127 
129  if ( !m )
130  return nullptr;
131 
132  QgsFeatureRenderer *r = m->createRenderer( element, context );
133  if ( r )
134  {
135  r->setUsingSymbolLevels( element.attribute( QStringLiteral( "symbollevels" ), QStringLiteral( "0" ) ).toInt() );
136  r->setForceRasterRender( element.attribute( QStringLiteral( "forceraster" ), QStringLiteral( "0" ) ).toInt() );
137 
138  //restore layer effect
139  QDomElement effectElem = element.firstChildElement( QStringLiteral( "effect" ) );
140  if ( !effectElem.isNull() )
141  {
142  r->setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
143  }
144 
145  // restore order by
146  QDomElement orderByElem = element.firstChildElement( QStringLiteral( "orderby" ) );
147  r->mOrderBy.load( orderByElem );
148  r->setOrderByEnabled( element.attribute( QStringLiteral( "enableorderby" ), QStringLiteral( "0" ) ).toInt() );
149  }
150  return r;
151 }
152 
153 QDomElement QgsFeatureRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
154 {
155  Q_UNUSED( context );
156  // create empty renderer element
157  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
158  rendererElem.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? "1" : "0" ) );
159 
161  mPaintEffect->saveProperties( doc, rendererElem );
162 
163  if ( !mOrderBy.isEmpty() )
164  {
165  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
166  mOrderBy.save( orderBy );
167  rendererElem.appendChild( orderBy );
168  }
169  rendererElem.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? "1" : "0" ) );
170  return rendererElem;
171 }
172 
173 QgsFeatureRenderer *QgsFeatureRenderer::loadSld( const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage )
174 {
175  QDomElement element = node.toElement();
176  if ( element.isNull() )
177  return nullptr;
178 
179  // get the UserStyle element
180  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
181  if ( userStyleElem.isNull() )
182  {
183  // UserStyle element not found, nothing will be rendered
184  errorMessage = QStringLiteral( "Info: UserStyle element not found." );
185  return nullptr;
186  }
187 
188  // get the FeatureTypeStyle element
189  QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
190  if ( featTypeStyleElem.isNull() )
191  {
192  errorMessage = QStringLiteral( "Info: FeatureTypeStyle element not found." );
193  return nullptr;
194  }
195 
196  // use the RuleRenderer when more rules are present or the rule
197  // has filters or min/max scale denominators set,
198  // otherwise use the SingleSymbol renderer
199  bool needRuleRenderer = false;
200  int ruleCount = 0;
201 
202  QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
203  while ( !ruleElem.isNull() )
204  {
205  ruleCount++;
206 
207  // more rules present, use the RuleRenderer
208  if ( ruleCount > 1 )
209  {
210  QgsDebugMsg( "more Rule elements found: need a RuleRenderer" );
211  needRuleRenderer = true;
212  break;
213  }
214 
215  QDomElement ruleChildElem = ruleElem.firstChildElement();
216  while ( !ruleChildElem.isNull() )
217  {
218  // rule has filter or min/max scale denominator, use the RuleRenderer
219  if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
220  ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
221  ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
222  {
223  QgsDebugMsg( "Filter or Min/MaxScaleDenominator element found: need a RuleRenderer" );
224  needRuleRenderer = true;
225  break;
226  }
227 
228  ruleChildElem = ruleChildElem.nextSiblingElement();
229  }
230 
231  if ( needRuleRenderer )
232  {
233  break;
234  }
235 
236  ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
237  }
238 
239  QString rendererType;
240  if ( needRuleRenderer )
241  {
242  rendererType = QStringLiteral( "RuleRenderer" );
243  }
244  else
245  {
246  rendererType = QStringLiteral( "singleSymbol" );
247  }
248  QgsDebugMsg( QString( "Instantiating a '%1' renderer..." ).arg( rendererType ) );
249 
250  // create the renderer and return it
252  if ( !m )
253  {
254  errorMessage = QStringLiteral( "Error: Unable to get metadata for '%1' renderer." ).arg( rendererType );
255  return nullptr;
256  }
257 
258  QgsFeatureRenderer *r = m->createRendererFromSld( featTypeStyleElem, geomType );
259  return r;
260 }
261 
262 QDomElement QgsFeatureRenderer::writeSld( QDomDocument &doc, const QString &styleName, const QgsStringMap &props ) const
263 {
264  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
265 
266  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
267  nameElem.appendChild( doc.createTextNode( styleName ) );
268  userStyleElem.appendChild( nameElem );
269 
270  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
271  toSld( doc, featureTypeStyleElem, props );
272  userStyleElem.appendChild( featureTypeStyleElem );
273 
274  return userStyleElem;
275 }
276 
278 {
279  return false;
280 }
281 
283 {
284  Q_UNUSED( key );
285  return false;
286 }
287 
288 void QgsFeatureRenderer::checkLegendSymbolItem( const QString &key, bool state )
289 {
290  Q_UNUSED( key );
291  Q_UNUSED( state );
292 }
293 
294 void QgsFeatureRenderer::setLegendSymbolItem( const QString &key, QgsSymbol *symbol )
295 {
296  Q_UNUSED( key );
297  delete symbol;
298 }
299 
301 {
302  return QgsLegendSymbolList();
303 }
304 
306 {
309 }
310 
312 {
313  return nullptr != symbolForFeature( feat, context );
314 }
315 
317 {
318  QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(),
321 }
322 
324 {
325  Q_FOREACH ( QPointF pt, pts )
326  renderVertexMarker( pt, context );
327 }
328 
329 void QgsFeatureRenderer::renderVertexMarkerPolygon( QPolygonF &pts, QList<QPolygonF> *rings, QgsRenderContext &context )
330 {
331  Q_FOREACH ( QPointF pt, pts )
332  renderVertexMarker( pt, context );
333 
334  if ( rings )
335  {
336  Q_FOREACH ( const QPolygonF &ring, *rings )
337  {
338  Q_FOREACH ( QPointF pt, ring )
339  renderVertexMarker( pt, context );
340  }
341  }
342 }
343 
345 {
346  QgsSymbolList lst;
347  QgsSymbol *s = symbolForFeature( feat, context );
348  if ( s ) lst.append( s );
349  return lst;
350 }
351 
353 {
354  QgsSymbolList lst;
355  QgsSymbol *s = originalSymbolForFeature( feat, context );
356  if ( s ) lst.append( s );
357  return lst;
358 }
359 
361 {
362  return mPaintEffect;
363 }
364 
366 {
367  delete mPaintEffect;
368  mPaintEffect = effect;
369 }
370 
372 {
373  return mOrderBy;
374 }
375 
377 {
378  mOrderBy = orderBy;
379 }
380 
382 {
383  return mOrderByEnabled;
384 }
385 
387 {
388  mOrderByEnabled = enabled;
389 }
390 
392 {
393  if ( symbol->type() == QgsSymbol::Marker )
394  {
395  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
396  if ( QgsSymbol::ScaleArea == QgsSymbol::ScaleMethod( method ) )
397  {
398  s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(sqrt(" + QString::number( s->size() ) + " * (" + field + ")),0)" ) );
399  }
400  else
401  {
402  s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(" + QString::number( s->size() ) + " * (" + field + "),0)" ) );
403  }
405  }
406  else if ( symbol->type() == QgsSymbol::Line )
407  {
408  QgsLineSymbol *s = static_cast<QgsLineSymbol *>( symbol );
409  s->setDataDefinedWidth( QgsProperty::fromExpression( "coalesce(" + QString::number( s->width() ) + " * (" + field + "),0)" ) );
410  }
411 }
412 
413 void QgsFeatureRenderer::convertSymbolRotation( QgsSymbol *symbol, const QString &field )
414 {
415  if ( symbol->type() == QgsSymbol::Marker )
416  {
417  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
419  ? QString::number( s->angle() ) + " + "
420  : QString() ) + field );
421  s->setDataDefinedAngle( dd );
422  }
423 }
virtual bool willRenderFeature(QgsFeature &feat, QgsRenderContext &context)
Returns whether the renderer will render a feature or not.
The class is used as a container of context for various read/write operations on other objects...
virtual QgsSymbolList originalSymbolsForFeature(QgsFeature &feat, QgsRenderContext &context)
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
void setEnabled(const bool enabled)
Sets whether the effect is enabled.
void setVertexMarkerAppearance(int type, int size)
set type and size of editing vertex markers for subsequent rendering
QList< QgsLegendSymbolItem > QgsLegendSymbolList
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:472
Calculate scale by the diameter.
Definition: qgssymbol.h:96
virtual void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:275
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
virtual QgsFeatureRenderer * createRendererFromSld(QDomElement &elem, QgsWkbTypes::GeometryType geomType)
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context)
store renderer info to XML element
VertexMarkerType
Editing vertex markers.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual QgsSymbol * originalSymbolForFeature(QgsFeature &feature, QgsRenderContext &context)
Return symbol for feature.
Definition: qgsrenderer.cpp:81
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a QgsPoint in map coordinates.
Definition: qgssymbol.h:320
Base class for visual effects which can be applied to QPicture drawings.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
void renderVertexMarkerPolyline(QPolygonF &pts, QgsRenderContext &context)
render editing vertex marker for a polyline
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:49
void CORE_EXPORT load(const QDomElement &elem)
Deserialize from XML.
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:250
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1136
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:458
Line symbol.
Definition: qgssymbol.h:85
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:61
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a wkb string in map coordinates.
Definition: qgsrenderer.cpp:43
QMap< QString, QString > QgsStringMap
Definition: qgis.h:340
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application&#39;s paint effect registry, used for managing paint effects. ...
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the renderer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the renderer.
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:43
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
return new default symbol for specified geometry type
Definition: qgssymbol.cpp:254
QString type() const
Definition: qgsrenderer.h:124
virtual QgsSymbolList symbolsForFeature(QgsFeature &feat, QgsRenderContext &context)
Returns list of symbols used for rendering the feature.
static QgsPaintEffect * defaultStack()
Returns a new effect stack consisting of a sensible selection of default effects. ...
void setForceRasterRender(bool forceRaster)
Sets whether the renderer should be rendered to a raster destination.
Definition: qgsrenderer.h:366
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
Calculate scale by the area.
Definition: qgssymbol.h:95
double width() const
Definition: qgssymbol.cpp:1549
virtual QgsFeatureRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context)=0
Return new instance of the renderer given the DOM element.
virtual ~QgsFeatureRenderer()
Definition: qgsrenderer.cpp:71
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, int currentVertexMarkerSize=0)
Render a feature.
Definition: qgssymbol.cpp:676
QgsRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
static void convertSymbolSizeScale(QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field)
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbol.cpp:1401
ScaleMethod
Scale method.
Definition: qgssymbol.h:93
A store for object properties.
Definition: qgsproperty.h:189
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y. (Useful to assist vertex editing.)
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:36
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer...
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
void setDataDefinedWidth(const QgsProperty &property)
Set data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1568
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
void renderVertexMarkerPolygon(QPolygonF &pts, QList< QPolygonF > *rings, QgsRenderContext &context)
render editing vertex marker for a polygon
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:136
static void convertSymbolRotation(QgsSymbol *symbol, const QString &field)
Marker symbol.
Definition: qgssymbol.h:84
virtual QgsSymbol * symbolForFeature(QgsFeature &feature, QgsRenderContext &context)=0
To be overridden.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
SymbolType type() const
Definition: qgssymbol.h:112
double size() const
Returns the size for the whole symbol, which is the maximum size of all marker symbol layers in the s...
Definition: qgssymbol.cpp:1233
int mCurrentVertexMarkerSize
The current size of editing marker.
Definition: qgsrenderer.h:456
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
Stores metadata about one renderer class.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:48
virtual QDomElement writeSld(QDomDocument &doc, const QString &styleName, const QgsStringMap &props=QgsStringMap()) const
create the SLD UserStyle element following the SLD v1.1 specs with the given name ...
virtual QSet< QString > legendKeysForFeature(QgsFeature &feature, QgsRenderContext &context)
Return legend keys matching a specified feature.
Definition: qgsrenderer.cpp:86
virtual bool legendSymbolItemsCheckable() const
items of symbology items in legend should be checkable
void setDataDefinedSize(const QgsProperty &property)
Set data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1310
int mCurrentVertexMarkerType
The current type of editing marker.
Definition: qgsrenderer.h:454
void renderFeatureWithSymbol(QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
return a new renderer - used by default in vector layers
Definition: qgsrenderer.cpp:76
virtual bool filterNeedsGeometry() const
Returns true if this renderer requires the geometry to apply the filter.
Definition: qgsrenderer.cpp:93
Represents a vector layer which manages a vector based data sets.
QgsFeatureRenderer(const QString &type)
Definition: qgsrenderer.cpp:58
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer...
static QgsRendererRegistry * rendererRegistry()
Returns the application&#39;s renderer registry, used for managing vector layer renderers.
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1113
virtual bool renderFeature(QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false)
Render a feature using this renderer in the given context.
Definition: qgsrenderer.cpp:98
Represents a list of OrderByClauses, with the most important first and the least important last...
void renderVertexMarker(QPointF pt, QgsRenderContext &context)
render editing vertex marker at specified point
virtual QString dump() const
Returns debug information about this renderer.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.