QGIS API Documentation  2.14.0-Essen
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 "qgsfillsymbollayerv2.h"
19 #include "qgspainteffect.h"
20 #include "qgseffectstack.h"
21 #include "qgsgloweffect.h"
22 
23 #define ROOF_EXPRESSION \
24  "translate(" \
25  " $geometry," \
26  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
27  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
28  ")"
29 
30 #define WALL_EXPRESSION \
31  "order_parts( "\
32  " extrude(" \
33  " segments_to_lines( $geometry )," \
34  " cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )," \
35  " sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height )" \
36  " )," \
37  " '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 ) ) ))'," \
38  " False" \
39  ")"
40 
41 #define ORDER_BY_EXPRESSION \
42  "distance(" \
43  " $geometry," \
44  " translate(" \
45  " @map_extent_center," \
46  " 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) )," \
47  " 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) )" \
48  " )" \
49  ")"
50 
51 #define WALL_SHADING_EXPRESSION \
52  "set_color_part( " \
53  " @symbol_color," \
54  " 'value'," \
55  " 40 + 19 * abs( $pi - azimuth( " \
56  " point_n( geometry_n($geometry, @geometry_part_num) , 1 ), " \
57  " point_n( geometry_n($geometry, @geometry_part_num) , 2 )" \
58  " ) ) " \
59  ")"
60 
62  : QgsFeatureRendererV2( "25dRenderer" )
63 {
64  mSymbol.reset( new QgsFillSymbolV2() );
65 
66  mSymbol->deleteSymbolLayer( 0 ); // We never asked for the default layer
67 
69 
70  QgsStringMap wallProperties;
71  wallProperties.insert( "geometryModifier", WALL_EXPRESSION );
72  wallProperties.insert( "symbolType", "Fill" );
74 
75  QgsStringMap roofProperties;
76  roofProperties.insert( "geometryModifier", ROOF_EXPRESSION );
77  roofProperties.insert( "symbolType", "Fill" );
79 
80  floor->setLocked( true );
81 
82  mSymbol->appendSymbolLayer( floor );
83  mSymbol->appendSymbolLayer( walls );
84  mSymbol->appendSymbolLayer( roof );
85 
86  QgsEffectStack* effectStack = new QgsEffectStack();
87  QgsOuterGlowEffect* glowEffect = new QgsOuterGlowEffect();
88  glowEffect->setBlurLevel( 5 );
89  glowEffect->setSpreadUnit( QgsSymbolV2::MapUnit );
90  effectStack->appendEffect( glowEffect );
91  floor->setPaintEffect( effectStack );
92 
93  // These methods must only be used after the above initialization!
94 
95  setRoofColor( QColor( "#fdbf6f" ) );
96  setWallColor( QColor( "#777777" ) );
97 
98  wallLayer()->setDataDefinedProperty( "color", new QgsDataDefined( QString( WALL_SHADING_EXPRESSION ) ) );
99 
100  setShadowSpread( 4 );
101  setShadowColor( QColor( "#111111" ) );
102 
106  false );
107 
108  setOrderBy( orderBy );
109  setOrderByEnabled( true );
110 }
111 
113 {
114  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
115 
116  rendererElem.setAttribute( "type", "25dRenderer" );
117 
118  QDomElement symbolElem = QgsSymbolLayerV2Utils::saveSymbol( "symbol", mSymbol.data(), doc );
119 
120  rendererElem.appendChild( symbolElem );
121 
122  return rendererElem;
123 }
124 
126 {
127  Qgs25DRenderer* renderer = new Qgs25DRenderer();
128 
129  QDomNodeList symbols = element.elementsByTagName( "symbol" );
130  if ( symbols.size() )
131  {
132  renderer->mSymbol.reset( QgsSymbolLayerV2Utils::loadSymbol( symbols.at( 0 ).toElement() ) );
133  }
134 
135  return renderer;
136 }
137 
139 {
140  mSymbol->startRender( context, &fields );
141 }
142 
144 {
145  mSymbol->stopRender( context );
146 }
147 
149 {
150  return mSymbol->usedAttributes().toList();
151 }
152 
154 {
155  Qgs25DRenderer* c = new Qgs25DRenderer();
156  c->mSymbol.reset( mSymbol->clone() );
157  return c;
158 }
159 
161 {
162  Q_UNUSED( feature )
163  Q_UNUSED( context )
164  return mSymbol.data();
165 }
166 
168 {
169  Q_UNUSED( context );
170  QgsSymbolV2List lst;
171  lst.append( mSymbol.data() );
172  return lst;
173 }
174 
175 QgsFillSymbolLayerV2* Qgs25DRenderer::roofLayer() const
176 {
177  return static_cast<QgsFillSymbolLayerV2*>( mSymbol->symbolLayer( 2 )->subSymbol()->symbolLayer( 0 ) );
178 }
179 
180 QgsFillSymbolLayerV2* Qgs25DRenderer::wallLayer() const
181 {
182  return static_cast<QgsFillSymbolLayerV2*>( mSymbol->symbolLayer( 1 )->subSymbol()->symbolLayer( 0 ) );
183 }
184 
185 QgsOuterGlowEffect* Qgs25DRenderer::glowEffect() const
186 {
187  QgsEffectStack* stack = static_cast<QgsEffectStack*>( mSymbol->symbolLayer( 0 )->paintEffect() );
188  return static_cast<QgsOuterGlowEffect*>( stack->effect( 0 ) );
189 }
190 
192 {
193  return glowEffect()->enabled();
194 }
195 
197 {
198  glowEffect()->setEnabled( value );
199 }
200 
202 {
203  return glowEffect()->color();
204 }
205 
207 {
208  glowEffect()->setColor( shadowColor );
209 }
210 
212 {
213  return glowEffect()->spread();
214 }
215 
216 void Qgs25DRenderer::setShadowSpread( double spread )
217 {
218  glowEffect()->setSpread( spread );
219 }
220 
222 {
223  return wallLayer()->fillColor();
224 }
225 
227 {
228  wallLayer()->setFillColor( wallColor );
229  wallLayer()->setOutlineColor( wallColor );
230 }
231 
233 {
234  wallLayer()->getDataDefinedProperty( "color" )->setActive( enabled );
235 }
236 
238 {
239  return wallLayer()->getDataDefinedProperty( "color" )->isActive();
240 }
241 
243 {
244  return roofLayer()->fillColor();
245 }
246 
248 {
249  roofLayer()->setFillColor( roofColor );
250  roofLayer()->setOutlineColor( roofColor );
251 }
252 
254 {
255  if ( renderer->type() == "25dRenderer" )
256  {
257  return static_cast<Qgs25DRenderer*>( renderer->clone() );
258  }
259  else
260  {
261  return new Qgs25DRenderer();
262  }
263 }
264 
QColor shadowColor() const
Get the shadow&#39;s color.
void setLocked(bool locked)
QDomNodeList elementsByTagName(const QString &tagname) const
void stopRender(QgsRenderContext &context) override
Needs to be called when a render cycle has finished to clean up.
void setActive(bool active)
#define RENDERER_TAG_NAME
Definition: qgsrendererv2.h:49
static QgsSymbolLayerV2 * create(const QgsStringMap &properties)
void setEnabled(const bool enabled)
Sets whether the effect is enabled.
bool wallShadingEnabled()
Get wall shading enabled.
A container class for data source field mapping or expression.
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Needs to be called when a new render cycle is started.
virtual void setOutlineColor(const QColor &color)
Set outline color.
QDomNode appendChild(const QDomNode &newChild)
static QgsFeatureRendererV2 * create(QDomElement &element)
Create a new 2.5D renderer from XML.
void setSpreadUnit(const QgsSymbolV2::OutputUnit unit)
Sets the units used for the glow spread distance.
Definition: qgsgloweffect.h:75
static Qgs25DRenderer * convertFromRenderer(QgsFeatureRendererV2 *renderer)
Try to convert from an existing renderer.
bool enabled() const
Returns whether the effect is enabled.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbolV2 *symbol, QDomDocument &doc)
Container of fields for a vector layer.
Definition: qgsfield.h:187
#define WALL_SHADING_EXPRESSION
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QDomElement save(QDomDocument &doc) override
store renderer info to XML element
virtual QColor fillColor() const
Get fill color.
QColor wallColor() const
Get the wall color.
static QgsSymbolV2 * loadSymbol(const QDomElement &element)
Attempts to load a symbol from a DOM element.
void reset(T *other)
QString type() const
Definition: qgsrendererv2.h:83
QDomElement toElement() const
void setBlurLevel(const int level)
Sets blur level (strength) for the glow.
virtual QgsFeatureRendererV2 * clone() const =0
void append(const T &value)
double spread() const
Returns the spread distance used for drawing the glow effect.
Definition: qgsgloweffect.h:67
void setAttribute(const QString &name, const QString &value)
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer...
void setShadowSpread(double shadowSpread)
Set the shadow&#39;s spread distance in map units.
#define ORDER_BY_EXPRESSION
The output shall be in map unitx.
Definition: qgssymbolv2.h:65
A paint effect which consists of a stack of other chained paint effects.
virtual Q_DECL_DEPRECATED QgsSymbolV2List symbols()
For symbol levels.
void setSpread(const double spread)
Sets the spread distance for drawing the glow effect.
Definition: qgsgloweffect.h:59
void appendEffect(QgsPaintEffect *effect)
Appends an effect to the end of the stack.
#define ROOF_EXPRESSION
virtual void setFillColor(const QColor &color)
Set fill color.
T * data() const
A paint effect which draws a glow outside of a picture.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Contains information about the context of a rendering operation.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
QColor roofColor() const
Get the roof color.
#define WALL_EXPRESSION
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
void setRoofColor(const QColor &roofColor)
Set the roof color.
QColor color() const
Returns the color for the glow.
void setShadowEnabled(bool value)
Enable or disable the shadow.
void setWallShadingEnabled(bool enabled)
Set wall shading enabled.
QgsFeatureRendererV2 * clone() const override
iterator insert(const Key &key, const T &value)
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature, QgsRenderContext &context) override
To be overridden.
QList< QString > usedAttributes() override
Returns a set of attributes required for this renderer.
int size() const
QDomElement createElement(const QString &tagName)
QgsPaintEffect * effect(int index) const
Returns a pointer to the effect at a specified index within the stack.
void setShadowColor(const QColor &shadowColor)
Set the shadow&#39;s color.
void setColor(const QColor &color)
Sets the color for the glow.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setWallColor(const QColor &wallColor)
Set the wall color.
double shadowSpread() const
Get the shadow&#39;s spread distance in map units.
bool isActive() const
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
bool shadowEnabled() const
Is the shadow enabled.
Represents a list of OrderByClauses, with the most important first and the least important last...
QDomNode at(int index) const
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.