QGIS API Documentation  2.2.0-Valmiera
 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 
21 QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer(): mXAttribute( "" ), mYAttribute( "" ), mDistanceUnit( QgsSymbolV2::MM ), mScale( 1.0 ),
22  mVectorFieldType( Cartesian ), mAngleOrientation( ClockwiseFromNorth ), mAngleUnits( Degrees ), mXIndex( -1 ), mYIndex( -1 )
23 {
25 }
26 
28 {
29 }
30 
32 {
33  mDistanceUnit = unit; //other units are not used
34 }
35 
37 {
38  return mDistanceUnit;
39 }
40 
42 {
44  if ( properties.contains( "x_attribute" ) )
45  {
46  symbolLayer->setXAttribute( properties["x_attribute"] );
47  }
48  if ( properties.contains( "y_attribute" ) )
49  {
50  symbolLayer->setYAttribute( properties["y_attribute"] );
51  }
52  if ( properties.contains( "distance_unit" ) )
53  {
54  symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) );
55  }
56  if ( properties.contains( "scale" ) )
57  {
58  symbolLayer->setScale( properties["scale"].toDouble() );
59  }
60  if ( properties.contains( "vector_field_type" ) )
61  {
62  symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
63  }
64  if ( properties.contains( "angle_orientation" ) )
65  {
66  symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
67  }
68  if ( properties.contains( "angle_units" ) )
69  {
70  symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
71  }
72  return symbolLayer;
73 }
74 
76 {
77  if ( symbol->type() == QgsSymbolV2::Line )
78  {
79  mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
80  return true;
81  }
82  return false;
83 }
84 
86 {
87  if ( !mLineSymbol )
88  {
89  return;
90  }
91 
92  const QgsRenderContext& ctx = context.renderContext();
93 
94  const QgsFeature* f = context.feature();
95  if ( !f )
96  {
97  //preview
98  QPolygonF line;
99  line << QPointF( 0, 50 );
100  line << QPointF( 100, 50 );
101  mLineSymbol->renderPolyline( line, 0, context.renderContext() );
102  }
103 
104  double xComponent = 0;
105  double yComponent = 0;
106 
107  double xVal = 0;
108  if ( mXIndex != -1 )
109  {
110  xVal = f->attribute( mXIndex ).toDouble();
111  }
112  double yVal = 0;
113  if ( mYIndex != -1 )
114  {
115  yVal = f->attribute( mYIndex ).toDouble();
116  }
117 
118  switch ( mVectorFieldType )
119  {
120  case Cartesian:
122  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
123  break;
124  case Polar:
125  convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
126  xComponent = xComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
127  yComponent = yComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
128  break;
129  case Height:
130  xComponent = 0;
131  yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
132  break;
133  default:
134  break;
135  }
136 
137  xComponent *= mScale;
138  yComponent *= mScale;
139 
140  QPolygonF line;
141  line << point;
142  line << QPointF( point.x() + xComponent, point.y() - yComponent );
143  mLineSymbol->renderPolyline( line, f, context.renderContext() );
144 }
145 
147 {
148  if ( mLineSymbol )
149  {
150  mLineSymbol->startRender( context.renderContext() );
151  }
152 
153  const QgsVectorLayer* layer = context.layer();
154  if ( layer )
155  {
156  mXIndex = layer->fieldNameIndex( mXAttribute );
157  mYIndex = layer->fieldNameIndex( mYAttribute );
158  }
159  else
160  {
161  mXIndex = -1;
162  mYIndex = -1;
163  }
164 }
165 
167 {
168  if ( mLineSymbol )
169  {
170  mLineSymbol->stopRender( context.renderContext() );
171  }
172 }
173 
175 {
177  if ( mLineSymbol )
178  {
179  clonedLayer->setSubSymbol( mLineSymbol->clone() );
180  }
181  return clonedLayer;
182 }
183 
185 {
187  properties["x_attribute"] = mXAttribute;
188  properties["y_attribute"] = mYAttribute;
189  properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit );
190  properties["scale"] = QString::number( mScale );
191  properties["vector_field_type"] = QString::number( mVectorFieldType );
192  properties["angle_orientation"] = QString::number( mAngleOrientation );
193  properties["angle_units"] = QString::number( mAngleUnits );
194  return properties;
195 }
196 
197 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
198 {
199  element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
200  mLineSymbol->toSld( doc, element, props );
201 }
202 
204 {
205  Q_UNUSED( element );
206  return NULL;
207 }
208 
210 {
211  if ( mLineSymbol )
212  {
214  }
215 }
216 
218 {
219  QSet<QString> attributes;
220  if ( !mXAttribute.isEmpty() )
221  {
222  attributes.insert( mXAttribute );
223  }
224  if ( !mYAttribute.isEmpty() )
225  {
226  attributes.insert( mYAttribute );
227  }
228  return attributes;
229 }
230 
231 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
232 {
233  //convert angle to degree and to north orientation
235  {
236  if ( angle <= 90 )
237  {
238  angle = 90 - angle;
239  }
240  else
241  {
242  angle = 360 - angle + 90;
243  }
244  }
245 
246  if ( mAngleUnits == Degrees )
247  {
248  angle = angle * M_PI / 180.0;
249  }
250 
251  x = length * sin( angle );
252  y = length * cos( angle );
253 }