src/core/renderer/qgsuniquevaluerenderer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgsuniquevaluerenderer.cpp  -  description
00003                              -------------------
00004     begin                : July 2004
00005     copyright            : (C) 2004 by Marco Hugentobler
00006     email                : marco.hugentobler@autoform.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 /* $Id: qgsuniquevaluerenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */
00018 
00019 #include "qgsuniquevaluerenderer.h"
00020 #include "qgsfeature.h"
00021 #include "qgsvectordataprovider.h"
00022 #include "qgsvectorlayer.h"
00023 #include "qgssymbol.h"
00024 #include "qgssymbologyutils.h"
00025 #include "qgslogger.h"
00026 #include <math.h>
00027 #include <QDomNode>
00028 #include <QPainter>
00029 #include <QImage>
00030 #include <vector>
00031 
00032 QgsUniqueValueRenderer::QgsUniqueValueRenderer( QGis::GeometryType type ): mClassificationField( 0 )
00033 {
00034   mGeometryType = type;
00035   mSymbolAttributesDirty = false;
00036 }
00037 
00038 QgsUniqueValueRenderer::QgsUniqueValueRenderer( const QgsUniqueValueRenderer& other )
00039 {
00040   mGeometryType = other.mGeometryType;
00041   mClassificationField = other.mClassificationField;
00042   QMap<QString, QgsSymbol*> s = other.mSymbols;
00043   for ( QMap<QString, QgsSymbol*>::iterator it = s.begin(); it != s.end(); ++it )
00044   {
00045     QgsSymbol* s = new QgsSymbol( * it.value() );
00046     insertValue( it.key(), s );
00047   }
00048   updateSymbolAttributes();
00049 }
00050 
00051 QgsUniqueValueRenderer& QgsUniqueValueRenderer::operator=( const QgsUniqueValueRenderer & other )
00052 {
00053   if ( this != &other )
00054   {
00055     mGeometryType = other.mGeometryType;
00056     mClassificationField = other.mClassificationField;
00057     clearValues();
00058     for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00059     {
00060       QgsSymbol* s = new QgsSymbol( *it.value() );
00061       insertValue( it.key(), s );
00062     }
00063     updateSymbolAttributes();
00064   }
00065   return *this;
00066 }
00067 
00068 QgsUniqueValueRenderer::~QgsUniqueValueRenderer()
00069 {
00070   for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin();it != mSymbols.end();++it )
00071   {
00072     delete it.value();
00073   }
00074 }
00075 
00076 const QList<QgsSymbol*> QgsUniqueValueRenderer::symbols() const
00077 {
00078   QList <QgsSymbol*> symbollist;
00079   for ( QMap<QString, QgsSymbol*>::const_iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00080   {
00081     symbollist.append( it.value() );
00082   }
00083   return symbollist;
00084 }
00085 
00086 void QgsUniqueValueRenderer::insertValue( QString name, QgsSymbol* symbol )
00087 {
00088   mSymbols.insert( name, symbol );
00089   mSymbolAttributesDirty = true;
00090 }
00091 
00092 void QgsUniqueValueRenderer::setClassificationField( int field )
00093 {
00094   mClassificationField = field;
00095 }
00096 
00097 int QgsUniqueValueRenderer::classificationField() const
00098 {
00099   return mClassificationField;
00100 }
00101 
00102 bool QgsUniqueValueRenderer::willRenderFeature( QgsFeature *f )
00103 {
00104   return ( symbolForFeature( f ) != 0 );
00105 }
00106 
00107 void QgsUniqueValueRenderer::renderFeature( QPainter* p, QgsFeature& f, QImage* img, bool selected, double widthScale, double rasterScaleFactor )
00108 {
00109   QgsSymbol* symbol = symbolForFeature( &f );
00110   if ( !symbol ) //no matching symbol
00111   {
00112     if ( img && mGeometryType == QGis::Point )
00113     {
00114       img->fill( 0 );
00115     }
00116     else if ( mGeometryType != QGis::Point )
00117     {
00118       p->setPen( Qt::NoPen );
00119       p->setBrush( Qt::NoBrush );
00120     }
00121     return;
00122   }
00123 
00124   // Point
00125   if ( img && mGeometryType == QGis::Point )
00126   {
00127     double fieldScale = 1.0;
00128     double rotation = 0.0;
00129 
00130     if ( symbol->scaleClassificationField() >= 0 )
00131     {
00132       //first find out the value for the scale classification attribute
00133       const QgsAttributeMap& attrs = f.attributeMap();
00134       fieldScale = sqrt( fabs( attrs[symbol->scaleClassificationField()].toDouble() ) );
00135     }
00136     if ( symbol->rotationClassificationField() >= 0 )
00137     {
00138       const QgsAttributeMap& attrs = f.attributeMap();
00139       rotation = attrs[symbol->rotationClassificationField()].toDouble();
00140     }
00141     *img = symbol->getPointSymbolAsImage( widthScale, selected, mSelectionColor,
00142                                           fieldScale, rotation, rasterScaleFactor );
00143   }
00144   // Line, polygon
00145   else if ( mGeometryType != QGis::Point )
00146   {
00147     if ( !selected )
00148     {
00149       QPen pen = symbol->pen();
00150       pen.setWidthF( widthScale * pen.widthF() );
00151       p->setPen( pen );
00152       if ( mGeometryType == QGis::Polygon )
00153       {
00154         QBrush brush = symbol->brush();
00155         scaleBrush( brush, rasterScaleFactor ); //scale brush content for printout
00156         p->setBrush( brush );
00157       }
00158     }
00159     else
00160     {
00161       QPen pen = symbol->pen();
00162       pen.setWidthF( widthScale * pen.widthF() );
00163       if ( mGeometryType == QGis::Polygon )
00164       {
00165         QBrush brush = symbol->brush();
00166         scaleBrush( brush, rasterScaleFactor ); //scale brush content for printout
00167         brush.setColor( mSelectionColor );
00168         p->setBrush( brush );
00169       }
00170       else //dont draw outlines of polygons in selection colour otherwise they appear merged
00171       {
00172         pen.setColor( mSelectionColor );
00173       }
00174       p->setPen( pen );
00175     }
00176   }
00177 }
00178 
00179 QgsSymbol *QgsUniqueValueRenderer::symbolForFeature( const QgsFeature *f )
00180 {
00181   //first find out the value
00182   const QgsAttributeMap& attrs = f->attributeMap();
00183   QString value = attrs[mClassificationField].toString();
00184 
00185   QMap<QString, QgsSymbol*>::iterator it = mSymbols.find( value );
00186   if ( it == mSymbols.end() )
00187   {
00188     return 0;
00189   }
00190   else
00191   {
00192     return it.value();
00193   }
00194 }
00195 
00196 int QgsUniqueValueRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
00197 {
00198   mGeometryType = vl.geometryType();
00199   QDomNode classnode = rnode.namedItem( "classificationfield" );
00200   QString classificationField = classnode.toElement().text();
00201 
00202   QgsVectorDataProvider* theProvider = vl.dataProvider();
00203   if ( !theProvider )
00204   {
00205     return 1;
00206   }
00207 
00208   int classificationId = theProvider->fieldNameIndex( classificationField );
00209   if ( classificationId == -1 )
00210   {
00211     return 2; //@todo: handle gracefully in gui situation where user needs to nominate field
00212   }
00213   setClassificationField( classificationId );
00214 
00215   QDomNode symbolnode = rnode.namedItem( "symbol" );
00216   while ( !symbolnode.isNull() )
00217   {
00218     QgsSymbol* msy = new QgsSymbol( mGeometryType );
00219     msy->readXML( symbolnode, &vl );
00220     insertValue( msy->lowerValue(), msy );
00221     symbolnode = symbolnode.nextSibling();
00222   }
00223   updateSymbolAttributes();
00224   vl.setRenderer( this );
00225   return 0;
00226 }
00227 
00228 void QgsUniqueValueRenderer::clearValues()
00229 {
00230   for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin();it != mSymbols.end();++it )
00231   {
00232     delete it.value();
00233   }
00234   mSymbols.clear();
00235   updateSymbolAttributes();
00236 }
00237 
00238 void QgsUniqueValueRenderer::updateSymbolAttributes()
00239 {
00240   mSymbolAttributesDirty = false;
00241 
00242   mSymbolAttributes.clear();
00243 
00244   QMap<QString, QgsSymbol*>::iterator it;
00245   for ( it = mSymbols.begin(); it != mSymbols.end(); ++it )
00246   {
00247     int rotationField = ( *it )->rotationClassificationField();
00248     if ( rotationField >= 0 && !( mSymbolAttributes.contains( rotationField ) ) )
00249     {
00250       mSymbolAttributes.append( rotationField );
00251     }
00252     int scaleField = ( *it )->scaleClassificationField();
00253     if ( scaleField >= 0 && !( mSymbolAttributes.contains( scaleField ) ) )
00254     {
00255       mSymbolAttributes.append( scaleField );
00256     }
00257   }
00258 }
00259 
00260 QString QgsUniqueValueRenderer::name() const
00261 {
00262   return "Unique Value";
00263 }
00264 
00265 QgsAttributeList QgsUniqueValueRenderer::classificationAttributes() const
00266 {
00267   QgsAttributeList list( mSymbolAttributes );
00268   if ( ! list.contains( mClassificationField ) )
00269   {
00270     list.append( mClassificationField );
00271   }
00272   return list;
00273 }
00274 
00275 bool QgsUniqueValueRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
00276 {
00277   const QgsVectorDataProvider* theProvider = vl.dataProvider();
00278   if ( !theProvider )
00279   {
00280     return false;
00281   }
00282 
00283   QString classificationFieldName;
00284   QgsFieldMap::const_iterator field_it = theProvider->fields().find( mClassificationField );
00285   if ( field_it != theProvider->fields().constEnd() )
00286   {
00287     classificationFieldName = field_it.value().name();
00288   }
00289 
00290   bool returnval = true;
00291   QDomElement uniquevalue = document.createElement( "uniquevalue" );
00292   layer_node.appendChild( uniquevalue );
00293   QDomElement classificationfield = document.createElement( "classificationfield" );
00294   QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
00295   classificationfield.appendChild( classificationfieldtxt );
00296   uniquevalue.appendChild( classificationfield );
00297   for ( QMap<QString, QgsSymbol*>::const_iterator it = mSymbols.begin();it != mSymbols.end();++it )
00298   {
00299     if ( !( it.value()->writeXML( uniquevalue, document, &vl ) ) )
00300     {
00301       returnval = false;
00302     }
00303   }
00304   return returnval;
00305 }
00306 
00307 QgsRenderer* QgsUniqueValueRenderer::clone() const
00308 {
00309   QgsUniqueValueRenderer* r = new QgsUniqueValueRenderer( *this );
00310   return r;
00311 }

Generated on Fri Jan 9 01:51:13 2009 for Quantum GIS API Documentation by  doxygen 1.5.1