QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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.
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)
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.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
double size() const
Returns the symbol size.
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
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:577
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:920
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
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.
QgsUnitTypes::RenderUnit mOffsetUnit
Offset units.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties...
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
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.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:320
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:572
QColor color() const override
The fill color.
void startRender(QgsSymbolRenderContext &context) override
QgsFields fields() const
Fields of the layer.
Definition: qgssymbol.h:653
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...
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
Struct for storing maximum and minimum scales for measurements in map units.
void setMapUnitScale(const QgsMapUnitScale &scale) override
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
virtual void setSize(double size)
Sets the symbol size.
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbol.h:628
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
void stopRender(QgsSymbolRenderContext &context) override
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.
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
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:110
static QgsSymbolLayer * createFromSld(QDomElement &element)