QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include "qgsfillsymbol.h"
27 
28 #define ROOF_EXPRESSION \
29  "translate(" \
30  " $geometry," \
31  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
32  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
33  ")"
34 
35 #define WALL_EXPRESSION \
36  "order_parts( "\
37  " extrude(" \
38  " segments_to_lines( $geometry )," \
39  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
40  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
41  " )," \
42  " '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 ) ) ))'," \
43  " False" \
44  ")"
45 
46 #define ORDER_BY_EXPRESSION \
47  "distance(" \
48  " $geometry," \
49  " translate(" \
50  " @map_extent_center," \
51  " 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) )," \
52  " 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) )" \
53  " )" \
54  ")"
55 
56 #define WALL_SHADING_EXPRESSION \
57  "set_color_part( " \
58  " @symbol_color," \
59  " 'value'," \
60  " 40 + 19 * abs( $pi - azimuth( " \
61  " point_n( geometry_n($geometry, @geometry_part_num) , 1 ), " \
62  " point_n( geometry_n($geometry, @geometry_part_num) , 2 )" \
63  " ) ) " \
64  ")"
65 
67  : QgsFeatureRenderer( QStringLiteral( "25dRenderer" ) )
68 {
69  mSymbol.reset( new QgsFillSymbol() );
70 
71  mSymbol->deleteSymbolLayer( 0 ); // We never asked for the default layer
72 
74 
75  QVariantMap wallProperties;
76  wallProperties.insert( QStringLiteral( "geometryModifier" ), WALL_EXPRESSION );
77  wallProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
79 
80  QVariantMap roofProperties;
81  roofProperties.insert( QStringLiteral( "geometryModifier" ), ROOF_EXPRESSION );
82  roofProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
84 
85  floor->setLocked( true );
86 
87  mSymbol->appendSymbolLayer( floor );
88  mSymbol->appendSymbolLayer( walls );
89  mSymbol->appendSymbolLayer( roof );
90 
91  QgsEffectStack *effectStack = new QgsEffectStack();
92  QgsOuterGlowEffect *glowEffect = new QgsOuterGlowEffect();
93  glowEffect->setBlurLevel( 5 );
95  effectStack->appendEffect( glowEffect );
96  floor->setPaintEffect( effectStack );
97 
98  // These methods must only be used after the above initialization!
99 
100  setRoofColor( QColor( 177, 169, 124 ) );
101  setWallColor( QColor( 119, 119, 119 ) );
102 
104 
105  setShadowSpread( 4 );
106  setShadowColor( QColor( 17, 17, 17 ) );
107 
111  false );
112 
113  setOrderBy( orderBy );
114  setOrderByEnabled( true );
115 }
116 
117 QDomElement Qgs25DRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
118 {
119  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
120 
121  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "25dRenderer" ) );
122 
123  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "symbol" ), mSymbol.get(), doc, context );
124 
125  rendererElem.appendChild( symbolElem );
126 
127  return rendererElem;
128 }
129 
130 QgsFeatureRenderer *Qgs25DRenderer::create( QDomElement &element, const QgsReadWriteContext &context )
131 {
132  Qgs25DRenderer *renderer = new Qgs25DRenderer();
133 
134  QDomNodeList symbols = element.elementsByTagName( QStringLiteral( "symbol" ) );
135  if ( symbols.size() )
136  {
137  renderer->mSymbol.reset( QgsSymbolLayerUtils::loadSymbol( symbols.at( 0 ).toElement(), context ) );
138  }
139 
140  return renderer;
141 }
142 
144 {
145  QgsFeatureRenderer::startRender( context, fields );
146 
147  mSymbol->startRender( context, fields );
148 }
149 
151 {
153 
154  mSymbol->stopRender( context );
155 }
156 
157 QSet<QString> Qgs25DRenderer::usedAttributes( const QgsRenderContext &context ) const
158 {
159  return mSymbol->usedAttributes( context );
160 }
161 
163 {
165  c->mSymbol.reset( mSymbol->clone() );
166  return c;
167 }
168 
170 {
171  Q_UNUSED( feature )
172  Q_UNUSED( context )
173  return mSymbol.get();
174 }
175 
177 {
178  Q_UNUSED( context )
179  QgsSymbolList lst;
180  lst.append( mSymbol.get() );
181  return lst;
182 }
183 
185 {
186  if ( mSymbol )
187  {
188  QgsStyleSymbolEntity entity( mSymbol.get() );
189  return visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) );
190  }
191  return true;
192 }
193 
194 QgsFillSymbolLayer *Qgs25DRenderer::roofLayer() const
195 {
196  return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 2 )->subSymbol()->symbolLayer( 0 ) );
197 }
198 
199 QgsFillSymbolLayer *Qgs25DRenderer::wallLayer() const
200 {
201  return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 1 )->subSymbol()->symbolLayer( 0 ) );
202 }
203 
204 QgsOuterGlowEffect *Qgs25DRenderer::glowEffect() const
205 {
206  QgsEffectStack *stack = static_cast<QgsEffectStack *>( mSymbol->symbolLayer( 0 )->paintEffect() );
207  return static_cast<QgsOuterGlowEffect *>( stack->effect( 0 ) );
208 }
209 
211 {
212  return glowEffect()->enabled();
213 }
214 
216 {
217  glowEffect()->setEnabled( value );
218 }
219 
221 {
222  return glowEffect()->color();
223 }
224 
225 void Qgs25DRenderer::setShadowColor( const QColor &shadowColor )
226 {
227  glowEffect()->setColor( shadowColor );
228 }
229 
231 {
232  return glowEffect()->spread();
233 }
234 
235 void Qgs25DRenderer::setShadowSpread( double spread )
236 {
237  glowEffect()->setSpread( spread );
238 }
239 
241 {
242  return wallLayer()->fillColor();
243 }
244 
245 void Qgs25DRenderer::setWallColor( const QColor &wallColor )
246 {
247  wallLayer()->setFillColor( wallColor );
248  wallLayer()->setStrokeColor( wallColor );
249 }
250 
252 {
254 }
255 
257 {
259 }
260 
262 {
263  return roofLayer()->fillColor();
264 }
265 
266 void Qgs25DRenderer::setRoofColor( const QColor &roofColor )
267 {
268  roofLayer()->setFillColor( roofColor );
269  roofLayer()->setStrokeColor( roofColor );
270 }
271 
273 {
274  if ( renderer->type() == QLatin1String( "25dRenderer" ) )
275  {
276  return static_cast<Qgs25DRenderer *>( renderer->clone() );
277  }
278  else
279  {
280  return new Qgs25DRenderer();
281  }
282 }
283 
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 unique ID, geometry and a list of field...
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: qgsfillsymbol.h:30
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:65
double spread() const
Returns the spread distance used for drawing the glow effect.
Definition: qgsgloweffect.h:74
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:83
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:1219
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)
Sets whether the layer's colors are 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:38
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
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:49
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:43
Contains information relating to the style entity currently being visited.