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