Quantum GIS API Documentation  master-ce49b66
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( "" ), mDistanceUnit( QgsSymbolV2::MM ), 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 void QgsVectorFieldSymbolLayer::setOutputUnit( QgsSymbolV2::OutputUnit unit )
00032 {
00033   mDistanceUnit = unit; //other units are not used
00034 }
00035 
00036 QgsSymbolV2::OutputUnit QgsVectorFieldSymbolLayer::outputUnit() const
00037 {
00038   return mDistanceUnit;
00039 }
00040 
00041 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::create( const QgsStringMap& properties )
00042 {
00043   QgsVectorFieldSymbolLayer* symbolLayer = new QgsVectorFieldSymbolLayer();
00044   if ( properties.contains( "x_attribute" ) )
00045   {
00046     symbolLayer->setXAttribute( properties["x_attribute"] );
00047   }
00048   if ( properties.contains( "y_attribute" ) )
00049   {
00050     symbolLayer->setYAttribute( properties["y_attribute"] );
00051   }
00052   if ( properties.contains( "distance_unit" ) )
00053   {
00054     symbolLayer->setDistanceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["distance_unit"] ) );
00055   }
00056   if ( properties.contains( "scale" ) )
00057   {
00058     symbolLayer->setScale( properties["scale"].toDouble() );
00059   }
00060   if ( properties.contains( "vector_field_type" ) )
00061   {
00062     symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
00063   }
00064   if ( properties.contains( "angle_orientation" ) )
00065   {
00066     symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
00067   }
00068   if ( properties.contains( "angle_units" ) )
00069   {
00070     symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
00071   }
00072   return symbolLayer;
00073 }
00074 
00075 bool QgsVectorFieldSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
00076 {
00077   if ( symbol->type() == QgsSymbolV2::Line )
00078   {
00079     mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
00080     return true;
00081   }
00082   return false;
00083 }
00084 
00085 void QgsVectorFieldSymbolLayer::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
00086 {
00087   if ( !mLineSymbol )
00088   {
00089     return;
00090   }
00091 
00092   const QgsRenderContext& ctx = context.renderContext();
00093 
00094   const QgsFeature* f = context.feature();
00095   if ( !f )
00096   {
00097     //preview
00098     QPolygonF line;
00099     line << QPointF( 0, 50 );
00100     line << QPointF( 100, 50 );
00101     mLineSymbol->renderPolyline( line, 0, context.renderContext() );
00102   }
00103 
00104   double xComponent = 0;
00105   double yComponent = 0;
00106 
00107   double xVal = 0;
00108   if ( mXIndex != -1 )
00109   {
00110     xVal = f->attribute( mXIndex ).toDouble();
00111   }
00112   double yVal = 0;
00113   if ( mYIndex != -1 )
00114   {
00115     yVal = f->attribute( mYIndex ).toDouble();
00116   }
00117 
00118   switch ( mVectorFieldType )
00119   {
00120     case Cartesian:
00121       xComponent = xVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
00122       yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
00123       break;
00124     case Polar:
00125       convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
00126       xComponent = xComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
00127       yComponent = yComponent * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
00128       break;
00129     case Height:
00130       xComponent = 0;
00131       yComponent = yVal * QgsSymbolLayerV2Utils::lineWidthScaleFactor( ctx, mDistanceUnit );
00132       break;
00133     default:
00134       break;
00135   }
00136 
00137   xComponent *= mScale;
00138   yComponent *= mScale;
00139 
00140   QPolygonF line;
00141   line << point;
00142   line << QPointF( point.x() + xComponent, point.y() - yComponent );
00143   mLineSymbol->renderPolyline( line, f, context.renderContext() );
00144 }
00145 
00146 void QgsVectorFieldSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
00147 {
00148   if ( mLineSymbol )
00149   {
00150     mLineSymbol->startRender( context.renderContext() );
00151   }
00152 
00153   const QgsVectorLayer* layer = context.layer();
00154   if ( layer )
00155   {
00156     mXIndex = layer->fieldNameIndex( mXAttribute );
00157     mYIndex = layer->fieldNameIndex( mYAttribute );
00158   }
00159   else
00160   {
00161     mXIndex = -1;
00162     mYIndex = -1;
00163   }
00164 }
00165 
00166 void QgsVectorFieldSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
00167 {
00168   if ( mLineSymbol )
00169   {
00170     mLineSymbol->stopRender( context.renderContext() );
00171   }
00172 }
00173 
00174 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::clone() const
00175 {
00176   QgsSymbolLayerV2* clonedLayer = QgsVectorFieldSymbolLayer::create( properties() );
00177   if ( mLineSymbol )
00178   {
00179     clonedLayer->setSubSymbol( mLineSymbol->clone() );
00180   }
00181   return clonedLayer;
00182 }
00183 
00184 QgsStringMap QgsVectorFieldSymbolLayer::properties() const
00185 {
00186   QgsStringMap properties;
00187   properties["x_attribute"] = mXAttribute;
00188   properties["y_attribute"] = mYAttribute;
00189   properties["distance_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mDistanceUnit );
00190   properties["scale"] = QString::number( mScale );
00191   properties["vector_field_type"] = QString::number( mVectorFieldType );
00192   properties["angle_orientation"] = QString::number( mAngleOrientation );
00193   properties["angle_units"] = QString::number( mAngleUnits );
00194   return properties;
00195 }
00196 
00197 void QgsVectorFieldSymbolLayer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
00198 {
00199   element.appendChild( doc.createComment( "VectorField not implemented yet..." ) );
00200   mLineSymbol->toSld( doc, element, props );
00201 }
00202 
00203 QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::createFromSld( QDomElement &element )
00204 {
00205   Q_UNUSED( element );
00206   return NULL;
00207 }
00208 
00209 void QgsVectorFieldSymbolLayer::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
00210 {
00211   if ( mLineSymbol )
00212   {
00213     mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
00214   }
00215 }
00216 
00217 QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes() const
00218 {
00219   QSet<QString> attributes;
00220   if ( !mXAttribute.isEmpty() )
00221   {
00222     attributes.insert( mXAttribute );
00223   }
00224   if ( !mYAttribute.isEmpty() )
00225   {
00226     attributes.insert( mYAttribute );
00227   }
00228   return attributes;
00229 }
00230 
00231 void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
00232 {
00233   //convert angle to degree and to north orientation
00234   if ( mAngleOrientation == CounterclockwiseFromEast )
00235   {
00236     if ( angle <= 90 )
00237     {
00238       angle = 90 - angle;
00239     }
00240     else
00241     {
00242       angle = 360 - angle + 90;
00243     }
00244   }
00245 
00246   if ( mAngleUnits == Degrees )
00247   {
00248     angle = angle * M_PI / 180.0;
00249   }
00250 
00251   x = length * sin( angle );
00252   y = length * cos( angle );
00253 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines