QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgs25drenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgs25drenderer.cpp - qgs25drenderer
3  -----------------------------------
4 
5  begin : 14.1.2016
6  Copyright : (C) 2016 Matthias Kuhn
7  Email : matthias at opengis dot ch
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  ***************************************************************************/
16 #include "qgs25drenderer.h"
18 #include "qgsfillsymbollayer.h"
19 #include "qgspainteffect.h"
20 #include "qgseffectstack.h"
21 #include "qgsgloweffect.h"
22 #include "qgsproperty.h"
23 #include "qgssymbollayerutils.h"
25 #include "qgsstyleentityvisitor.h"
26 
27 #define ROOF_EXPRESSION \
28  "translate(" \
29  " $geometry," \
30  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
31  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
32  ")"
33 
34 #define WALL_EXPRESSION \
35  "order_parts( "\
36  " extrude(" \
37  " segments_to_lines( $geometry )," \
38  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
39  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
40  " )," \
41  " 'distance( $geometry, translate( @map_extent_center, 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) ), 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) ) ))'," \
42  " False" \
43  ")"
44 
45 #define ORDER_BY_EXPRESSION \
46  "distance(" \
47  " $geometry," \
48  " translate(" \
49  " @map_extent_center," \
50  " 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) )," \
51  " 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) )" \
52  " )" \
53  ")"
54 
55 #define WALL_SHADING_EXPRESSION \
56  "set_color_part( " \
57  " @symbol_color," \
58  " 'value'," \
59  " 40 + 19 * abs( $pi - azimuth( " \
60  " point_n( geometry_n($geometry, @geometry_part_num) , 1 ), " \
61  " point_n( geometry_n($geometry, @geometry_part_num) , 2 )" \
62  " ) ) " \
63  ")"
64 
66  : QgsFeatureRenderer( QStringLiteral( "25dRenderer" ) )
67 {
68  mSymbol.reset( new QgsFillSymbol() );
69 
70  mSymbol->deleteSymbolLayer( 0 ); // We never asked for the default layer
71 
73 
74  QVariantMap wallProperties;
75  wallProperties.insert( QStringLiteral( "geometryModifier" ), WALL_EXPRESSION );
76  wallProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
78 
79  QVariantMap roofProperties;
80  roofProperties.insert( QStringLiteral( "geometryModifier" ), ROOF_EXPRESSION );
81  roofProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
83 
84  floor->setLocked( true );
85 
86  mSymbol->appendSymbolLayer( floor );
87  mSymbol->appendSymbolLayer( walls );
88  mSymbol->appendSymbolLayer( roof );
89 
90  QgsEffectStack *effectStack = new QgsEffectStack();
91  QgsOuterGlowEffect *glowEffect = new QgsOuterGlowEffect();
92  glowEffect->setBlurLevel( 5 );
94  effectStack->appendEffect( glowEffect );
95  floor->setPaintEffect( effectStack );
96 
97  // These methods must only be used after the above initialization!
98 
99  setRoofColor( QColor( 177, 169, 124 ) );
100  setWallColor( QColor( 119, 119, 119 ) );
101 
103 
104  setShadowSpread( 4 );
105  setShadowColor( QColor( 17, 17, 17 ) );
106 
110  false );
111 
112  setOrderBy( orderBy );
113  setOrderByEnabled( true );
114 }
115 
116 QDomElement Qgs25DRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
117 {
118  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
119 
120  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "25dRenderer" ) );
121 
122  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "symbol" ), mSymbol.get(), doc, context );
123 
124  rendererElem.appendChild( symbolElem );
125 
126  return rendererElem;
127 }
128 
129 QgsFeatureRenderer *Qgs25DRenderer::create( QDomElement &element, const QgsReadWriteContext &context )
130 {
131  Qgs25DRenderer *renderer = new Qgs25DRenderer();
132 
133  QDomNodeList symbols = element.elementsByTagName( QStringLiteral( "symbol" ) );
134  if ( symbols.size() )
135  {
136  renderer->mSymbol.reset( QgsSymbolLayerUtils::loadSymbol( symbols.at( 0 ).toElement(), context ) );
137  }
138 
139  return renderer;
140 }
141 
143 {
144  QgsFeatureRenderer::startRender( context, fields );
145 
146  mSymbol->startRender( context, fields );
147 }
148 
150 {
152 
153  mSymbol->stopRender( context );
154 }
155 
156 QSet<QString> Qgs25DRenderer::usedAttributes( const QgsRenderContext &context ) const
157 {
158  return mSymbol->usedAttributes( context );
159 }
160 
162 {
164  c->mSymbol.reset( mSymbol->clone() );
165  return c;
166 }
167 
169 {
170  Q_UNUSED( feature )
171  Q_UNUSED( context )
172  return mSymbol.get();
173 }
174 
176 {
177  Q_UNUSED( context )
178  QgsSymbolList lst;
179  lst.append( mSymbol.get() );
180  return lst;
181 }
182 
184 {
185  if ( mSymbol )
186  {
187  QgsStyleSymbolEntity entity( mSymbol.get() );
188  return visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) );
189  }
190  return true;
191 }
192 
193 QgsFillSymbolLayer *Qgs25DRenderer::roofLayer() const
194 {
195  return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 2 )->subSymbol()->symbolLayer( 0 ) );
196 }
197 
198 QgsFillSymbolLayer *Qgs25DRenderer::wallLayer() const
199 {
200  return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 1 )->subSymbol()->symbolLayer( 0 ) );
201 }
202 
203 QgsOuterGlowEffect *Qgs25DRenderer::glowEffect() const
204 {
205  QgsEffectStack *stack = static_cast<QgsEffectStack *>( mSymbol->symbolLayer( 0 )->paintEffect() );
206  return static_cast<QgsOuterGlowEffect *>( stack->effect( 0 ) );
207 }
208 
210 {
211  return glowEffect()->enabled();
212 }
213 
215 {
216  glowEffect()->setEnabled( value );
217 }
218 
220 {
221  return glowEffect()->color();
222 }
223 
224 void Qgs25DRenderer::setShadowColor( const QColor &shadowColor )
225 {
226  glowEffect()->setColor( shadowColor );
227 }
228 
230 {
231  return glowEffect()->spread();
232 }
233 
234 void Qgs25DRenderer::setShadowSpread( double spread )
235 {
236  glowEffect()->setSpread( spread );
237 }
238 
240 {
241  return wallLayer()->fillColor();
242 }
243 
244 void Qgs25DRenderer::setWallColor( const QColor &wallColor )
245 {
246  wallLayer()->setFillColor( wallColor );
247  wallLayer()->setStrokeColor( wallColor );
248 }
249 
251 {
253 }
254 
256 {
258 }
259 
261 {
262  return roofLayer()->fillColor();
263 }
264 
265 void Qgs25DRenderer::setRoofColor( const QColor &roofColor )
266 {
267  roofLayer()->setFillColor( roofColor );
268  roofLayer()->setStrokeColor( roofColor );
269 }
270 
272 {
273  if ( renderer->type() == QLatin1String( "25dRenderer" ) )
274  {
275  return static_cast<Qgs25DRenderer *>( renderer->clone() );
276  }
277  else
278  {
279  return new Qgs25DRenderer();
280  }
281 }
282 
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
QColor roofColor() const
Gets the roof color.
void setWallColor(const QColor &wallColor)
Set the wall color.
QColor shadowColor() const
Gets the shadow's color.
QgsFeatureRenderer * clone() const override
Create a deep copy of this renderer.
static Qgs25DRenderer * convertFromRenderer(QgsFeatureRenderer *renderer)
Try to convert from an existing renderer.
double shadowSpread() const
Gets the shadow's spread distance in map units.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Create a new 2.5D renderer from XML.
void setWallShadingEnabled(bool enabled)
Set wall shading enabled.
void setRoofColor(const QColor &roofColor)
Set the roof color.
void setShadowEnabled(bool value)
Enable or disable the shadow.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
bool wallShadingEnabled() const
Gets wall shading enabled.
bool shadowEnabled() const
Is the shadow enabled.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
QColor wallColor() const
Gets the wall color.
void setShadowColor(const QColor &shadowColor)
Set the shadow's color.
void setShadowSpread(double shadowSpread)
Set the shadow's spread distance in map units.
A paint effect which consists of a stack of other chained paint effects.
void appendEffect(QgsPaintEffect *effect)
Appends an effect to the end of the stack.
QgsPaintEffect * effect(int index) const
Returns a pointer to the effect at a specified index within the stack.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer.
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QString type() const
Definition: qgsrenderer.h:141
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:94
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
Container of fields for a vector layer.
Definition: qgsfields.h:45
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1307
static QgsSymbolLayer * create(const QVariantMap &properties)
Creates the symbol layer.
void setSpread(const double spread)
Sets the spread distance for drawing the glow effect.
Definition: qgsgloweffect.h:64
double spread() const
Returns the spread distance used for drawing the glow effect.
Definition: qgsgloweffect.h:73
QColor color() const
Returns the color for the glow.
void setBlurLevel(const double level)
Sets blur level (radius) for the glow.
void setSpreadUnit(const QgsUnitTypes::RenderUnit unit)
Sets the units used for the glow spread distance.
Definition: qgsgloweffect.h:82
void setColor(const QColor &color)
Sets the color for the glow.
A paint effect which draws a glow outside of a picture.
void setEnabled(bool enabled)
Sets whether the effect is enabled.
bool enabled() const
Returns whether the effect is enabled.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
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.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleFillSymbolLayer using the specified properties map containing symbol propertie...
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
static QgsSymbol * loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
@ PropertyFillColor
Fill color.
virtual void setFillColor(const QColor &color)
Set fill color.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
virtual QColor fillColor() const
Gets fill color.
virtual void setStrokeColor(const QColor &color)
Set stroke color.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
void setLocked(bool locked)
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:65
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:169
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define WALL_SHADING_EXPRESSION
#define ORDER_BY_EXPRESSION
#define WALL_EXPRESSION
#define ROOF_EXPRESSION
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:51
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:45
Contains information relating to the style entity currently being visited.