QGIS API Documentation  3.0.2-Girona (307d082)
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 {
24  setSubSymbol( new QgsLineSymbol() );
25 }
26 
28 {
30  mDistanceUnit = unit;
31 }
32 
34 {
35  if ( QgsMarkerSymbolLayer::outputUnit() == mDistanceUnit )
36  {
37  return mDistanceUnit;
38  }
40 }
41 
43 {
45  mDistanceMapUnitScale = scale;
46 }
47 
49 {
50  if ( QgsMarkerSymbolLayer::mapUnitScale() == mDistanceMapUnitScale )
51  {
52  return mDistanceMapUnitScale;
53  }
54  return QgsMapUnitScale();
55 }
56 
58 {
60  if ( properties.contains( QStringLiteral( "x_attribute" ) ) )
61  {
62  symbolLayer->setXAttribute( properties[QStringLiteral( "x_attribute" )] );
63  }
64  if ( properties.contains( QStringLiteral( "y_attribute" ) ) )
65  {
66  symbolLayer->setYAttribute( properties[QStringLiteral( "y_attribute" )] );
67  }
68  if ( properties.contains( QStringLiteral( "distance_unit" ) ) )
69  {
70  symbolLayer->setDistanceUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "distance_unit" )] ) );
71  }
72  if ( properties.contains( QStringLiteral( "distance_map_unit_scale" ) ) )
73  {
74  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "distance_map_unit_scale" )] ) );
75  }
76  if ( properties.contains( QStringLiteral( "scale" ) ) )
77  {
78  symbolLayer->setScale( properties[QStringLiteral( "scale" )].toDouble() );
79  }
80  if ( properties.contains( QStringLiteral( "vector_field_type" ) ) )
81  {
82  symbolLayer->setVectorFieldType( static_cast< VectorFieldType >( properties[QStringLiteral( "vector_field_type" )].toInt() ) );
83  }
84  if ( properties.contains( QStringLiteral( "angle_orientation" ) ) )
85  {
86  symbolLayer->setAngleOrientation( static_cast< AngleOrientation >( properties[QStringLiteral( "angle_orientation" )].toInt() ) );
87  }
88  if ( properties.contains( QStringLiteral( "angle_units" ) ) )
89  {
90  symbolLayer->setAngleUnits( static_cast< AngleUnits >( properties[QStringLiteral( "angle_units" )].toInt() ) );
91  }
92  if ( properties.contains( QStringLiteral( "size" ) ) )
93  {
94  symbolLayer->setSize( properties[QStringLiteral( "size" )].toDouble() );
95  }
96  if ( properties.contains( QStringLiteral( "size_unit" ) ) )
97  {
98  symbolLayer->setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "size_unit" )] ) );
99  }
100  if ( properties.contains( QStringLiteral( "size_map_unit_scale" ) ) )
101  {
102  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "size_map_unit_scale" )] ) );
103  }
104  if ( properties.contains( QStringLiteral( "offset" ) ) )
105  {
106  symbolLayer->setOffset( QgsSymbolLayerUtils::decodePoint( properties[QStringLiteral( "offset" )] ) );
107  }
108  if ( properties.contains( QStringLiteral( "offset_unit" ) ) )
109  {
110  symbolLayer->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "offset_unit" )] ) );
111  }
112  if ( properties.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
113  {
114  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "offset_map_unit_scale" )] ) );
115  }
116  return symbolLayer;
117 }
118 
120 {
121  if ( symbol->type() == QgsSymbol::Line )
122  {
123  mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) );
124  return true;
125  }
126  return false;
127 }
128 
130 {
131  if ( !mLineSymbol )
132  {
133  return;
134  }
135 
136  const QgsRenderContext &ctx = context.renderContext();
137 
138  const QgsFeature *f = context.feature();
139  if ( !f )
140  {
141  //preview
142  QPolygonF line;
143  line << QPointF( 0, 50 );
144  line << QPointF( 100, 50 );
145  mLineSymbol->renderPolyline( line, nullptr, context.renderContext() );
146  }
147 
148  double xComponent = 0;
149  double yComponent = 0;
150 
151  double xVal = 0;
152  if ( f && mXIndex != -1 )
153  {
154  xVal = f->attribute( mXIndex ).toDouble();
155  }
156  double yVal = 0;
157  if ( f && mYIndex != -1 )
158  {
159  yVal = f->attribute( mYIndex ).toDouble();
160  }
161 
162  switch ( mVectorFieldType )
163  {
164  case Cartesian:
165  xComponent = ctx.convertToPainterUnits( xVal, mDistanceUnit, mDistanceMapUnitScale );
166  yComponent = ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale );
167  break;
168  case Polar:
169  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
170  xComponent = ctx.convertToPainterUnits( xComponent, mDistanceUnit, mDistanceMapUnitScale );
171  yComponent = ctx.convertToPainterUnits( yComponent, mDistanceUnit, mDistanceMapUnitScale );
172  break;
173  case Height:
174  xComponent = 0;
175  yComponent = ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale );
176  break;
177  default:
178  break;
179  }
180 
181  xComponent *= mScale;
182  yComponent *= mScale;
183 
184  QPolygonF line;
185  line << point;
186  line << QPointF( point.x() + xComponent, point.y() - yComponent );
187  mLineSymbol->renderPolyline( line, f, context.renderContext() );
188 }
189 
191 {
192  if ( mLineSymbol )
193  {
194  mLineSymbol->startRender( context.renderContext(), context.fields() );
195  }
196 
197  QgsFields fields = context.fields();
198  if ( !fields.isEmpty() )
199  {
200  mXIndex = fields.lookupField( mXAttribute );
201  mYIndex = fields.lookupField( mYAttribute );
202  }
203  else
204  {
205  mXIndex = -1;
206  mYIndex = -1;
207  }
208 }
209 
211 {
212  if ( mLineSymbol )
213  {
214  mLineSymbol->stopRender( context.renderContext() );
215  }
216 }
217 
219 {
221  if ( mLineSymbol )
222  {
223  clonedLayer->setSubSymbol( mLineSymbol->clone() );
224  }
225  return static_cast< QgsVectorFieldSymbolLayer * >( clonedLayer );
226 }
227 
229 {
231  properties[QStringLiteral( "x_attribute" )] = mXAttribute;
232  properties[QStringLiteral( "y_attribute" )] = mYAttribute;
233  properties[QStringLiteral( "distance_unit" )] = QgsUnitTypes::encodeUnit( mDistanceUnit );
234  properties[QStringLiteral( "distance_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceMapUnitScale );
235  properties[QStringLiteral( "scale" )] = QString::number( mScale );
236  properties[QStringLiteral( "vector_field_type" )] = QString::number( mVectorFieldType );
237  properties[QStringLiteral( "angle_orientation" )] = QString::number( mAngleOrientation );
238  properties[QStringLiteral( "angle_units" )] = QString::number( mAngleUnits );
239  properties[QStringLiteral( "size" )] = QString::number( mSize );
240  properties[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
241  properties[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
242  properties[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
243  properties[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
244  properties[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
245  return properties;
246 }
247 
248 void QgsVectorFieldSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
249 {
250  element.appendChild( doc.createComment( QStringLiteral( "VectorField not implemented yet..." ) ) );
251  mLineSymbol->toSld( doc, element, props );
252 }
253 
255 {
256  Q_UNUSED( element );
257  return nullptr;
258 }
259 
261 {
262  if ( mLineSymbol )
263  {
264  mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
265  }
266 }
267 
268 QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
269 {
270  QSet<QString> attributes = QgsMarkerSymbolLayer::usedAttributes( context );
271  if ( !mXAttribute.isEmpty() )
272  {
273  attributes.insert( mXAttribute );
274  }
275  if ( !mYAttribute.isEmpty() )
276  {
277  attributes.insert( mYAttribute );
278  }
279  if ( mLineSymbol )
280  {
281  attributes.unite( mLineSymbol->usedAttributes( context ) );
282  }
283  return attributes;
284 }
285 
286 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double &x, double &y ) const
287 {
288  //convert angle to degree and to north orientation
289  if ( mAngleOrientation == CounterclockwiseFromEast )
290  {
291  if ( angle <= 90 )
292  {
293  angle = 90 - angle;
294  }
295  else
296  {
297  angle = 360 - angle + 90;
298  }
299  }
300 
301  if ( mAngleUnits == Degrees )
302  {
303  angle = angle * M_PI / 180.0;
304  }
305 
306  x = length * std::sin( angle );
307  y = length * std::cos( angle );
308 }
309 
311 {
312  if ( mLineSymbol )
313  mLineSymbol->setColor( color );
314 
315  mColor = color;
316 }
317 
319 {
320  return mLineSymbol ? mLineSymbol->color() : mColor;
321 }
322 
323 
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:299
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:534
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.
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:62
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:479
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
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.
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:453
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
set layer&#39;s subsymbol. takes ownership of the passed symbol
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
Definition: qgssymbol.h:113
Struct for storing maximum and minimum scales for measurements in map units.
void setMapUnitScale(const QgsMapUnitScale &scale) override
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbol.h:509
void stopRender(QgsSymbolRenderContext &context) override
bool isEmpty() const
Check whether the container is empty.
Definition: qgsfields.cpp:110
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:255
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:100
static QgsSymbolLayer * createFromSld(QDomElement &element)