QGIS API Documentation  master-6164ace
src/core/symbology-ng/qgssymbollayerv2.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgssymbollayerv2.cpp
00003     ---------------------
00004     begin                : November 2009
00005     copyright            : (C) 2009 by Martin Dobias
00006     email                : wonder dot sk at gmail dot com
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #include "qgssymbollayerv2.h"
00017 #include "qgsclipper.h"
00018 #include "qgsexpression.h"
00019 #include "qgsrendercontext.h"
00020 #include "qgsvectorlayer.h"
00021 
00022 #include <QSize>
00023 #include <QPainter>
00024 #include <QPointF>
00025 #include <QPolygonF>
00026 
00027 const QgsExpression* QgsSymbolLayerV2::dataDefinedProperty( const QString& property ) const
00028 {
00029   QMap< QString, QgsExpression* >::const_iterator it = mDataDefinedProperties.find( property );
00030   if ( it != mDataDefinedProperties.constEnd() )
00031   {
00032     return it.value();
00033   }
00034   return 0;
00035 }
00036 
00037 QgsExpression* QgsSymbolLayerV2::expression( const QString& property )
00038 {
00039   QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.find( property );
00040   if ( it != mDataDefinedProperties.end() )
00041   {
00042     return it.value();
00043   }
00044   return 0;
00045 }
00046 
00047 QString QgsSymbolLayerV2::dataDefinedPropertyString( const QString& property ) const
00048 {
00049   const QgsExpression* ex = dataDefinedProperty( property );
00050   return ex ? ex->expression() : QString();
00051 }
00052 
00053 void QgsSymbolLayerV2::setDataDefinedProperty( const QString& property, const QString& expressionString )
00054 {
00055   removeDataDefinedProperty( property );
00056   mDataDefinedProperties.insert( property, new QgsExpression( expressionString ) );
00057 }
00058 
00059 void QgsSymbolLayerV2::removeDataDefinedProperty( const QString& property )
00060 {
00061   QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.find( property );
00062   if ( it != mDataDefinedProperties.end() )
00063   {
00064     delete( it.value() );
00065     mDataDefinedProperties.erase( it );
00066   }
00067 }
00068 
00069 void QgsSymbolLayerV2::removeDataDefinedProperties()
00070 {
00071   QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.begin();
00072   for ( ; it != mDataDefinedProperties.constEnd(); ++it )
00073   {
00074     delete( it.value() );
00075   }
00076   mDataDefinedProperties.clear();
00077 }
00078 
00079 void QgsSymbolLayerV2::prepareExpressions( const QgsVectorLayer* vl )
00080 {
00081   if ( !vl )
00082   {
00083     return;
00084   }
00085 
00086   const QgsFields& fields = vl->pendingFields();
00087   QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.begin();
00088   for ( ; it != mDataDefinedProperties.end(); ++it )
00089   {
00090     if ( it.value() )
00091     {
00092       it.value()->prepare( fields );
00093     }
00094   }
00095 }
00096 
00097 QSet<QString> QgsSymbolLayerV2::usedAttributes() const
00098 {
00099   QSet<QString> attributes;
00100   QStringList columns;
00101 
00102   QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
00103   for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
00104   {
00105     if ( ddIt.value() )
00106     {
00107       columns.append( ddIt.value()->referencedColumns() );
00108     }
00109   }
00110 
00111   QStringList::const_iterator it = columns.constBegin();
00112   for ( ; it != columns.constEnd(); ++it )
00113   {
00114     attributes.insert( *it );
00115   }
00116   return attributes;
00117 }
00118 
00119 void QgsSymbolLayerV2::saveDataDefinedProperties( QgsStringMap& stringMap ) const
00120 {
00121   QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
00122   for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
00123   {
00124     if ( ddIt.value() )
00125     {
00126       stringMap.insert( ddIt.key() + "_expression", ddIt.value()->expression() );
00127     }
00128   }
00129 }
00130 
00131 void QgsSymbolLayerV2::copyDataDefinedProperties( QgsSymbolLayerV2* destLayer ) const
00132 {
00133   if ( !destLayer )
00134   {
00135     return;
00136   }
00137   destLayer->removeDataDefinedProperties();
00138 
00139   QMap< QString, QgsExpression* >::const_iterator ddIt = mDataDefinedProperties.constBegin();
00140   for ( ; ddIt != mDataDefinedProperties.constEnd(); ++ddIt )
00141   {
00142     if ( ddIt.value() )
00143     {
00144       destLayer->setDataDefinedProperty( ddIt.key(), ddIt.value()->expression() );
00145     }
00146   }
00147 }
00148 
00149 
00150 QgsMarkerSymbolLayerV2::QgsMarkerSymbolLayerV2( bool locked )
00151     : QgsSymbolLayerV2( QgsSymbolV2::Marker, locked ), mSizeUnit( QgsSymbolV2::MM ),  mOffsetUnit( QgsSymbolV2::MM )
00152 {
00153 }
00154 
00155 QgsLineSymbolLayerV2::QgsLineSymbolLayerV2( bool locked )
00156     : QgsSymbolLayerV2( QgsSymbolV2::Line, locked ), mWidthUnit( QgsSymbolV2::MM )
00157 {
00158 }
00159 
00160 QgsFillSymbolLayerV2::QgsFillSymbolLayerV2( bool locked )
00161     : QgsSymbolLayerV2( QgsSymbolV2::Fill, locked ), mAngle( 0.0 )
00162 {
00163 }
00164 
00165 void QgsMarkerSymbolLayerV2::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
00166 {
00167   startRender( context );
00168   renderPoint( QPointF( size.width() / 2, size.height() / 2 ), context );
00169   stopRender( context );
00170 }
00171 
00172 void QgsMarkerSymbolLayerV2::setOutputUnit( QgsSymbolV2::OutputUnit unit )
00173 {
00174   mSizeUnit = unit;
00175   mOffsetUnit = unit;
00176 }
00177 
00178 void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY )
00179 {
00180   offsetX = mOffset.x();
00181   offsetY = mOffset.y();
00182 
00183   QgsExpression* offsetExpression = expression( "offset" );
00184   if ( offsetExpression )
00185   {
00186     QPointF offset = QgsSymbolLayerV2Utils::decodePoint( offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
00187     offsetX = offset.x();
00188     offsetY = offset.y();
00189   }
00190 
00191   offsetX *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
00192   offsetY *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
00193 }
00194 
00195 QPointF QgsMarkerSymbolLayerV2::_rotatedOffset( const QPointF& offset, double angle )
00196 {
00197   angle = DEG2RAD( angle );
00198   double c = cos( angle ), s = sin( angle );
00199   return QPointF( offset.x() * c - offset.y() * s, offset.x() * s + offset.y() * c );
00200 }
00201 
00202 QgsSymbolV2::OutputUnit QgsMarkerSymbolLayerV2::outputUnit() const
00203 {
00204   QgsSymbolV2::OutputUnit unit = mSizeUnit;
00205   if ( mOffsetUnit != unit )
00206   {
00207     return QgsSymbolV2::Mixed;
00208   }
00209   return unit;
00210 }
00211 
00212 void QgsLineSymbolLayerV2::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
00213 {
00214   QPolygonF points;
00215   // we're adding 0.5 to get rid of blurred preview:
00216   // drawing antialiased lines of width 1 at (x,0)-(x,100) creates 2px line
00217   points << QPointF( 0, size.height() / 2 + 0.5 ) << QPointF( size.width(), size.height() / 2 + 0.5 );
00218 
00219   startRender( context );
00220   renderPolyline( points, context );
00221   stopRender( context );
00222 }
00223 
00224 void QgsLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
00225 {
00226   renderPolyline( points, context );
00227   if ( rings )
00228   {
00229     foreach ( const QPolygonF& ring, *rings )
00230       renderPolyline( ring, context );
00231   }
00232 }
00233 
00234 
00235 void QgsFillSymbolLayerV2::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
00236 {
00237   QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
00238   startRender( context );
00239   renderPolygon( poly, NULL, context );
00240   stopRender( context );
00241 }
00242 
00243 void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings )
00244 {
00245   if ( !p )
00246   {
00247     return;
00248   }
00249 
00250   if ( rings == NULL )
00251   {
00252     // simple polygon without holes
00253     p->drawPolygon( points );
00254   }
00255   else
00256   {
00257     // polygon with holes must be drawn using painter path
00258     QPainterPath path;
00259     QPolygonF outerRing = points;
00260     path.addPolygon( outerRing );
00261 
00262     QList<QPolygonF>::const_iterator it = rings->constBegin();
00263     for ( ; it != rings->constEnd(); ++it )
00264     {
00265       QPolygonF ring = *it;
00266       path.addPolygon( ring );
00267     }
00268 
00269     p->drawPath( path );
00270   }
00271 }
00272 
00273 void QgsMarkerSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
00274 {
00275   QDomElement symbolizerElem = doc.createElement( "se:PointSymbolizer" );
00276   if ( !props.value( "uom", "" ).isEmpty() )
00277     symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
00278   element.appendChild( symbolizerElem );
00279 
00280   // <Geometry>
00281   QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );
00282 
00283   writeSldMarker( doc, symbolizerElem, props );
00284 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines