QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsvectorfieldsymbollayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorfieldsymbollayer.cpp
3  -----------------------------
4  begin : Octorer 25, 2011
5  copyright : (C) 2011 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsvectorlayer.h"
20 
21 QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer(): mXAttribute( "" ), mYAttribute( "" ), mDistanceUnit( QgsSymbolV2::MM ), mScale( 1.0 ),
22  mVectorFieldType( Cartesian ), mAngleOrientation( ClockwiseFromNorth ), mAngleUnits( Degrees ), mXIndex( -1 ), mYIndex( -1 )
23 {
25 }
26 
28 {
29 }
30 
32 {
34  mDistanceUnit = unit;
35 }
36 
38 {
39  if ( QgsMarkerSymbolLayerV2::outputUnit() == mDistanceUnit )
40  {
41  return mDistanceUnit;
42  }
43  return QgsSymbolV2::Mixed;
44 }
45 
47 {
49  mDistanceMapUnitScale = scale;
50 }
51 
53 {
54  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mDistanceMapUnitScale )
55  {
56  return mDistanceMapUnitScale;
57  }
58  return QgsMapUnitScale();
59 }
60 
62 {
64  if ( properties.contains( "x_attribute" ) )
65  {
66  symbolLayer->setXAttribute( properties["x_attribute"] );
67  }
68  if ( properties.contains( "y_attribute" ) )
69  {
70  symbolLayer->setYAttribute( properties["y_attribute"] );
71  }
72  if ( properties.contains( "distance_unit" ) )
73  {
74  symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) );
75  }
76  if ( properties.contains( "distance_map_unit_scale" ) )
77  {
78  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["distance_map_unit_scale"] ) );
79  }
80  if ( properties.contains( "scale" ) )
81  {
82  symbolLayer->setScale( properties["scale"].toDouble() );
83  }
84  if ( properties.contains( "vector_field_type" ) )
85  {
86  symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
87  }
88  if ( properties.contains( "angle_orientation" ) )
89  {
90  symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
91  }
92  if ( properties.contains( "angle_units" ) )
93  {
94  symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
95  }
96  if ( properties.contains( "size" ) )
97  {
98  symbolLayer->setSize( properties["size"].toDouble() );
99  }
100  if ( properties.contains( "size_unit" ) )
101  {
102  symbolLayer->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["size_unit"] ) );
103  }
104  if ( properties.contains( "size_map_unit_scale" ) )
105  {
106  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["size_map_unit_scale"] ) );
107  }
108  if ( properties.contains( "offset" ) )
109  {
110  symbolLayer->setOffset( QgsSymbolLayerV2Utils::decodePoint( properties["offset"] ) );
111  }
112  if ( properties.contains( "offset_unit" ) )
113  {
114  symbolLayer->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["offset_unit"] ) );
115  }
116  if ( properties.contains( "offset_map_unit_scale" ) )
117  {
118  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["offset_map_unit_scale"] ) );
119  }
120  return symbolLayer;
121 }
122 
124 {
125  if ( symbol->type() == QgsSymbolV2::Line )
126  {
127  mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
128  return true;
129  }
130  return false;
131 }
132 
134 {
135  if ( !mLineSymbol )
136  {
137  return;
138  }
139 
140  const QgsRenderContext& ctx = context.renderContext();
141 
142  const QgsFeature* f = context.feature();
143  if ( !f )
144  {
145  //preview
146  QPolygonF line;
147  line << QPointF( 0, 50 );
148  line << QPointF( 100, 50 );
149  mLineSymbol->renderPolyline( line, 0, context.renderContext() );
150  }
151 
152  double xComponent = 0;
153  double yComponent = 0;
154 
155  double xVal = 0;
156  if ( mXIndex != -1 )
157  {
158  xVal = f->attribute( mXIndex ).toDouble();
159  }
160  double yVal = 0;
161  if ( mYIndex != -1 )
162  {
163  yVal = f->attribute( mYIndex ).toDouble();
164  }
165 
166  switch ( mVectorFieldType )
167  {
168  case Cartesian:
169  xComponent = xVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
170  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
171  break;
172  case Polar:
173  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
174  xComponent = xComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
175  yComponent = yComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
176  break;
177  case Height:
178  xComponent = 0;
179  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
180  break;
181  default:
182  break;
183  }
184 
185  xComponent *= mScale;
186  yComponent *= mScale;
187 
188  QPolygonF line;
189  line << point;
190  line << QPointF( point.x() + xComponent, point.y() - yComponent );
191  mLineSymbol->renderPolyline( line, f, context.renderContext() );
192 }
193 
195 {
196  if ( mLineSymbol )
197  {
198  mLineSymbol->startRender( context.renderContext(), context.fields() );
199  }
200 
201  const QgsFields* fields = context.fields();
202  if ( fields )
203  {
204  mXIndex = fields->fieldNameIndex( mXAttribute );
205  mYIndex = fields->fieldNameIndex( mYAttribute );
206  }
207  else
208  {
209  mXIndex = -1;
210  mYIndex = -1;
211  }
212 }
213 
215 {
216  if ( mLineSymbol )
217  {
218  mLineSymbol->stopRender( context.renderContext() );
219  }
220 }
221 
223 {
225  if ( mLineSymbol )
226  {
227  clonedLayer->setSubSymbol( mLineSymbol->clone() );
228  }
229  return clonedLayer;
230 }
231 
233 {
235  properties["x_attribute"] = mXAttribute;
236  properties["y_attribute"] = mYAttribute;
237  properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit );
238  properties["distance_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mDistanceMapUnitScale );
239  properties["scale"] = QString::number( mScale );
240  properties["vector_field_type"] = QString::number( mVectorFieldType );
241  properties["angle_orientation"] = QString::number( mAngleOrientation );
242  properties["angle_units"] = QString::number( mAngleUnits );
243  properties["size"] = QString::number( mSize );
244  properties["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
245  properties["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
246  properties["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
247  properties["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
248  properties["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
249  return properties;
250 }
251 
252 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
253 {
254  element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
255  mLineSymbol->toSld( doc, element, props );
256 }
257 
259 {
260  Q_UNUSED( element );
261  return NULL;
262 }
263 
265 {
266  if ( mLineSymbol )
267  {
268  mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
269  }
270 }
271 
273 {
274  QSet<QString> attributes;
275  if ( !mXAttribute.isEmpty() )
276  {
277  attributes.insert( mXAttribute );
278  }
279  if ( !mYAttribute.isEmpty() )
280  {
281  attributes.insert( mYAttribute );
282  }
283  return attributes;
284 }
285 
286 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
287 {
288  //convert angle to degree and to north orientation
289  if ( mAngleOrientation == CounterclockwiseFromEast )
290  {
291  if ( angle <= 90 )
292  {
293  angle = 90 - angle;
294  }
295  else
296  {
297  angle = 360 - angle + 90;
298  }
299  }
300 
301  if ( mAngleUnits == Degrees )
302  {
303  angle = angle * M_PI / 180.0;
304  }
305 
306  x = length * sin( angle );
307  y = length * cos( angle );
308 }
309 
310 
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
void setXAttribute(const QString &attribute)
QgsMapUnitScale mSizeMapUnitScale
void setYAttribute(const QString &attribute)
QgsSymbolV2::OutputUnit outputUnit() const
void setMapUnitScale(const QgsMapUnitScale &scale)
SymbolType type() const
Definition: qgssymbolv2.h:79
void setAngleUnits(AngleUnits units)
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name - case insensitive TODO: sort out case sensitive (indexFromName()) vs...
Definition: qgsfield.cpp:208
void setOffset(QPointF offset)
void setMapUnitScale(const QgsMapUnitScale &scale)
static QPointF decodePoint(QString str)
Container of fields for a vector layer.
Definition: qgsfield.h:172
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
QgsSymbolV2::OutputUnit outputUnit() const
QMap< QString, QString > QgsStringMap
Definition: qgis.h:416
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
void startRender(QgsSymbolV2RenderContext &context)
A symbol layer class for displaying displacement arrows based on point layer attributes.
void stopRender(QgsSymbolV2RenderContext &context)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:213
QgsMapUnitScale mapUnitScale() const
static QString encodePoint(QPointF point)
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
#define M_PI
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
void setDistanceMapUnitScale(const QgsMapUnitScale &scale)
bool setSubSymbol(QgsSymbolV2 *symbol)
QgsMapUnitScale mapUnitScale() const
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)
virtual QgsSymbolV2 * clone() const
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)
Contains information about the context of a rendering operation.
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
QPainter * painter()
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
void stopRender(QgsRenderContext &context)
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns the line width scale factor depending on the unit and the paint device.
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:191
QgsSymbolLayerV2 * clone() const
void setDistanceUnit(QgsSymbolV2::OutputUnit unit)
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:219
void setAngleOrientation(AngleOrientation orientation)
QgsSymbolV2::OutputUnit mOffsetUnit
QgsSymbolV2::OutputUnit mSizeUnit
QgsMapUnitScale mOffsetMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QSet< QString > usedAttributes() const
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=0)
Draw icon of the symbol that occupyies area given by size using the painter.
void setSize(double size)
double size
Definition: qgssvgcache.cpp:77
virtual bool setSubSymbol(QgsSymbolV2 *symbol)
void setVectorFieldType(VectorFieldType type)
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
static QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)