QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
22  : mXAttribute( "" )
23  , mYAttribute( "" )
24  , mDistanceUnit( QgsSymbolV2::MM )
25  , mScale( 1.0 )
26  , mVectorFieldType( Cartesian )
27  , mAngleOrientation( ClockwiseFromNorth )
28  , mAngleUnits( Degrees )
29  , mLineSymbol( 0 )
30  , mXIndex( -1 )
31  , mYIndex( -1 )
32 {
34 }
35 
37 {
38  delete mLineSymbol;
39 }
40 
42 {
44  mDistanceUnit = unit;
45 }
46 
48 {
49  if ( QgsMarkerSymbolLayerV2::outputUnit() == mDistanceUnit )
50  {
51  return mDistanceUnit;
52  }
53  return QgsSymbolV2::Mixed;
54 }
55 
57 {
59  mDistanceMapUnitScale = scale;
60 }
61 
63 {
64  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mDistanceMapUnitScale )
65  {
66  return mDistanceMapUnitScale;
67  }
68  return QgsMapUnitScale();
69 }
70 
72 {
74  if ( properties.contains( "x_attribute" ) )
75  {
76  symbolLayer->setXAttribute( properties["x_attribute"] );
77  }
78  if ( properties.contains( "y_attribute" ) )
79  {
80  symbolLayer->setYAttribute( properties["y_attribute"] );
81  }
82  if ( properties.contains( "distance_unit" ) )
83  {
84  symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) );
85  }
86  if ( properties.contains( "distance_map_unit_scale" ) )
87  {
88  symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["distance_map_unit_scale"] ) );
89  }
90  if ( properties.contains( "scale" ) )
91  {
92  symbolLayer->setScale( properties["scale"].toDouble() );
93  }
94  if ( properties.contains( "vector_field_type" ) )
95  {
96  symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
97  }
98  if ( properties.contains( "angle_orientation" ) )
99  {
100  symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
101  }
102  if ( properties.contains( "angle_units" ) )
103  {
104  symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
105  }
106  if ( properties.contains( "size" ) )
107  {
108  symbolLayer->setSize( properties["size"].toDouble() );
109  }
110  if ( properties.contains( "size_unit" ) )
111  {
112  symbolLayer->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["size_unit"] ) );
113  }
114  if ( properties.contains( "size_map_unit_scale" ) )
115  {
116  symbolLayer->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["size_map_unit_scale"] ) );
117  }
118  if ( properties.contains( "offset" ) )
119  {
120  symbolLayer->setOffset( QgsSymbolLayerV2Utils::decodePoint( properties["offset"] ) );
121  }
122  if ( properties.contains( "offset_unit" ) )
123  {
124  symbolLayer->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["offset_unit"] ) );
125  }
126  if ( properties.contains( "offset_map_unit_scale" ) )
127  {
128  symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["offset_map_unit_scale"] ) );
129  }
130  return symbolLayer;
131 }
132 
134 {
135  if ( symbol->type() == QgsSymbolV2::Line )
136  {
137  delete mLineSymbol;
138  mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
139  return true;
140  }
141  return false;
142 }
143 
145 {
146  if ( !mLineSymbol )
147  {
148  return;
149  }
150 
151  const QgsRenderContext& ctx = context.renderContext();
152 
153  const QgsFeature* f = context.feature();
154  if ( !f )
155  {
156  //preview
157  QPolygonF line;
158  line << QPointF( 0, 50 );
159  line << QPointF( 100, 50 );
160  mLineSymbol->renderPolyline( line, 0, context.renderContext() );
161  }
162 
163  double xComponent = 0;
164  double yComponent = 0;
165 
166  double xVal = 0;
167  if ( f && mXIndex != -1 )
168  {
169  xVal = f->attribute( mXIndex ).toDouble();
170  }
171  double yVal = 0;
172  if ( f && mYIndex != -1 )
173  {
174  yVal = f->attribute( mYIndex ).toDouble();
175  }
176 
177  switch ( mVectorFieldType )
178  {
179  case Cartesian:
180  xComponent = xVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
181  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
182  break;
183  case Polar:
184  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
185  xComponent = xComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
186  yComponent = yComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
187  break;
188  case Height:
189  xComponent = 0;
190  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit, mDistanceMapUnitScale );
191  break;
192  default:
193  break;
194  }
195 
196  xComponent *= mScale;
197  yComponent *= mScale;
198 
199  QPolygonF line;
200  line << point;
201  line << QPointF( point.x() + xComponent, point.y() - yComponent );
202  mLineSymbol->renderPolyline( line, f, context.renderContext() );
203 }
204 
206 {
207  if ( mLineSymbol )
208  {
209  mLineSymbol->startRender( context.renderContext(), context.fields() );
210  }
211 
212  const QgsFields* fields = context.fields();
213  if ( fields )
214  {
215  mXIndex = fields->fieldNameIndex( mXAttribute );
216  mYIndex = fields->fieldNameIndex( mYAttribute );
217  }
218  else
219  {
220  mXIndex = -1;
221  mYIndex = -1;
222  }
223 }
224 
226 {
227  if ( mLineSymbol )
228  {
229  mLineSymbol->stopRender( context.renderContext() );
230  }
231 }
232 
234 {
236  if ( mLineSymbol )
237  {
238  clonedLayer->setSubSymbol( mLineSymbol->clone() );
239  }
240  return clonedLayer;
241 }
242 
244 {
246  properties["x_attribute"] = mXAttribute;
247  properties["y_attribute"] = mYAttribute;
248  properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit );
249  properties["distance_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mDistanceMapUnitScale );
250  properties["scale"] = QString::number( mScale );
251  properties["vector_field_type"] = QString::number( mVectorFieldType );
252  properties["angle_orientation"] = QString::number( mAngleOrientation );
253  properties["angle_units"] = QString::number( mAngleUnits );
254  properties["size"] = QString::number( mSize );
255  properties["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
256  properties["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
257  properties["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
258  properties["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
259  properties["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
260  return properties;
261 }
262 
263 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
264 {
265  element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
266  mLineSymbol->toSld( doc, element, props );
267 }
268 
270 {
271  Q_UNUSED( element );
272  return NULL;
273 }
274 
276 {
277  if ( mLineSymbol )
278  {
279  mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
280  }
281 }
282 
284 {
285  QSet<QString> attributes;
286  if ( !mXAttribute.isEmpty() )
287  {
288  attributes.insert( mXAttribute );
289  }
290  if ( !mYAttribute.isEmpty() )
291  {
292  attributes.insert( mYAttribute );
293  }
294  return attributes;
295 }
296 
297 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
298 {
299  //convert angle to degree and to north orientation
300  if ( mAngleOrientation == CounterclockwiseFromEast )
301  {
302  if ( angle <= 90 )
303  {
304  angle = 90 - angle;
305  }
306  else
307  {
308  angle = 360 - angle + 90;
309  }
310  }
311 
312  if ( mAngleUnits == Degrees )
313  {
314  angle = angle * M_PI / 180.0;
315  }
316 
317  x = length * sin( angle );
318  y = length * cos( angle );
319 }
320 
321