|
QGIS API Documentation
master-3f58142
|
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 }