QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgssymbollayerv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbollayerv2.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 "qgssymbollayerv2.h"
17 #include "qgsclipper.h"
18 #include "qgsexpression.h"
19 #include "qgsrendercontext.h"
20 #include "qgsvectorlayer.h"
21 
22 #include <QSize>
23 #include <QPainter>
24 #include <QPointF>
25 #include <QPolygonF>
26 
27 const QgsExpression* QgsSymbolLayerV2::dataDefinedProperty( const QString& property ) const
28 {
29  QMap< QString, QgsExpression* >::const_iterator it = mDataDefinedProperties.find( property );
30  if ( it != mDataDefinedProperties.constEnd() )
31  {
32  return it.value();
33  }
34  return 0;
35 }
36 
37 QgsExpression* QgsSymbolLayerV2::expression( const QString& property )
38 {
39  QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.find( property );
40  if ( it != mDataDefinedProperties.end() )
41  {
42  return it.value();
43  }
44  return 0;
45 }
46 
47 QString QgsSymbolLayerV2::dataDefinedPropertyString( const QString& property ) const
48 {
49  const QgsExpression* ex = dataDefinedProperty( property );
50  return ex ? ex->expression() : QString();
51 }
52 
53 void QgsSymbolLayerV2::setDataDefinedProperty( const QString& property, const QString& expressionString )
54 {
55  removeDataDefinedProperty( property );
56  mDataDefinedProperties.insert( property, new QgsExpression( expressionString ) );
57 }
58 
59 void QgsSymbolLayerV2::removeDataDefinedProperty( const QString& property )
60 {
61  QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.find( property );
62  if ( it != mDataDefinedProperties.end() )
63  {
64  delete( it.value() );
65  mDataDefinedProperties.erase( it );
66  }
67 }
68 
70 {
71  QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.begin();
72  for ( ; it != mDataDefinedProperties.constEnd(); ++it )
73  {
74  delete( it.value() );
75  }
76  mDataDefinedProperties.clear();
77 }
78 
80 {
81  if ( !vl )
82  {
83  return;
84  }
85 
86  const QgsFields& fields = vl->pendingFields();
87  QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.begin();
88  for ( ; it != mDataDefinedProperties.end(); ++it )
89  {
90  if ( it.value() )
91  {
92  it.value()->prepare( fields );
93  }
94  }
95 }
96 
97 QSet<QString> QgsSymbolLayerV2::usedAttributes() const
98 {
99  QStringList columns;
100 
101  QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
102  for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
103  {
104  if ( ddIt.value() )
105  {
106  columns.append( ddIt.value()->referencedColumns() );
107  }
108  }
109 
110  QSet<QString> attributes;
111  QStringList::const_iterator it = columns.constBegin();
112  for ( ; it != columns.constEnd(); ++it )
113  {
114  attributes.insert( *it );
115  }
116 
117  return attributes;
118 }
119 
121 {
122  QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
123  for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
124  {
125  if ( ddIt.value() )
126  {
127  stringMap.insert( ddIt.key() + "_expression", ddIt.value()->expression() );
128  }
129  }
130 }
131 
133 {
134  if ( !destLayer )
135  return;
136 
137  destLayer->removeDataDefinedProperties();
138 
139  QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
140  for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
141  {
142  if ( ddIt.value() )
143  {
144  destLayer->setDataDefinedProperty( ddIt.key(), ddIt.value()->expression() );
145  }
146  }
147 }
148 
149 
151  : QgsSymbolLayerV2( QgsSymbolV2::Marker, locked ), mSizeUnit( QgsSymbolV2::MM ), mOffsetUnit( QgsSymbolV2::MM )
152 {
153 }
154 
156  : QgsSymbolLayerV2( QgsSymbolV2::Line, locked ), mWidthUnit( QgsSymbolV2::MM )
157 {
158 }
159 
161  : QgsSymbolLayerV2( QgsSymbolV2::Fill, locked ), mAngle( 0.0 )
162 {
163 }
164 
166 {
167  startRender( context );
168  renderPoint( QPointF( size.width() / 2, size.height() / 2 ), context );
169  stopRender( context );
170 }
171 
173 {
174  mSizeUnit = unit;
175  mOffsetUnit = unit;
176 }
177 
178 void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY )
179 {
180  offsetX = mOffset.x();
181  offsetY = mOffset.y();
182 
183  QgsExpression* offsetExpression = expression( "offset" );
184  if ( offsetExpression )
185  {
186  QPointF offset = QgsSymbolLayerV2Utils::decodePoint( offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
187  offsetX = offset.x();
188  offsetY = offset.y();
189  }
190 
193 }
194 
195 QPointF QgsMarkerSymbolLayerV2::_rotatedOffset( const QPointF& offset, double angle )
196 {
197  angle = DEG2RAD( angle );
198  double c = cos( angle ), s = sin( angle );
199  return QPointF( offset.x() * c - offset.y() * s, offset.x() * s + offset.y() * c );
200 }
201 
203 {
205  if ( mOffsetUnit != unit )
206  {
207  return QgsSymbolV2::Mixed;
208  }
209  return unit;
210 }
211 
213 {
214  QPolygonF points;
215  // we're adding 0.5 to get rid of blurred preview:
216  // drawing antialiased lines of width 1 at (x,0)-(x,100) creates 2px line
217  points << QPointF( 0, size.height() / 2 + 0.5 ) << QPointF( size.width(), size.height() / 2 + 0.5 );
218 
219  startRender( context );
220  renderPolyline( points, context );
221  stopRender( context );
222 }
223 
224 void QgsLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
225 {
226  renderPolyline( points, context );
227  if ( rings )
228  {
229  foreach ( const QPolygonF& ring, *rings )
230  renderPolyline( ring, context );
231  }
232 }
233 
234 
236 {
237  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
238  startRender( context );
239  renderPolygon( poly, NULL, context );
240  stopRender( context );
241 }
242 
243 void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings )
244 {
245  if ( !p )
246  {
247  return;
248  }
249 
250  if ( rings == NULL )
251  {
252  // simple polygon without holes
253  p->drawPolygon( points );
254  }
255  else
256  {
257  // polygon with holes must be drawn using painter path
258  QPainterPath path;
259  QPolygonF outerRing = points;
260  path.addPolygon( outerRing );
261 
262  QList<QPolygonF>::const_iterator it = rings->constBegin();
263  for ( ; it != rings->constEnd(); ++it )
264  {
265  QPolygonF ring = *it;
266  path.addPolygon( ring );
267  }
268 
269  p->drawPath( path );
270  }
271 }
272 
273 void QgsMarkerSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
274 {
275  QDomElement symbolizerElem = doc.createElement( "se:PointSymbolizer" );
276  if ( !props.value( "uom", "" ).isEmpty() )
277  symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
278  element.appendChild( symbolizerElem );
279 
280  // <Geometry>
281  QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );
282 
283  writeSldMarker( doc, symbolizerElem, props );
284 }
virtual QSet< QString > usedAttributes() const
void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:88
virtual void removeDataDefinedProperties()
QMap< QString, QgsExpression * > mDataDefinedProperties
void markerOffset(QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY)
virtual QgsSymbolV2::OutputUnit outputUnit() const
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
#define DEG2RAD(x)
virtual void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
static QPointF decodePoint(QString str)
Container of fields for a vector layer.
Definition: qgsfield.h:162
virtual void renderPolygon(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)=0
virtual void setOutputUnit(QgsSymbolV2::OutputUnit unit)
virtual void removeDataDefinedProperty(const QString &property)
QMap< QString, QString > QgsStringMap
Definition: qgis.h:348
virtual QString dataDefinedPropertyString(const QString &property) const
virtual void startRender(QgsSymbolV2RenderContext &context)=0
virtual void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
const QgsFeature * feature() const
Definition: qgssymbolv2.h:179
virtual void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)=0
virtual void prepareExpressions(const QgsVectorLayer *vl)
QgsMarkerSymbolLayerV2(bool locked=false)
const QString & expression() const
virtual void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)
virtual void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)=0
void _renderPolygon(QPainter *p, const QPolygonF &points, const QList< QPolygonF > *rings)
Default method to render polygon.
void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)
QgsFillSymbolLayerV2(bool locked=false)
static void createGeometryElement(QDomDocument &doc, QDomElement &element, QString geomFunc)
QgsLineSymbolLayerV2(bool locked=false)
virtual const QgsExpression * dataDefinedProperty(const QString &property) const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:158
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u)
Returns the line width scale factor depending on the unit and the paint device.
QgsSymbolV2::OutputUnit mOffsetUnit
QgsSymbolV2::OutputUnit mSizeUnit
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:75
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves data defined properties to string map.
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
virtual QgsExpression * expression(const QString &property)
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies data defined properties of this layer to another symbol layer.
virtual void setDataDefinedProperty(const QString &property, const QString &expressionString)
static QPointF _rotatedOffset(const QPointF &offset, double angle)