QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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"
17
18#include <memory>
19
20#include "qgseffectstack.h"
21#include "qgsfillsymbol.h"
22#include "qgsfillsymbollayer.h"
24#include "qgsgloweffect.h"
25#include "qgspainteffect.h"
26#include "qgsproperty.h"
28#include "qgssymbollayerutils.h"
29
30#define ROOF_EXPRESSION \
31 "translate(" \
32 " @geometry," \
33 " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
34 " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
35 ")"
36
37#define WALL_EXPRESSION \
38 "order_parts( "\
39 " extrude(" \
40 " segments_to_lines( @geometry )," \
41 " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
42 " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
43 " )," \
44 " '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 ) ) ))'," \
45 " False" \
46 ")"
47
48#define ORDER_BY_EXPRESSION \
49 "distance(" \
50 " @geometry," \
51 " translate(" \
52 " @map_extent_center," \
53 " 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) )," \
54 " 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) )" \
55 " )" \
56 ")"
57
58#define WALL_SHADING_EXPRESSION \
59 "set_color_part( " \
60 " @symbol_color," \
61 " 'value'," \
62 " 40 + 19 * abs( $pi - azimuth( " \
63 " point_n( geometry_n(@geometry, @geometry_part_num) , 1 ), " \
64 " point_n( geometry_n(@geometry, @geometry_part_num) , 2 )" \
65 " ) ) " \
66 ")"
67
69 : QgsFeatureRenderer( QStringLiteral( "25dRenderer" ) )
70{
71 mSymbol = std::make_unique<QgsFillSymbol>( );
72
73 mSymbol->deleteSymbolLayer( 0 ); // We never asked for the default layer
74
76
77 QVariantMap wallProperties;
78 wallProperties.insert( QStringLiteral( "geometryModifier" ), WALL_EXPRESSION );
79 wallProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
81
82 QVariantMap roofProperties;
83 roofProperties.insert( QStringLiteral( "geometryModifier" ), ROOF_EXPRESSION );
84 roofProperties.insert( QStringLiteral( "symbolType" ), QStringLiteral( "Fill" ) );
86
87 floor->setLocked( true );
88
89 mSymbol->appendSymbolLayer( floor );
90 mSymbol->appendSymbolLayer( walls );
91 mSymbol->appendSymbolLayer( roof );
92
93 QgsEffectStack *effectStack = new QgsEffectStack();
94 QgsOuterGlowEffect *glowEffect = new QgsOuterGlowEffect();
95 glowEffect->setBlurLevel( 5 );
96 glowEffect->setSpreadUnit( Qgis::RenderUnit::MapUnits );
97 effectStack->appendEffect( glowEffect );
98 floor->setPaintEffect( effectStack );
99
100 // These methods must only be used after the above initialization!
101
102 setRoofColor( QColor( 177, 169, 124 ) );
103 setWallColor( QColor( 119, 119, 119 ) );
104
105 wallLayer()->setDataDefinedProperty( QgsSymbolLayer::Property::FillColor, QgsProperty::fromExpression( QString( WALL_SHADING_EXPRESSION ) ) );
106
107 setShadowSpread( 4 );
108 setShadowColor( QColor( 17, 17, 17 ) );
109
113 false );
114
116 setOrderByEnabled( true );
117}
118
119QDomElement Qgs25DRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
120{
121 QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
122
123 rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "25dRenderer" ) );
124
125 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "symbol" ), mSymbol.get(), doc, context );
126
127 saveRendererData( doc, rendererElem, context );
128
129 rendererElem.appendChild( symbolElem );
130
131 return rendererElem;
132}
133
135{
137 if ( mSymbol && mSymbol->flags().testFlag( Qgis::SymbolFlag::AffectsLabeling ) )
139
140 return res;
141}
142
143QgsFeatureRenderer *Qgs25DRenderer::create( QDomElement &element, const QgsReadWriteContext &context )
144{
145 Qgs25DRenderer *renderer = new Qgs25DRenderer();
146
147 const QDomNodeList symbols = element.elementsByTagName( QStringLiteral( "symbol" ) );
148 if ( symbols.size() )
149 {
150 renderer->mSymbol = QgsSymbolLayerUtils::loadSymbol( symbols.at( 0 ).toElement(), context );
151 }
152
153 return renderer;
154}
155
157{
158 QgsFeatureRenderer::startRender( context, fields );
159
160 mSymbol->startRender( context, fields );
161}
162
164{
166
167 mSymbol->stopRender( context );
168}
169
170QSet<QString> Qgs25DRenderer::usedAttributes( const QgsRenderContext &context ) const
171{
172 return mSymbol->usedAttributes( context );
173}
174
176{
178 c->mSymbol.reset( mSymbol->clone() );
179 return c;
180}
181
183{
184 Q_UNUSED( feature )
185 Q_UNUSED( context )
186 return mSymbol.get();
187}
188
190{
191 Q_UNUSED( context )
192 QgsSymbolList lst;
193 lst.append( mSymbol.get() );
194 return lst;
195}
196
198{
199 if ( mSymbol )
200 {
201 QgsStyleSymbolEntity entity( mSymbol.get() );
202 return visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) );
203 }
204 return true;
205}
206
207QgsFillSymbolLayer *Qgs25DRenderer::roofLayer() const
208{
209 return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 2 )->subSymbol()->symbolLayer( 0 ) );
210}
211
212QgsFillSymbolLayer *Qgs25DRenderer::wallLayer() const
213{
214 return static_cast<QgsFillSymbolLayer *>( mSymbol->symbolLayer( 1 )->subSymbol()->symbolLayer( 0 ) );
215}
216
217QgsOuterGlowEffect *Qgs25DRenderer::glowEffect() const
218{
219 QgsEffectStack *stack = static_cast<QgsEffectStack *>( mSymbol->symbolLayer( 0 )->paintEffect() );
220 return static_cast<QgsOuterGlowEffect *>( stack->effect( 0 ) );
221}
222
224{
225 return glowEffect()->enabled();
226}
227
228void Qgs25DRenderer::setShadowEnabled( bool value ) const
229{
230 glowEffect()->setEnabled( value );
231}
232
234{
235 return glowEffect()->color();
236}
237
239{
240 glowEffect()->setColor( shadowColor );
241}
242
244{
245 return glowEffect()->spread();
246}
247
248void Qgs25DRenderer::setShadowSpread( double spread ) const
249{
250 glowEffect()->setSpread( spread );
251}
252
254{
255 return wallLayer()->fillColor();
256}
257
258void Qgs25DRenderer::setWallColor( const QColor &wallColor ) const
259{
260 wallLayer()->setFillColor( wallColor );
261 wallLayer()->setStrokeColor( wallColor );
262}
263
265{
266 wallLayer()->dataDefinedProperties().property( QgsSymbolLayer::Property::FillColor ).setActive( enabled );
267}
268
270{
271 return wallLayer()->dataDefinedProperties().property( QgsSymbolLayer::Property::FillColor ).isActive();
272}
273
275{
276 return roofLayer()->fillColor();
277}
278
279void Qgs25DRenderer::setRoofColor( const QColor &roofColor ) const
280{
281 roofLayer()->setFillColor( roofColor );
282 roofLayer()->setStrokeColor( roofColor );
283}
284
286{
287 if ( renderer->type() == QLatin1String( "25dRenderer" ) )
288 {
289 return static_cast<Qgs25DRenderer *>( renderer->clone() );
290 }
291 else
292 {
293 auto res = std::make_unique< Qgs25DRenderer >();
294 renderer->copyRendererData( res.get() );
295 return res.release();
296 }
297}
298
QFlags< FeatureRendererFlag > FeatureRendererFlags
Flags controlling behavior of vector feature renderers.
Definition qgis.h:838
@ AffectsLabeling
If present, indicates that the renderer will participate in the map labeling problem.
Definition qgis.h:829
@ MapUnits
Map units.
Definition qgis.h:5185
@ AffectsLabeling
If present, indicates that the symbol will participate in the map labeling problem.
Definition qgis.h:849
Qgis::FeatureRendererFlags flags() const override
Returns flags associated with the renderer.
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.
void setShadowSpread(double shadowSpread) const
Set the shadow's spread distance in map units.
QColor roofColor() const
Gets the roof color.
void setWallShadingEnabled(bool enabled) const
Set wall shading enabled.
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 setShadowColor(const QColor &shadowColor) const
Set the shadow's color.
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.
void setRoofColor(const QColor &roofColor) const
Set the roof color.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
Stores renderer properties to an XML element.
void setWallColor(const QColor &wallColor) const
Set the wall color.
QColor wallColor() const
Gets the wall color.
void setShadowEnabled(bool value) const
Enable or disable the shadow.
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.
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the renderer.
QgsFeatureRenderer(const QString &type)
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QString type() const
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
void saveRendererData(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context)
Saves generic renderer data into the specified element.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of 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:58
Container of fields for a vector layer.
Definition qgsfields.h:46
Abstract base class for fill symbol layers.
static QgsSymbolLayer * create(const QVariantMap &properties)
Creates the symbol layer.
A paint effect which draws a glow outside of a picture.
bool enabled() const
Returns whether the effect is enabled.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
A container for the context for various read/write operations on 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:1397
static std::unique_ptr< 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.
Abstract base class for symbol layers.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
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:55
QList< QgsSymbol * > QgsSymbolList
Definition qgsrenderer.h:49
Contains information relating to the style entity currently being visited.