QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 {
287  if ( !mXAttribute.isEmpty() )
288  {
289  attributes.insert( mXAttribute );
290  }
291  if ( !mYAttribute.isEmpty() )
292  {
293  attributes.insert( mYAttribute );
294  }
295  if ( mLineSymbol )
296  {
297  attributes.unite( mLineSymbol->usedAttributes() );
298  }
299  return attributes;
300 }
301 
302 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
303 {
304  //convert angle to degree and to north orientation
305  if ( mAngleOrientation == CounterclockwiseFromEast )
306  {
307  if ( angle <= 90 )
308  {
309  angle = 90 - angle;
310  }
311  else
312  {
313  angle = 360 - angle + 90;
314  }
315  }
316 
317  if ( mAngleUnits == Degrees )
318  {
319  angle = angle * M_PI / 180.0;
320  }
321 
322  x = length * sin( angle );
323  y = length * cos( angle );
324 }
325 
327 {
328  if ( mLineSymbol )
329  mLineSymbol->setColor( color );
330 
331  mColor = color;
332 }
333 
335 {
336  return mLineSymbol ? mLineSymbol->color() : mColor;
337 }
338 
339 
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
Renders a marker at the specified point.
QgsMapUnitScale mapUnitScale() const override
void setXAttribute(const QString &attribute)
QgsSymbolV2::OutputUnit outputUnit() const override
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:394
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:65
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
void setYAttribute(const QString &attribute)
bool contains(const Key &key) const
virtual QgsLineSymbolV2 * clone() const override
QDomNode appendChild(const QDomNode &newChild)
void setAngleUnits(AngleUnits units)
virtual QSet< QString > usedAttributes() const
Returns the set of attributes referenced by the layer.
double size() const
Returns the symbol size.
void setOffset(QPointF offset)
Sets the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered marker...
Container of fields for a vector layer.
Definition: qgsfield.h:252
SymbolType type() const
Definition: qgssymbolv2.h:107
Line symbol.
Definition: qgssymbolv2.h:82
static QPointF decodePoint(const QString &str)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:388
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)
Sets the map unit scale for the symbol&#39;s offset.
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)
Sets the units for the symbol&#39;s offset.
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const
Writes the SLD element following the SLD v1.1 specs.
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
A symbol layer class for displaying displacement arrows based on point layer attributes.
void setColor(const QColor &color)
Mixed units in symbol layers.
Definition: qgssymbolv2.h:69
QString number(int n, int base)
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, const QgsStringMap &props) const override
Writes the SLD element following the SLD v1.1 specs.
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)
Sets the units for the symbol&#39;s size.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setDistanceMapUnitScale(const QgsMapUnitScale &scale)
void stopRender(QgsSymbolV2RenderContext &context) override
virtual QColor color() const override
The fill color.
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:571
void setColor(const QColor &color) override
The fill color.
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()
void stopRender(QgsRenderContext &context)
QSet< T > & unite(const QSet< T > &other)
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
QColor color() const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:359
QDomComment createComment(const QString &value)
void setDistanceUnit(QgsSymbolV2::OutputUnit unit)
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
void setAngleOrientation(AngleOrientation orientation)
QgsSymbolV2::OutputUnit mOffsetUnit
Offset units.
double toDouble(bool *ok) const
QgsSymbolV2::OutputUnit mSizeUnit
Marker size unit.
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
double mSize
Marker size.
QSet< QString > usedAttributes() const
Return a list of attributes required to render this feature.
void setSize(double size)
Sets the symbol size.
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
virtual bool setSubSymbol(QgsSymbolV2 *symbol)
set layer&#39;s subsymbol. takes ownership of the passed symbol
void setVectorFieldType(VectorFieldType type)
QPointF mOffset
Marker offset.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override