Quantum GIS API Documentation  1.8
src/core/symbology-ng/qgsvectorfieldsymbollayer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                               qgsvectorfieldsymbollayer.cpp
00003                               -----------------------------
00004   begin                : Octorer 25, 2011
00005   copyright            : (C) 2011 by Marco Hugentobler
00006   email                : marco dot hugentobler at sourcepole dot ch
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgsvectorfieldsymbollayer.h"
00019 #include "qgsvectorlayer.h"
00020 
00021 QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer(): mXAttribute( "" ), mYAttribute( "" ), mScale( 1.0 ),
00022     mVectorFieldType( Cartesian ), mAngleOrientation( ClockwiseFromNorth ), mAngleUnits( Degrees ), mXIndex( -1 ), mYIndex( -1 )
00023 {
00024   setSubSymbol( new QgsLineSymbolV2() );
00025 }
00026 
00027 QgsVectorFieldSymbolLayer::~QgsVectorFieldSymbolLayer()
00028 {
00029 }
00030 
00031 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::create( const QgsStringMap& properties )
00032 {
00033   QgsVectorFieldSymbolLayer* symbolLayer = new QgsVectorFieldSymbolLayer();
00034   if ( properties.contains( "x_attribute" ) )
00035   {
00036     symbolLayer->setXAttribute( properties["x_attribute"] );
00037   }
00038   if ( properties.contains( "y_attribute" ) )
00039   {
00040     symbolLayer->setYAttribute( properties["y_attribute"] );
00041   }
00042   if ( properties.contains( "scale" ) )
00043   {
00044     symbolLayer->setScale( properties["scale"].toDouble() );
00045   }
00046   if ( properties.contains( "vector_field_type" ) )
00047   {
00048     symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
00049   }
00050   if ( properties.contains( "angle_orientation" ) )
00051   {
00052     symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
00053   }
00054   if ( properties.contains( "angle_units" ) )
00055   {
00056     symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
00057   }
00058   return symbolLayer;
00059 }
00060 
00061 bool QgsVectorFieldSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
00062 {
00063   if ( symbol->type() == QgsSymbolV2::Line )
00064   {
00065     mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
00066     return true;
00067   }
00068   return false;
00069 }
00070 
00071 void QgsVectorFieldSymbolLayer::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
00072 {
00073   if ( !mLineSymbol )
00074   {
00075     return;
00076   }
00077 
00078   const QgsFeature* f = context.feature();
00079   if ( !f )
00080   {
00081     //preview
00082     QPolygonF line;
00083     line << QPointF( 0, 50 );
00084     line << QPointF( 100, 50 );
00085     mLineSymbol->renderPolyline( line, 0, context.renderContext() );
00086   }
00087 
00088   double xComponent = 0;
00089   double yComponent = 0;
00090 
00091   double xVal = 0;
00092   if ( mXIndex != -1 )
00093   {
00094     xVal = f->attributeMap()[mXIndex].toDouble();
00095   }
00096   double yVal = 0;
00097   if ( mYIndex != -1 )
00098   {
00099     yVal = f->attributeMap()[mYIndex].toDouble();
00100   }
00101 
00102   switch ( mVectorFieldType )
00103   {
00104     case Cartesian:
00105       xComponent = context.outputLineWidth( xVal );
00106       yComponent = context.outputLineWidth( yVal );
00107       break;
00108     case Polar:
00109       convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
00110       xComponent = context.outputLineWidth( xComponent );
00111       yComponent = context.outputLineWidth( yComponent );
00112       break;
00113     case Height:
00114       xComponent = 0;
00115       yComponent = context.outputLineWidth( yVal );
00116       break;
00117     default:
00118       break;
00119   }
00120 
00121   xComponent *= mScale;
00122   yComponent *= mScale;
00123 
00124   QPolygonF line;
00125   line << point;
00126   line << QPointF( point.x() + xComponent, point.y() - yComponent );
00127   mLineSymbol->renderPolyline( line, f, context.renderContext() );
00128 }
00129 
00130 void QgsVectorFieldSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
00131 {
00132   if ( mLineSymbol )
00133   {
00134     mLineSymbol->startRender( context.renderContext() );
00135   }
00136 
00137   const QgsVectorLayer* layer = context.layer();
00138   if ( layer )
00139   {
00140     mXIndex = layer->fieldNameIndex( mXAttribute );
00141     mYIndex = layer->fieldNameIndex( mYAttribute );
00142   }
00143   else
00144   {
00145     mXIndex = -1;
00146     mYIndex = -1;
00147   }
00148 }
00149 
00150 void QgsVectorFieldSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
00151 {
00152   if ( mLineSymbol )
00153   {
00154     mLineSymbol->stopRender( context.renderContext() );
00155   }
00156 }
00157 
00158 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::clone() const
00159 {
00160   QgsSymbolLayerV2* clonedLayer = QgsVectorFieldSymbolLayer::create( properties() );
00161   if ( mLineSymbol )
00162   {
00163     clonedLayer->setSubSymbol( mLineSymbol->clone() );
00164   }
00165   return clonedLayer;
00166 }
00167 
00168 QgsStringMap QgsVectorFieldSymbolLayer::properties() const
00169 {
00170   QgsStringMap properties;
00171   properties["x_attribute"] = mXAttribute;
00172   properties["y_attribute"] = mYAttribute;
00173   properties["scale"] = QString::number( mScale );
00174   properties["vector_field_type"] = QString::number( mVectorFieldType );
00175   properties["angle_orientation"] = QString::number( mAngleOrientation );
00176   properties["angle_units"] = QString::number( mAngleUnits );
00177   return properties;
00178 }
00179 
00180 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
00181 {
00182   element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
00183   mLineSymbol->toSld( doc, element, props );
00184 }
00185 
00186 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::createFromSld( QDomElement &element )
00187 {
00188   Q_UNUSED( element );
00189   return NULL;
00190 }
00191 
00192 void QgsVectorFieldSymbolLayer::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
00193 {
00194   if ( mLineSymbol )
00195   {
00196     mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
00197   }
00198 }
00199 
00200 QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes() const
00201 {
00202   QSet<QString> attributes;
00203   if ( !mXAttribute.isEmpty() )
00204   {
00205     attributes.insert( mXAttribute );
00206   }
00207   if ( !mYAttribute.isEmpty() )
00208   {
00209     attributes.insert( mYAttribute );
00210   }
00211   return attributes;
00212 }
00213 
00214 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
00215 {
00216   //convert angle to degree and to north orientation
00217   if ( mAngleOrientation == CounterclockwiseFromEast )
00218   {
00219     if ( angle <= 90 )
00220     {
00221       angle = 90 - angle;
00222     }
00223     else
00224     {
00225       angle = 360 - angle + 90;
00226     }
00227   }
00228 
00229   if ( mAngleUnits == Degrees )
00230   {
00231     angle = angle * M_PI / 180.0;
00232   }
00233 
00234   x = length * sin( angle );
00235   y = length * cos( angle );
00236 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines