QGIS API Documentation  2.99.0-Master (08ee180)
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( QLatin1String( "" ) )
24  , mYAttribute( QLatin1String( "" ) )
25  , mDistanceUnit( QgsUnitTypes::RenderMillimeters )
26  , mScale( 1.0 )
27  , mVectorFieldType( Cartesian )
28  , mAngleOrientation( ClockwiseFromNorth )
29  , mAngleUnits( Degrees )
30  , mLineSymbol( nullptr )
31  , mXIndex( -1 )
32  , mYIndex( -1 )
33 {
34  setSubSymbol( new QgsLineSymbol() );
35 }
36 
38 {
39  delete mLineSymbol;
40 }
41 
43 {
45  mDistanceUnit = unit;
46 }
47 
49 {
50  if ( QgsMarkerSymbolLayer::outputUnit() == mDistanceUnit )
51  {
52  return mDistanceUnit;
53  }
55 }
56 
58 {
60  mDistanceMapUnitScale = scale;
61 }
62 
64 {
65  if ( QgsMarkerSymbolLayer::mapUnitScale() == mDistanceMapUnitScale )
66  {
67  return mDistanceMapUnitScale;
68  }
69  return QgsMapUnitScale();
70 }
71 
73 {
75  if ( properties.contains( QStringLiteral( "x_attribute" ) ) )
76  {
77  symbolLayer->setXAttribute( properties[QStringLiteral( "x_attribute" )] );
78  }
79  if ( properties.contains( QStringLiteral( "y_attribute" ) ) )
80  {
81  symbolLayer->setYAttribute( properties[QStringLiteral( "y_attribute" )] );
82  }
83  if ( properties.contains( QStringLiteral( "distance_unit" ) ) )
84  {
85  symbolLayer->setDistanceUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "distance_unit" )] ) );
86  }
87  if ( properties.contains( QStringLiteral( "distance_map_unit_scale" ) ) )
88  {
89  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "distance_map_unit_scale" )] ) );
90  }
91  if ( properties.contains( QStringLiteral( "scale" ) ) )
92  {
93  symbolLayer->setScale( properties[QStringLiteral( "scale" )].toDouble() );
94  }
95  if ( properties.contains( QStringLiteral( "vector_field_type" ) ) )
96  {
97  symbolLayer->setVectorFieldType( static_cast< VectorFieldType >( properties[QStringLiteral( "vector_field_type" )].toInt() ) );
98  }
99  if ( properties.contains( QStringLiteral( "angle_orientation" ) ) )
100  {
101  symbolLayer->setAngleOrientation( static_cast< AngleOrientation >( properties[QStringLiteral( "angle_orientation" )].toInt() ) );
102  }
103  if ( properties.contains( QStringLiteral( "angle_units" ) ) )
104  {
105  symbolLayer->setAngleUnits( static_cast< AngleUnits >( properties[QStringLiteral( "angle_units" )].toInt() ) );
106  }
107  if ( properties.contains( QStringLiteral( "size" ) ) )
108  {
109  symbolLayer->setSize( properties[QStringLiteral( "size" )].toDouble() );
110  }
111  if ( properties.contains( QStringLiteral( "size_unit" ) ) )
112  {
113  symbolLayer->setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "size_unit" )] ) );
114  }
115  if ( properties.contains( QStringLiteral( "size_map_unit_scale" ) ) )
116  {
117  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "size_map_unit_scale" )] ) );
118  }
119  if ( properties.contains( QStringLiteral( "offset" ) ) )
120  {
121  symbolLayer->setOffset( QgsSymbolLayerUtils::decodePoint( properties[QStringLiteral( "offset" )] ) );
122  }
123  if ( properties.contains( QStringLiteral( "offset_unit" ) ) )
124  {
125  symbolLayer->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "offset_unit" )] ) );
126  }
127  if ( properties.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
128  {
129  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "offset_map_unit_scale" )] ) );
130  }
131  return symbolLayer;
132 }
133 
135 {
136  if ( symbol->type() == QgsSymbol::Line )
137  {
138  delete mLineSymbol;
139  mLineSymbol = static_cast<QgsLineSymbol*>( 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 = QgsSymbolLayerUtils::convertToPainterUnits( ctx, xVal, mDistanceUnit, mDistanceMapUnitScale );
182  yComponent = QgsSymbolLayerUtils::convertToPainterUnits( ctx, yVal, mDistanceUnit, mDistanceMapUnitScale );
183  break;
184  case Polar:
185  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
186  xComponent = QgsSymbolLayerUtils::convertToPainterUnits( ctx, xComponent, mDistanceUnit, mDistanceMapUnitScale );
187  yComponent = QgsSymbolLayerUtils::convertToPainterUnits( ctx, yComponent, mDistanceUnit, mDistanceMapUnitScale );
188  break;
189  case Height:
190  xComponent = 0;
191  yComponent = QgsSymbolLayerUtils::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  QgsFields fields = context.fields();
214  if ( !fields.isEmpty() )
215  {
216  mXIndex = fields.lookupField( mXAttribute );
217  mYIndex = fields.lookupField( 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[QStringLiteral( "x_attribute" )] = mXAttribute;
248  properties[QStringLiteral( "y_attribute" )] = mYAttribute;
249  properties[QStringLiteral( "distance_unit" )] = QgsUnitTypes::encodeUnit( mDistanceUnit );
250  properties[QStringLiteral( "distance_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceMapUnitScale );
251  properties[QStringLiteral( "scale" )] = QString::number( mScale );
252  properties[QStringLiteral( "vector_field_type" )] = QString::number( mVectorFieldType );
253  properties[QStringLiteral( "angle_orientation" )] = QString::number( mAngleOrientation );
254  properties[QStringLiteral( "angle_units" )] = QString::number( mAngleUnits );
255  properties[QStringLiteral( "size" )] = QString::number( mSize );
256  properties[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
257  properties[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
258  properties[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
259  properties[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
260  properties[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::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( QStringLiteral( "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 = QgsMarkerSymbolLayer::usedAttributes();
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.
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:291
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.
virtual QSet< QString > usedAttributes() const
Returns the set of attributes referenced by the layer.
void setYAttribute(const QString &attribute)
QgsFields fields() const
Fields of the layer.
Definition: qgssymbol.h:438
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void setAngleUnits(AngleUnits units)
void setDistanceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the distance.
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
Helper functions for various unit types.
Definition: qgsunittypes.h:35
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Definition: qgssymbol.cpp:1645
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
Definition: qgssymbol.cpp:583
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:36
points (eg for font sizes)
Definition: qgsunittypes.h:98
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s offset.
QSet< QString > usedAttributes() const
Return a list of attributes required to render this feature.
Definition: qgssymbol.cpp:636
QPointF mOffset
Marker offset.
Line symbol.
Definition: qgssymbol.h:69
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:135
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:328
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:387
A symbol layer class for displaying displacement arrows based on point layer attributes.
virtual bool setSubSymbol(QgsSymbol *symbol)
set 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 setSize(double size)
Sets the symbol size.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
#define M_PI
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draw icon of the symbol that occupyies area given by size using the painter.
Definition: qgssymbol.cpp:448
void setMapUnitScale(const QgsMapUnitScale &scale) override
QColor color() const
Definition: qgssymbol.cpp:437
void setDistanceMapUnitScale(const QgsMapUnitScale &scale)
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
QgsRenderContext & renderContext()
Definition: qgssymbol.h:393
virtual 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.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol&#39;s size.
bool setSubSymbol(QgsSymbol *symbol) override
set layer&#39;s subsymbol. takes ownership of the passed symbol
Contains information about the context of a rendering operation.
QPainter * painter()
SymbolType type() const
Definition: qgssymbol.h:96
Struct for storing maximum and minimum scales for measurements in map units.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QSet< QString > usedAttributes() const override
Returns the set of attributes referenced by the layer.
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbol.h:432
static Q_INVOKABLE RenderUnit decodeRenderUnit(const QString &string, bool *ok=0)
Decodes a render unit from a string.
void stopRender(QgsSymbolRenderContext &context) override
bool isEmpty() const
Check whether the container is empty.
Definition: qgsfields.cpp:112
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:277
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:408
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:91
virtual QgsLineSymbol * clone() const override
Get a deep copy of this symbol.
Definition: qgssymbol.cpp:1713
void setColor(const QColor &color)
Definition: qgssymbol.cpp:428
static QgsSymbolLayer * createFromSld(QDomElement &element)