00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgis.h"
00020 #include "qgslogger.h"
00021 #include "qgsfeature.h"
00022 #include "qgsgraduatedsymbolrenderer.h"
00023 #include "qgssymbol.h"
00024 #include "qgssymbologyutils.h"
00025 #include "qgsvectordataprovider.h"
00026 #include "qgsvectorlayer.h"
00027 #include "qgsrendercontext.h"
00028 #include <math.h>
00029 #include <QDomNode>
00030 #include <QDomElement>
00031 #include <QImage>
00032 #include <QPainter>
00033
00034
00035 QgsGraduatedSymbolRenderer::QgsGraduatedSymbolRenderer( QGis::GeometryType type, Mode mode )
00036 {
00037 mGeometryType = type;
00038 }
00039
00040 QgsGraduatedSymbolRenderer::QgsGraduatedSymbolRenderer( const QgsGraduatedSymbolRenderer& other )
00041 {
00042 mMode = other.mMode;
00043 mGeometryType = other.mGeometryType;
00044 mClassificationField = other.mClassificationField;
00045 const QList<QgsSymbol*> s = other.symbols();
00046 for ( QList<QgsSymbol*>::const_iterator it = s.begin(); it != s.end(); ++it )
00047 {
00048 addSymbol( new QgsSymbol( **it ) );
00049 }
00050 updateSymbolAttributes();
00051 }
00052
00053 QgsGraduatedSymbolRenderer& QgsGraduatedSymbolRenderer::operator=( const QgsGraduatedSymbolRenderer & other )
00054 {
00055 if ( this != &other )
00056 {
00057 mMode = other.mMode;
00058 mGeometryType = other.mGeometryType;
00059 mClassificationField = other.mClassificationField;
00060 removeSymbols();
00061 const QList<QgsSymbol*> s = other.symbols();
00062 for ( QList<QgsSymbol*>::const_iterator it = s.begin(); it != s.end(); ++it )
00063 {
00064 addSymbol( new QgsSymbol( **it ) );
00065 }
00066 updateSymbolAttributes();
00067 }
00068
00069 return *this;
00070 }
00071
00072 QgsGraduatedSymbolRenderer::~QgsGraduatedSymbolRenderer()
00073 {
00074
00075 }
00076
00077
00078 QgsGraduatedSymbolRenderer::Mode QgsGraduatedSymbolRenderer::mode() const
00079 {
00080
00081
00082
00083
00084 return mMode;
00085 }
00086
00087 void QgsGraduatedSymbolRenderer::setMode( QgsGraduatedSymbolRenderer::Mode theMode )
00088 {
00089
00090
00091
00092
00093 mMode = theMode;
00094 }
00095
00096 const QList<QgsSymbol*> QgsGraduatedSymbolRenderer::symbols() const
00097 {
00098 return mSymbols;
00099 }
00100
00101 void QgsGraduatedSymbolRenderer::removeSymbols()
00102 {
00103
00104 for ( QList<QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00105 {
00106 delete *it;
00107 }
00108
00109
00110 mSymbols.clear();
00111 updateSymbolAttributes();
00112 }
00113
00114 bool QgsGraduatedSymbolRenderer::willRenderFeature( QgsFeature *f )
00115 {
00116 return ( symbolForFeature( f ) != 0 );
00117 }
00118
00119 void QgsGraduatedSymbolRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity )
00120 {
00121 QPainter *p = renderContext.painter();
00122 QgsSymbol* theSymbol = symbolForFeature( &f );
00123 if ( !theSymbol )
00124 {
00125 if ( img && mGeometryType == QGis::Point )
00126 {
00127 img->fill( 0 );
00128 }
00129 else if ( mGeometryType != QGis::Point )
00130 {
00131 p->setPen( Qt::NoPen );
00132 p->setBrush( Qt::NoBrush );
00133 }
00134 return;
00135 }
00136
00137
00138
00139 if ( img && mGeometryType == QGis::Point )
00140 {
00141 double fieldScale = 1.0;
00142 double rotation = 0.0;
00143
00144 if ( theSymbol->scaleClassificationField() >= 0 )
00145 {
00146
00147 const QgsAttributeMap& attrs = f.attributeMap();
00148 fieldScale = sqrt( fabs( attrs[theSymbol->scaleClassificationField()].toDouble() ) );
00149 QgsDebugMsgLevel( QString( "Feature has field scale factor %1" ).arg( fieldScale ), 3 );
00150 }
00151 if ( theSymbol->rotationClassificationField() >= 0 )
00152 {
00153 const QgsAttributeMap& attrs = f.attributeMap();
00154 rotation = attrs[theSymbol->rotationClassificationField()].toDouble();
00155 QgsDebugMsgLevel( QString( "Feature has rotation factor %1" ).arg( rotation ), 3 );
00156 }
00157
00158 QString oldName;
00159
00160 if ( theSymbol->symbolField() >= 0 )
00161 {
00162 const QgsAttributeMap& attrs = f.attributeMap();
00163 QString name = attrs[theSymbol->symbolField()].toString();
00164 QgsDebugMsgLevel( QString( "Feature has name %1" ).arg( name ), 3 );
00165 oldName = theSymbol->pointSymbolName();
00166 theSymbol->setNamedPointSymbol( name );
00167 }
00168
00169 double scale = renderContext.scaleFactor();
00170
00171 if ( theSymbol->pointSizeUnits() )
00172 {
00173 scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel();
00174 }
00175
00176 *img = theSymbol->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale,
00177 rotation, renderContext.rasterScaleFactor(), opacity );
00178
00179 if ( !oldName.isNull() )
00180 {
00181 theSymbol->setNamedPointSymbol( oldName );
00182 }
00183 }
00184
00185
00186 if ( mGeometryType != QGis::Point )
00187 {
00188 if ( !selected )
00189 {
00190 QPen pen = theSymbol->pen();
00191 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
00192 p->setPen( pen );
00193
00194 if ( mGeometryType == QGis::Polygon )
00195 {
00196 QBrush brush = theSymbol->brush();
00197 scaleBrush( brush, renderContext.rasterScaleFactor() );
00198 p->setBrush( brush );
00199 }
00200 }
00201 else
00202 {
00203 QPen pen = theSymbol->pen();
00204 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
00205
00206 if ( mGeometryType == QGis::Polygon )
00207 {
00208 QBrush brush = theSymbol->brush();
00209 scaleBrush( brush, renderContext.rasterScaleFactor() );
00210 brush.setColor( mSelectionColor );
00211 p->setBrush( brush );
00212 }
00213 else
00214 {
00215 pen.setColor( mSelectionColor );
00216 }
00217 p->setPen( pen );
00218 }
00219 }
00220 }
00221
00222 QgsSymbol *QgsGraduatedSymbolRenderer::symbolForFeature( const QgsFeature* f )
00223 {
00224
00225 const QgsAttributeMap& attrs = f->attributeMap();
00226 double value = attrs[mClassificationField].toDouble();
00227
00228 QList<QgsSymbol*>::iterator it;
00229
00230 for ( it = mSymbols.begin(); it != mSymbols.end(); ++it )
00231 {
00232 if ( value >= ( *it )->lowerValue().toDouble() && value <= ( *it )->upperValue().toDouble() )
00233 {
00234 break;
00235 }
00236 }
00237
00238 if ( it == mSymbols.end() )
00239 {
00240 return 0;
00241 }
00242 return ( *it );
00243 }
00244
00245 int QgsGraduatedSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
00246 {
00247 mGeometryType = vl.geometryType();
00248 QDomNode modeNode = rnode.namedItem( "mode" );
00249 QString modeValue = modeNode.toElement().text();
00250 QDomNode classnode = rnode.namedItem( "classificationfield" );
00251 QString classificationField = classnode.toElement().text();
00252
00253 QgsVectorDataProvider* theProvider = vl.dataProvider();
00254 if ( !theProvider )
00255 {
00256 return 1;
00257 }
00258 if ( modeValue == "Empty" )
00259 {
00260 mMode = QgsGraduatedSymbolRenderer::Empty;
00261 }
00262 else if ( modeValue == "Quantile" )
00263 {
00264 mMode = QgsGraduatedSymbolRenderer::Quantile;
00265 }
00266 else
00267 {
00268 mMode = QgsGraduatedSymbolRenderer::EqualInterval;
00269 }
00270
00271 int classificationId = theProvider->fieldNameIndex( classificationField );
00272 if ( classificationId == -1 )
00273 {
00274 return 2;
00275 }
00276 setClassificationField( classificationId );
00277
00278 QDomNode symbolnode = rnode.namedItem( "symbol" );
00279 while ( !symbolnode.isNull() )
00280 {
00281 QgsSymbol* sy = new QgsSymbol( mGeometryType );
00282 sy->readXML( symbolnode, &vl );
00283 addSymbol( sy );
00284
00285 symbolnode = symbolnode.nextSibling();
00286 }
00287 updateSymbolAttributes();
00288 vl.setRenderer( this );
00289 return 0;
00290 }
00291
00292 QgsAttributeList QgsGraduatedSymbolRenderer::classificationAttributes() const
00293 {
00294 QgsAttributeList list( mSymbolAttributes );
00295 if ( ! list.contains( mClassificationField ) )
00296 {
00297 list.append( mClassificationField );
00298 }
00299 return list;
00300 }
00301
00302 void QgsGraduatedSymbolRenderer::updateSymbolAttributes()
00303 {
00304
00305
00306
00307 mSymbolAttributes.clear();
00308
00309 QList<QgsSymbol*>::iterator it;
00310 for ( it = mSymbols.begin(); it != mSymbols.end(); ++it )
00311 {
00312 int rotationField = ( *it )->rotationClassificationField();
00313 if ( rotationField >= 0 && !mSymbolAttributes.contains( rotationField ) )
00314 {
00315 mSymbolAttributes.append( rotationField );
00316 }
00317 int scaleField = ( *it )->scaleClassificationField();
00318 if ( scaleField >= 0 && !mSymbolAttributes.contains( scaleField ) )
00319 {
00320 mSymbolAttributes.append( scaleField );
00321 }
00322 int symbolField = ( *it )->symbolField();
00323 if ( symbolField >= 0 && !mSymbolAttributes.contains( symbolField ) )
00324 {
00325 mSymbolAttributes.append( symbolField );
00326 }
00327 }
00328 }
00329
00330 QString QgsGraduatedSymbolRenderer::name() const
00331 {
00332 return "Graduated Symbol";
00333 }
00334
00335 bool QgsGraduatedSymbolRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
00336 {
00337 bool returnval = true;
00338 QDomElement graduatedsymbol = document.createElement( "graduatedsymbol" );
00339 layer_node.appendChild( graduatedsymbol );
00340
00341
00342
00343
00344
00345 QString modeValue = "";
00346 if ( mMode == QgsGraduatedSymbolRenderer::Empty )
00347 {
00348 modeValue == "Empty";
00349 }
00350 else if ( QgsGraduatedSymbolRenderer::Quantile )
00351 {
00352 modeValue = "Quantile";
00353 }
00354 else
00355 {
00356 modeValue = "Equal Interval";
00357 }
00358 QDomElement modeElement = document.createElement( "mode" );
00359 QDomText modeText = document.createTextNode( modeValue );
00360 modeElement.appendChild( modeText );
00361 graduatedsymbol.appendChild( modeElement );
00362
00363
00364
00365
00366
00367
00368
00369 QDomElement classificationfield = document.createElement( "classificationfield" );
00370
00371 const QgsVectorDataProvider* theProvider = vl.dataProvider();
00372 if ( !theProvider )
00373 {
00374 return false;
00375 }
00376
00377 QString classificationFieldName;
00378 if ( vl.pendingFields().contains( mClassificationField ) )
00379 {
00380 classificationFieldName = vl.pendingFields()[ mClassificationField ].name();
00381 }
00382
00383 QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
00384 classificationfield.appendChild( classificationfieldtxt );
00385 graduatedsymbol.appendChild( classificationfield );
00386 for ( QList<QgsSymbol*>::const_iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00387 {
00388 if ( !( *it )->writeXML( graduatedsymbol, document, &vl ) )
00389 {
00390 returnval = false;
00391 }
00392 }
00393 return returnval;
00394 }
00395
00396 QgsRenderer* QgsGraduatedSymbolRenderer::clone() const
00397 {
00398 QgsGraduatedSymbolRenderer* r = new QgsGraduatedSymbolRenderer( *this );
00399 return r;
00400 }