QGIS API Documentation  2.12.0-Lyon
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 
22  : mXAttribute( "" )
23  , mYAttribute( "" )
24  , mDistanceUnit( QgsSymbolV2::MM )
25  , mScale( 1.0 )
26  , mVectorFieldType( Cartesian )
27  , mAngleOrientation( ClockwiseFromNorth )
28  , mAngleUnits( Degrees )
29  , mLineSymbol( 0 )
30  , mXIndex( -1 )
31  , mYIndex( -1 )
32 {
34 }
35 
37 {
38  delete mLineSymbol;
39 }
40 
42 {
44  mDistanceUnit = unit;
45 }
46 
48 {
49  if ( QgsMarkerSymbolLayerV2::outputUnit() == mDistanceUnit )
50  {
51  return mDistanceUnit;
52  }
53  return QgsSymbolV2::Mixed;
54 }
55 
57 {
59  mDistanceMapUnitScale = scale;
60 }
61 
63 {
64  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mDistanceMapUnitScale )
65  {
66  return mDistanceMapUnitScale;
67  }
68  return QgsMapUnitScale();
69 }
70 
72 {
74  if ( properties.contains( "x_attribute" ) )
75  {
76  symbolLayer->setXAttribute( properties["x_attribute"] );
77  }
78  if ( properties.contains( "y_attribute" ) )
79  {
80  symbolLayer->setYAttribute( properties["y_attribute"] );
81  }
82  if ( properties.contains( "distance_unit" ) )
83  {
84  symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) );
85  }
86  if ( properties.contains( "distance_map_unit_scale" ) )
87  {
88  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["distance_map_unit_scale"] ) );
89  }
90  if ( properties.contains( "scale" ) )
91  {
92  symbolLayer->setScale( properties["scale"].toDouble() );
93  }
94  if ( properties.contains( "vector_field_type" ) )
95  {
96  symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
97  }
98  if ( properties.contains( "angle_orientation" ) )
99  {
100  symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
101  }
102  if ( properties.contains( "angle_units" ) )
103  {
104  symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
105  }
106  if ( properties.contains( "size" ) )
107  {
108  symbolLayer->setSize( properties["size"].toDouble() );
109  }
110  if ( properties.contains( "size_unit" ) )
111  {
112  symbolLayer->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["size_unit"] ) );
113  }
114  if ( properties.contains( "size_map_unit_scale" ) )
115  {
116  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["size_map_unit_scale"] ) );
117  }
118  if ( properties.contains( "offset" ) )
119  {
120  symbolLayer->setOffset( QgsSymbolLayerV2Utils::decodePoint( properties["offset"] ) );
121  }
122  if ( properties.contains( "offset_unit" ) )
123  {
124  symbolLayer->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["offset_unit"] ) );
125  }
126  if ( properties.contains( "offset_map_unit_scale" ) )
127  {
128  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["offset_map_unit_scale"] ) );
129  }
130  return symbolLayer;
131 }
132 
134 {
135  if ( symbol->type() == QgsSymbolV2::Line )
136  {
137  delete mLineSymbol;
138  mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
139  return true;
140  }
141  return false;
142 }
143 
145 {
146  if ( !mLineSymbol )
147  {
148  return;
149  }
150 
151  const QgsRenderContext& ctx = context.renderContext();
152 
153  const QgsFeature* f = context.feature();
154  if ( !f )
155  {
156  //preview
157  QPolygonF line;
158  line << QPointF( 0, 50 );
159  line << QPointF( 100, 50 );
160  mLineSymbol->renderPolyline( line, 0, context.renderContext() );
161  }
162 
163  double xComponent = 0;
164  double yComponent = 0;
165 
166  double xVal = 0;
167  if ( f && mXIndex != -1 )
168  {
169  xVal = f->attribute( mXIndex ).toDouble();
170  }
171  double yVal = 0;
172  if ( f && mYIndex != -1 )
173  {
174  yVal = f->attribute( mYIndex ).toDouble();
175  }
176 
177  switch ( mVectorFieldType )
178  {
179  case Cartesian:
180  xComponent = QgsSymbolLayerV2Utils::convertToPainterUnits( ctx, xVal, mDistanceUnit, mDistanceMapUnitScale );
181  yComponent = QgsSymbolLayerV2Utils::convertToPainterUnits( ctx, yVal, mDistanceUnit, mDistanceMapUnitScale );
182  break;
183  case Polar:
184  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
185  xComponent = QgsSymbolLayerV2Utils::convertToPainterUnits( ctx, xComponent, mDistanceUnit, mDistanceMapUnitScale );
186  yComponent = QgsSymbolLayerV2Utils::convertToPainterUnits( ctx, yComponent, mDistanceUnit, mDistanceMapUnitScale );
187  break;
188  case Height:
189  xComponent = 0;
190  yComponent = QgsSymbolLayerV2Utils::convertToPainterUnits( ctx, yVal, mDistanceUnit, mDistanceMapUnitScale );
191  break;
192  default:
193  break;
194  }
195 
196  xComponent *= mScale;
197  yComponent *= mScale;
198 
199  QPolygonF line;
200  line << point;
201  line << QPointF( point.x() + xComponent, point.y() - yComponent );
202  mLineSymbol->renderPolyline( line, f, context.renderContext() );
203 }
204 
206 {
207  if ( mLineSymbol )
208  {
209  mLineSymbol->startRender( context.renderContext(), context.fields() );
210  }
211 
212  const QgsFields* fields = context.fields();
213  if ( fields )
214  {
215  mXIndex = fields->fieldNameIndex( mXAttribute );
216  mYIndex = fields->fieldNameIndex( mYAttribute );
217  }
218  else
219  {
220  mXIndex = -1;
221  mYIndex = -1;
222  }
223 }
224 
226 {
227  if ( mLineSymbol )
228  {
229  mLineSymbol->stopRender( context.renderContext() );
230  }
231 }
232 
234 {
236  if ( mLineSymbol )
237  {
238  clonedLayer->setSubSymbol( mLineSymbol->clone() );
239  }
240  return clonedLayer;
241 }
242 
244 {
246  properties["x_attribute"] = mXAttribute;
247  properties["y_attribute"] = mYAttribute;
248  properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit );
249  properties["distance_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mDistanceMapUnitScale );
250  properties["scale"] = QString::number( mScale );
251  properties["vector_field_type"] = QString::number( mVectorFieldType );
252  properties["angle_orientation"] = QString::number( mAngleOrientation );
253  properties["angle_units"] = QString::number( mAngleUnits );
254  properties["size"] = QString::number( mSize );
255  properties["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
256  properties["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
257  properties["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
258  properties["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
259  properties["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
260  return properties;
261 }
262 
263 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, const QgsStringMap& props ) const
264 {
265  element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
266  mLineSymbol->toSld( doc, element, props );
267 }
268 
270 {
271  Q_UNUSED( element );
272  return NULL;
273 }
274 
276 {
277  if ( mLineSymbol )
278  {
279  mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
280  }
281 }
282 
284 {
285  QSet<QString> attributes;
286  if ( !mXAttribute.isEmpty() )
287  {
288  attributes.insert( mXAttribute );
289  }
290  if ( !mYAttribute.isEmpty() )
291  {
292  attributes.insert( mYAttribute );
293  }
294  return attributes;
295 }
296 
297 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
298 {
299  //convert angle to degree and to north orientation
300  if ( mAngleOrientation == CounterclockwiseFromEast )
301  {
302  if ( angle <= 90 )
303  {
304  angle = 90 - angle;
305  }
306  else
307  {
308  angle = 360 - angle + 90;
309  }
310  }
311 
312  if ( mAngleUnits == Degrees )
313  {
314  angle = angle * M_PI / 180.0;
315  }
316 
317  x = length * sin( angle );
318  y = length * cos( angle );
319 }
320 
321 
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
QgsMapUnitScale mapUnitScale() const override
void setXAttribute(const QString &attribute)
QgsSymbolV2::OutputUnit outputUnit() const override
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:55
QgsMapUnitScale mSizeMapUnitScale
void setYAttribute(const QString &attribute)
bool contains(const Key &key) const
QDomNode appendChild(const QDomNode &newChild)
SymbolType type() const
Definition: qgssymbolv2.h:95
void setAngleUnits(AngleUnits units)
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:382
void setOffset(QPointF offset)
Container of fields for a vector layer.
Definition: qgsfield.h:177
Line symbol.
Definition: qgssymbolv2.h:71
static QPointF decodePoint(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:176
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
A symbol layer class for displaying displacement arrows based on point layer attributes.
Mixed units in symbol layers.
Definition: qgssymbolv2.h:59
QString number(int n, int base)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:283
static QString encodePoint(QPointF point)
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
QgsStringMap properties() const override
bool isEmpty() 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 setMapUnitScale(const QgsMapUnitScale &scale) override
void setDistanceMapUnitScale(const QgsMapUnitScale &scale)
void stopRender(QgsSymbolV2RenderContext &context) override
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 startRender(QgsSymbolV2RenderContext &context) override
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
bool setSubSymbol(QgsSymbolV2 *symbol) override
Contains information about the context of a rendering operation.
QPainter * painter()
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:238
void stopRender(QgsRenderContext &context)
QgsSymbolV2::OutputUnit outputUnit() const override
Struct for storing maximum and minimum scales for measurements in map units.
QgsMapUnitScale mapUnitScale() const override
QSet< QString > usedAttributes() const override
Returns the set of attributes referenced by the layer.
void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size) override
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:254
QDomComment createComment(const QString &value)
void setDistanceUnit(QgsSymbolV2::OutputUnit unit)
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:289
void setAngleOrientation(AngleOrientation orientation)
QgsSymbolV2::OutputUnit mOffsetUnit
double toDouble(bool *ok) const
QgsSymbolV2::OutputUnit mSizeUnit
QgsMapUnitScale mOffsetMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QgsSymbolLayerV2 * clone() const override
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)
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
virtual QgsSymbolV2 * clone() const override
virtual bool setSubSymbol(QgsSymbolV2 *symbol)
void setVectorFieldType(VectorFieldType type)
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override