QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 #include "qgssymbollayerutils.h"
22 
24 {
25  setSubSymbol( new QgsLineSymbol() );
26 }
27 
29 {
31  mDistanceUnit = unit;
32 }
33 
35 {
36  if ( QgsMarkerSymbolLayer::outputUnit() == mDistanceUnit )
37  {
38  return mDistanceUnit;
39  }
41 }
42 
44 {
46  mDistanceMapUnitScale = scale;
47 }
48 
50 {
51  if ( QgsMarkerSymbolLayer::mapUnitScale() == mDistanceMapUnitScale )
52  {
53  return mDistanceMapUnitScale;
54  }
55  return QgsMapUnitScale();
56 }
57 
59 {
61  if ( properties.contains( QStringLiteral( "x_attribute" ) ) )
62  {
63  symbolLayer->setXAttribute( properties[QStringLiteral( "x_attribute" )] );
64  }
65  if ( properties.contains( QStringLiteral( "y_attribute" ) ) )
66  {
67  symbolLayer->setYAttribute( properties[QStringLiteral( "y_attribute" )] );
68  }
69  if ( properties.contains( QStringLiteral( "distance_unit" ) ) )
70  {
71  symbolLayer->setDistanceUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "distance_unit" )] ) );
72  }
73  if ( properties.contains( QStringLiteral( "distance_map_unit_scale" ) ) )
74  {
75  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "distance_map_unit_scale" )] ) );
76  }
77  if ( properties.contains( QStringLiteral( "scale" ) ) )
78  {
79  symbolLayer->setScale( properties[QStringLiteral( "scale" )].toDouble() );
80  }
81  if ( properties.contains( QStringLiteral( "vector_field_type" ) ) )
82  {
83  symbolLayer->setVectorFieldType( static_cast< VectorFieldType >( properties[QStringLiteral( "vector_field_type" )].toInt() ) );
84  }
85  if ( properties.contains( QStringLiteral( "angle_orientation" ) ) )
86  {
87  symbolLayer->setAngleOrientation( static_cast< AngleOrientation >( properties[QStringLiteral( "angle_orientation" )].toInt() ) );
88  }
89  if ( properties.contains( QStringLiteral( "angle_units" ) ) )
90  {
91  symbolLayer->setAngleUnits( static_cast< AngleUnits >( properties[QStringLiteral( "angle_units" )].toInt() ) );
92  }
93  if ( properties.contains( QStringLiteral( "size" ) ) )
94  {
95  symbolLayer->setSize( properties[QStringLiteral( "size" )].toDouble() );
96  }
97  if ( properties.contains( QStringLiteral( "size_unit" ) ) )
98  {
99  symbolLayer->setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "size_unit" )] ) );
100  }
101  if ( properties.contains( QStringLiteral( "size_map_unit_scale" ) ) )
102  {
103  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "size_map_unit_scale" )] ) );
104  }
105  if ( properties.contains( QStringLiteral( "offset" ) ) )
106  {
107  symbolLayer->setOffset( QgsSymbolLayerUtils::decodePoint( properties[QStringLiteral( "offset" )] ) );
108  }
109  if ( properties.contains( QStringLiteral( "offset_unit" ) ) )
110  {
111  symbolLayer->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "offset_unit" )] ) );
112  }
113  if ( properties.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
114  {
115  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "offset_map_unit_scale" )] ) );
116  }
117  return symbolLayer;
118 }
119 
121 {
122  if ( symbol->type() == QgsSymbol::Line )
123  {
124  mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) );
125  return true;
126  }
127  return false;
128 }
129 
131 {
132  if ( !mLineSymbol )
133  {
134  return;
135  }
136 
137  const QgsRenderContext &ctx = context.renderContext();
138 
139  const QgsFeature *f = context.feature();
140  if ( !f )
141  {
142  //preview
143  QPolygonF line;
144  line << QPointF( 0, 50 );
145  line << QPointF( 100, 50 );
146  mLineSymbol->renderPolyline( line, nullptr, context.renderContext() );
147  }
148 
149  double xComponent = 0;
150  double yComponent = 0;
151 
152  double xVal = 0;
153  if ( f && mXIndex != -1 )
154  {
155  xVal = f->attribute( mXIndex ).toDouble();
156  }
157  double yVal = 0;
158  if ( f && mYIndex != -1 )
159  {
160  yVal = f->attribute( mYIndex ).toDouble();
161  }
162 
163  switch ( mVectorFieldType )
164  {
165  case Cartesian:
166  xComponent = ctx.convertToPainterUnits( xVal, mDistanceUnit, mDistanceMapUnitScale );
167  yComponent = ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale );
168  break;
169  case Polar:
170  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
171  xComponent = ctx.convertToPainterUnits( xComponent, mDistanceUnit, mDistanceMapUnitScale );
172  yComponent = ctx.convertToPainterUnits( yComponent, mDistanceUnit, mDistanceMapUnitScale );
173  break;
174  case Height:
175  xComponent = 0;
176  yComponent = ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale );
177  break;
178  default:
179  break;
180  }
181 
182  xComponent *= mScale;
183  yComponent *= mScale;
184 
185  QPolygonF line;
186  line << point;
187  line << QPointF( point.x() + xComponent, point.y() - yComponent );
188  mLineSymbol->renderPolyline( line, f, context.renderContext() );
189 }
190 
192 {
193  if ( mLineSymbol )
194  {
195  mLineSymbol->startRender( context.renderContext(), context.fields() );
196  }
197 
198  QgsFields fields = context.fields();
199  if ( !fields.isEmpty() )
200  {
201  mXIndex = fields.lookupField( mXAttribute );
202  mYIndex = fields.lookupField( mYAttribute );
203  }
204  else
205  {
206  mXIndex = -1;
207  mYIndex = -1;
208  }
209 }
210 
212 {
213  if ( mLineSymbol )
214  {
215  mLineSymbol->stopRender( context.renderContext() );
216  }
217 }
218 
220 {
222  if ( mLineSymbol )
223  {
224  clonedLayer->setSubSymbol( mLineSymbol->clone() );
225  }
226  return static_cast< QgsVectorFieldSymbolLayer * >( clonedLayer );
227 }
228 
230 {
232  properties[QStringLiteral( "x_attribute" )] = mXAttribute;
233  properties[QStringLiteral( "y_attribute" )] = mYAttribute;
234  properties[QStringLiteral( "distance_unit" )] = QgsUnitTypes::encodeUnit( mDistanceUnit );
235  properties[QStringLiteral( "distance_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceMapUnitScale );
236  properties[QStringLiteral( "scale" )] = QString::number( mScale );
237  properties[QStringLiteral( "vector_field_type" )] = QString::number( mVectorFieldType );
238  properties[QStringLiteral( "angle_orientation" )] = QString::number( mAngleOrientation );
239  properties[QStringLiteral( "angle_units" )] = QString::number( mAngleUnits );
240  properties[QStringLiteral( "size" )] = QString::number( mSize );
241  properties[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
242  properties[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
243  properties[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
244  properties[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
245  properties[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
246  return properties;
247 }
248 
249 void QgsVectorFieldSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
250 {
251  element.appendChild( doc.createComment( QStringLiteral( "VectorField not implemented yet..." ) ) );
252  mLineSymbol->toSld( doc, element, props );
253 }
254 
256 {
257  Q_UNUSED( element )
258  return nullptr;
259 }
260 
262 {
263  if ( mLineSymbol )
264  {
265  mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
266  }
267 }
268 
269 QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
270 {
271  QSet<QString> attributes = QgsMarkerSymbolLayer::usedAttributes( context );
272  if ( !mXAttribute.isEmpty() )
273  {
274  attributes.insert( mXAttribute );
275  }
276  if ( !mYAttribute.isEmpty() )
277  {
278  attributes.insert( mYAttribute );
279  }
280  if ( mLineSymbol )
281  {
282  attributes.unite( mLineSymbol->usedAttributes( context ) );
283  }
284  return attributes;
285 }
286 
288 {
290  return true;
291  if ( mLineSymbol && mLineSymbol->hasDataDefinedProperties() )
292  return true;
293  return false;
294 }
295 
296 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double &x, double &y ) const
297 {
298  //convert angle to degree and to north orientation
299  if ( mAngleOrientation == CounterclockwiseFromEast )
300  {
301  if ( angle <= 90 )
302  {
303  angle = 90 - angle;
304  }
305  else
306  {
307  angle = 360 - angle + 90;
308  }
309  }
310 
311  if ( mAngleUnits == Degrees )
312  {
313  angle = angle * M_PI / 180.0;
314  }
315 
316  x = length * std::sin( angle );
317  y = length * std::cos( angle );
318 }
319 
321 {
322  if ( mLineSymbol )
323  mLineSymbol->setColor( color );
324 
325  mColor = color;
326 }
327 
329 {
330  return mLineSymbol ? mLineSymbol->color() : mColor;
331 }
332 
333 
QgsVectorFieldSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
void setOffset(QPointF offset)
Sets the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered marker...
QgsMapUnitScale mapUnitScale() const override
QgsMapUnitScale mapUnitScale() const override
void setXAttribute(const QString &attribute)
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol&#39;s offset.
void setYAttribute(const QString &attribute)
QgsFields fields() const
Fields of the layer.
Definition: qgssymbol.h:680
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
void setAngleUnits(AngleUnits units)
void setDistanceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the distance.
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Container of fields for a vector layer.
Definition: qgsfields.h:42
Mixed or unknown units.
Definition: qgsunittypes.h:119
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s offset.
QPointF mOffset
Marker offset.
Line symbol.
Definition: qgssymbol.h:86
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:587
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:966
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties...
A symbol layer class for displaying displacement arrows based on point layer attributes.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer&#39;s subsymbol. takes ownership of the passed symbol.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
QgsUnitTypes::RenderUnit mOffsetUnit
Offset units.
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
double size() const
Returns the symbol size.
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...
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setDistanceMapUnitScale(const QgsMapUnitScale &scale)
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:574
QColor color() const override
The fill color.
void startRender(QgsSymbolRenderContext &context) override
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
void setColor(const QColor &color) override
The fill color.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol&#39;s size.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer&#39;s subsymbol. takes ownership of the passed symbol.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
Struct for storing maximum and minimum scales for measurements in map units.
void setMapUnitScale(const QgsMapUnitScale &scale) override
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbol.h:655
virtual void setSize(double size)
Sets the symbol size.
void stopRender(QgsSymbolRenderContext &context) override
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
double mSize
Marker size.
void setAngleOrientation(AngleOrientation orientation)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
void setVectorFieldType(VectorFieldType type)
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:111
static QgsSymbolLayer * createFromSld(QDomElement &element)